116 lines
4.7 KiB
C
116 lines
4.7 KiB
C
// 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;
|
|
}
|