From 2c2ba3bd5f9d70ba9ec4273ab2eb7fc47d465a49 Mon Sep 17 00:00:00 2001 From: opencode Date: Fri, 13 Nov 2026 09:34:32 +0000 Subject: [PATCH] docs(xie): the ROM's XImage entry points and the 1-bit format --- dwt/gui/build/xshow.bin | Bin 0 -> 872 bytes dwt/gui/build/xshow.coff | Bin 0 -> 1384 bytes dwt/gui/build/xshow.lst | 626 +++++++++++++++++++++++++++ dwt/gui/build/xshow.map | 36 ++ dwt/gui/evidence/png_rows.py | 79 ++++ dwt/gui/evidence/xshow_frame2650.png | Bin 0 -> 16394 bytes dwt/gui/evidence/xshow_frame2680.png | Bin 0 -> 16394 bytes dwt/gui/evidence/xshow_pixels.txt | 75 ++++ dwt/gui/evidence/xshow_run.log | 37 ++ dwt/gui/xshow.asm | 348 +++++++++++++++ dwt/gui/xshow.lua | 301 +++++++++++++ dwt/loader/build/xshow.bin | Bin 0 -> 872 bytes dwt/loader/build/xshow.coff | Bin 0 -> 1384 bytes dwt/loader/build/xshow.lst | 626 +++++++++++++++++++++++++++ dwt/loader/build/xshow.map | 36 ++ dwt/loader/build/xshow.obj | Bin 0 -> 1428 bytes dwt/notes/GUI_APPS.md | 168 ++++++- 17 files changed, 2330 insertions(+), 2 deletions(-) create mode 100644 dwt/gui/build/xshow.bin create mode 100644 dwt/gui/build/xshow.coff create mode 100644 dwt/gui/build/xshow.lst create mode 100644 dwt/gui/build/xshow.map create mode 100644 dwt/gui/evidence/png_rows.py create mode 100644 dwt/gui/evidence/xshow_frame2650.png create mode 100644 dwt/gui/evidence/xshow_frame2680.png create mode 100644 dwt/gui/evidence/xshow_pixels.txt create mode 100644 dwt/gui/evidence/xshow_run.log create mode 100644 dwt/gui/xshow.asm create mode 100644 dwt/gui/xshow.lua create mode 100644 dwt/loader/build/xshow.bin create mode 100644 dwt/loader/build/xshow.coff create mode 100644 dwt/loader/build/xshow.lst create mode 100644 dwt/loader/build/xshow.map create mode 100644 dwt/loader/build/xshow.obj diff --git a/dwt/gui/build/xshow.bin b/dwt/gui/build/xshow.bin new file mode 100644 index 0000000000000000000000000000000000000000..3c94913bd05a31f4e68b6325728dfb43ac8d4fbb GIT binary patch literal 872 zcma))u}i~16vi($^>S)M2Pa*!h`9I{D9xZy3XzUZHiMIb)c+u3(o(D`3Kj*yRj`B5 zwWH{ug9vUnDwIy*TEBZqNGT~eeRtgV-tT)aspf5dCfHaCjWOnNTMIOgGq0t+-i-va z15JwZ_kGC>YlXM{$5Iu3pG&+;p`*emvzOBhZ+-2Wyo*kgGxTh73pK|MdpdNL7WpKgHUHLER7OZiaiElTNMBUVSI(g45s@s10s|S^;$()EvB7 z6GpYY-4Cjb=F0LVX%ZT%Ur~i{0`7qpa2K=<(0(Q+0Tf9$DWBW@j2ZbESrUd67S$yh z?V_cnJ5i@-OKissX?nd&-MQm)7kPZ{A&-GPJtoEc6mdx3FWoqvkyG{Q{YEK=+v%%C zuZp=GpA^*$N0=bAN%7Efhjv#nQ@LBxxdqlU!lB!WDN3hvyy& z1_J>b3&AUdwAU$GXdyznDHXz1lJ@-G+uhsEu>l(ghWBRYd++yVc4h|T(BjG2_P`}t zBBE>LsIvM*ejNjRBZV%l1Fx?d?X9Qn*|?)v_bySS#)H$?+-PsehrYydt{UgdH6MQC z(eAE%3ZdgZ<7L7S?)?Q{KQ}bBh6SPaRZoSQBfhu*GRIoQ{Pocr2C%;SK*JVaz^jc)Tg&YIJY7GhD9>>OX|K80={e)IIHkx(4bEP#tKCRv5>Q?*5e6cwI%hw3?Jg zt=AG^f}RdR>**$FH$nT8TM3}3v?2914^9%s!UeUY3~M}zOKrRteU?5$P(NGufWli#=>$B!oGLG|Kls&5m^0|7udMxBI$p5Odri?sA6;5#C z!%DoPSI5@8fUX7`!7jlLVau>DVO`i)u;k=3eK1q{B`3IPrf7VI<<7wJ>OFKHJw%uL z`JV*L&c82wY8-iCmYFxhn`bBguJC<=hSQyE^Q;nWC9j)b? bit + 0013 ; 7F34092 XCreateImage(d,visual,depth,format,offset,d + 0014 ; 7FA06E XPutImage(d,drawable,gc,image,sx,sy,dx,dy,w + 0015 ; 7F341B0 XDestroyImage(image) + 0016 ; 7FAAAD6 XGetImage(d,drawable,x,y,w,h,plane_mask,for + 0017 ; (XGetImage is documented from disassembly; this probe + 0018 ; + 0019 ; Calling convention: reserve one slot with `move a14,- + 0020 ; last-to-first upward through a14, then `calla`. The + 0021 ; the return address and the reserved slot, and restore + 0022 ; sp/a14 from RAM markers (xtext.asm records that exact + 0023 ; + 0024 ; Xlib clobbers the CPU's SETF field state, so field 1 + 0025 ; established after every call. a10/a11/a12 survive ev + 0026 ; a9 (the GC) survives XCreateImage and XPutImage; a7 ( + 0027 ; XPutImage. XDestroyImage saves only a11/a13, so it r + 0028 ; + 0029 ; Markers: + 0030 ; 01890100 display 01890120 window 01890140 stage + 0031 ; 01890180 gc 018901A0 XPutImage return 01 + 0032 ; These are the xhello-compatible cells the runner repo + 0033 ; cells sit in the heap and were overwritten after its + 0034 ; are mirrored into .bss at 018D8000h (below), which no + 0035 ; 018D8000 stage 018D8020 display 018D8040 window + 0036 ; 018D8080 image 018D80A0 putret 018D80C0 syncret + 0037 ; Stage: 1 start, 2 display, 3 window, 4 mapped, 5 gc, + 0038 ; 8 synced; 091h..097h = the step that failed. + 0039 ; + 0040 ; Scratch argument area: 01894000h (the app's own stack + 0041 + 0042 00000000 .text + 0043 00000000 _start: + 0044 00000000 0550 setf 16, 0, 0 + 0045 00000010 0740 setf 32, 0, 1 + 0046 00000020 098F mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7 + 00000030 FF00 + 0047 + 0048 00000040 09E0 movi 1, a0, L + 00000050 00000001 + 0049 00000070 0780 move a0, @01890140h, 1 ; stage = 1 + 00000080 01890140 + 0050 000000A0 0780 move a0, @m_stage, 1 + 000000B0 00000000+ + 0051 + 0052 ; ---- convention check: strlen("0::0") == 4 --------- + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 2 + + 0053 000000D0 A3CF move a14, -*sp, 1 + 0054 000000E0 09EE movi 01894000h, a14, L + 000000F0 01894000 + 0055 00000110 09E0 movi 3FACE948h, a0, L ; ROM "0::0" + 00000120 3FACE948 + 0056 00000140 920E move a0, *a14+, 1 + 0057 00000150 0D5F calla 3FB458D0h ; strlen + 00000160 3FB458D0 + 0058 00000180 0550 setf 16, 0, 0 + 0059 00000190 0740 setf 32, 0, 1 + 0060 000001A0 0788 move a8, @m_strlen, 1 + 000001B0 000000E0+ + 0061 000001D0 09E0 movi 4, a0, L + 000001E0 00000004 + 0062 00000200 4808 cmp a0, a8 + 0063 00000210 CB00 jrne fail_abi + 00000220 0171 + 0064 + 0065 ; ---- display = XOpenDisplay("0::0") ---------------- + 0066 00000230 A3CF move a14, -*sp, 1 + 0067 00000240 09EE movi 01894000h, a14, L + 00000250 01894000 + 0068 00000270 09E0 movi 3FACE948h, a0, L + 00000280 3FACE948 + 0069 000002A0 920E move a0, *a14+, 1 + 0070 000002B0 0D5F calla 3F9C2570h ; XOpenDisplay + 000002C0 3F9C2570 + 0071 000002E0 0550 setf 16, 0, 0 + 0072 000002F0 0740 setf 32, 0, 1 + 0073 00000300 4D0B move a8, a11 + 0074 00000310 078B move a11, @01890100h, 1 ; MARK display + 00000320 01890100 + 0075 00000340 078B move a11, @m_display, 1 + 00000350 00000020+ + 0076 00000370 4D6B move a11, a11 + 0077 00000380 CA00 jreq fail_open + 00000390 015E + 0078 000003A0 09E0 movi 2, a0, L + 000003B0 00000002 + 0079 000003D0 0780 move a0, @01890140h, 1 ; stage = 2 + 000003E0 01890140 + 0080 00000400 0780 move a0, @m_stage, 1 + 00000410 00000000+ + 0081 + 0082 ; ---- root = *(*(display+0x480)+0x40) --------------- + 0083 00000430 B76A move *a11(0480h), a10, 1 + 00000440 0480 + 0084 00000450 B74A move *a10(040h), a10, 1 + 00000460 0040 + 0085 + 0086 ; ---- window = XCreateSimpleWindow(d,root,100,100,400 + 0087 ; white background (pixel 1), black border, so a black + 0088 00000470 A3CF move a14, -*sp, 1 + 0089 00000480 09EE movi 01894000h, a14, L + 00000490 01894000 + 0090 000004B0 09E0 movi 1, a0, L + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 3 + + 000004C0 00000001 + 0091 000004E0 920E move a0, *a14+, 1 ; background = 1 (white) + 0092 000004F0 09E0 movi 0, a0, L + 00000500 00000000 + 0093 00000520 920E move a0, *a14+, 1 ; border = 0 (black) + 0094 00000530 09E0 movi 2, a0, L + 00000540 00000002 + 0095 00000560 920E move a0, *a14+, 1 ; border width + 0096 00000570 09E0 movi 200, a0, L + 00000580 000000C8 + 0097 000005A0 920E move a0, *a14+, 1 ; height + 0098 000005B0 09E0 movi 400, a0, L + 000005C0 00000190 + 0099 000005E0 920E move a0, *a14+, 1 ; width + 0100 000005F0 09E0 movi 100, a0, L + 00000600 00000064 + 0101 00000620 920E move a0, *a14+, 1 ; y + 0102 00000630 920E move a0, *a14+, 1 ; x + 0103 00000640 934E move a10, *a14+, 1 ; parent = root + 0104 00000650 936E move a11, *a14+, 1 ; display + 0105 00000660 0D5F calla 3FD41B90h ; XCreateSimpleWindow + 00000670 3FD41B90 + 0106 00000690 0550 setf 16, 0, 0 + 0107 000006A0 0740 setf 32, 0, 1 + 0108 000006B0 4D0A move a8, a10 + 0109 000006C0 078A move a10, @01890120h, 1 ; MARK window + 000006D0 01890120 + 0110 000006F0 078A move a10, @m_window, 1 + 00000700 00000040+ + 0111 00000720 4D4A move a10, a10 + 0112 00000730 CA00 jreq fail_win + 00000740 0127 + 0113 00000750 09E0 movi 3, a0, L + 00000760 00000003 + 0114 00000780 0780 move a0, @01890140h, 1 ; stage = 3 + 00000790 01890140 + 0115 000007B0 0780 move a0, @m_stage, 1 + 000007C0 00000000+ + 0116 + 0117 ; ---- XMapWindow(display, window) ------------------- + 0118 000007E0 A3CF move a14, -*sp, 1 + 0119 000007F0 09EE movi 01894000h, a14, L + 00000800 01894000 + 0120 00000820 934E move a10, *a14+, 1 + 0121 00000830 936E move a11, *a14+, 1 + 0122 00000840 0D5F calla 3FD645B0h ; XMapWindow + 00000850 3FD645B0 + 0123 00000870 0550 setf 16, 0, 0 + 0124 00000880 0740 setf 32, 0, 1 + 0125 00000890 09E0 movi 4, a0, L + 000008A0 00000004 + 0126 000008C0 0780 move a0, @01890140h, 1 ; stage = 4 + 000008D0 01890140 + 0127 000008F0 0780 move a0, @m_stage, 1 + 00000900 00000000+ + 0128 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 4 + + 0129 ; ---- gc = XCreateGC(d, window, 0, NULL) ------------ + 0130 00000920 A3CF move a14, -*sp, 1 + 0131 00000930 09EE movi 01894000h, a14, L + 00000940 01894000 + 0132 00000960 09E0 movi 0, a0, L + 00000970 00000000 + 0133 00000990 920E move a0, *a14+, 1 ; values + 0134 000009A0 920E move a0, *a14+, 1 ; mask = 0 + 0135 000009B0 934E move a10, *a14+, 1 ; drawable + 0136 000009C0 936E move a11, *a14+, 1 ; display + 0137 000009D0 0D5F calla 3F997000h ; XCreateGC + 000009E0 3F997000 + 0138 00000A00 0550 setf 16, 0, 0 + 0139 00000A10 0740 setf 32, 0, 1 + 0140 00000A20 4D09 move a8, a9 ; GC + 0141 00000A30 0789 move a9, @01890180h, 1 ; MARK gc + 00000A40 01890180 + 0142 00000A60 0789 move a9, @m_gc, 1 + 00000A70 00000060+ + 0143 00000A90 4D29 move a9, a9 + 0144 00000AA0 CA00 jreq fail_gc + 00000AB0 00F4 + 0145 + 0146 ; ---- XSetForeground(display, gc, 0) -- draw with pen + 0147 00000AC0 A3CF move a14, -*sp, 1 + 0148 00000AD0 09EE movi 01894000h, a14, L + 00000AE0 01894000 + 0149 00000B00 09E0 movi 0, a0, L + 00000B10 00000000 + 0150 00000B30 920E move a0, *a14+, 1 ; pixel = 0 + 0151 00000B40 932E move a9, *a14+, 1 ; gc + 0152 00000B50 936E move a11, *a14+, 1 ; display + 0153 00000B60 0D5F calla 3FD99A60h ; XSetForeground + 00000B70 3FD99A60 + 0154 00000B90 0550 setf 16, 0, 0 + 0155 00000BA0 0740 setf 32, 0, 1 + 0156 00000BB0 09E0 movi 5, a0, L + 00000BC0 00000005 + 0157 00000BE0 0780 move a0, @01890140h, 1 ; stage = 5 + 00000BF0 01890140 + 0158 00000C10 0780 move a0, @m_stage, 1 + 00000C20 00000000+ + 0159 + 0160 ; ---- image = XCreateImage(d, NULL, 1, XYBitmap, 0, + 0161 ; bitmap, 32, 32, 32, 0) --- + 0162 00000C40 A3CF move a14, -*sp, 1 + 0163 00000C50 09EE movi 01894000h, a14, L + 00000C60 01894000 + 0164 00000C80 09E0 movi 0, a0, L + 00000C90 00000000 + 0165 00000CB0 920E move a0, *a14+, 1 ; bytes_per_line = 0 (let it comput + 0166 00000CC0 09E0 movi 32, a0, L + 00000CD0 00000020 + 0167 00000CF0 920E move a0, *a14+, 1 ; bitmap_pad = 32 + 0168 00000D00 09E0 movi 32, a0, L + 00000D10 00000020 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 5 + + 0169 00000D30 920E move a0, *a14+, 1 ; height + 0170 00000D40 920E move a0, *a14+, 1 ; width + 0171 00000D50 09E0 movi BITMAP, a0, L + 00000D60 00000000" + 0172 00000D80 920E move a0, *a14+, 1 ; data + 0173 00000D90 09E0 movi 0, a0, L + 00000DA0 00000000 + 0174 00000DC0 920E move a0, *a14+, 1 ; offset + 0175 00000DD0 920E move a0, *a14+, 1 ; format = 0 (XYBitmap) + 0176 00000DE0 09E0 movi 1, a0, L + 00000DF0 00000001 + 0177 00000E10 920E move a0, *a14+, 1 ; depth = 1 + 0178 00000E20 4400 sub a0, a0 + 0179 00000E30 920E move a0, *a14+, 1 ; visual = NULL + 0180 00000E40 936E move a11, *a14+, 1 ; display + 0181 00000E50 0D5F calla 3F9A0490h ; XCreateImage + 00000E60 3F9A0490 + 0182 00000E80 0550 setf 16, 0, 0 + 0183 00000E90 0740 setf 32, 0, 1 + 0184 00000EA0 4D07 move a8, a7 ; image (a7 survives XPutImage) + 0185 00000EB0 0788 move a8, @01890160h, 1 ; MARK image + 00000EC0 01890160 + 0186 00000EE0 0788 move a8, @m_image, 1 + 00000EF0 00000080+ + 0187 00000F10 4D08 move a8, a8 + 0188 00000F20 CA00 jreq fail_img + 00000F30 00B0 + 0189 00000F40 09E0 movi 6, a0, L + 00000F50 00000006 + 0190 00000F70 0780 move a0, @01890140h, 1 ; stage = 6 + 00000F80 01890140 + 0191 00000FA0 0780 move a0, @m_stage, 1 + 00000FB0 00000000+ + 0192 + 0193 ; ---- let the WM frame/reparent and map the window (x + 0194 ; A draw issued before the reparent can be lost, so sy + 0195 00000FD0 09EC movi 4, a12, L + 00000FE0 00000004 + 0196 00001000 map_wait: + 0197 00001000 A3CF move a14, -*sp, 1 + 0198 00001010 09EE movi 01894000h, a14, L + 00001020 01894000 + 0199 00001040 09E0 movi 0, a0, L + 00001050 00000000 + 0200 00001070 920E move a0, *a14+, 1 ; discard = 0 + 0201 00001080 936E move a11, *a14+, 1 ; display + 0202 00001090 0D5F calla 3FD9F6B0h ; XSync + 000010A0 3FD9F6B0 + 0203 000010C0 0550 setf 16, 0, 0 + 0204 000010D0 0740 setf 32, 0, 1 + 0205 000010E0 3DEC dsjs a12, map_wait + 0206 + 0207 ; ---- XPutImage(d, win, gc, image, 0,0, 20,20, 32,32) + 0208 000010F0 A3CF move a14, -*sp, 1 + 0209 00001100 09EE movi 01894000h, a14, L + 00001110 01894000 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 6 + + 0210 00001130 09E0 movi 32, a0, L + 00001140 00000020 + 0211 00001160 920E move a0, *a14+, 1 ; h + 0212 00001170 920E move a0, *a14+, 1 ; w + 0213 00001180 09E0 movi 20, a0, L + 00001190 00000014 + 0214 000011B0 920E move a0, *a14+, 1 ; dst_y + 0215 000011C0 920E move a0, *a14+, 1 ; dst_x + 0216 000011D0 4400 sub a0, a0 + 0217 000011E0 920E move a0, *a14+, 1 ; src_y + 0218 000011F0 920E move a0, *a14+, 1 ; src_x + 0219 00001200 92EE move a7, *a14+, 1 ; image + 0220 00001210 932E move a9, *a14+, 1 ; gc + 0221 00001220 934E move a10, *a14+, 1 ; drawable + 0222 00001230 936E move a11, *a14+, 1 ; display + 0223 00001240 0D5F calla 3F9D0370h ; XPutImage + 00001250 3F9D0370 + 0224 00001270 0550 setf 16, 0, 0 + 0225 00001280 0740 setf 32, 0, 1 + 0226 00001290 0788 move a8, @018901A0h, 1 ; MARK putimage return + 000012A0 018901A0 + 0227 000012C0 0788 move a8, @m_putret, 1 + 000012D0 000000A0+ + 0228 000012F0 09E0 movi 7, a0, L + 00001300 00000007 + 0229 00001320 0780 move a0, @01890140h, 1 ; stage = 7 + 00001330 01890140 + 0230 00001350 0780 move a0, @m_stage, 1 + 00001360 00000000+ + 0231 + 0232 ; ---- control: the same image with h = 16 at dst_y = + 0233 ; The PNG must show exactly 16 rows here (src rows 0.. + 0234 ; what proves the 32-row draw above is the image, not + 0235 00001380 A3CF move a14, -*sp, 1 + 0236 00001390 09EE movi 01894000h, a14, L + 000013A0 01894000 + 0237 000013C0 09E0 movi 16, a0, L + 000013D0 00000010 + 0238 000013F0 920E move a0, *a14+, 1 ; h = 16 + 0239 00001400 09E0 movi 32, a0, L + 00001410 00000020 + 0240 00001430 920E move a0, *a14+, 1 ; w = 32 + 0241 00001440 09E0 movi 60, a0, L + 00001450 0000003C + 0242 00001470 920E move a0, *a14+, 1 ; dst_y = 60 + 0243 00001480 09E0 movi 20, a0, L + 00001490 00000014 + 0244 000014B0 920E move a0, *a14+, 1 ; dst_x = 20 + 0245 000014C0 4400 sub a0, a0 + 0246 000014D0 920E move a0, *a14+, 1 ; src_y = 0 + 0247 000014E0 920E move a0, *a14+, 1 ; src_x = 0 + 0248 000014F0 92EE move a7, *a14+, 1 ; image + 0249 00001500 932E move a9, *a14+, 1 ; gc + 0250 00001510 934E move a10, *a14+, 1 ; drawable + 0251 00001520 936E move a11, *a14+, 1 ; display + 0252 00001530 0D5F calla 3F9D0370h ; XPutImage + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 7 + + 00001540 3F9D0370 + 0253 00001560 0550 setf 16, 0, 0 + 0254 00001570 0740 setf 32, 0, 1 + 0255 + 0256 ; ---- flush, twice: the request is only in the client + 0257 00001580 A3CF move a14, -*sp, 1 + 0258 00001590 09EE movi 01894000h, a14, L + 000015A0 01894000 + 0259 000015C0 09E0 movi 0, a0, L + 000015D0 00000000 + 0260 000015F0 920E move a0, *a14+, 1 + 0261 00001600 936E move a11, *a14+, 1 + 0262 00001610 0D5F calla 3FD9F6B0h ; XSync + 00001620 3FD9F6B0 + 0263 00001640 0550 setf 16, 0, 0 + 0264 00001650 0740 setf 32, 0, 1 + 0265 00001660 0788 move a8, @018901C0h, 1 ; MARK sync return + 00001670 018901C0 + 0266 00001690 0788 move a8, @m_syncret, 1 + 000016A0 000000C0+ + 0267 + 0268 000016C0 A3CF move a14, -*sp, 1 + 0269 000016D0 09EE movi 01894000h, a14, L + 000016E0 01894000 + 0270 00001700 09E0 movi 0, a0, L + 00001710 00000000 + 0271 00001730 920E move a0, *a14+, 1 + 0272 00001740 936E move a11, *a14+, 1 + 0273 00001750 0D5F calla 3FD9F6B0h ; XSync + 00001760 3FD9F6B0 + 0274 00001780 0550 setf 16, 0, 0 + 0275 00001790 0740 setf 32, 0, 1 + 0276 000017A0 0788 move a8, @018901C0h, 1 + 000017B0 018901C0 + 0277 000017D0 0788 move a8, @m_syncret, 1 + 000017E0 000000C0+ + 0278 + 0279 00001800 09E0 movi 8, a0, L + 00001810 00000008 + 0280 00001830 0780 move a0, @01890140h, 1 ; stage = 8 + 00001840 01890140 + 0281 00001860 0780 move a0, @m_stage, 1 + 00001870 00000000+ + 0282 + 0283 ; ---- XDestroyImage(image) -------------------------- + 0284 00001890 A3CF move a14, -*sp, 1 + 0285 000018A0 09EE movi 01894000h, a14, L + 000018B0 01894000 + 0286 000018D0 92EE move a7, *a14+, 1 + 0287 000018E0 0D5F calla 3F9A0D80h ; XDestroyImage + 000018F0 3F9A0D80 + 0288 00001910 0550 setf 16, 0, 0 + 0289 00001920 0740 setf 32, 0, 1 + 0290 00001930 C01A jruc done + 0291 + 0292 00001940 fail_abi: + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 8 + + 0293 00001940 09E0 movi 091h, a0, L + 00001950 00000091 + 0294 00001970 C010 jruc failed + 0295 00001980 fail_open: + 0296 00001980 09E0 movi 092h, a0, L + 00001990 00000092 + 0297 000019B0 C00C jruc failed + 0298 000019C0 fail_win: + 0299 000019C0 09E0 movi 093h, a0, L + 000019D0 00000093 + 0300 000019F0 C008 jruc failed + 0301 00001A00 fail_gc: + 0302 00001A00 09E0 movi 095h, a0, L + 00001A10 00000095 + 0303 00001A30 C004 jruc failed + 0304 00001A40 fail_img: + 0305 00001A40 09E0 movi 096h, a0, L + 00001A50 00000096 + 0306 00001A70 0300 jruc failed + 0307 00001A80 failed: + 0308 00001A80 0780 move a0, @01890140h, 1 + 00001A90 01890140 + 0309 00001AB0 0780 move a0, @m_stage, 1 + 00001AC0 00000000+ + 0310 + 0311 00001AE0 done: + 0312 00001AE0 09AF mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7 + 00001AF0 00FF + 0313 00001B00 09E8 movi 0, a8, L + 00001B10 00000000 + 0314 00001B30 0960 rets + 0315 + 0316 00000000 .data + 0317 ; 32 rows of 4 bytes, LSB-first pixels: a solid row at + 0318 ; at y=31, and a one-pixel diagonal between them. The + 0319 ; rows make the drawn height readable straight off the + 0320 00000000 BITMAP: + 0321 00000000 FF .byte 0FFh, 0FFh, 0FFh, 0FFh, 002h, 000h, 000h, 000h + 00000008 FF + 00000010 FF + 00000018 FF + 00000020 02 + 00000028 00 + 00000030 00 + 00000038 00 + 0322 00000040 04 .byte 004h, 000h, 000h, 000h, 008h, 000h, 000h, 000h + 00000048 00 + 00000050 00 + 00000058 00 + 00000060 08 + 00000068 00 + 00000070 00 + 00000078 00 + 0323 00000080 10 .byte 010h, 000h, 000h, 000h, 020h, 000h, 000h, 000h + 00000088 00 + 00000090 00 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 9 + + 00000098 00 + 000000A0 20 + 000000A8 00 + 000000B0 00 + 000000B8 00 + 0324 000000C0 40 .byte 040h, 000h, 000h, 000h, 080h, 000h, 000h, 000h + 000000C8 00 + 000000D0 00 + 000000D8 00 + 000000E0 80 + 000000E8 00 + 000000F0 00 + 000000F8 00 + 0325 00000100 00 .byte 000h, 001h, 000h, 000h, 000h, 002h, 000h, 000h + 00000108 01 + 00000110 00 + 00000118 00 + 00000120 00 + 00000128 02 + 00000130 00 + 00000138 00 + 0326 00000140 00 .byte 000h, 004h, 000h, 000h, 000h, 008h, 000h, 000h + 00000148 04 + 00000150 00 + 00000158 00 + 00000160 00 + 00000168 08 + 00000170 00 + 00000178 00 + 0327 00000180 00 .byte 000h, 010h, 000h, 000h, 000h, 020h, 000h, 000h + 00000188 10 + 00000190 00 + 00000198 00 + 000001A0 00 + 000001A8 20 + 000001B0 00 + 000001B8 00 + 0328 000001C0 00 .byte 000h, 040h, 000h, 000h, 000h, 080h, 000h, 000h + 000001C8 40 + 000001D0 00 + 000001D8 00 + 000001E0 00 + 000001E8 80 + 000001F0 00 + 000001F8 00 + 0329 00000200 00 .byte 000h, 000h, 001h, 000h, 000h, 000h, 002h, 000h + 00000208 00 + 00000210 01 + 00000218 00 + 00000220 00 + 00000228 00 + 00000230 02 + 00000238 00 + 0330 00000240 00 .byte 000h, 000h, 004h, 000h, 000h, 000h, 008h, 000h + 00000248 00 + 00000250 04 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 10 + + 00000258 00 + 00000260 00 + 00000268 00 + 00000270 08 + 00000278 00 + 0331 00000280 00 .byte 000h, 000h, 010h, 000h, 000h, 000h, 020h, 000h + 00000288 00 + 00000290 10 + 00000298 00 + 000002A0 00 + 000002A8 00 + 000002B0 20 + 000002B8 00 + 0332 000002C0 00 .byte 000h, 000h, 040h, 000h, 000h, 000h, 080h, 000h + 000002C8 00 + 000002D0 40 + 000002D8 00 + 000002E0 00 + 000002E8 00 + 000002F0 80 + 000002F8 00 + 0333 00000300 00 .byte 000h, 000h, 000h, 001h, 000h, 000h, 000h, 002h + 00000308 00 + 00000310 00 + 00000318 01 + 00000320 00 + 00000328 00 + 00000330 00 + 00000338 02 + 0334 00000340 00 .byte 000h, 000h, 000h, 004h, 000h, 000h, 000h, 008h + 00000348 00 + 00000350 00 + 00000358 04 + 00000360 00 + 00000368 00 + 00000370 00 + 00000378 08 + 0335 00000380 00 .byte 000h, 000h, 000h, 010h, 000h, 000h, 000h, 020h + 00000388 00 + 00000390 00 + 00000398 10 + 000003A0 00 + 000003A8 00 + 000003B0 00 + 000003B8 20 + 0336 000003C0 00 .byte 000h, 000h, 000h, 040h, 0FFh, 0FFh, 0FFh, 0FFh + 000003C8 00 + 000003D0 00 + 000003D8 40 + 000003E0 FF + 000003E8 FF + 000003F0 FF + 000003F8 FF + 0337 00000400 BITMAP_END: + 0338 + 0339 00000000 .bss m_stage, 32, 1 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 11 + + 0340 00000020 .bss m_display, 32, 1 + 0341 00000040 .bss m_window, 32, 1 + 0342 00000060 .bss m_gc, 32, 1 + 0343 00000080 .bss m_image, 32, 1 + 0344 000000A0 .bss m_putret, 32, 1 + 0345 000000C0 .bss m_syncret, 32, 1 + 0346 000000E0 .bss m_strlen, 32, 1 + 0347 + 0348 .end + + No Errors, No Warnings diff --git a/dwt/gui/build/xshow.map b/dwt/gui/build/xshow.map new file mode 100644 index 0000000..aff3b96 --- /dev/null +++ b/dwt/gui/build/xshow.map @@ -0,0 +1,36 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Fri Nov 13 09:31:54 2026 + +OUTPUT FILE NAME: +ENTRY POINT SYMBOL: 0 + + +SECTION ALLOCATION MAP + + output attributes/ +section page origin length input sections +-------- ---- ---------- ---------- ---------------- +.text 0 01840000 00001B40 + 01840000 00001B40 XSHOW.obj (.text) + +.data 0 018D0000 00000400 + 018D0000 00000400 XSHOW.obj (.data) + +.bss 0 018D8000 00000100 UNINITIALIZED + 018D8000 00000100 XSHOW.obj (.bss) + + +GLOBAL SYMBOLS + +address name address name +-------- ---- -------- ---- +018D8000 .bss 01840000 .text +018D0000 .data 01841B40 etext +01840000 .text 018D0000 .data +018D0400 edata 018D0400 edata +018D8100 end 018D8000 .bss +01841B40 etext 018D8100 end + +[6 symbols] diff --git a/dwt/gui/evidence/png_rows.py b/dwt/gui/evidence/png_rows.py new file mode 100644 index 0000000..e003e3a --- /dev/null +++ b/dwt/gui/evidence/png_rows.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Print a region of an 8-bit PNG as ASCII, one screen row per line. + +The evidence PNGs are captured by MAME under -video none, so there is no +ImageMagick/PIL dependency here: this decodes the PNG with zlib directly +(non-interlaced, 8-bit grey/RGB/RGBA only) and prints '#' for dark pixels. + +Usage: + python3 dwt/gui/evidence/png_rows.py PNG X Y W H +""" +import struct +import sys +import zlib + + +def read_png(path): + data = open(path, "rb").read() + if data[:8] != b"\x89PNG\r\n\x1a\n": + raise SystemExit("not a PNG: " + path) + off, idat = 8, b"" + w = h = bitdepth = colour = None + while off < len(data): + length = struct.unpack(">I", data[off:off + 4])[0] + kind = data[off + 4:off + 8] + chunk = data[off + 8:off + 8 + length] + off += 12 + length + if kind == b"IHDR": + w, h, bitdepth, colour, _, _, interlace = struct.unpack(">IIBBBBB", chunk) + if bitdepth != 8 or interlace != 0: + raise SystemExit("only 8-bit non-interlaced PNGs") + elif kind == b"IDAT": + idat += chunk + elif kind == b"IEND": + break + bpp = {0: 1, 2: 3, 4: 2, 6: 4}[colour] + stride = w * bpp + raw = zlib.decompress(idat) + out = bytearray(h * stride) + prev = bytearray(stride) + pos = 0 + for y in range(h): + filt = raw[pos] + pos += 1 + line = bytearray(raw[pos:pos + stride]) + pos += stride + if filt == 1: + for i in range(bpp, stride): + line[i] = (line[i] + line[i - bpp]) & 0xFF + elif filt == 2: + for i in range(stride): + line[i] = (line[i] + prev[i]) & 0xFF + elif filt == 3: + for i in range(stride): + left = line[i - bpp] if i >= bpp else 0 + line[i] = (line[i] + ((left + prev[i]) >> 1)) & 0xFF + elif filt == 4: + for i in range(stride): + left = line[i - bpp] if i >= bpp else 0 + up = prev[i] + upleft = prev[i - bpp] if i >= bpp else 0 + p = left + up - upleft + pa, pb, pc = abs(p - left), abs(p - up), abs(p - upleft) + pred = left if (pa <= pb and pa <= pc) else (up if pb <= pc else upleft) + line[i] = (line[i] + pred) & 0xFF + out[y * stride:(y + 1) * stride] = line + prev = line + return w, h, bpp, bytes(out) + + +def main(): + path, x0, y0, cw, ch = sys.argv[1], *map(int, sys.argv[2:6]) + w, _, bpp, px = read_png(path) + for y in range(y0, y0 + ch): + row = "".join("#" if px[(y * w + x) * bpp] < 128 else "." for x in range(x0, x0 + cw)) + print("%4d %s" % (y, row)) + + +if __name__ == "__main__": + main() diff --git a/dwt/gui/evidence/xshow_frame2650.png b/dwt/gui/evidence/xshow_frame2650.png new file mode 100644 index 0000000000000000000000000000000000000000..7735dc13961014fd9b090cf1f1e13904045add3b GIT binary patch literal 16394 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 Xku;b7jy?;XgCV!=+FG>v&~N`676y0k literal 0 HcmV?d00001 diff --git a/dwt/gui/evidence/xshow_frame2680.png b/dwt/gui/evidence/xshow_frame2680.png new file mode 100644 index 0000000000000000000000000000000000000000..7735dc13961014fd9b090cf1f1e13904045add3b GIT binary patch literal 16394 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 Xku;b7jy?;XgCV!=+FG>v&~N`676y0k literal 0 HcmV?d00001 diff --git a/dwt/gui/evidence/xshow_pixels.txt b/dwt/gui/evidence/xshow_pixels.txt new file mode 100644 index 0000000..4241b99 --- /dev/null +++ b/dwt/gui/evidence/xshow_pixels.txt @@ -0,0 +1,75 @@ +# xshow_frame2650.png, decoded with: python3 dwt/gui/evidence/png_rows.py dwt/gui/evidence/xshow_frame2650.png 118 118 40 64 +# window content origin is screen (102,102): XPutImage dst (20,20) -> row 122, +# dst (20,60) -> row 162. Full 32-row image: 122..153. h=16 control: 162..177. + + 118 ........................................ + 119 ........................................ + 120 ........................................ + 121 ........................................ + 122 ....################################.... + 123 .....#.................................. + 124 ......#................................. + 125 .......#................................ + 126 ........#............................... + 127 .........#.............................. + 128 ..........#............................. + 129 ...........#............................ + 130 ............#........................... + 131 .............#.......................... + 132 ..............#......................... + 133 ...............#........................ + 134 ................#....................... + 135 .................#...................... + 136 ..................#..................... + 137 ...................#.................... + 138 ....................#................... + 139 .....................#.................. + 140 ......................#................. + 141 .......................#................ + 142 ........................#............... + 143 .........................#.............. + 144 ..........................#............. + 145 ...........................#............ + 146 ............................#........... + 147 .............................#.......... + 148 ..............................#......... + 149 ...............................#........ + 150 ................................#....... + 151 .................................#...... + 152 ..................................#..... + 153 ....################################.... + 154 ........................................ + 155 ........................................ + 156 ........................................ + 157 ........................................ + 158 ........................................ + 159 ........................................ + 160 ........................................ + 161 ........................................ + 162 ....################################.... + 163 .....#.................................. + 164 ......#................................. + 165 .......#................................ + 166 ........#............................... + 167 .........#.............................. + 168 ..........#............................. + 169 ...........#............................ + 170 ............#........................... + 171 .............#.......................... + 172 ..............#......................... + 173 ...............#........................ + 174 ................#....................... + 175 .................#...................... + 176 ..................#..................... + 177 ...................#.................... + 178 ........................................ + 179 ........................................ + 180 ........................................ + 181 ........................................ + +# second observation, 30 frames later: the same rows, byte-identical PNG +$ python3 dwt/gui/evidence/png_rows.py dwt/gui/evidence/xshow_frame2680.png 118 118 40 64 | diff - <(python3 dwt/gui/evidence/png_rows.py dwt/gui/evidence/xshow_frame2650.png 118 118 40 64) +(no output: identical) +$ md5sum dwt/gui/evidence/xshow_frame2650.png dwt/gui/evidence/xshow_frame2680.png +ab9d63844aa5a3dd9d281a6bee3c76c2 dwt/gui/evidence/xshow_frame2650.png +ab9d63844aa5a3dd9d281a6bee3c76c2 dwt/gui/evidence/xshow_frame2680.png diff --git a/dwt/gui/evidence/xshow_run.log b/dwt/gui/evidence/xshow_run.log new file mode 100644 index 0000000..c455c4d --- /dev/null +++ b/dwt/gui/evidence/xshow_run.log @@ -0,0 +1,37 @@ +Warning: -video none doesn't make much sense without -seconds_to_run +ALSA lib seq_hw.c:540:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory +vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901 +XSHOW: payload dwt/loader/build/loader.bin (1220 B) -> bit 01880000 +XSHOW: COFF dwt/gui/build/xshow.coff (1384 B) -> bit 01900000 +XSHOW: file magic=0090 nscns=3 opthdr=28 entry=00000000 textstart=01840000 +XSHOW: sec .text paddr=01840000 size=6976 bits (872 B) flags=0x20 +XSHOW: sec .data paddr=018D0000 size=1024 bits (128 B) flags=0x40 +XSHOW: sec .bss paddr=018D8000 size=256 bits (32 B) flags=0x80 +XSHOW: .data first 16 bytes: FF FF FF FF 02 00 00 00 04 00 00 00 08 00 00 00 +vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901 +vt1200: scanline#1 line=1 enabled=1 +vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1 +vt1200: screen_update#3 frame=1 clip_y=0..0 screen=1280x901 +vt1200: scanline#2 line=0 enabled=1 +vt1200: screen_update#4 frame=1 clip_y=1..1 screen=1280x901 +vt1200: scanline#3 line=1 enabled=1 +vt1200: scanline#4 line=2 enabled=1 +XSHOW: loader poked 610 words, readback 0 bad at 01880000 +XSHOW: COFF poked 692 words, readback 0 bad at 01900000 +XSHOW: descriptor @01882C00 magic=4C44/5231 buf=01900000 len=1384 mode=0 +XSHOW: will resume at 3F579970 after create_process +XSHOW: frame 2500: entered loader at 01880000 (caller SP=007F52B0) +XSHOW: f2540 cells stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 +XSHOW: f2540 mirror stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 strlen=00000004 +XSHOW: f2650 cells stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 +XSHOW: f2650 mirror stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 strlen=00000004 +XSHOW: snapshot /home/arti/.t3/worktrees/vt1200/fix-issue-4-ximage-4368fd1dbccf74ec/dwt/gui/evidence/xshow_frame2650.png ok=true +XSHOW: final cells stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 +XSHOW: final mirror stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 strlen=00000004 +XSHOW: loader status=0 entry=01840000 text=01840000/6976 bits +XSHOW: PC at exit = 3F5799D0 +XSHOW: final image@00988130 width=00000020 height=00000020 xoffset=00000000 format=00000000 data=018D0000 byte_order=00000000 bitmap_unit=00000020 bitmap_bit_order=00000000 bitmap_pad=00000020 depth=00000001 bytes_per_line=00000004 bits_per_pixel=00000001 +XSHOW: final dpy@0093C910 byte_order=00000000 bitmap_unit=00000020 scanline_pad=00000020 bitmap_bit_order=00000000 +XSHOW: final pixmap_formats n=1 list=00367D90 +XSHOW: final fmt[0] depth=00000001 bits_per_pixel=00000001 pad=00000020 +Average speed: 111.50% (37 seconds) diff --git a/dwt/gui/xshow.asm b/dwt/gui/xshow.asm new file mode 100644 index 0000000..31061da --- /dev/null +++ b/dwt/gui/xshow.asm @@ -0,0 +1,348 @@ +; xshow.asm -- create a 1-bit XImage and XPutImage it onto a mapped window. +; +; Run as a first-class process created by the COFF loader (create_process), NOT +; in the rdebug dispatcher's context: a connect made from the rdebug process is +; accepted at the service layer but the server never reads the X11 setup. +; +; The image is a 32x32 XYBitmap (format 0), depth 1, created by the ROM's own +; XCreateImage and drawn with XPutImage. Its data is a checkerboard of 8x8 +; cells, written into .data at build time, so the PNG shows either the pattern +; or nothing -- there is nothing to misread. +; +; XImage entry points used here (Ghidra address -> bit address): +; 7F34092 XCreateImage(d,visual,depth,format,offset,data,w,h,pad,bpl) 3F9A0490 +; 7FA06E XPutImage(d,drawable,gc,image,sx,sy,dx,dy,w,h) 3F9D0370 +; 7F341B0 XDestroyImage(image) 3F9A0D80 +; 7FAAAD6 XGetImage(d,drawable,x,y,w,h,plane_mask,format) 3FD556B0 +; (XGetImage is documented from disassembly; this probe does not call it.) +; +; Calling convention: reserve one slot with `move a14,-*sp,1`, push arguments +; last-to-first upward through a14, then `calla`. The callee's `rets 2` pops +; the return address and the reserved slot, and restores a14. Do NOT reload +; sp/a14 from RAM markers (xtext.asm records that exact crash). +; +; Xlib clobbers the CPU's SETF field state, so field 1 (32-bit) is re- +; established after every call. a10/a11/a12 survive every call used here; +; a9 (the GC) survives XCreateImage and XPutImage; a7 (the image) survives +; XPutImage. XDestroyImage saves only a11/a13, so it runs last. +; +; Markers: +; 01890100 display 01890120 window 01890140 stage 01890160 image +; 01890180 gc 018901A0 XPutImage return 018901C0 last XSync +; These are the xhello-compatible cells the runner reports. xhello's own +; cells sit in the heap and were overwritten after its run, so the same values +; are mirrored into .bss at 018D8000h (below), which nothing else uses: +; 018D8000 stage 018D8020 display 018D8040 window 018D8060 gc +; 018D8080 image 018D80A0 putret 018D80C0 syncret 018D80E0 strlen +; Stage: 1 start, 2 display, 3 window, 4 mapped, 5 gc, 6 image, 7 putimage, +; 8 synced; 091h..097h = the step that failed. +; +; Scratch argument area: 01894000h (the app's own stack is elsewhere). + + .text +_start: + setf 16, 0, 0 + setf 32, 0, 1 + mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7 + + movi 1, a0, L + move a0, @01890140h, 1 ; stage = 1 + move a0, @m_stage, 1 + + ; ---- convention check: strlen("0::0") == 4 -------------------- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 3FACE948h, a0, L ; ROM "0::0" + move a0, *a14+, 1 + calla 3FB458D0h ; strlen + setf 16, 0, 0 + setf 32, 0, 1 + move a8, @m_strlen, 1 + movi 4, a0, L + cmp a0, a8 + jrne fail_abi + + ; ---- display = XOpenDisplay("0::0") --------------------------- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 3FACE948h, a0, L + move a0, *a14+, 1 + calla 3F9C2570h ; XOpenDisplay + setf 16, 0, 0 + setf 32, 0, 1 + move a8, a11 + move a11, @01890100h, 1 ; MARK display + move a11, @m_display, 1 + move a11, a11 + jreq fail_open + movi 2, a0, L + move a0, @01890140h, 1 ; stage = 2 + move a0, @m_stage, 1 + + ; ---- root = *(*(display+0x480)+0x40) -------------------------- + move *a11(0480h), a10, 1 + move *a10(040h), a10, 1 + + ; ---- window = XCreateSimpleWindow(d,root,100,100,400,200,2,0,1) + ; white background (pixel 1), black border, so a black bitmap shows. + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 1, a0, L + move a0, *a14+, 1 ; background = 1 (white) + movi 0, a0, L + move a0, *a14+, 1 ; border = 0 (black) + movi 2, a0, L + move a0, *a14+, 1 ; border width + movi 200, a0, L + move a0, *a14+, 1 ; height + movi 400, a0, L + move a0, *a14+, 1 ; width + movi 100, a0, L + move a0, *a14+, 1 ; y + move a0, *a14+, 1 ; x + move a10, *a14+, 1 ; parent = root + move a11, *a14+, 1 ; display + calla 3FD41B90h ; XCreateSimpleWindow + setf 16, 0, 0 + setf 32, 0, 1 + move a8, a10 + move a10, @01890120h, 1 ; MARK window + move a10, @m_window, 1 + move a10, a10 + jreq fail_win + movi 3, a0, L + move a0, @01890140h, 1 ; stage = 3 + move a0, @m_stage, 1 + + ; ---- XMapWindow(display, window) ----------------------------- + move a14, -*sp, 1 + movi 01894000h, a14, L + move a10, *a14+, 1 + move a11, *a14+, 1 + calla 3FD645B0h ; XMapWindow + setf 16, 0, 0 + setf 32, 0, 1 + movi 4, a0, L + move a0, @01890140h, 1 ; stage = 4 + move a0, @m_stage, 1 + + ; ---- gc = XCreateGC(d, window, 0, NULL) ---------------------- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 0, a0, L + move a0, *a14+, 1 ; values + move a0, *a14+, 1 ; mask = 0 + move a10, *a14+, 1 ; drawable + move a11, *a14+, 1 ; display + calla 3F997000h ; XCreateGC + setf 16, 0, 0 + setf 32, 0, 1 + move a8, a9 ; GC + move a9, @01890180h, 1 ; MARK gc + move a9, @m_gc, 1 + move a9, a9 + jreq fail_gc + + ; ---- XSetForeground(display, gc, 0) -- draw with pen 0 (black) -- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 0, a0, L + move a0, *a14+, 1 ; pixel = 0 + move a9, *a14+, 1 ; gc + move a11, *a14+, 1 ; display + calla 3FD99A60h ; XSetForeground + setf 16, 0, 0 + setf 32, 0, 1 + movi 5, a0, L + move a0, @01890140h, 1 ; stage = 5 + move a0, @m_stage, 1 + + ; ---- image = XCreateImage(d, NULL, 1, XYBitmap, 0, + ; bitmap, 32, 32, 32, 0) ------------- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 0, a0, L + move a0, *a14+, 1 ; bytes_per_line = 0 (let it compute) + movi 32, a0, L + move a0, *a14+, 1 ; bitmap_pad = 32 + movi 32, a0, L + move a0, *a14+, 1 ; height + move a0, *a14+, 1 ; width + movi BITMAP, a0, L + move a0, *a14+, 1 ; data + movi 0, a0, L + move a0, *a14+, 1 ; offset + move a0, *a14+, 1 ; format = 0 (XYBitmap) + movi 1, a0, L + move a0, *a14+, 1 ; depth = 1 + sub a0, a0 + move a0, *a14+, 1 ; visual = NULL + move a11, *a14+, 1 ; display + calla 3F9A0490h ; XCreateImage + setf 16, 0, 0 + setf 32, 0, 1 + move a8, a7 ; image (a7 survives XPutImage) + move a8, @01890160h, 1 ; MARK image + move a8, @m_image, 1 + move a8, a8 + jreq fail_img + movi 6, a0, L + move a0, @01890140h, 1 ; stage = 6 + move a0, @m_stage, 1 + + ; ---- let the WM frame/reparent and map the window (xtext) ----- + ; A draw issued before the reparent can be lost, so sync first. + movi 4, a12, L +map_wait: + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 0, a0, L + move a0, *a14+, 1 ; discard = 0 + move a11, *a14+, 1 ; display + calla 3FD9F6B0h ; XSync + setf 16, 0, 0 + setf 32, 0, 1 + dsjs a12, map_wait + + ; ---- XPutImage(d, win, gc, image, 0,0, 20,20, 32,32) --------- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 32, a0, L + move a0, *a14+, 1 ; h + move a0, *a14+, 1 ; w + movi 20, a0, L + move a0, *a14+, 1 ; dst_y + move a0, *a14+, 1 ; dst_x + sub a0, a0 + move a0, *a14+, 1 ; src_y + move a0, *a14+, 1 ; src_x + move a7, *a14+, 1 ; image + move a9, *a14+, 1 ; gc + move a10, *a14+, 1 ; drawable + move a11, *a14+, 1 ; display + calla 3F9D0370h ; XPutImage + setf 16, 0, 0 + setf 32, 0, 1 + move a8, @018901A0h, 1 ; MARK putimage return + move a8, @m_putret, 1 + movi 7, a0, L + move a0, @01890140h, 1 ; stage = 7 + move a0, @m_stage, 1 + + ; ---- control: the same image with h = 16 at dst_y = 60 -------- + ; The PNG must show exactly 16 rows here (src rows 0..15): that is + ; what proves the 32-row draw above is the image, not the window. + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 16, a0, L + move a0, *a14+, 1 ; h = 16 + movi 32, a0, L + move a0, *a14+, 1 ; w = 32 + movi 60, a0, L + move a0, *a14+, 1 ; dst_y = 60 + movi 20, a0, L + move a0, *a14+, 1 ; dst_x = 20 + sub a0, a0 + move a0, *a14+, 1 ; src_y = 0 + move a0, *a14+, 1 ; src_x = 0 + move a7, *a14+, 1 ; image + move a9, *a14+, 1 ; gc + move a10, *a14+, 1 ; drawable + move a11, *a14+, 1 ; display + calla 3F9D0370h ; XPutImage + setf 16, 0, 0 + setf 32, 0, 1 + + ; ---- flush, twice: the request is only in the client buffer --- + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 0, a0, L + move a0, *a14+, 1 + move a11, *a14+, 1 + calla 3FD9F6B0h ; XSync + setf 16, 0, 0 + setf 32, 0, 1 + move a8, @018901C0h, 1 ; MARK sync return + move a8, @m_syncret, 1 + + move a14, -*sp, 1 + movi 01894000h, a14, L + movi 0, a0, L + move a0, *a14+, 1 + move a11, *a14+, 1 + calla 3FD9F6B0h ; XSync + setf 16, 0, 0 + setf 32, 0, 1 + move a8, @018901C0h, 1 + move a8, @m_syncret, 1 + + movi 8, a0, L + move a0, @01890140h, 1 ; stage = 8 + move a0, @m_stage, 1 + + ; ---- XDestroyImage(image) ------------------------------------ + move a14, -*sp, 1 + movi 01894000h, a14, L + move a7, *a14+, 1 + calla 3F9A0D80h ; XDestroyImage + setf 16, 0, 0 + setf 32, 0, 1 + jruc done + +fail_abi: + movi 091h, a0, L + jruc failed +fail_open: + movi 092h, a0, L + jruc failed +fail_win: + movi 093h, a0, L + jruc failed +fail_gc: + movi 095h, a0, L + jruc failed +fail_img: + movi 096h, a0, L + jruc failed +failed: + move a0, @01890140h, 1 + move a0, @m_stage, 1 + +done: + mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7 + movi 0, a8, L + rets + + .data + ; 32 rows of 4 bytes, LSB-first pixels: a solid row at y=0, a solid row + ; at y=31, and a one-pixel diagonal between them. The top and bottom + ; rows make the drawn height readable straight off the PNG. +BITMAP: + .byte 0FFh, 0FFh, 0FFh, 0FFh, 002h, 000h, 000h, 000h + .byte 004h, 000h, 000h, 000h, 008h, 000h, 000h, 000h + .byte 010h, 000h, 000h, 000h, 020h, 000h, 000h, 000h + .byte 040h, 000h, 000h, 000h, 080h, 000h, 000h, 000h + .byte 000h, 001h, 000h, 000h, 000h, 002h, 000h, 000h + .byte 000h, 004h, 000h, 000h, 000h, 008h, 000h, 000h + .byte 000h, 010h, 000h, 000h, 000h, 020h, 000h, 000h + .byte 000h, 040h, 000h, 000h, 000h, 080h, 000h, 000h + .byte 000h, 000h, 001h, 000h, 000h, 000h, 002h, 000h + .byte 000h, 000h, 004h, 000h, 000h, 000h, 008h, 000h + .byte 000h, 000h, 010h, 000h, 000h, 000h, 020h, 000h + .byte 000h, 000h, 040h, 000h, 000h, 000h, 080h, 000h + .byte 000h, 000h, 000h, 001h, 000h, 000h, 000h, 002h + .byte 000h, 000h, 000h, 004h, 000h, 000h, 000h, 008h + .byte 000h, 000h, 000h, 010h, 000h, 000h, 000h, 020h + .byte 000h, 000h, 000h, 040h, 0FFh, 0FFh, 0FFh, 0FFh +BITMAP_END: + + .bss m_stage, 32, 1 + .bss m_display, 32, 1 + .bss m_window, 32, 1 + .bss m_gc, 32, 1 + .bss m_image, 32, 1 + .bss m_putret, 32, 1 + .bss m_syncret, 32, 1 + .bss m_strlen, 32, 1 + + .end diff --git a/dwt/gui/xshow.lua b/dwt/gui/xshow.lua new file mode 100644 index 0000000..c3c752a --- /dev/null +++ b/dwt/gui/xshow.lua @@ -0,0 +1,301 @@ +-- xshow.lua -- run dwt/gui/build/xshow.coff through the COFF loader and report +-- whether the 1-bit XImage reached the screen. +-- +-- Same debugger-assisted path as dwt/loader/loader.lua (no network, no rdebug, +-- no sudo): at frame XSHOW_AT it pokes the loader at bit 0x01880000, the COFF +-- at XSHOW_BUF (default 0x01900000), the descriptor at 0x01882C00, and sets +-- PC = 0x01880000. The loader copies the sections and calls create_process(). +-- +-- Env: +-- XSHOW_AT injection frame (default 2500) +-- XSHOW_END inspection/exit frame (default 2700) +-- XSHOW_SNAP frame to snapshot (default XSHOW_END) +-- XSHOW_COFF COFF (default dwt/gui/build/xshow.coff) +-- XSHOW_BIN loader payload (default dwt/loader/build/loader.bin) +-- XSHOW_BUF COFF buffer bit address (default 0x01900000) +-- XSHOW_OUT evidence dir (default dwt/gui/evidence) +-- XSHOW_NOSNAP 1 = do not write a PNG +-- +-- Marker cells (the payload writes both blocks): +-- 01890100/120/140/160/180/1A0/1C0 xhello-compatible cells (heap; may be +-- overwritten after the app finishes) +-- 018D8000/20/40/60/80/A0/C0/E0 .bss mirror: stage, display, window, +-- gc, image, putret, syncret, strlen + +local function hex(v, w) return string.format("%0" .. (w or 8) .. "X", v) end + +local machine = manager.machine +local cpu = machine.devices[':maincpu'] +local dbg = machine.debugger +local prog = cpu.spaces['program'] + +if not dbg then + print("XSHOW: debugger not enabled; pass -debug") + machine:exit() + return +end + +local AT = tonumber(os.getenv("XSHOW_AT") or "2500") +local ENDF = tonumber(os.getenv("XSHOW_END") or "2700") +local SNAP = tonumber(os.getenv("XSHOW_SNAP") or tostring(ENDF)) +local BIN = os.getenv("XSHOW_BIN") or "dwt/loader/build/loader.bin" +local COFF = os.getenv("XSHOW_COFF") or "dwt/gui/build/xshow.coff" +local BUF = tonumber(os.getenv("XSHOW_BUF") or "0x01900000") +local OUT = os.getenv("XSHOW_OUT") or "dwt/gui/evidence" +local NOSNAP = os.getenv("XSHOW_NOSNAP") == "1" + +local LOADER_BASE = 0x01880000 +local DESC = 0x01882C00 +local RESULT = 0x01882D00 + +local function slurp(p) + local f, err = io.open(p, "rb") + if not f then error("cannot open " .. p .. ": " .. tostring(err)) end + local s = f:read("*a") + f:close() + return s +end + +local function u16(s, o) + return s:byte(o + 1) + s:byte(o + 2) * 256 +end + +local function u32(s, o) + return s:byte(o + 1) + s:byte(o + 2) * 256 + + s:byte(o + 3) * 65536 + s:byte(o + 4) * 16777216 +end + +local function parse_coff(d) + local c = { data = d } + c.magic = u16(d, 0) + c.nscns = u16(d, 2) + c.opthdr = u16(d, 16) + c.sections = {} + if c.opthdr > 0 then + c.optmagic = u16(d, 20) + c.entry = u32(d, 20 + 16) + c.textstart = u32(d, 20 + 20) + c.datastart = u32(d, 20 + 24) + end + local base = 20 + c.opthdr + for i = 0, c.nscns - 1 do + local o = base + i * 40 + local name = d:sub(o + 1, o + 8):gsub("%z", "") + c.sections[#c.sections + 1] = { + name = name, + paddr = u32(d, o + 8), + size = u32(d, o + 16), -- bits + scnptr = u32(d, o + 20), + flags = u32(d, o + 36), + } + end + return c +end + +local function poke_bytes(bitaddr, data) + local n = math.floor((#data + 1) / 2) + for i = 0, n - 1 do + local lo = data:byte(i * 2 + 1) or 0 + local hi = data:byte(i * 2 + 2) or 0 + prog:write_u16(bitaddr + i * 16, lo + hi * 256) + end + return n +end + +local function verify_bytes(bitaddr, data) + local n = math.floor((#data + 1) / 2) + local bad = 0 + for i = 0, n - 1 do + local lo = data:byte(i * 2 + 1) or 0 + local hi = data:byte(i * 2 + 2) or 0 + if prog:read_u16(bitaddr + i * 16) ~= lo + hi * 256 then + bad = bad + 1 + end + end + return n, bad +end + +local function w32(a, v) prog:write_u32(a, v) end +local function r32(a) + local ok, v = pcall(function() return prog:read_u32(a) end) + if ok then return v end + return 0xDEADBEEF +end + +local loader = slurp(BIN) +local coff = slurp(COFF) +local app = parse_coff(coff) + +print(string.format("XSHOW: payload %s (%d B) -> bit %s", BIN, #loader, hex(LOADER_BASE))) +print(string.format("XSHOW: COFF %s (%d B) -> bit %s", COFF, #coff, hex(BUF))) +print(string.format("XSHOW: file magic=%04X nscns=%d opthdr=%d entry=%s textstart=%s", + app.magic, app.nscns, app.opthdr, hex(app.entry or 0), hex(app.textstart or 0))) +for _, s in ipairs(app.sections) do + print(string.format("XSHOW: sec %-8s paddr=%s size=%d bits (%d B) flags=%#x", + s.name, hex(s.paddr), s.size, math.floor(s.size / 8), s.flags)) +end + +-- The .data bytes the probe will hand to XCreateImage, read out of the COFF. +for _, s in ipairs(app.sections) do + if s.name == ".data" and s.scnptr ~= 0 and s.size > 0 then + local nb = math.floor(s.size / 8) + local bytes = coff:sub(s.scnptr + 1, s.scnptr + nb) + local first = {} + for i = 1, math.min(16, #bytes) do first[#first + 1] = string.format("%02X", bytes:byte(i)) end + print(string.format("XSHOW: .data first %d bytes: %s", #first, table.concat(first, " "))) + end +end + +local frames = 0 +local injected = false +local inspected = false +local snapped = false + +local function markers() + return { + stage = r32(0x01890140), + display = r32(0x01890100), + window = r32(0x01890120), + image = r32(0x01890160), + gc = r32(0x01890180), + putret = r32(0x018901A0), + syncret = r32(0x018901C0), + } +end + +local function mirror() + return { + stage = r32(0x018D8000), + display = r32(0x018D8020), + window = r32(0x018D8040), + gc = r32(0x018D8060), + image = r32(0x018D8080), + putret = r32(0x018D80A0), + syncret = r32(0x018D80C0), + strlen = r32(0x018D80E0), + } +end + +local function report(tag) + local m = markers() + local r = mirror() + print(string.format( + "XSHOW: %s cells stage=%s display=%s window=%s gc=%s image=%s putret=%s syncret=%s", + tag, hex(m.stage), hex(m.display), hex(m.window), hex(m.gc), hex(m.image), + hex(m.putret), hex(m.syncret))) + print(string.format( + "XSHOW: %s mirror stage=%s display=%s window=%s gc=%s image=%s putret=%s syncret=%s strlen=%s", + tag, hex(r.stage), hex(r.display), hex(r.window), hex(r.gc), hex(r.image), + hex(r.putret), hex(r.syncret), hex(r.strlen))) +end + +-- Dump the XImage fields the ROM's own code reads (byte offsets are the +-- standard 32-bit XImage layout; 0x120/0x140/0x160 = depth/bpl/bpp). +local IMG_FIELDS = { + { "width", 0x000 }, { "height", 0x020 }, { "xoffset", 0x040 }, + { "format", 0x060 }, { "data", 0x080 }, { "byte_order", 0x0A0 }, + { "bitmap_unit", 0x0C0 }, { "bitmap_bit_order", 0x0E0 }, + { "bitmap_pad", 0x100 }, { "depth", 0x120 }, { "bytes_per_line", 0x140 }, + { "bits_per_pixel", 0x160 }, +} + +local function dump_image(ptr, tag) + if ptr == 0 then return end + local parts = {} + for _, f in ipairs(IMG_FIELDS) do + parts[#parts + 1] = string.format("%s=%s", f[1], hex(r32(ptr + f[2]))) + end + print(string.format("XSHOW: %s image@%s %s", tag, hex(ptr), table.concat(parts, " "))) +end + +local function dump_dpy(ptr, tag) + if ptr == 0 then return end + print(string.format( + "XSHOW: %s dpy@%s byte_order=%s bitmap_unit=%s scanline_pad=%s bitmap_bit_order=%s", + tag, hex(ptr), hex(r32(ptr + 0x1A0)), hex(r32(ptr + 0x1C0)), + hex(r32(ptr + 0x1E0)), hex(r32(ptr + 0x200)))) + -- XPutImage's bits_per_pixel check walks dpy->pixmap_formats: count at + -- +0x220, pointer at +0x240, entry stride 0x80 bits, depth at +0x20, + -- bits_per_pixel at +0x40. + local n = r32(ptr + 0x220) + local list = r32(ptr + 0x240) + print(string.format("XSHOW: %s pixmap_formats n=%d list=%s", tag, n, hex(list))) + for i = 0, math.min(n, 8) - 1 do + local e = list + i * 0x80 + print(string.format("XSHOW: %s fmt[%d] depth=%s bits_per_pixel=%s pad=%s", + tag, i, hex(r32(e + 0x20)), hex(r32(e + 0x40)), hex(r32(e + 0x60)))) + end +end + +local function inject() + poke_bytes(LOADER_BASE, loader) + local _, bad = verify_bytes(LOADER_BASE, loader) + print(string.format("XSHOW: loader poked %d words, readback %d bad at %s", + math.floor((#loader + 1) / 2), bad, hex(LOADER_BASE))) + + poke_bytes(BUF, coff) + local _, cbad = verify_bytes(BUF, coff) + print(string.format("XSHOW: COFF poked %d words, readback %d bad at %s", + math.floor((#coff + 1) / 2), cbad, hex(BUF))) + + w32(DESC + 0x00, 0) + prog:write_u16(DESC + 0x00, 0x4C44) -- "LD" + prog:write_u16(DESC + 0x10, 0x5231) -- "R1" + w32(DESC + 0x20, BUF) + w32(DESC + 0x40, #coff) + w32(DESC + 0x60, 0) -- mode 0: debug-resume + print(string.format("XSHOW: descriptor @%s magic=%04X/%04X buf=%s len=%d mode=%d", + hex(DESC), prog:read_u16(DESC + 0x00), prog:read_u16(DESC + 0x10), + hex(r32(DESC + 0x20)), r32(DESC + 0x40), r32(DESC + 0x60))) + + local orig_pc = cpu.state['PC'].value + w32(0x01882A20, orig_pc) -- LD_ORIG_PC + print(string.format("XSHOW: will resume at %s after create_process", hex(orig_pc))) + cpu.state['A8'].value = 0 + cpu.state['PC'].value = LOADER_BASE + injected = true + print(string.format("XSHOW: frame %d: entered loader at %s (caller SP=%s)", + frames, hex(LOADER_BASE), hex(cpu.state['SP'].value))) +end + +local function snapshot(path) + local screen = nil + for _, s in pairs(machine.screens) do screen = s break end + if not screen then + print("XSHOW: no screen device") + return + end + local ok, err = pcall(function() return screen:snapshot(path) end) + print(string.format("XSHOW: snapshot %s ok=%s %s", path, tostring(ok), tostring(err or ""))) +end + +emu.register_frame_done(function() + frames = frames + 1 + if frames == AT and not injected then inject() end + if injected and not inspected and frames >= AT + 40 then + inspected = true + report("f" .. frames) + end + if injected and frames == SNAP and not snapped then + snapped = true + report("f" .. frames) + if not NOSNAP then snapshot(OUT .. "/xshow_frame" .. frames .. ".png") end + end + if frames >= ENDF then + if injected then + report("final") + local st = r32(RESULT + 0x000) + print(string.format("XSHOW: loader status=%d entry=%s text=%s/%d bits", + st, hex(r32(RESULT + 0x020)), + hex(r32(RESULT + 0x040)), r32(RESULT + 0x060))) + print(string.format("XSHOW: PC at exit = %s", hex(cpu.state['PC'].value))) + local m = markers() + dump_image(m.image, "final") + dump_dpy(m.display, "final") + end + machine:exit() + end +end, "vt1200-xshow") + +dbg.visible_cpu = cpu +dbg.execution_state = 'run' diff --git a/dwt/loader/build/xshow.bin b/dwt/loader/build/xshow.bin new file mode 100644 index 0000000000000000000000000000000000000000..3c94913bd05a31f4e68b6325728dfb43ac8d4fbb GIT binary patch literal 872 zcma))u}i~16vi($^>S)M2Pa*!h`9I{D9xZy3XzUZHiMIb)c+u3(o(D`3Kj*yRj`B5 zwWH{ug9vUnDwIy*TEBZqNGT~eeRtgV-tT)aspf5dCfHaCjWOnNTMIOgGq0t+-i-va z15JwZ_kGC>YlXM{$5Iu3pG&+;p`*emvzOBhZ+-2Wyo*kgGxTh73pK|MdpdNL7WpKgHUHLER7OZiaiElTNMBUVSI(g45s@s10s|S^;$()EvB7 z6GpYY-4Cjb=F0LVX%ZT%Ur~i{0`7qpa2K=<(0(Q+0Tf9$DWBW@j2ZbESrUd67S$yh z?V_cnJ5i@-OKissX?nd&-MQm)7kPZ{A&-GPJtoEc6mdx3FWoqvkyG{Q{YEK=+v%%C zuZp=GpA^*$N0=bAN%7Efhjv#nQ@LBxxdqlU!lB!WDN3hvyy& z1_J>b3&AUdwAU$GXdyznDHXz1lJ@-G+uhsEu>l(ghWBRYd++yVc4h|T(BjG2_P`}t zBBE>LsIvM*ejNjRBZV%l1Fx?d?X9Qn*|?)v_bySS#)H$?+-PsehrYydt{UgdH6MQC z(eAE%3ZdgZ<7L7S?)?Q{KQ}bBh6SPaRZoSQBfhu*GRIoQ{Pocr2C%;SK*JVaz^jc)Tg&YIJY7GhD9>>OX|K80={e)IIHkx(4bEP#tKCRv5>Q?*5e6cwI%hw3?Jg zt=AG^f}RdR>**$FH$nT8TM3}3v?2914^9%s!UeUY3~M}zOKrRteU?5$P(NGufWli#=>$B!oGLG|Kls&5m^0|7udMxBI$p5Odri?sA6;5#C z!%DoPSI5@8fUX7`!7jlLVau>DVO`i)u;k=3eK1q{B`3IPrf7VI<<7wJ>OFKHJw%uL z`JV*L&c82wY8-iCmYFxhn`bBguJC<=hSQyE^Q;nWC9j)b? bit + 0013 ; 7F34092 XCreateImage(d,visual,depth,format,offset,d + 0014 ; 7FA06E XPutImage(d,drawable,gc,image,sx,sy,dx,dy,w + 0015 ; 7F341B0 XDestroyImage(image) + 0016 ; 7FAAAD6 XGetImage(d,drawable,x,y,w,h,plane_mask,for + 0017 ; (XGetImage is documented from disassembly; this probe + 0018 ; + 0019 ; Calling convention: reserve one slot with `move a14,- + 0020 ; last-to-first upward through a14, then `calla`. The + 0021 ; the return address and the reserved slot, and restore + 0022 ; sp/a14 from RAM markers (xtext.asm records that exact + 0023 ; + 0024 ; Xlib clobbers the CPU's SETF field state, so field 1 + 0025 ; established after every call. a10/a11/a12 survive ev + 0026 ; a9 (the GC) survives XCreateImage and XPutImage; a7 ( + 0027 ; XPutImage. XDestroyImage saves only a11/a13, so it r + 0028 ; + 0029 ; Markers: + 0030 ; 01890100 display 01890120 window 01890140 stage + 0031 ; 01890180 gc 018901A0 XPutImage return 01 + 0032 ; These are the xhello-compatible cells the runner repo + 0033 ; cells sit in the heap and were overwritten after its + 0034 ; are mirrored into .bss at 018D8000h (below), which no + 0035 ; 018D8000 stage 018D8020 display 018D8040 window + 0036 ; 018D8080 image 018D80A0 putret 018D80C0 syncret + 0037 ; Stage: 1 start, 2 display, 3 window, 4 mapped, 5 gc, + 0038 ; 8 synced; 091h..097h = the step that failed. + 0039 ; + 0040 ; Scratch argument area: 01894000h (the app's own stack + 0041 + 0042 00000000 .text + 0043 00000000 _start: + 0044 00000000 0550 setf 16, 0, 0 + 0045 00000010 0740 setf 32, 0, 1 + 0046 00000020 098F mmtm sp, a0,a1,a2,a3,a4,a5,a6,a7 + 00000030 FF00 + 0047 + 0048 00000040 09E0 movi 1, a0, L + 00000050 00000001 + 0049 00000070 0780 move a0, @01890140h, 1 ; stage = 1 + 00000080 01890140 + 0050 000000A0 0780 move a0, @m_stage, 1 + 000000B0 00000000+ + 0051 + 0052 ; ---- convention check: strlen("0::0") == 4 --------- + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 2 + + 0053 000000D0 A3CF move a14, -*sp, 1 + 0054 000000E0 09EE movi 01894000h, a14, L + 000000F0 01894000 + 0055 00000110 09E0 movi 3FACE948h, a0, L ; ROM "0::0" + 00000120 3FACE948 + 0056 00000140 920E move a0, *a14+, 1 + 0057 00000150 0D5F calla 3FB458D0h ; strlen + 00000160 3FB458D0 + 0058 00000180 0550 setf 16, 0, 0 + 0059 00000190 0740 setf 32, 0, 1 + 0060 000001A0 0788 move a8, @m_strlen, 1 + 000001B0 000000E0+ + 0061 000001D0 09E0 movi 4, a0, L + 000001E0 00000004 + 0062 00000200 4808 cmp a0, a8 + 0063 00000210 CB00 jrne fail_abi + 00000220 0171 + 0064 + 0065 ; ---- display = XOpenDisplay("0::0") ---------------- + 0066 00000230 A3CF move a14, -*sp, 1 + 0067 00000240 09EE movi 01894000h, a14, L + 00000250 01894000 + 0068 00000270 09E0 movi 3FACE948h, a0, L + 00000280 3FACE948 + 0069 000002A0 920E move a0, *a14+, 1 + 0070 000002B0 0D5F calla 3F9C2570h ; XOpenDisplay + 000002C0 3F9C2570 + 0071 000002E0 0550 setf 16, 0, 0 + 0072 000002F0 0740 setf 32, 0, 1 + 0073 00000300 4D0B move a8, a11 + 0074 00000310 078B move a11, @01890100h, 1 ; MARK display + 00000320 01890100 + 0075 00000340 078B move a11, @m_display, 1 + 00000350 00000020+ + 0076 00000370 4D6B move a11, a11 + 0077 00000380 CA00 jreq fail_open + 00000390 015E + 0078 000003A0 09E0 movi 2, a0, L + 000003B0 00000002 + 0079 000003D0 0780 move a0, @01890140h, 1 ; stage = 2 + 000003E0 01890140 + 0080 00000400 0780 move a0, @m_stage, 1 + 00000410 00000000+ + 0081 + 0082 ; ---- root = *(*(display+0x480)+0x40) --------------- + 0083 00000430 B76A move *a11(0480h), a10, 1 + 00000440 0480 + 0084 00000450 B74A move *a10(040h), a10, 1 + 00000460 0040 + 0085 + 0086 ; ---- window = XCreateSimpleWindow(d,root,100,100,400 + 0087 ; white background (pixel 1), black border, so a black + 0088 00000470 A3CF move a14, -*sp, 1 + 0089 00000480 09EE movi 01894000h, a14, L + 00000490 01894000 + 0090 000004B0 09E0 movi 1, a0, L + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 3 + + 000004C0 00000001 + 0091 000004E0 920E move a0, *a14+, 1 ; background = 1 (white) + 0092 000004F0 09E0 movi 0, a0, L + 00000500 00000000 + 0093 00000520 920E move a0, *a14+, 1 ; border = 0 (black) + 0094 00000530 09E0 movi 2, a0, L + 00000540 00000002 + 0095 00000560 920E move a0, *a14+, 1 ; border width + 0096 00000570 09E0 movi 200, a0, L + 00000580 000000C8 + 0097 000005A0 920E move a0, *a14+, 1 ; height + 0098 000005B0 09E0 movi 400, a0, L + 000005C0 00000190 + 0099 000005E0 920E move a0, *a14+, 1 ; width + 0100 000005F0 09E0 movi 100, a0, L + 00000600 00000064 + 0101 00000620 920E move a0, *a14+, 1 ; y + 0102 00000630 920E move a0, *a14+, 1 ; x + 0103 00000640 934E move a10, *a14+, 1 ; parent = root + 0104 00000650 936E move a11, *a14+, 1 ; display + 0105 00000660 0D5F calla 3FD41B90h ; XCreateSimpleWindow + 00000670 3FD41B90 + 0106 00000690 0550 setf 16, 0, 0 + 0107 000006A0 0740 setf 32, 0, 1 + 0108 000006B0 4D0A move a8, a10 + 0109 000006C0 078A move a10, @01890120h, 1 ; MARK window + 000006D0 01890120 + 0110 000006F0 078A move a10, @m_window, 1 + 00000700 00000040+ + 0111 00000720 4D4A move a10, a10 + 0112 00000730 CA00 jreq fail_win + 00000740 0127 + 0113 00000750 09E0 movi 3, a0, L + 00000760 00000003 + 0114 00000780 0780 move a0, @01890140h, 1 ; stage = 3 + 00000790 01890140 + 0115 000007B0 0780 move a0, @m_stage, 1 + 000007C0 00000000+ + 0116 + 0117 ; ---- XMapWindow(display, window) ------------------- + 0118 000007E0 A3CF move a14, -*sp, 1 + 0119 000007F0 09EE movi 01894000h, a14, L + 00000800 01894000 + 0120 00000820 934E move a10, *a14+, 1 + 0121 00000830 936E move a11, *a14+, 1 + 0122 00000840 0D5F calla 3FD645B0h ; XMapWindow + 00000850 3FD645B0 + 0123 00000870 0550 setf 16, 0, 0 + 0124 00000880 0740 setf 32, 0, 1 + 0125 00000890 09E0 movi 4, a0, L + 000008A0 00000004 + 0126 000008C0 0780 move a0, @01890140h, 1 ; stage = 4 + 000008D0 01890140 + 0127 000008F0 0780 move a0, @m_stage, 1 + 00000900 00000000+ + 0128 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 4 + + 0129 ; ---- gc = XCreateGC(d, window, 0, NULL) ------------ + 0130 00000920 A3CF move a14, -*sp, 1 + 0131 00000930 09EE movi 01894000h, a14, L + 00000940 01894000 + 0132 00000960 09E0 movi 0, a0, L + 00000970 00000000 + 0133 00000990 920E move a0, *a14+, 1 ; values + 0134 000009A0 920E move a0, *a14+, 1 ; mask = 0 + 0135 000009B0 934E move a10, *a14+, 1 ; drawable + 0136 000009C0 936E move a11, *a14+, 1 ; display + 0137 000009D0 0D5F calla 3F997000h ; XCreateGC + 000009E0 3F997000 + 0138 00000A00 0550 setf 16, 0, 0 + 0139 00000A10 0740 setf 32, 0, 1 + 0140 00000A20 4D09 move a8, a9 ; GC + 0141 00000A30 0789 move a9, @01890180h, 1 ; MARK gc + 00000A40 01890180 + 0142 00000A60 0789 move a9, @m_gc, 1 + 00000A70 00000060+ + 0143 00000A90 4D29 move a9, a9 + 0144 00000AA0 CA00 jreq fail_gc + 00000AB0 00F4 + 0145 + 0146 ; ---- XSetForeground(display, gc, 0) -- draw with pen + 0147 00000AC0 A3CF move a14, -*sp, 1 + 0148 00000AD0 09EE movi 01894000h, a14, L + 00000AE0 01894000 + 0149 00000B00 09E0 movi 0, a0, L + 00000B10 00000000 + 0150 00000B30 920E move a0, *a14+, 1 ; pixel = 0 + 0151 00000B40 932E move a9, *a14+, 1 ; gc + 0152 00000B50 936E move a11, *a14+, 1 ; display + 0153 00000B60 0D5F calla 3FD99A60h ; XSetForeground + 00000B70 3FD99A60 + 0154 00000B90 0550 setf 16, 0, 0 + 0155 00000BA0 0740 setf 32, 0, 1 + 0156 00000BB0 09E0 movi 5, a0, L + 00000BC0 00000005 + 0157 00000BE0 0780 move a0, @01890140h, 1 ; stage = 5 + 00000BF0 01890140 + 0158 00000C10 0780 move a0, @m_stage, 1 + 00000C20 00000000+ + 0159 + 0160 ; ---- image = XCreateImage(d, NULL, 1, XYBitmap, 0, + 0161 ; bitmap, 32, 32, 32, 0) --- + 0162 00000C40 A3CF move a14, -*sp, 1 + 0163 00000C50 09EE movi 01894000h, a14, L + 00000C60 01894000 + 0164 00000C80 09E0 movi 0, a0, L + 00000C90 00000000 + 0165 00000CB0 920E move a0, *a14+, 1 ; bytes_per_line = 0 (let it comput + 0166 00000CC0 09E0 movi 32, a0, L + 00000CD0 00000020 + 0167 00000CF0 920E move a0, *a14+, 1 ; bitmap_pad = 32 + 0168 00000D00 09E0 movi 32, a0, L + 00000D10 00000020 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 5 + + 0169 00000D30 920E move a0, *a14+, 1 ; height + 0170 00000D40 920E move a0, *a14+, 1 ; width + 0171 00000D50 09E0 movi BITMAP, a0, L + 00000D60 00000000" + 0172 00000D80 920E move a0, *a14+, 1 ; data + 0173 00000D90 09E0 movi 0, a0, L + 00000DA0 00000000 + 0174 00000DC0 920E move a0, *a14+, 1 ; offset + 0175 00000DD0 920E move a0, *a14+, 1 ; format = 0 (XYBitmap) + 0176 00000DE0 09E0 movi 1, a0, L + 00000DF0 00000001 + 0177 00000E10 920E move a0, *a14+, 1 ; depth = 1 + 0178 00000E20 4400 sub a0, a0 + 0179 00000E30 920E move a0, *a14+, 1 ; visual = NULL + 0180 00000E40 936E move a11, *a14+, 1 ; display + 0181 00000E50 0D5F calla 3F9A0490h ; XCreateImage + 00000E60 3F9A0490 + 0182 00000E80 0550 setf 16, 0, 0 + 0183 00000E90 0740 setf 32, 0, 1 + 0184 00000EA0 4D07 move a8, a7 ; image (a7 survives XPutImage) + 0185 00000EB0 0788 move a8, @01890160h, 1 ; MARK image + 00000EC0 01890160 + 0186 00000EE0 0788 move a8, @m_image, 1 + 00000EF0 00000080+ + 0187 00000F10 4D08 move a8, a8 + 0188 00000F20 CA00 jreq fail_img + 00000F30 00B0 + 0189 00000F40 09E0 movi 6, a0, L + 00000F50 00000006 + 0190 00000F70 0780 move a0, @01890140h, 1 ; stage = 6 + 00000F80 01890140 + 0191 00000FA0 0780 move a0, @m_stage, 1 + 00000FB0 00000000+ + 0192 + 0193 ; ---- let the WM frame/reparent and map the window (x + 0194 ; A draw issued before the reparent can be lost, so sy + 0195 00000FD0 09EC movi 4, a12, L + 00000FE0 00000004 + 0196 00001000 map_wait: + 0197 00001000 A3CF move a14, -*sp, 1 + 0198 00001010 09EE movi 01894000h, a14, L + 00001020 01894000 + 0199 00001040 09E0 movi 0, a0, L + 00001050 00000000 + 0200 00001070 920E move a0, *a14+, 1 ; discard = 0 + 0201 00001080 936E move a11, *a14+, 1 ; display + 0202 00001090 0D5F calla 3FD9F6B0h ; XSync + 000010A0 3FD9F6B0 + 0203 000010C0 0550 setf 16, 0, 0 + 0204 000010D0 0740 setf 32, 0, 1 + 0205 000010E0 3DEC dsjs a12, map_wait + 0206 + 0207 ; ---- XPutImage(d, win, gc, image, 0,0, 20,20, 32,32) + 0208 000010F0 A3CF move a14, -*sp, 1 + 0209 00001100 09EE movi 01894000h, a14, L + 00001110 01894000 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 6 + + 0210 00001130 09E0 movi 32, a0, L + 00001140 00000020 + 0211 00001160 920E move a0, *a14+, 1 ; h + 0212 00001170 920E move a0, *a14+, 1 ; w + 0213 00001180 09E0 movi 20, a0, L + 00001190 00000014 + 0214 000011B0 920E move a0, *a14+, 1 ; dst_y + 0215 000011C0 920E move a0, *a14+, 1 ; dst_x + 0216 000011D0 4400 sub a0, a0 + 0217 000011E0 920E move a0, *a14+, 1 ; src_y + 0218 000011F0 920E move a0, *a14+, 1 ; src_x + 0219 00001200 92EE move a7, *a14+, 1 ; image + 0220 00001210 932E move a9, *a14+, 1 ; gc + 0221 00001220 934E move a10, *a14+, 1 ; drawable + 0222 00001230 936E move a11, *a14+, 1 ; display + 0223 00001240 0D5F calla 3F9D0370h ; XPutImage + 00001250 3F9D0370 + 0224 00001270 0550 setf 16, 0, 0 + 0225 00001280 0740 setf 32, 0, 1 + 0226 00001290 0788 move a8, @018901A0h, 1 ; MARK putimage return + 000012A0 018901A0 + 0227 000012C0 0788 move a8, @m_putret, 1 + 000012D0 000000A0+ + 0228 000012F0 09E0 movi 7, a0, L + 00001300 00000007 + 0229 00001320 0780 move a0, @01890140h, 1 ; stage = 7 + 00001330 01890140 + 0230 00001350 0780 move a0, @m_stage, 1 + 00001360 00000000+ + 0231 + 0232 ; ---- control: the same image with h = 16 at dst_y = + 0233 ; The PNG must show exactly 16 rows here (src rows 0.. + 0234 ; what proves the 32-row draw above is the image, not + 0235 00001380 A3CF move a14, -*sp, 1 + 0236 00001390 09EE movi 01894000h, a14, L + 000013A0 01894000 + 0237 000013C0 09E0 movi 16, a0, L + 000013D0 00000010 + 0238 000013F0 920E move a0, *a14+, 1 ; h = 16 + 0239 00001400 09E0 movi 32, a0, L + 00001410 00000020 + 0240 00001430 920E move a0, *a14+, 1 ; w = 32 + 0241 00001440 09E0 movi 60, a0, L + 00001450 0000003C + 0242 00001470 920E move a0, *a14+, 1 ; dst_y = 60 + 0243 00001480 09E0 movi 20, a0, L + 00001490 00000014 + 0244 000014B0 920E move a0, *a14+, 1 ; dst_x = 20 + 0245 000014C0 4400 sub a0, a0 + 0246 000014D0 920E move a0, *a14+, 1 ; src_y = 0 + 0247 000014E0 920E move a0, *a14+, 1 ; src_x = 0 + 0248 000014F0 92EE move a7, *a14+, 1 ; image + 0249 00001500 932E move a9, *a14+, 1 ; gc + 0250 00001510 934E move a10, *a14+, 1 ; drawable + 0251 00001520 936E move a11, *a14+, 1 ; display + 0252 00001530 0D5F calla 3F9D0370h ; XPutImage + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 7 + + 00001540 3F9D0370 + 0253 00001560 0550 setf 16, 0, 0 + 0254 00001570 0740 setf 32, 0, 1 + 0255 + 0256 ; ---- flush, twice: the request is only in the client + 0257 00001580 A3CF move a14, -*sp, 1 + 0258 00001590 09EE movi 01894000h, a14, L + 000015A0 01894000 + 0259 000015C0 09E0 movi 0, a0, L + 000015D0 00000000 + 0260 000015F0 920E move a0, *a14+, 1 + 0261 00001600 936E move a11, *a14+, 1 + 0262 00001610 0D5F calla 3FD9F6B0h ; XSync + 00001620 3FD9F6B0 + 0263 00001640 0550 setf 16, 0, 0 + 0264 00001650 0740 setf 32, 0, 1 + 0265 00001660 0788 move a8, @018901C0h, 1 ; MARK sync return + 00001670 018901C0 + 0266 00001690 0788 move a8, @m_syncret, 1 + 000016A0 000000C0+ + 0267 + 0268 000016C0 A3CF move a14, -*sp, 1 + 0269 000016D0 09EE movi 01894000h, a14, L + 000016E0 01894000 + 0270 00001700 09E0 movi 0, a0, L + 00001710 00000000 + 0271 00001730 920E move a0, *a14+, 1 + 0272 00001740 936E move a11, *a14+, 1 + 0273 00001750 0D5F calla 3FD9F6B0h ; XSync + 00001760 3FD9F6B0 + 0274 00001780 0550 setf 16, 0, 0 + 0275 00001790 0740 setf 32, 0, 1 + 0276 000017A0 0788 move a8, @018901C0h, 1 + 000017B0 018901C0 + 0277 000017D0 0788 move a8, @m_syncret, 1 + 000017E0 000000C0+ + 0278 + 0279 00001800 09E0 movi 8, a0, L + 00001810 00000008 + 0280 00001830 0780 move a0, @01890140h, 1 ; stage = 8 + 00001840 01890140 + 0281 00001860 0780 move a0, @m_stage, 1 + 00001870 00000000+ + 0282 + 0283 ; ---- XDestroyImage(image) -------------------------- + 0284 00001890 A3CF move a14, -*sp, 1 + 0285 000018A0 09EE movi 01894000h, a14, L + 000018B0 01894000 + 0286 000018D0 92EE move a7, *a14+, 1 + 0287 000018E0 0D5F calla 3F9A0D80h ; XDestroyImage + 000018F0 3F9A0D80 + 0288 00001910 0550 setf 16, 0, 0 + 0289 00001920 0740 setf 32, 0, 1 + 0290 00001930 C01A jruc done + 0291 + 0292 00001940 fail_abi: + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 8 + + 0293 00001940 09E0 movi 091h, a0, L + 00001950 00000091 + 0294 00001970 C010 jruc failed + 0295 00001980 fail_open: + 0296 00001980 09E0 movi 092h, a0, L + 00001990 00000092 + 0297 000019B0 C00C jruc failed + 0298 000019C0 fail_win: + 0299 000019C0 09E0 movi 093h, a0, L + 000019D0 00000093 + 0300 000019F0 C008 jruc failed + 0301 00001A00 fail_gc: + 0302 00001A00 09E0 movi 095h, a0, L + 00001A10 00000095 + 0303 00001A30 C004 jruc failed + 0304 00001A40 fail_img: + 0305 00001A40 09E0 movi 096h, a0, L + 00001A50 00000096 + 0306 00001A70 0300 jruc failed + 0307 00001A80 failed: + 0308 00001A80 0780 move a0, @01890140h, 1 + 00001A90 01890140 + 0309 00001AB0 0780 move a0, @m_stage, 1 + 00001AC0 00000000+ + 0310 + 0311 00001AE0 done: + 0312 00001AE0 09AF mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7 + 00001AF0 00FF + 0313 00001B00 09E8 movi 0, a8, L + 00001B10 00000000 + 0314 00001B30 0960 rets + 0315 + 0316 00000000 .data + 0317 ; 32 rows of 4 bytes, LSB-first pixels: a solid row at + 0318 ; at y=31, and a one-pixel diagonal between them. The + 0319 ; rows make the drawn height readable straight off the + 0320 00000000 BITMAP: + 0321 00000000 FF .byte 0FFh, 0FFh, 0FFh, 0FFh, 002h, 000h, 000h, 000h + 00000008 FF + 00000010 FF + 00000018 FF + 00000020 02 + 00000028 00 + 00000030 00 + 00000038 00 + 0322 00000040 04 .byte 004h, 000h, 000h, 000h, 008h, 000h, 000h, 000h + 00000048 00 + 00000050 00 + 00000058 00 + 00000060 08 + 00000068 00 + 00000070 00 + 00000078 00 + 0323 00000080 10 .byte 010h, 000h, 000h, 000h, 020h, 000h, 000h, 000h + 00000088 00 + 00000090 00 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 9 + + 00000098 00 + 000000A0 20 + 000000A8 00 + 000000B0 00 + 000000B8 00 + 0324 000000C0 40 .byte 040h, 000h, 000h, 000h, 080h, 000h, 000h, 000h + 000000C8 00 + 000000D0 00 + 000000D8 00 + 000000E0 80 + 000000E8 00 + 000000F0 00 + 000000F8 00 + 0325 00000100 00 .byte 000h, 001h, 000h, 000h, 000h, 002h, 000h, 000h + 00000108 01 + 00000110 00 + 00000118 00 + 00000120 00 + 00000128 02 + 00000130 00 + 00000138 00 + 0326 00000140 00 .byte 000h, 004h, 000h, 000h, 000h, 008h, 000h, 000h + 00000148 04 + 00000150 00 + 00000158 00 + 00000160 00 + 00000168 08 + 00000170 00 + 00000178 00 + 0327 00000180 00 .byte 000h, 010h, 000h, 000h, 000h, 020h, 000h, 000h + 00000188 10 + 00000190 00 + 00000198 00 + 000001A0 00 + 000001A8 20 + 000001B0 00 + 000001B8 00 + 0328 000001C0 00 .byte 000h, 040h, 000h, 000h, 000h, 080h, 000h, 000h + 000001C8 40 + 000001D0 00 + 000001D8 00 + 000001E0 00 + 000001E8 80 + 000001F0 00 + 000001F8 00 + 0329 00000200 00 .byte 000h, 000h, 001h, 000h, 000h, 000h, 002h, 000h + 00000208 00 + 00000210 01 + 00000218 00 + 00000220 00 + 00000228 00 + 00000230 02 + 00000238 00 + 0330 00000240 00 .byte 000h, 000h, 004h, 000h, 000h, 000h, 008h, 000h + 00000248 00 + 00000250 04 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 10 + + 00000258 00 + 00000260 00 + 00000268 00 + 00000270 08 + 00000278 00 + 0331 00000280 00 .byte 000h, 000h, 010h, 000h, 000h, 000h, 020h, 000h + 00000288 00 + 00000290 10 + 00000298 00 + 000002A0 00 + 000002A8 00 + 000002B0 20 + 000002B8 00 + 0332 000002C0 00 .byte 000h, 000h, 040h, 000h, 000h, 000h, 080h, 000h + 000002C8 00 + 000002D0 40 + 000002D8 00 + 000002E0 00 + 000002E8 00 + 000002F0 80 + 000002F8 00 + 0333 00000300 00 .byte 000h, 000h, 000h, 001h, 000h, 000h, 000h, 002h + 00000308 00 + 00000310 00 + 00000318 01 + 00000320 00 + 00000328 00 + 00000330 00 + 00000338 02 + 0334 00000340 00 .byte 000h, 000h, 000h, 004h, 000h, 000h, 000h, 008h + 00000348 00 + 00000350 00 + 00000358 04 + 00000360 00 + 00000368 00 + 00000370 00 + 00000378 08 + 0335 00000380 00 .byte 000h, 000h, 000h, 010h, 000h, 000h, 000h, 020h + 00000388 00 + 00000390 00 + 00000398 10 + 000003A0 00 + 000003A8 00 + 000003B0 00 + 000003B8 20 + 0336 000003C0 00 .byte 000h, 000h, 000h, 040h, 0FFh, 0FFh, 0FFh, 0FFh + 000003C8 00 + 000003D0 00 + 000003D8 40 + 000003E0 FF + 000003E8 FF + 000003F0 FF + 000003F8 FF + 0337 00000400 BITMAP_END: + 0338 + 0339 00000000 .bss m_stage, 32, 1 + GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026 + (c) Copyright 1985, 1987, Texas Instruments Inc. + + PAGE 11 + + 0340 00000020 .bss m_display, 32, 1 + 0341 00000040 .bss m_window, 32, 1 + 0342 00000060 .bss m_gc, 32, 1 + 0343 00000080 .bss m_image, 32, 1 + 0344 000000A0 .bss m_putret, 32, 1 + 0345 000000C0 .bss m_syncret, 32, 1 + 0346 000000E0 .bss m_strlen, 32, 1 + 0347 + 0348 .end + + No Errors, No Warnings diff --git a/dwt/loader/build/xshow.map b/dwt/loader/build/xshow.map new file mode 100644 index 0000000..aff3b96 --- /dev/null +++ b/dwt/loader/build/xshow.map @@ -0,0 +1,36 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Fri Nov 13 09:31:54 2026 + +OUTPUT FILE NAME: +ENTRY POINT SYMBOL: 0 + + +SECTION ALLOCATION MAP + + output attributes/ +section page origin length input sections +-------- ---- ---------- ---------- ---------------- +.text 0 01840000 00001B40 + 01840000 00001B40 XSHOW.obj (.text) + +.data 0 018D0000 00000400 + 018D0000 00000400 XSHOW.obj (.data) + +.bss 0 018D8000 00000100 UNINITIALIZED + 018D8000 00000100 XSHOW.obj (.bss) + + +GLOBAL SYMBOLS + +address name address name +-------- ---- -------- ---- +018D8000 .bss 01840000 .text +018D0000 .data 01841B40 etext +01840000 .text 018D0000 .data +018D0400 edata 018D0400 edata +018D8100 end 018D8000 .bss +01841B40 etext 018D8100 end + +[6 symbols] diff --git a/dwt/loader/build/xshow.obj b/dwt/loader/build/xshow.obj new file mode 100644 index 0000000000000000000000000000000000000000..68ff9c6329ec3f85c2970971c6fcc7ef935b7354 GIT binary patch literal 1428 zcmcIkziSjh6n^VooSQSZUQ|?)W*bqP`wNt8p%4NqDXq*#ViQ4Da)srVdx_w=hk`-j zz*cYzA?=l-g(*ZxH>E;2EJE7zdowq;6Mtdj!0h{G=6mmZZ)SFSKLrQ(E`z9piYg5d1rt_^!EB%XAO4Ruzu(p4)eH0=^15ConDXiMNK(}GlwA7uW-%yMn|rt4EiykB3hPQjn(9mR@uBxCH@);y zb5F(Ff)I0Cgkax~>BAjFJOS)#ZR}>X<=x29R}gU9bDwg&=_*Y!9kZuKAZ zSDU?s&swz+Z;249TOz{xGE^@^729-7)n;vc%bQ=cuc^z;&hl(FR*ljZ+C#=&kwL91 z5-41S+M!bkrjTh{=a=m4Pc-T5eXx`=a;AfH@h zVAhdOiPPen<|-cO^ZU6rj#D0)EDx?%t0BCN=D7)C)u0%mGP8fF|4OUpVxYAL;3>&h z$yKc)wsag@pOV)mV-x>R(JOz@k&&BkE{0lph?RfkDOm^mcNvaw?tUX61 zlnh$I4`EOX#vsCh88n> 3) - 0x07E40000`, the ROM's byte base.) +#### 2.2.1 XImage — the bitmap path + +The table above ends at the drawing calls. The image entry points are separate, +and none of them is a request except `XPutImage`/`XGetImage`; `XCreateImage` and +`XDestroyImage` are client-side. Addresses were derived by disassembling +`vt1200_v22.bin` with `tools/smart34010/dis34` and then confirmed live (see +§2.2.2). Bit addresses again; Ghidra = bits / 8. + +| Xlib function | Ghidra | bits | shape seen | +|---|---|---|---| +| `XCreateImage(d,visual,depth,format,offset,data,w,h,bitmap_pad,bytes_per_line)` | `0x07F34092` | `0x3F9A0490` | 10 args; `calloc(1,0x58)` (0x3F703D90), fills the struct, `_XInitImageFuncPtrs` (0x3F9A6AA0) | +| `XPutImage(d,drawable,gc,image,src_x,src_y,dst_x,dst_y,w,h)` | `0x07F3A06E` | `0x3F9D0370` | 10 args; clips, checks `bits_per_pixel`, calls the workhorse below | +| `XDestroyImage(image)` | `0x07F341B0` | `0x3F9A0D80` | 1 arg; `free(image->data)`, `free(image->obdata)` if set, `free(image)` | +| `XGetImage(d,drawable,x,y,w,h,plane_mask,format)` | `0x07FAAAD6` | `0x3FD556B0` | 8 args; request opcode **73 (0x49)**, length 5 | + +Supporting routines, named so a trace can be followed: + +| routine | Ghidra | bits | what it is | +|---|---|---|---| +| PutImage request builder | `0x07F39D8E` | `0x3F9CEC70` | writes opcode **72 (0x48)** at request byte 0, length 6 at byte 2, `format = image->format` at byte 1, then drawable/gc/width/height/dst-x/dst-y/depth; dispatches the pixel copy | +| 1-bit pixel copier | `0x07F3965A` | `0x3F9CB2D0` | used when `depth == 1` **or** `format != ZPixmap`; appends the rows and bumps the request length | +| ZPixmap pixel copier | `0x07F39B18` | `0x3F9CD8C0` | used when `depth != 1` and `format == ZPixmap` | +| PutImage workhorse | `0x07F39E68` | `0x3F9CF340` | clipping, request-band splitting when the image does not fit the client buffer, then the request builder | +| `_XInitImageFuncPtrs` | `0x07F34D54` | `0x3F9A6AA0` | fills `image->f` (get_pixel at `image+0x200`, …) | +| image-field reporter | `0x07F34DA4` | `0x3F9A6D20` | prints `Bad image %s: %d found in routine: %s` (string `0x3F9A7348`) | + +**Drift check.** Pin each name to its bytes before trusting the table (`-s` is +the file offset, `(bit_address >> 3) - 0x07E40000`): + +``` +tools/smart34010/dis34 -l -o -b 3F9D0370 -s 0xFA06E vt1200_v22.bin +# expect: mmtm sp, a5,a7,a9,a10,a11,a12,a13 -> XPutImage +tools/smart34010/dis34 -l -o -b 3F9CEE00 -s 0xF9DC0 vt1200_v22.bin +# expect: movi 0x48 (opcode 72), movb a7,*a11, movk 6 -> PutImage request +tools/smart34010/dis34 -l -o -b 3FD55830 -s 0x16AB06 vt1200_v22.bin +# expect: movi 0x49 (opcode 73), movb a11,*a10, movk 5 -> GetImage request +tools/smart34010/dis34 -l -o -b 3F9A0490 -s 0xF4092 vt1200_v22.bin +# expect: mmtm sp, a3,a5,a7,a9,a10,a11,a13 -> XCreateImage (movi 0x58 follows) +tools/smart34010/dis34 -l -o -b 3F9A0D80 -s 0xF41B0 vt1200_v22.bin +# expect: mmtm sp, a11,a13 -> XDestroyImage +``` + +**XImage layout.** 32-bit fields; byte offsets as the ROM writes them in +`XCreateImage`, and as read back from a live image in §2.2.2: + +| off | field | off | field | off | field | +|---|---|---|---|---|---| +| `0x00` | width | `0x18` | bitmap_unit | `0x30` | red_mask | +| `0x04` | height | `0x1C` | bitmap_bit_order | `0x34` | green_mask | +| `0x08` | xoffset | `0x20` | bitmap_pad | `0x38` | blue_mask | +| `0x0C` | format | `0x24` | depth | `0x3C` | obdata | +| `0x10` | data | `0x28` | bytes_per_line | `0x40` | f.get_pixel … | +| `0x14` | byte_order | `0x2C` | bits_per_pixel | | | + +**The format contract, from the code** (not from Xlib headers): + +* `XCreateImage` **inherits the orders from the Display**: `image->byte_order = + *(dpy+0x1A0)`, `bitmap_unit = *(dpy+0x1C0)`, `bitmap_bit_order = + *(dpy+0x200)` (`0x3F9A0650`, `0x3F9A0680`, `0x3F9A06B0`). A client does not + have to know or guess them. +* `bits_per_pixel` starts at **1**. Only `format == ZPixmap (2)` replaces it, via + a lookup in the display's pixmap-format list (`dpy+0x220` count, `dpy+0x240` + pointer, entry stride `0x80` bits, depth at entry+`0x20`, bpp at entry+`0x40`; + no match falls back to `depth`). So **XYBitmap (0) and XYPixmap (1) are always + transported as 1 bit per pixel**, whatever `depth` says. +* `bytes_per_line` is computed from `width`/`offset`/`bitmap_pad` when the caller + passes 0 (`0x3F9A09C0`–`0x3F9A0C40`). +* `XCreateImage` itself rejects nothing — no depth, format or order check. +* `XPutImage` refuses exactly one case (`0x3F9D07B0`–`0x3F9D0B70`): `format == + ZPixmap` **and** `depth != 1` **and** `image->bits_per_pixel` differs from the + display's bits-per-pixel for that depth. It then prints the ROM's own message + and **returns without sending the request**; the caller sees no error. +* Everything else — `depth == 1`, and every non-ZPixmap format — takes the 1-bit + path and never reaches that check. + +**The two ROM messages, and what they actually mean here.** + +* `XPutImage: bits_per_pixel conversion unimplemented.` — string + `0x3F9D0E80`, printed at `0x3F9D0B40` into Xlib's error stream (`@0x00DAD00`). + It is literal: there is no `bits_per_pixel` conversion path in this Xlib. It + fires only for a ZPixmap image of depth ≠ 1 whose `bits_per_pixel` does not + match the server's; the request is dropped, not rejected over the wire, and + the process continues. A 1-bit `XYBitmap` can never trigger it. +* `XGetImage: Can't get requested memory` — string `0x3FD567A0`, printed at + `0x3FD55D30`. It is the **client-side malloc for the reply data** failing: the + call at `0x3FD55C70` allocates `4 × reply.length` bytes and, on NULL, prints + this and returns NULL (`0x3FD55D60`). It says nothing about the server. + +**Minimum image sequence** (same calling convention as §4): `XCreateGC` +(`0x3F997000`, mask 0 is enough) → `XCreateImage` → optional +`XSetForeground` → `XPutImage` → `XSync` (`0x3FD9F6B0`) → +`XDestroyImage`. Map and sync the window once before the put, exactly as for +text: the WM reparents the window, and a draw issued before that can be lost. +The probe in §2.2.2 is this sequence. + +#### 2.2.2 The image path, measured + +`dwt/gui/xshow.asm` (built with `dwt/loader/build.sh`, run through the COFF +loader — no network, no rdebug) opens its own connection as a `create_process` +child, creates a 400×200 window at 100,100, creates a 32×32 **XYBitmap** +(`depth = 1`, `format = 0`, LSBFirst both ways, `bitmap_unit = 32`, +`bitmap_pad = 32`, `bytes_per_line = 0` so `XCreateImage` computes it), uploads +it with `XPutImage` at window (20,20), syncs twice, and destroys it. A second +`XPutImage` of the same image with `h = 16` at (20,60) is the control. + +Measured values from the run (frame 2650, VR150, `VT1200_SKIP_LEVEL1=1`): + +``` +XSHOW: f2650 mirror stage=00000008 display=0093C910 window=00400001 gc=00987D70 image=00988130 putret=00000080 syncret=00000001 strlen=00000004 +XSHOW: final image@00988130 width=00000020 height=00000020 xoffset=00000000 format=00000000 data=018D0000 byte_order=00000000 bitmap_unit=00000020 bitmap_bit_order=00000000 bitmap_pad=00000020 depth=00000001 bytes_per_line=00000004 bits_per_pixel=00000001 +XSHOW: final dpy@0093C910 byte_order=00000000 bitmap_unit=00000020 scanline_pad=00000020 bitmap_bit_order=00000000 +XSHOW: final pixmap_formats n=1 list=00367D90 +XSHOW: final fmt[0] depth=00000001 bits_per_pixel=00000001 pad=00000020 +``` + +Stage 8 is "synced"; the checklist stages 1–7 are start, display, window, +mapped, gc, image, putimage. The picture: `dwt/gui/evidence/xshow_frame2650.png`. +Pixel rows (decoded from that PNG with +`python3 dwt/gui/evidence/png_rows.py dwt/gui/evidence/xshow_frame2650.png 118 118 40 64`, +saved as `dwt/gui/evidence/xshow_pixels.txt`) show the full 32-row image at +screen 122..153 and the 16-row control at 162..177: + +``` + 122 ....################################.... + 123 .....#.................................. + ... (one diagonal pixel per row) + 152 ..................................#..... + 153 ....################################.... + ... + 162 ....################################.... + 163 .....#.................................. + ... (control stops after 16 rows) + 177 ...................#.................... +``` + +The same payload run snapshot 30 frames later (`xshow_frame2680.png`, frame +2680) is byte-identical to the 2650 capture (md5 +`ab9d63844aa5a3dd9d281a6bee3c76c2`), so the picture is the window's state and +not a transient. + +What this proves, and what it does not: + +* **Measured:** the ROM's own `XCreateImage` builds the struct described above + from the ten arguments and the display's orders; `XPutImage` of a 1-bit + `XYBitmap` paints exactly `w × h` pixels at the requested destination, honours + a smaller `h`, and returns normally; `XDestroyImage` runs without harm. The + display advertises exactly one pixmap format (depth 1, bpp 1, pad 32). +* **Inferred / not measured:** `XGetImage` is documented from disassembly only — + the probe does not call it (it needs a real GET round trip and its allocation + path). Orders other than LSBFirst are *supposed* to work: the 1-bit copier + picks a normalization routine from a runtime table keyed by + `(bitmap_unit, bitmap_bit_order, byte_order)` for both the image and the + display (`0x3F9CB7C0`–`0x3F9CBB20`), but only LSBFirst/32 was run. A + non-1-bit ZPixmap is untested because the server has no such visual; only the + mismatch message above is established. + ### 2.3 X server internals that matter | what | Ghidra | bits | @@ -204,8 +360,9 @@ it is mapped should call `0x3FD64F60`. To draw text add `XLoadFont(d,"fixed")` (`0x3FD4AE80`), `XCreateGC` (`0x3F997000`) with `GCFont=0x4000`, `XSetForeground` (`0x3FD99A60`) and -`XDrawString` (`0x3FDA0000`). No event loop is needed for a static window; the -server keeps it after the client goes idle. +`XDrawString` (`0x3FDA0000`). To draw a bitmap add `XCreateImage` + +`XPutImage` (§2.2.1); §2.2.2 is the measured example. No event loop is needed +for a static window; the server keeps it after the client goes idle. Globals: only the `Display *` is per-app. There is **no global "current display" to initialise**; `XOpenDisplay` allocates and returns it. Window ids, @@ -349,6 +506,13 @@ live. | `dwt/gui/probe.lua`, `probe2.lua`, `probe3.lua` | frame snapshots + marker/PC telemetry + accept breakpoint | | `dwt/gui/run/mame.log` | boot, markers (`strlen=4`, `stage=2`, `disp=0`, `xclients=1`) | | `dwt/gui/run/gui_frame15571.png` | post-injection frame: normal Terminal Manager, no new window | +| `dwt/gui/xshow.asm` | the XImage probe (§2.2.2): XCreateImage + 2×XPutImage + XDestroyImage | +| `dwt/gui/xshow.lua`, `dwt/gui/build/xshow.coff` | the COFF-loader runner and the linked image it loads | +| `dwt/gui/build/xshow.bin`, `.lst`, `.map` | assembled `.text`, listing, map | +| `dwt/gui/evidence/xshow_frame2650.png` | 32-row diagonal at window (20,20); 16-row control at (20,60) | +| `dwt/gui/evidence/xshow_frame2680.png` | the same picture 30 frames later (byte-identical PNG) | +| `dwt/gui/evidence/xshow_pixels.txt`, `png_rows.py` | the PNG's rows as ASCII, and the dependency-free decoder that produced them | +| `dwt/gui/evidence/xshow_run.log` | the run: stage 8, the live XImage fields, the display's pixmap formats | ## 10. Transport settled: a `create_process` child opens a window -- 2.47.3