; iigsGsos.s — INLINE-form GS/OS class-1 wrappers for bare-metal apps.
;
; Real GS/OS 6.0.2 / 6.0.4 at $E100A8 expects the INLINE form:
;   jsl  $E100A8
;   dc.w callNum
;   dc.l pBlockPtr        ; 4 bytes (offset16 + bank8 + pad8)
;   <-- dispatcher returns here (A=error; RTL return PC bumped by +6
;       so it skips the inline operands and lands on the caller's
;       RTL below)
;
; The stack-based form documented at $E100B0 hangs on real hardware
; (and on MAME's GS/OS 6.0.2 boot disk); the inline form is the
; canonical surface ORCA-C / Apple sample code / gnoGsos.s all use.
;
; C ABI: arg0 is a 32-bit pointer to the parm block.  Under the
; W65816 ptr32 ABI that means A holds the low 16 bits (offset) and
; X holds the high 16 bits (bank in the low byte, pad in the high
; byte — always 0).  We forward both into the inline pBlock LONG.
;
; Two parm-block residency cases the wrapper must handle correctly:
;   - .data (static) parm blocks live in the caller's LOAD bank.
;   - Auto (stack) parm blocks live in BANK 0 (the stack is in $00).
; Using X = caller-supplied bank from the ptr32 ABI handles both:
; the C compiler emits `&op` for a stack `op` as ptr32 = (offset16:0,
; bank8=0), and `&staticParm` as (offset16:LoadBank, pad8=0).  Either
; way the wrapper's TXA picks up the right bank.  See gnoGsos.s for
; the equivalent pattern under GNO's interceptor.
;
; The Phase 1.1 fix that paired with this wrapper rewrite was a
; link816 cRELOC-on-DATA32 path (W65816 .long path in .data/.rodata
; now generates a 24-bit Loader-time bank fixup) -- without it the
; static-init pattern (parm.pathname = &staticGSString;) leaves the
; pathname pointer's bank=0 at runtime, GS/OS Open dereferences
; bank0:offset, hits junk, and returns $40 (invalidAccess).  Both
; halves are required for Phase 1.1 fopen-via-GS/OS to land.
;
; STRUCTURE per wrapper:
;   1. STA <pbPatch>         ; offset (low 16, from A)
;   2. SEP #$20              ; M=8 for byte-level bank store
;   3. TXA / STA <pbPatch>+2 ; bank (from X.low; X.high=0=pad stays 0)
;   4. REP #$20              ; M=16 again
;   5. JSL $E100A8
;   6. .word callNum         ; 2-byte inline operand
;   7. .long 0               ; 4-byte inline pBlock ptr (patched per call)
;     <-- dispatcher returns here
;   8. RTL                   ; return to C caller with A = GS/OS err

	.text
	.globl gsosOpen
	.globl gsosRead
	.globl gsosWrite
	.globl gsosClose
	.globl gsosGetEOF
	.globl gsosSetEOF
	.globl gsosSetMark
	.globl gsosGetMark
	.globl gsosDestroy
	.globl gsosChangePath
	.globl gsosGetPrefix
	.globl gsosGetFileInfo
	.globl gsosGetDirEntry
	.globl gsosCreate
	.globl gsosVolume
	.globl gsosGetDevNumber
	.globl gsosDInfo

; __gsosIsRealImpl — sentinel that distinguishes a REAL GS/OS dispatch
; surface from the universal-success stub in iigsGsosStub.s.  Both
; files define the symbol so the C-side accessor (__gsosAvailable in
; libc.c) can branch honestly: 1 = real wrappers linked, 0 = stub
; bytes only.  Lets newly-added GS/OS wrappers refuse to lie about
; succeeding when the dispatcher is the stub.
	.globl __gsosIsRealImpl
__gsosIsRealImpl:
	.word 1

; Macro: emit a uniform inline-form dispatch shim for one class-1 call.
; Caller passes the ptr32 to the parm block in A:X (A=offset, X=bank).
; The macro generates a unique pbLabel-suffixed `.long 0` slot whose
; low 24 bits get patched by the prologue, leaving the pad byte at 0.
	.macro gsosDispatch callNum, pbLabel
	; The two `sta \pbLabel` stores self-modify the INLINE pBlock slot
	; below, which lives in THIS wrapper's code bank (PBR). They must
	; target PBR, not DBR (the caller's data/globals bank): under multi-
	; segment this wrapper can land in seg2 while DBR=seg1, so a DBR-
	; relative store would patch the wrong bank, leaving the inline
	; `.long 0` unpatched -> GS/OS dispatches on a null pBlock. phb saves
	; the caller DBR; phk/plb sets DBR:=PBR for the patch; the final plb
	; restores the caller DBR before the dispatch. A (offset) and X (bank)
	; are untouched by phb/phk/plb. Stack is balanced before the jsl.
	phb
	phk
	plb
	sta \pbLabel
	sep #0x20
	txa
	sta \pbLabel+2
	rep #0x20
	plb
	jsl 0xe100a8
	.word \callNum
\pbLabel:
	.long 0
	rtl
	.endm

gsosCreate:
	gsosDispatch 0x2001, __gsosCreatePb

gsosVolume:
	gsosDispatch 0x2008, __gsosVolumePb

gsosGetDevNumber:
	gsosDispatch 0x2020, __gsosGetDevNumberPb

gsosDInfo:
	gsosDispatch 0x202c, __gsosDInfoPb

gsosOpen:
	gsosDispatch 0x2010, __gsosOpenPb

gsosRead:
	gsosDispatch 0x2012, __gsosReadPb

gsosWrite:
	gsosDispatch 0x2013, __gsosWritePb

gsosClose:
	gsosDispatch 0x2014, __gsosClosePb

gsosGetEOF:
	gsosDispatch 0x2019, __gsosGetEofPb

gsosSetEOF:
	gsosDispatch 0x2018, __gsosSetEofPb

gsosSetMark:
	gsosDispatch 0x2016, __gsosSetMarkPb

gsosGetMark:
	gsosDispatch 0x2017, __gsosGetMarkPb

gsosDestroy:
	gsosDispatch 0x2002, __gsosDestroyPb

gsosChangePath:
	gsosDispatch 0x2004, __gsosChangePathPb

gsosGetPrefix:
	gsosDispatch 0x200a, __gsosGetPrefixPb

gsosGetFileInfo:
	gsosDispatch 0x2006, __gsosGetFileInfoPb

gsosGetDirEntry:
	gsosDispatch 0x201c, __gsosGetDirEntryPb
