65816-llvm-mos/demos/orcaFrame.c
2026-05-18 14:43:35 -05:00

147 lines
4.3 KiB
C

// 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;
}