; iigsToolbox.s — multi-arg toolbox wrappers that can't be done as ; inline asm because the W65816 backend's inline-asm constraints ; can't take memory operands. ; ; C ABI on this target: ; - Arg 0 (i16): in A ; - Arg 0 (i32): low half in A, high half in X ; - Arg N>0 (i16):in stack at (4 + 2*(N-1)), S — args pushed ; rightmost-first, JSL adds 3 bytes of retaddr ; (4,S = arg1 lo) ; - i16 return: A ; - i32 return: A (low) + X (high) ; ; Toolbox calls expect: ; - Args on stack in toolbox order (rightmost pushed first), then ; a result slot of appropriate width pushed BEFORE the args (so ; the result ends up at the highest stack address after pushes). ; - Tool number in X. ; - JSL $E10000. ; - After JSL, pop result then args in reverse. ; ; All wrappers preserve nothing (toolbox clobbers A, X, Y, P). .text .globl TBoxNewHandle .globl TBoxDisposeHandle .globl TBoxQDStartUp .globl TBoxMoveTo .globl TBoxEMStartUp .globl TBoxGetNextEvent .globl TBoxNewWindow .globl TBoxCloseWindow ; ===================================================================== ; unsigned long TBoxNewHandle(u32 size, u16 userId, u16 attr, u32 addr) ; Entry: A = size lo, X = size hi ; 4,S = userId, 6,S = attr, 8,S = addr lo, 10,S = addr hi ; Tool layout (push order, leftmost=outermost on stack): ; [result lo][result hi][size lo][size hi][userId][attr][addr lo][addr hi] ; Wait: NewHandle args per Apple GS docs are ; (Long blockSize, Word userId, Word attributes, Long memAttr) ; pushed leftmost-first, so: ; PEA result hi, PEA result lo ; PUSH blockSize hi, PUSH blockSize lo (long, lo first then hi? no — let me check) ; ; Actually GS toolbox push order: each parameter is pushed in ; declaration order, low word first then high word for longs. ; Result space is pushed FIRST (and is read LAST after the pop ; sequence reverses everything). So: ; PEA 0 ; result hi ; PEA 0 ; result lo ; PHA size lo ; PHB? no: ; per https://www.brutaldeluxe.fr/products/crossdevtools/cadius/ ; Push order: parameters in order, longs as lo then hi. ; For NewHandle(blockSize=Long, userId=Word, attr=Word, memLoc=Long): ; pea 0 ; result lo ; pea 0 ; result hi ; pha ; blockSize lo ; phx ; blockSize hi (since size hi is in X) ; pha userId ; pha attr ; pha addrLo ; pha addrHi ; ldx #$0902 ; jsl $E10000 ; ; result is now on stack: pop hi then lo into A:X return ; ; Note: the IIgs toolbox actually expects result space to be HIGHER ; on stack (pushed first) so that pops in reverse give result last. ; ===================================================================== TBoxNewHandle: ; Stash size lo (in A) and size hi (in X) before we use the ; stack — both must be pushed AFTER the result slot. sta 0xe0 ; size lo to scratch stx 0xe2 ; size hi to scratch ; Push 4-byte result space (will be popped at end). pea 0 ; result lo pea 0 ; result hi ; Push blockSize: lo first then hi. lda 0xe0 ; size lo pha lda 0xe2 ; size hi pha ; Push userId (was at 4,S originally; pushes since added: 4 result + 4 size = 8; +4 for JSL retaddr offset baseline) ; Original 4,S; we've pha'd 8 bytes (result+size) on top of retaddr ; So userId is now at 4 + 8 = 12,S. lda 12, s ; userId pha ; attr was at 6,S originally; now at 6 + 8 + 2 (one more pha) = 16,S. lda 16, s ; attr pha ; addr lo was at 8,S originally; with all our pushes (4 result + 4 ; size + 2 user + 2 attr = 12), now at 8 + 12 = 20,S. lda 20, s ; addr lo pha ; addr hi was at 10,S originally; +14 = 24,S. lda 24, s ; addr hi pha ldx #0x0902 jsl 0xe10000 ; Pop result: hi then lo. Returns u32 in A:X (low in A, hi in X). pla ; result hi tax pla ; result lo → A rtl ; ===================================================================== ; void TBoxDisposeHandle(unsigned long handle) ; Entry: A = handle lo, X = handle hi ; ===================================================================== TBoxDisposeHandle: pha ; handle lo phx ; handle hi ldx #0x1002 jsl 0xe10000 rtl ; ===================================================================== ; void TBoxQDStartUp(u16 masterSCB, u16 pageSize, u16 userId) ; Entry: A = masterSCB, 4,S = pageSize, 6,S = userId ; Tool: PEA userId, PEA pageSize, PHA masterSCB, JSL X=$0204 ; ===================================================================== TBoxQDStartUp: sta 0xe0 ; stash masterSCB lda 6, s ; userId (originally 6,S, no pushes yet) pha ; userId pushed; subsequent loads need +2 lda 6, s ; pageSize was at 4,S; +2 = 6,S pha lda 0xe0 ; masterSCB pha ldx #0x0204 jsl 0xe10000 rtl ; ===================================================================== ; void TBoxMoveTo(short h, short v) ; Entry: A = h, 4,S = v ; ===================================================================== TBoxMoveTo: pha ; h lda 6, s ; v (originally 4,S; +2 after pha) pha ldx #0x3A04 jsl 0xe10000 rtl ; ===================================================================== ; void TBoxEMStartUp(u16 userId) ; Entry: A = userId ; Default queueSize=0, mouse clamp 0..639 / 0..199 ; Tool: PEA queueSize, PEA xMin, PEA xMax, PEA yMin, PEA yMax, PHA userId ; ===================================================================== TBoxEMStartUp: pea 0 ; queueSize = use default pea 0 ; xMin pea 0x27F ; xMax = 639 pea 0 ; yMin pea 0xC7 ; yMax = 199 pha ; userId (still in A from entry) ldx #0x0206 jsl 0xe10000 rtl ; ===================================================================== ; unsigned short TBoxGetNextEvent(u16 eventMask, void *theEvent) ; Entry: A = eventMask, 4,S = theEvent ; Tool: PHA result(word), PHA eventMask, PHA theEvent, JSL X=$0A06 ; ===================================================================== TBoxGetNextEvent: sta 0xe0 ; stash eventMask pea 0 ; result space (16-bit) lda 0xe0 ; eventMask pha lda 8, s ; theEvent (originally 4,S; +4 after pea+pha) pha ldx #0x0A06 jsl 0xe10000 pla ; result → A rtl ; ===================================================================== ; void *TBoxNewWindow(const void *paramList) ; Entry: A = paramList ; Tool: PEA result hi, PEA result lo, PHA paramList, JSL X=$090E ; Returns 32-bit window ptr in A:X (low in A, hi in X). ; ===================================================================== TBoxNewWindow: sta 0xe0 ; stash paramList pea 0 ; result hi pea 0 ; result lo lda 0xe0 ; paramList pha ldx #0x090E jsl 0xe10000 pla ; result lo → A plx ; result hi → X rtl ; ===================================================================== ; void TBoxCloseWindow(void *winPtr) ; Entry: A = winPtr lo, X = winPtr hi ; ===================================================================== TBoxCloseWindow: pha ; winPtr lo phx ; winPtr hi ldx #0x0B0E jsl 0xe10000 rtl