// cursorProbe.c - Phase 2.5 cursor-helpers smoke harness.
//
// Brings up the full desktop tool chain via startdesk() so that
// InitCursor() (the Cursor Mgr invariant the iigsCursorPush/Pop
// routines require) has been satisfied, then exercises the push/pop
// stack with both ROM shapes (busy/arrow) and an explicit Register
// of the originally-installed cursor.  Marker progression:
//
//   $70 = 0x10 after startdesk()'s InitCursor()           - sanity
//   $70 = 0x20 after iigsCursorPushBusy() returned 0
//   $70 = 0x30 after iigsCursorPushArrow() returned 0
//   $70 = 0x40 after iigsCursorPop() returned 0
//   $70 = 0x50 after iigsCursorPop() returned 0 (back to original)
//   $70 = 0x99 at end-of-main (all helpers green)
//
// A hang or stack imbalance in any push/pop wrapper would prevent the
// final marker.  An assertion path (NULL save buffer / overflow /
// underflow) trips a return code != 0 and we set 0xFE instead, so the
// harness can distinguish "ran but bad rc" from "hung".
//
// Build with: bash demos/build.sh cursorProbe
// Run with:   bash scripts/runViaFinder.sh demos/cursorProbe.omf \
//                  --check 0x70=0x99

#include "iigs/desktop.h"
#include "iigs/cursor.h"
#include "iigs/toolbox.h"


int main(void) {
    unsigned short userId = startdesk(640);
    (void)userId;

    volatile unsigned char *marker = (volatile unsigned char *)0x70;
    *marker = 0x10;

    // GetCursorAdr() must return non-NULL after startdesk() ran
    // InitCursor(); register that pointer as the registered fallback
    // so an underflow Pop has somewhere to land.  Note: registering
    // the live ROM cursor pointer (not a copy) is intentional - this
    // is the fallback, not a saved snapshot, and the ROM shape lives
    // at a fixed address in $E1 ROM bank.
    void *initial = GetCursorAdr();
    if (initial) {
        iigsCursorRegister((const IigsCursorT *)initial);
    }

    // Push busy.  The ROM wristwatch should now be the active cursor.
    if (iigsCursorPushBusy() != 0) {
        *marker = 0xFE;
        goto done;
    }
    *marker = 0x20;

    // Push arrow on top of busy.  InitCursor() reinstalls the ROM
    // arrow shape and stacks the busy underneath.
    if (iigsCursorPushArrow() != 0) {
        *marker = 0xFE;
        goto done;
    }
    *marker = 0x30;

    // Pop -> busy active again.
    if (iigsCursorPop() != 0) {
        *marker = 0xFE;
        goto done;
    }
    *marker = 0x40;

    // Pop -> originally-installed cursor active again.
    if (iigsCursorPop() != 0) {
        *marker = 0xFE;
        goto done;
    }
    *marker = 0x50;

    // All helpers green; final success marker.
    *marker = 0x99;

done:
    // Give the headless harness a window to snapshot the marker
    // before falling out of main into crt0's tear-down.
    for (volatile unsigned long s = 0; s < 200000UL; s++) { }

    return 0;
}
