/* * 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 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; }