/* * bank_read_page — прочитать из УЖЕ ОТКРЫТОГО файла прямо в EMM-страницу. * * Зачем отдельно от bank_load_file: та открывает и закрывает файл на каждый * вызов, а `open` на Sprinter стоит дорого — замер в MAME (PoP, 2026-08-25): * open 51,4 мс против 32,6 мс на чтение 16 КБ, то есть 61 % времени уходит * на открытие. Кто читает из одного файла несколько кусков (архив ресурсов, * поток музыки), обязан держать fd открытым — тогда эта цена платится раз. * * ESTEX принимает файловый буфер только в W1..W3; используем W3, сохраняя и * восстанавливая раскладку. Функция резидентна, поэтому её безопасно * вызывать из банкового кода huge: пока W3 занят целевой страницей, никакой * памяти вызывающего мы не читаем. Позицию в файле вызывающий ставит сам * (lseek) — здесь только перенос. * * Возврат: фактически прочитанный размер либо -1 + errno. */ #include #include #include #include int bank_read_page(int fd, uint8_t phys_page, uint16_t off, uint16_t size) { uint8_t saved; int n; if (off > 0x3FFFu || size > (uint16_t)(0x4000u - off)) { errno = EINVAL; return -1; } saved = _io_page_w3; sprinter_page_w3(phys_page); n = read(fd, (void *)(0xC000u + off), size); sprinter_page_w3(saved); return n; }