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

149 lines
4.7 KiB
C

// minicad.c - port of ORCA-C's MiniCAD.cc sample.
//
// MiniCAD is a tiny drawing program: each click in the content area
// creates a new line in the current window's line list. In the
// original you click to set the anchor, drag to draw a rubber-band
// line, release to commit. We seed three classic line-art patterns
// (curve-stitching, sunburst, mandala) instead of waiting for clicks
// because our minimal Event Manager doesn't have a working
// GetNextEvent path for mouse-drag tracking, but the data model and
// rendering pipeline match MiniCAD.cc verbatim.
#include "iigs/toolbox.h"
#include "iigs/desktop.h"
#define wInContent 19
#define fVis 0x0020
#define fMove 0x0080
#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 { short v1, h1, v2, h2; } LineRec;
static unsigned char gTitle[] = "\x07MiniCAD";
// Menu bar titles painted manually (DrawMenuBar hangs in our env).
static const unsigned char appleTitle[] = "\x01\x14";
static const unsigned char fileTitle[] = "\x04" "File";
static const unsigned char editTitle[] = "\x04" "Edit";
static const unsigned char optsTitle[] = "\x07" "Options";
static const unsigned char *const menuTitles[] = {
appleTitle, fileTitle, editTitle, optsTitle
};
static NewWindowParm gWp;
// Draw a curve-stitching pattern: 12 chord lines mapping the y-axis
// to a curve along the x-axis. Visually it traces a hyperbolic
// envelope (the classic "string art" pattern).
static void drawCurves(short ox, short oy) {
for (short i = 0; i < 12; i++) {
MoveTo((short)(ox + 0), (short)(oy + i * 6));
LineTo((short)(ox + 90 - i * 5), (short)(oy + 70 - i * 5));
}
}
// Draw a sunburst: 12 radial lines from a central point.
static void drawSunburst(short cx, short cy, short r) {
// Pre-computed cos/sin for 12 equally-spaced angles (every 30
// degrees), scaled by 1000. Avoids any float math.
static const short cosA[12] = { 1000, 866, 500, 0, -500, -866, -1000, -866, -500, 0, 500, 866 };
static const short sinA[12] = { 0, 500, 866, 1000, 866, 500, 0, -500, -866, -1000, -866, -500 };
for (short i = 0; i < 12; i++) {
short dx = (short)((long)cosA[i] * r / 1000);
short dy = (short)((long)sinA[i] * r / 1000);
MoveTo((short)(cx - dx), (short)(cy - dy));
LineTo((short)(cx + dx), (short)(cy + dy));
}
}
// Draw a mandala: 6-pointed star made of two overlapping triangles.
static void drawMandala(short cx, short cy, short r) {
short h = (short)((long)r * 866L / 1000L);
short h2 = (short)(r / 2);
// First triangle (point up).
MoveTo(cx, (short)(cy - r));
LineTo((short)(cx + h), (short)(cy + h2));
LineTo((short)(cx - h), (short)(cy + h2));
LineTo(cx, (short)(cy - r));
// Second triangle (point down).
MoveTo(cx, (short)(cy + r));
LineTo((short)(cx + h), (short)(cy - h2));
LineTo((short)(cx - h), (short)(cy - h2));
LineTo(cx, (short)(cy + r));
}
int main(void) {
unsigned short userId = startdesk(640);
(void)userId;
paintDesktopBackdrop();
paintMenuBarTitles(menuTitles, 4);
ShowCursor();
// Open the 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 = 30;
gWp.wPosition.v2 = 180; gWp.wPosition.h2 = 610;
gWp.wPlane = (void *)-1L;
void *win = NewWindow(&gWp);
if (win) {
BeginUpdate(win);
SetPort(win);
SetSolidPenPat(0);
// Three patterns laid out horizontally.
drawCurves(20, 30);
drawSunburst(280, 75, 50);
drawMandala(450, 75, 50);
EndUpdate(win);
}
for (volatile unsigned long s = 0; s < 400000UL; s++) { }
if (win) {
CloseWindow(win);
}
*(volatile unsigned char *)0x70 = 0x99;
return 0;
}