// helloWindow.c - GS/OS app that opens a Window Manager window and // draws a greeting in it. Runs under real GS/OS 6.0.2 in MAME. // // What this exercises: // - The full Window Manager StartUp chain (Memory + QD + Event + // Scheduler + Window). // - NewWindow ParamList with paramLength = sizeof (ORCA Clock.cc / // Reversi.cc convention). // - SetPort / ShowWindow / MoveTo / DrawString round-trip. // - Event-driven keypress wait via GetNextEvent. // - The W65816 backend's bank-byte relocation: // `gWp.wTitle = gTitle` stores a 32-bit pointer where the bank // byte is materialized via the new LDAi16imm_bank pseudo // (lowered to `lda $BE` reading PBR from a crt0-set DP slot). // Toolbox calls now receive correct `bank:offset` pointers for // any `&global` argument — no wrapper-side workarounds needed. // // Why fTitle is NOT set in wFrameBits despite wTitle being valid: // The Window Manager hangs trying to render a titled window without // Font Manager initialization. A "real" titled-window demo would // need to drive QDStartUp's font allocation and possibly start the // Font Manager (FMStartUp) — that's the next milestone. #include "iigs/toolbox.h" #define fVis 0x0020 #define fMove 0x0080 #define fZoom 0x0100 #define fGrow 0x0400 #define fClose 0x4000 #define fTitle 0x8000 typedef struct { short v1, h1, v2, h2; } Rect; typedef struct { unsigned short paramLength; unsigned short wFrameBits; void *wTitle; unsigned long wRefCon; Rect wZoom; void *wColor; short wYOrigin, wXOrigin; short wDataH, wDataV; short wMaxHeight, wMaxWidth; short wScrollVer, wScrollHor; short wPageVer, wPageHor; unsigned long wInfoRefCon; short wInfoHeight; void *wFrameDefProc; void *wInfoDefProc; void *wContDefProc; Rect wPosition; void *wPlane; void *wStorage; } NewWindowParm; // Pascal strings: leading length byte, then characters. static unsigned char gTitle[] = "\x09llvm816!!"; static unsigned char gMsg[] = "\x14Hello from llvm816!"; // ParamList in BSS so the bank byte of &gWp resolves to PBR via the // new LDAi16imm_bank reloc path. static NewWindowParm gWp; static unsigned short blockAddr(void *handle) { return (unsigned short)(unsigned long)*(void **)handle; } int main(void) { unsigned short userId = MMStartUp(); void *dpH = NewHandle(0x900UL, userId, 0xC005, (void *)0); unsigned short dpBase = blockAddr(dpH); QDStartUp(dpBase, 0, 0xA0, userId); EMStartUp((unsigned short)(dpBase + 0x100), 0x14, 0, 0, 0x14F, 0xC7, userId); SchStartUp(); WindStartUp(userId); // Zero the parm block, then set only the fields we want non-zero. { unsigned char *p = (unsigned char *)&gWp; for (unsigned short i = 0; i < sizeof gWp; i++) { p[i] = 0; } } gWp.paramLength = (unsigned short)sizeof gWp; // fVis+fMove only — fTitle requires Font Manager startup (FMStartUp // with proper DP allocation) which is a TODO for the full ORCA- // style desktop init. wTitle is still set to prove the new // R_W65816_BANK16 reloc produces the correct bank byte at runtime // (even though WM doesn't dereference it without fTitle). gWp.wFrameBits = fVis | fMove; gWp.wTitle = gTitle; gWp.wMaxHeight = 200; gWp.wMaxWidth = 320; gWp.wPosition.v1 = 40; gWp.wPosition.h1 = 30; gWp.wPosition.v2 = 140; gWp.wPosition.h2 = 290; gWp.wPlane = (void *)-1L; void *win = NewWindow(&gWp); if (win) { SetPort(win); ShowWindow(win); MoveTo(20, 30); DrawString(gMsg); } // Brief visible linger before checking events (so snapshot demos can // capture the window). Then wait for a real keypress. for (volatile unsigned long s = 0; s < 400000UL; s++) { } short evt[8]; while (1) { if (GetNextEvent(0xFFFF, evt)) { break; } } SysBeep(); *(volatile unsigned char *)0x70 = 0x99; return 0; }