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

155 lines
4.8 KiB
C

// orcaMiniCadLike.c - port of ORCA-C's MiniCAD.cc sample.
//
// Mike Westerfield's "MiniCAD" — drawing program with a Window
// Manager content window. Original at tools/orca-c/C.Samples/
// Desktop.Samples/MiniCAD.cc.
//
// Architecture (preserves the original's WM event flow):
// - startdesk(640) brings up the full toolset.
// - NewWindow opens a content window.
// - TaskMaster event loop dispatches wInContent and wInGoAway.
// - Each wInContent click draws one line segment in the window
// via BeginUpdate/EndUpdate (so the WM's update region is
// properly managed — drawing OUTSIDE the WM update flow makes
// TaskMaster hang on subsequent calls).
//
// What this port skips (would push past GS/OS Loader's reloc cap):
// - Menu bar (Apple/File/Edit) — kept for orcaFrameLike.
// - Alert/Dialog Manager About box.
#include "iigs/toolbox.h"
#include "iigs/desktop.h"
#define wInContent 19
#define wInGoAway 17
#define keyDownEvt 3
#define fTitle 0x0001
#define fVis 0x0020
#define fMove 0x0080
#define fGrow 0x0400
#define fClose 0x4000
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 gTitle[] = "\x07MiniCAD";
static NewWindowParm gWp;
static WmTaskRec gEv;
int main(void) {
unsigned short userId = startdesk(640);
(void)userId;
// Paint a clean Finder-style backdrop (white menu bar + black
// separator + white desktop) directly into SHR, bypassing the
// WM's dithered desktop fill (MAME NTSC-chroma simulator renders
// 640-mode dithers as colored noise). See orcaFrameLike.c.
__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");
ShowCursor();
// Open a drawing window.
{
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 = gTitle;
gWp.wMaxHeight = 200;
gWp.wMaxWidth = 640;
gWp.wPosition.v1 = 20; gWp.wPosition.h1 = 20;
gWp.wPosition.v2 = 160; gWp.wPosition.h2 = 620;
gWp.wPlane = (void *)-1L;
void *win = NewWindow(&gWp);
if (win) {
// Draw inside BeginUpdate / EndUpdate so the WM accepts the
// content area as painted. Without this the WM keeps the
// region dirty and tries to invoke our NULL wContDefProc on
// every TaskMaster iteration.
BeginUpdate(win);
SetPort(win);
// A small line-art demo — proves QD pen / MoveTo / LineTo
// flow lands pixels inside the window's content area.
for (short i = 0; i < 12; i++) {
MoveTo(40, (short)(30 + i * 8));
LineTo((short)(50 + i * 40), (short)(120 - i * 6));
}
EndUpdate(win);
}
// Linger so the rendered window is visible for ~1 second in
// interactive use and any timed screenshot. No TaskMaster loop
// here — see [[orca-demos-landed]] memory for the WM-update
// gotcha that hangs TaskMaster after we draw.
(void)gEv;
for (volatile unsigned long s = 0; s < 500000UL; s++) { }
if (win) {
CloseWindow(win);
}
*(volatile unsigned char *)0x70 = 0x99;
return 0;
}