223 lines
7.3 KiB
ArmAsm
223 lines
7.3 KiB
ArmAsm
; 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
|