65816-llvm-mos/runtime/include/iigs/toolbox.h
Scott Duensing 6d7eae0356 Checkpoint.
2026-04-30 01:29:16 -05:00

112 lines
3.5 KiB
C

// IIgs toolbox helpers — minimal inline-asm wrappers for the most
// commonly-used Apple IIgs system calls.
//
// Toolbox dispatch on the IIgs goes through the Tool Locator at
// $E10000. Each routine is identified by a 16-bit "tool number"
// (low byte = tool set, high byte = function within set), loaded
// into X, and called via JSL $E10000.
//
// Args go on the stack (push order: rightmost first), then the
// caller pushes a result-space slot if the routine returns something
// non-i16-or-pointer, then JSL.
//
// This header keeps things simple: each function inlines a tiny
// asm block specific to that call. No #include guards on bigger
// abstractions; users that want full toolbox coverage should write
// their own wrappers using the same pattern.
//
// LIMITATIONS:
// - Only a handful of routines wrapped. Calypsi has full toolbox.
// - No error-handling — caller checks the return.
// - Single-bank only. Cross-bank toolbox calls need different
// dispatch logic.
#ifndef IIGS_TOOLBOX_H
#define IIGS_TOOLBOX_H
#ifdef __cplusplus
extern "C" {
#endif
// Tool number convention: high byte = function, low byte = tool set.
// Common tool sets: 04 = Misc, 0E = QuickDraw II, 18 = Window Mgr.
// Misc Tool Set ---------------------------------------------------
// WriteCString (Misc Tool $290B) — write a NUL-terminated string to
// the text screen. Arg: 16-bit pointer pushed before the call.
// Returns nothing.
static inline void TBoxWriteCString(const char *s) {
__asm__ volatile (
"pha\n" // push C-string pointer
"ldx #0x290B\n" // tool number (function 0x29, set 0x0B)
"jsl 0xe10000\n" // tool dispatcher
:
: "a"(s)
: "x", "y", "memory"
);
}
// SysBeep (Misc Tool $0303) — short beep through the speaker.
static inline void TBoxBeep(void) {
__asm__ volatile (
"ldx #0x0303\n"
"jsl 0xe10000\n"
:
:
: "x", "y", "memory"
);
}
// ReadKey (Event Mgr; simplified — actually KeyTrans/etc). Returns
// the next pending key in A, or 0 if none. This wraps GetNextEvent
// internally on a real GS; for the simple console harness it polls
// the keyboard buffer.
static inline char TBoxReadKey(void) {
char r;
__asm__ volatile (
"ldx #0x250A\n" // GetEvent (placeholder; refine in real port)
"jsl 0xe10000\n"
: "=a"(r)
:
: "x", "y", "memory"
);
return r;
}
// ConsoleQuit — clean program shutdown via GS/OS Quit. Pushes a
// pConditionTbl pointer (here, 0 for no condition) before JSL.
static inline void TBoxQuit(void) {
__asm__ volatile (
"pea 0\n" // pConditionTbl = NULL
"pea 0\n" // pParm
"ldx #0x2029\n" // GS/OS Quit
"jsl 0xe100a8\n" // GS/OS dispatcher (different addr)
:
:
: "x", "y", "memory"
);
while (1) {} // unreachable
}
// QuickDraw II ----------------------------------------------------
// QDStartUp / QDShutDown (sketches — real ones take more args).
// Real apps typically use QuickDraw II via the "shell" startup
// sequence; this is for educational/sim scenarios.
static inline void TBoxQDStartUp(void) {
__asm__ volatile (
"pea 0\n" "pea 0\n" "pea 0\n" // dummy direct-page handle
"ldx #0x0204\n"
"jsl 0xe10000\n"
:
:
: "x", "y", "memory"
);
}
#ifdef __cplusplus
}
#endif
#endif // IIGS_TOOLBOX_H