docs(xie): the ROM's XImage entry points and the 1-bit format #11
No files matched your search
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,626 @@
|
||||
GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026
|
||||
(c) Copyright 1985, 1987, Texas Instruments Inc.
|
||||
|
||||
PAGE 1
|
||||
|
||||
0001 ; xshow.asm -- create a 1-bit XImage and XPutImage it o
|
||||
0002 ;
|
||||
0003 ; Run as a first-class process created by the COFF load
|
||||
0004 ; in the rdebug dispatcher's context: a connect made fr
|
||||
0005 ; accepted at the service layer but the server never re
|
||||
0006 ;
|
||||
0007 ; The image is a 32x32 XYBitmap (format 0), depth 1, cr
|
||||
0008 ; XCreateImage and drawn with XPutImage. Its data is a
|
||||
0009 ; cells, written into .data at build time, so the PNG s
|
||||
0010 ; or nothing -- there is nothing to misread.
|
||||
0011 ;
|
||||
0012 ; XImage entry points used here (Ghidra address -> 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
|
||||
@@ -0,0 +1,36 @@
|
||||
*****************************************************
|
||||
GSP COFF Linker, Version 2.00, 87.300
|
||||
*****************************************************
|
||||
Fri Nov 13 09:31:54 2026
|
||||
|
||||
OUTPUT FILE NAME: <XSHOW.out>
|
||||
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]
|
||||
@@ -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()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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'
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,626 @@
|
||||
GSP COFF Assembler, Version 2.00, 87.300 Fri Nov 13 09:31:54 2026
|
||||
(c) Copyright 1985, 1987, Texas Instruments Inc.
|
||||
|
||||
PAGE 1
|
||||
|
||||
0001 ; xshow.asm -- create a 1-bit XImage and XPutImage it o
|
||||
0002 ;
|
||||
0003 ; Run as a first-class process created by the COFF load
|
||||
0004 ; in the rdebug dispatcher's context: a connect made fr
|
||||
0005 ; accepted at the service layer but the server never re
|
||||
0006 ;
|
||||
0007 ; The image is a 32x32 XYBitmap (format 0), depth 1, cr
|
||||
0008 ; XCreateImage and drawn with XPutImage. Its data is a
|
||||
0009 ; cells, written into .data at build time, so the PNG s
|
||||
0010 ; or nothing -- there is nothing to misread.
|
||||
0011 ;
|
||||
0012 ; XImage entry points used here (Ghidra address -> 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
|
||||
@@ -0,0 +1,36 @@
|
||||
*****************************************************
|
||||
GSP COFF Linker, Version 2.00, 87.300
|
||||
*****************************************************
|
||||
Fri Nov 13 09:31:54 2026
|
||||
|
||||
OUTPUT FILE NAME: <XSHOW.out>
|
||||
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]
|
||||
Binary file not shown.
+166
-2
@@ -108,6 +108,162 @@ tools/smart34010/dis34 -l -o -b 3FD645B0 -s 0x16C8B6 vt1200_v22.bin
|
||||
(The `-s` values are file offsets: `(bit_address >> 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
|
||||
|
||||
|
||||
Reference in new issue
Block a user