// orcaFrame.c - ORCA-style desktop application. // // Opens a Window Manager window via startdesk()'s full toolset chain, // runs an event loop via TaskMaster until the user clicks the close // box, presses Q, or the watchdog fires. // // Modeled after ORCA-C's Frame.cc / Reversi.cc samples. Exercises // our LLVM/Clang toolchain + the new bank-byte relocation // end-to-end against the real GS/OS 6.0.2 / 6.0.4 Window Manager. // // **Status (2026-05-16):** structurally green. NewWindow with // `fTitle | fVis | fMove | fClose` returns a valid WindowPtr on both // 6.0.2 (sys602.po) and 6.0.4 (tools/gsos/6.0.4 - System.Disk.po). // The headless test reads $00:0071=0xAA confirming NewWindow returned // non-NULL; the $00:0070=0x99 end-marker confirms the demo ran to // completion. Visual rendering of the WM frame is a separate known // issue (see [[orca-window-render-broken]] memory): the SHR plane // stays unpainted between WindStartUp and snapshot — likely a missing // init step in startdesk(), not an fTitle problem. #include "iigs/toolbox.h" #include "iigs/desktop.h" // wFrameBits constants from ORCA's window.h #define fTitle 0x0001 #define fVis 0x0020 #define fMove 0x0080 #define fClose 0x4000 // TaskMaster event codes #define wInGoAway 17 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; typedef struct { unsigned short wmWhat; unsigned long wmMessage; unsigned long wmWhen; short wmWhereV, wmWhereH; unsigned short wmModifiers; unsigned long wmTaskData; unsigned long wmTaskMask; unsigned long wmLastClickTick; unsigned long wmClickCount; unsigned long wmTaskData2; unsigned long wmTaskData3; unsigned long wmTaskData4; } WmTaskRec; static unsigned char gMsg[] = "\x14Hello from llvm816!"; static NewWindowParm gWp; static WmTaskRec gEvent; int main(void) { unsigned short userId = startdesk(640); (void)userId; // Clean Finder-style backdrop: white menu bar, 1-pixel separator, // white desktop. Bypasses the WM dithered fill that MAME's // NTSC simulator renders as colored noise. __asm__ volatile ( "rep #0x30\n" "ldx #0x0000\n" "1:\n" ".byte 0xa9, 0xff, 0xff\n" ".byte 0x9f, 0x00, 0x20, 0xe1\n" "inx\n inx\n" ".byte 0xe0, 0x20, 0x08\n" "bcc 1b\n" "2:\n" ".byte 0xa9, 0x00, 0x00\n" ".byte 0x9f, 0x00, 0x20, 0xe1\n" "inx\n inx\n" ".byte 0xe0, 0xc0, 0x08\n" "bcc 2b\n" "3:\n" ".byte 0xa9, 0xff, 0xff\n" ".byte 0x9f, 0x00, 0x20, 0xe1\n" "inx\n inx\n" ".byte 0xe0, 0x00, 0x7d\n" "bcc 3b\n" ::: "a", "x", "memory"); // Build the NewWindow ParamList: zero everything first, then set // only the fields we care about. { unsigned char *p = (unsigned char *)&gWp; for (unsigned short i = 0; i < sizeof gWp; i++) p[i] = 0; } gWp.paramLength = (unsigned short)sizeof gWp; gWp.wFrameBits = fVis | fMove | fClose; gWp.wTitle = (void *)0; gWp.wMaxHeight = 200; gWp.wMaxWidth = 320; gWp.wPosition.v1 = 40; gWp.wPosition.h1 = 60; gWp.wPosition.v2 = 140; gWp.wPosition.h2 = 580; gWp.wPlane = (void *)-1L; ShowCursor(); void *win = NewWindow(&gWp); if (win) { *(volatile unsigned char *)0x71 = 0xAA; BeginUpdate(win); SetPort(win); MoveTo(20, 30); DrawString(gMsg); EndUpdate(win); } (void)gEvent; for (volatile unsigned long s = 0; s < 300000UL; s++) { } if (win) { CloseWindow(win); } *(volatile unsigned char *)0x70 = 0x99; return 0; }