/*
 * ffirst / fnext — directory iteration via ESTEX $19 / $1A.
 *
 *   ESTEX F_FIRST  ($19):
 *     HL = pattern, DE = buffer, A = attribute mask, B = format (0/1)
 *     CF = err / A = error code
 *   ESTEX F_NEXT   ($1A):
 *     DE = same buffer
 *     CF = err / A = error code
 *
 *   We always use format B=1 — 256-byte buffer with NUL-terminated DOS
 *   "name.ext" name at offset 33.
 *
 *   ABI note: ffirst takes uint8_t as its 3rd arg.  SDCC pushes a *single*
 *   byte for that (via `push af; inc sp`), not two — so the callee must
 *   pop ret-addr (2 bytes) AND consume the attr byte (`inc sp`) on the way
 *   out.  Naively `pop bc` would over-eat into the caller's frame.
 */

#include <dir.h>

int ffirst(const char *pattern, ffblk_t *buf, uint8_t attrib) __naked
{
    (void)pattern; (void)buf; (void)attrib;
    __asm
        ;; On entry: HL = pattern, DE = buf, [SP+0..1] = ret, [SP+2] = attr.
        ld    iy, #2
        add   iy, sp
        ld    a, 0 (iy)         ; A = attr (read without disturbing SP)

        push  ix
        ld    bc, #0x0119       ; ESTEX F_FIRST; format: 1 = DOS "name.ext" layout
        rst   #0x10
        pop   ix

        pop   hl                ; HL = return address
        inc   sp                ; consume the 1-byte attr

        jr    c, _ff_err
        ld    de, #0
        jp    (hl)

    _ff_err:
        call  __errno_set
        ld    de, #-1
        jp    (hl)
    __endasm;
}

int fnext(ffblk_t *buf) __naked
{
    (void)buf;
    __asm
        ;; HL = buf on entry; ESTEX F_NEXT wants buf in DE.
        push  ix
        ex    de, hl
        ld    c, #0x1A          ; ESTEX F_NEXT
        rst   #0x10
        pop   ix
        jr    c, _fnext_err
        ld    de, #0
        ret
    _fnext_err:
        call  __errno_set
        ld    de, #-1
        ret
    __endasm;
}
