mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
308 lines
9.1 KiB
NASM
308 lines
9.1 KiB
NASM
; xtext.asm -- open a window on the live DWT X server and draw text in it.
|
|
;
|
|
; 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, so
|
|
; XOpenDisplay returns an unusable Display. A fresh process works.
|
|
;
|
|
; This is xhello.asm plus the text path:
|
|
; XLoadFont(d,"fixed") 3FD4AE80
|
|
; XCreateGC(d,win,mask,&values) 3F997000
|
|
; XSetForeground(d,gc,1) 3FD99A60
|
|
; XMapWindow(d,win) 3FD645B0
|
|
; XSync(d,0) / XDrawString(...) loop 3FD9F6B0 / 3FDA0000
|
|
;
|
|
; The GC is created with a zero value-mask, so the server fills it from the
|
|
; screen's default GC (which carries the server's default font, "fixed"). The
|
|
; draw is repeated with an XSync between iterations so that it lands after the
|
|
; WM has framed/reparented/mapped the window; a single early draw can be lost
|
|
; when the window is reparented.
|
|
;
|
|
; Calling convention (the one the firmware itself uses; see the WM at
|
|
; 07F57044 and the TM at 07E5D2B4):
|
|
;
|
|
; MOVE A14,-*SP,1 ; reserve the slot the callee restores A14 from
|
|
; MOVI argN,A0 / MOVE A0,*A14+,1 ; last argument first, upward via A14
|
|
; ...
|
|
; MOVI arg0,A0 / MOVE A0,*A14+,1 ; first argument last
|
|
; CALLA target
|
|
;
|
|
; The callee's `rets 2` pops the return address and the reserved slot, so SP is
|
|
; restored by the call itself; A14 is restored from that slot. Do NOT keep the
|
|
; entry SP/A14 in RAM and restore them after each call: the app's own stack and
|
|
; Xlib data structures use the same free heap, and a clobbered saved-SP cell
|
|
; turns the next call into a wild push. That exact pattern crashed the first
|
|
; version of this payload at XCreateGC.
|
|
;
|
|
; Xlib clobbers the CPU's SETF field state, so the ABI's 32-bit field 1 is
|
|
; re-established after every call. The Display pointer and the window/GC ids
|
|
; are kept in callee-saved registers (a11/a10/a12).
|
|
;
|
|
; Markers live in 224 bytes of zero padding at the end of .text (01842000h),
|
|
; NOT in the free heap: the first version's cells at 01895000h were overwritten
|
|
; by the OS heap (the string "Exiting\n" landed on them).
|
|
;
|
|
; 01842000 stage (1 start, 2 display, 3 window, 4 font, 5 GC, 6 setfg,
|
|
; 7 map, 8 synced/drawn, 9 flushed, 0FFh failed)
|
|
; 01842020 display pointer
|
|
; 01842040 font id returned by XLoadFont
|
|
; 01842060 window id
|
|
; 01842080 GC id returned by XCreateGC
|
|
; 018420A0 XSetForeground return
|
|
; 018420C0 XMapWindow return
|
|
; 018420E0 last XSync return
|
|
; 01842100 first XDrawString return
|
|
; 01842120 second XDrawString return
|
|
; 01842140 final XSync return
|
|
; 01841760 strlen("0::0") -- must be 4
|
|
;
|
|
; Scratch: 01894000 argument area
|
|
|
|
.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, @01842000h, 1 ; 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 ; arg0
|
|
calla 3FB458D0h ; strlen
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, @01842160h, 1 ; MARK strlen
|
|
movi 4, a0, L
|
|
cmp a0, a8
|
|
jrne failed
|
|
|
|
movi 2, a0, L
|
|
move a0, @01842000h, 1 ; stage = 2
|
|
|
|
; ---- display = XOpenDisplay("0::0") ---------------------------
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi 3FACE948h, a0, L
|
|
move a0, *a14+, 1 ; arg0 = name
|
|
calla 3F9C2570h ; XOpenDisplay
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, a11 ; Display * (callee-saved)
|
|
move a11, @01842020h, 1 ; MARK display
|
|
move a11, a11
|
|
jreq failed
|
|
|
|
; ---- root = *(*(display+0x480)+0x40) --------------------------
|
|
move *a11(0480h), a10, 1
|
|
move *a10(040h), a10, 1
|
|
|
|
movi 3, a0, L
|
|
move a0, @01842000h, 1 ; stage = 3
|
|
|
|
; ---- window = XCreateSimpleWindow(d,root,100,100,400,200,2,1,0) --
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi 0, a0, L
|
|
move a0, *a14+, 1 ; background = 0 (black)
|
|
movi 1, a0, L
|
|
move a0, *a14+, 1 ; border = 1 (white)
|
|
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 ; window id
|
|
move a10, @01842060h, 1 ; MARK window
|
|
move a10, a10
|
|
jreq failed
|
|
|
|
movi 4, a0, L
|
|
move a0, @01842000h, 1 ; stage = 4
|
|
|
|
; ---- font = XLoadFont(display, "fixed") -----------------------
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi FONTNAME, a0, L
|
|
move a0, *a14+, 1 ; arg1 = name
|
|
move a11, *a14+, 1 ; arg0 = display
|
|
calla 3FD4AE80h ; XLoadFont
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, a9 ; Font (callee-saved)
|
|
move a9, @01842040h, 1 ; MARK font
|
|
move a9, a9
|
|
jreq failed
|
|
|
|
movi 5, a0, L
|
|
move a0, @01842000h, 1 ; stage = 5
|
|
|
|
; ---- gc = XCreateGC(d, window, 0, NULL) ----------------------
|
|
; mask 0 -> server default GC values (no value-list to misparse).
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi 0, a0, L
|
|
move a0, *a14+, 1 ; arg3 = values
|
|
move a0, *a14+, 1 ; arg2 = mask 0
|
|
move a10, *a14+, 1 ; arg1 = drawable
|
|
move a11, *a14+, 1 ; arg0 = display
|
|
calla 3F997000h ; XCreateGC
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, a12 ; GC (callee-saved)
|
|
move a12, @01842080h, 1 ; MARK gc
|
|
move a12, a12
|
|
jreq failed
|
|
|
|
; ---- XSetForeground(display, gc, 1) --------------------------
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi 1, a0, L
|
|
move a0, *a14+, 1 ; arg2 = pixel 1 (white)
|
|
move a12, *a14+, 1 ; arg1 = gc
|
|
move a11, *a14+, 1 ; arg0 = display
|
|
calla 3FD99A60h ; XSetForeground
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, @018420A0h, 1 ; MARK setfg
|
|
movi 6, a0, L
|
|
move a0, @01842000h, 1 ; stage = 6
|
|
|
|
; ---- XMapWindow(display, window) -----------------------------
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
move a10, *a14+, 1 ; window
|
|
move a11, *a14+, 1 ; display
|
|
calla 3FD645B0h ; XMapWindow
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, @018420C0h, 1 ; MARK map
|
|
movi 7, a0, L
|
|
move a0, @01842000h, 1 ; stage = 7
|
|
|
|
; ---- sync + draw, repeated: the WM needs time to frame/map -----
|
|
movi 4, a9, L
|
|
draw_loop:
|
|
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 (flush + round trip)
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, @018420E0h, 1 ; MARK last sync
|
|
|
|
; ---- XDrawString(display, window, gc, 20, 80, msg1, 12) ------
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi 12, a0, L
|
|
move a0, *a14+, 1 ; arg6 = length
|
|
movi MSG1, a0, L
|
|
move a0, *a14+, 1 ; arg5 = string
|
|
movi 80, a0, L
|
|
move a0, *a14+, 1 ; arg4 = y
|
|
movi 20, a0, L
|
|
move a0, *a14+, 1 ; arg3 = x
|
|
move a12, *a14+, 1 ; arg2 = gc
|
|
move a10, *a14+, 1 ; arg1 = window
|
|
move a11, *a14+, 1 ; arg0 = display
|
|
calla 3FDA0000h ; XDrawString
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, @01842100h, 1 ; MARK draw1
|
|
|
|
; ---- XDrawString(display, window, gc, 20, 120, msg2, 10) ----
|
|
move a14, -*sp, 1
|
|
movi 01894000h, a14, L
|
|
movi 10, a0, L
|
|
move a0, *a14+, 1 ; arg6 = length
|
|
movi MSG2, a0, L
|
|
move a0, *a14+, 1 ; arg5 = string
|
|
movi 120, a0, L
|
|
move a0, *a14+, 1 ; arg4 = y
|
|
movi 20, a0, L
|
|
move a0, *a14+, 1 ; arg3 = x
|
|
move a12, *a14+, 1 ; arg2 = gc
|
|
move a10, *a14+, 1 ; arg1 = window
|
|
move a11, *a14+, 1 ; arg0 = display
|
|
calla 3FDA0000h ; XDrawString
|
|
setf 16, 0, 0
|
|
setf 32, 0, 1
|
|
move a8, @01842120h, 1 ; MARK draw2
|
|
|
|
; DSJS has a short range; trampoline to the long backward jump.
|
|
dsjs a9, draw_next
|
|
jruc draw_done
|
|
draw_next:
|
|
jruc draw_loop
|
|
draw_done:
|
|
|
|
movi 8, a0, L
|
|
move a0, @01842000h, 1 ; stage = 8
|
|
|
|
; ---- final XSync flushes the last PolyText8 -----------------
|
|
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
|
|
move a8, @01842140h, 1 ; MARK final sync
|
|
|
|
movi 9, a0, L
|
|
move a0, @01842000h, 1 ; stage = 9 (text drawn and flushed)
|
|
jruc done
|
|
|
|
failed:
|
|
movi 0FFh, a0, L
|
|
move a0, @01842000h, 1
|
|
|
|
done:
|
|
mmfm sp, a0,a1,a2,a3,a4,a5,a6,a7
|
|
movi 0, a8, L
|
|
rets
|
|
|
|
MSG1: .byte "HELLO VT1200", 0
|
|
MSG2: .byte "text works", 0
|
|
FONTNAME: .byte "-DEC-Terminal-Medium-R-Normal--14-140-75-75-C-8-ISO8859-1", 0
|
|
|
|
; 224 bytes of padding: marker cells 01842000h..0184217Fh live here.
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.end
|