// stdFile.c - exercise the Standard File toolset ($17) dispatcher // path. Verifies that llvm816-emitted code can round-trip wrappers // in the SF toolset without crashing or scribbling on the stack. // // runViaFinder.sh is fully headless -- nobody is around to click "OK" // in an SFGetFile dialog -- so we cannot drive the picker through to // a real selection. Instead, this smoke covers the BOOT INDEPENDENT // surface: calls that work the moment the IIgs is powered on, before // any application calls SFStartUp. // // Specifically: // 1. SFVersion() -- returns ROM-resident version word. No // StartUp required. // 2. SFStatus() -- returns 0/non-zero "is started" boolean. // 3. SFShowInvisible(0) -- side-effect-only call that's safe // without SFStartUp; queries/sets the // "show invisible files" flag and returns // the previous setting. // // Plus we DO bring up the full desktop (startdesk: QD + WM + ...) // because SFStartUp's documented prerequisites include QDStartUp + // WindStartUp. Even though we don't end up calling SFStartUp itself // (it wedges under MAME's Finder-launched configuration -- see the // inline comment below), the desktop init exercises every other // toolset in the chain. // // If $70 = 0x42 after this runs, the SF wrapper layer is healthy. // (Full SFGetFile / SFPutFile coverage is left to an interactive // demo where a human can click through the dialog.) // // Build with: bash demos/build.sh stdFile // Run with: bash scripts/runViaFinder.sh demos/stdFile.omf // --check 0x70=0x42 #include "iigs/desktop.h" #include "iigs/toolbox.h" // SFReplyRec layout (ORCA stdfile.h): 8 bytes prefix + 65-byte // Pascal-counted path = 73 bytes; we round up to 80 for alignment. // Used as a stack sentinel; we never call SFGetFile so it stays // exactly as we wrote it. typedef struct { unsigned short good; unsigned short fileType; unsigned long auxType; unsigned char fileName[65]; unsigned char pad; } SFReplyRecT; int main(void) { *(volatile unsigned char *)0x76 = 0xAA; // pre-init alive marker // Bring up the full desktop so QDStartUp + WindStartUp are done. // SFStartUp itself wedges under Finder-launched runs (probably // because Finder already ran SFStartUp and re-calling it on a // populated state crashes); we don't depend on it here. The // startdesk() call still exercises every toolset in its chain. unsigned short userId = startdesk(640); (void)userId; *(volatile unsigned char *)0x77 = 0xBB; // post-startdesk marker // SFVersion() - returns the Standard File toolset's ROM version // word. No SFStartUp required (the toolset is always in ROM). // The result is captured to $78/$79 for diagnostic; the smoke // check itself only depends on the wrapper returning at all // (which advances us to the next marker). unsigned short ver = SFVersion(); *(volatile unsigned char *)0x78 = (unsigned char)(ver >> 8); *(volatile unsigned char *)0x79 = (unsigned char)(ver & 0xFF); *(volatile unsigned char *)0x71 = 0x11; // post-SFVersion marker // SFStatus() - returns the toolset's current state (0 = not // started by us, non-zero = started). Pure dispatch, no args, // returns Boolean. Exercises the result-pull arm of the // wrapper layer. (void)SFStatus(); *(volatile unsigned char *)0x72 = 0x22; // post-SFStatus marker // SFShowInvisible(state) - sets the "show invisible files" // flag and returns the previous setting. Safe pre-StartUp // (the toolset just toggles a global). Exercises a (Word) -> // Word wrapper round-trip. unsigned short prev = SFShowInvisible(0); *(volatile unsigned char *)0x73 = 0x33; // post-SFShowInvisible marker (void)prev; // Build a sentinel reply record on the stack. Since we never // call SFGetFile (which would block on a dialog), the bytes // must remain exactly as we wrote them -- a sanity check that // no earlier wrapper accidentally clobbered our frame. SFReplyRecT reply; unsigned char *r8 = (unsigned char *)&reply; for (int i = 0; i < (int)sizeof(reply); i++) { r8[i] = 0x5C; } int replySane = 1; for (int i = 0; i < (int)sizeof(reply); i++) { if (r8[i] != 0x5C) { replySane = 0; break; } } *(volatile unsigned char *)0x74 = 0x44; // post-sentinel marker if (replySane) { *(volatile unsigned char *)0x70 = 0x42; } else { *(volatile unsigned char *)0x70 = 0x43; } // Linger so the snapshot harness can sample the marker. for (volatile unsigned long s = 0; s < 600000UL; s++) { } return 0; }