65816-llvm-mos/demos/midiProbe.c
Scott Duensing 3388f3c5a5 More updates
2026-06-03 20:46:31 -05:00

75 lines
3.4 KiB
C

// midiProbe.c - exercise the Note Synth toolset ($19) dispatcher
// path. Verifies the wrapper-to-toolset dispatch round trip:
//
// 1. iigsSoundProbeInit (MMStartUp + SoundStartUp) -- bare prereq.
// 2. NSVersion() -- returns the Note Synth ROM-resident version
// word; works without a prior NSStartUp because
// the toolset is always present.
// 3. NSStatus() -- returns the current toolset state.
// 4. AllNotesOff() -- silent (no audible side effect even if the
// toolset never had a StartUp); pure dispatch.
//
// Why NOT a full NSStartUp + NoteOn + NoteOff sequence? NSStartUp
// takes a pointer to a complex InstrumentT struct (envelope list,
// wave list with topKey/waveAddress/waveSize tuples, etc.). Getting
// the layout exactly right is fiddly and not what this smoke is
// trying to measure. Smoke goal is: "is the Note Synth dispatcher
// callable from llvm816-emitted code, and does the wrapper return
// without scribbling on the stack?" Three round-trip calls answer
// that.
//
// If $70 = 0x42 after this runs, the Note Synth wrapper layer is
// healthy. (Audible playback through NSStartUp / NoteOn / NoteOff
// is exercised when a real app uses it -- not part of THIS smoke.)
//
// Build with: bash demos/build.sh midiProbe
// Run with: bash scripts/runViaFinder.sh demos/midiProbe.omf
// --check 0x70=0x42
#include "iigs/sound.h"
#include "iigs/toolbox.h"
int main(void) {
*(volatile unsigned char *)0x76 = 0xAA; // pre-init alive marker
// Sound Manager must be up before Note Synth dispatch is willing
// to do real work. iigsSoundProbeInit() does MMStartUp +
// SoundStartUp idempotently (it's a no-op if Finder already did
// it).
unsigned short userId = iigsSoundProbeInit();
(void)userId;
*(volatile unsigned char *)0x77 = 0xBB; // post-iigsSoundProbeInit marker
// NSVersion: pre-StartUp call that returns the toolset's ROM
// version word. The toolset is in ROM on every IIgs so this
// always succeeds even if NSStartUp would not. We capture the
// result to a marker so a regression in the wrapper (wrong
// dispatcher ID, missed result pull, etc.) shows up as an
// unexpected $79 byte. $78/$79 = ROM version BCD.
unsigned short ver = NSVersion();
*(volatile unsigned char *)0x78 = (unsigned char)(ver >> 8);
*(volatile unsigned char *)0x79 = (unsigned char)(ver & 0xFF);
*(volatile unsigned char *)0x71 = 0x11; // post-NSVersion marker
// NSStatus: returns the toolset state (0 = uninited, non-zero =
// started). Like NSVersion, no StartUp required to call it.
// The return value isn't fixed (depends on whether Finder /
// earlier code brought it up), so we just check the wrapper
// returns at all.
(void)NSStatus();
*(volatile unsigned char *)0x73 = 0x22; // post-NSStatus marker
// AllNotesOff: side-effect-only dispatch. Silent if the
// toolset was never started; harmless otherwise. Proves a
// 0-arg / 0-result wrapper round-trips cleanly.
AllNotesOff();
*(volatile unsigned char *)0x74 = 0x33; // post-AllNotesOff marker
// Final smoke marker: the full sequence completed.
*(volatile unsigned char *)0x70 = 0x42;
// Linger so the snapshot harness can sample the marker.
for (volatile unsigned long s = 0; s < 600000UL; s++) { }
return 0;
}