// sound.c - implementation of iigs/sound.h.  Thin wrappers around
// the SoundManager toolset.  See header for what's intentionally not
// here.
//
// Phase 1.6 (2026-06-01) rewrote iigsPlayDocSample to populate the
// corrected 18-byte IigsSoundParmT struct (was a silently-broken
// 6-byte layout).  Channel moved out of the struct into FFStartSound's
// arg0 (gen-number/priority Word).
//
// Phase 2.4 (2026-06-01) added iigsLoadDocSample (WriteRamBlock
// wrapper) and the iigsSoundProbeInit/Shutdown pair so CLI-style
// sound demos don't have to pull in startdesk()'s full tool chain.
#include "iigs/sound.h"
#include "iigs/toolbox.h"


void iigsBeep(void) {
    SysBeep();
}


void iigsLoadDocSample(const signed char *wave, uint16_t size, uint16_t docOffset) {
    // WriteRamBlock signature is (Pointer source, Word byteCount,
    // Word docDestAddr) per Apple SoundManager / ORCA's
    // sound.h:114 inline(0x0908,dispatcher).  The C wrapper in
    // iigsToolbox.s forwards args 1-to-1.  Cast away const because the
    // toolbox stub takes a non-const void *; WriteRamBlock only reads.
    WriteRamBlock((void *)wave, size, docOffset);
}


void iigsPlayDocSample(void *docAddr, uint16_t pages,
                       uint16_t freqOffset, uint8_t volume,
                       uint16_t genNum) {
    // Static so the parm block survives past return - FFStartSound is
    // asynchronous and the SoundManager keeps the pointer until the
    // sample completes.  Single-sample model; for chained waves the
    // caller should manage its own SoundParamBlock storage.
    static IigsSoundParmT parm;
    parm.waveStart   = docAddr;
    parm.waveSize    = pages;
    parm.freqOffset  = freqOffset;
    parm.docBuffer   = 0;
    parm.bufferSize  = 0;
    parm.nextWavePtr = (struct IigsSoundParmT *)0;
    parm.volSetting  = (uint16_t)volume;  // high byte must be zero
    FFStartSound(genNum, &parm);
}


unsigned short iigsSoundProbeInit(void) {
    // MMStartUp returns the caller's userId.  The toolset
    // reference-counts startups; if Finder already brought it up,
    // this is a cheap no-op-with-existing-id.
    unsigned short userId = MMStartUp();
    SoundStartUp(userId);
    return userId;
}


void iigsSoundProbeShutdown(void) {
    SoundShutDown();
}


void iigsSoundStop(uint8_t generator) {
    FFStopSound((uint16_t)generator);
}


void iigsSoundWait(void) {
    while (FFSoundDoneStatus(0) == 0) {
        // spin until generator 0 reports idle
    }
}
