/* * bank1_enum.c — отделяет влияние адреса ffblk от переключений W3. * * Весь перебор исполняется при подключённом BANK1, а диагностический DTA * занимает последние 256 байт W1. Это историческая матрица, доказавшая, * что ни адрес DTA, ни чтение/запись W3 не снимают предел DSS. mode=0 не * трогает W3, mode=1 читает байт EMM, mode=2 пишет 24 байта EMM. */ #include #include #include #include #define FIND_ATTRS (FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_DIREC | FA_ARCH) __at (0x7F00) static ffblk_t find_buf; /* Копии wrapper находятся в том же W1, что и цикл. Так проверяется не * только адрес ffblk, но и адрес самой инструкции RST/возврата из DSS. */ static int p3_ffirst_local(const char *pattern, ffblk_t *buf, uint8_t attrib) __naked { (void)pattern; (void)buf; (void)attrib; __asm ld iy, #2 add iy, sp ld a, 0 (iy) push ix ld bc, #0x0119 rst #0x10 pop ix pop hl inc sp jr c, p3_ffirst_fail$ ld de, #0 jp (hl) p3_ffirst_fail$: call __errno_set ld de, #-1 jp (hl) __endasm; } static int p3_fnext_local(ffblk_t *buf) __naked { (void)buf; __asm push ix ex de, hl ld c, #0x1A rst #0x10 pop ix jr c, p3_fnext_fail$ ld de, #0 ret p3_fnext_fail$: call __errno_set ld de, #-1 ret __endasm; } uint16_t p3_enum_mode(uint8_t mode, uint8_t page, int *end_errno) __banked { uint16_t count = 0u; uint8_t payload[24]; uint16_t offset; errno = 0; if ((mode >= 3u ? p3_ffirst_local("*.*", &find_buf, FIND_ATTRS) : ffirst("*.*", &find_buf, FIND_ATTRS)) == 0) { for (;;) { count++; if (mode == 1u) { payload[0] = bank_load_byte(page, 0u); } else if (mode == 2u || mode == 4u) { offset = (uint16_t)(((count - 1u) % 640u) * 24u); bank_write(page, offset, payload, 24u); } errno = 0; if ((mode >= 3u ? p3_fnext_local(&find_buf) : fnext(&find_buf)) != 0) break; if (count == 2000u) break; } } *end_errno = errno; return count; }