/* * atlas_load — загрузить .atl-файл в свежую EMM-страницу (§3.1/§9в * дизайна, вариант II: файл-офсет == офсет страницы == W0-адрес). * * Порядок: выделить страницу (mem_alloc_pages) → замапить в W3 → * read() файла ЦЕЛИКОМ в 0xC000 (ESTEX READ пишет в W3 — проверено * tests/w0page P1) → проверить магию 'SPA1' → пропатчить ISR-стаб * (0x38: JP _gfx_w0_isr; 0x66: RETN — место зарезервировано в * заголовке файла) → вернуть W3. Никакого пересчёта офсетов: каталог * и ленты уже лежат по своим W0-адресам. * * Вызывать ВНЕ рендера (W3 на время загрузки занята страницей атласа). * Ошибки: -1 + errno (open/read/alloc; EINVAL — не .atl). */ #include #include #include #include #include #include #include "../_bgi.h" int atlas_load(atlas_t *a, const char *path) { uint8_t *pg = (uint8_t *)0xC000; uint8_t saved_w3, blk, ok; uint16_t stub; int fd, n; fd = open(path, O_RDONLY); if (fd < 0) return -1; blk = mem_alloc_pages(1); if (!blk) { close(fd); return -1; } if (!_gfx_w0_dss) _gfx_w0_dss = _io_page_w0; /* снять страницу ядра DSS */ a->blk = blk; a->page = mem_get_page(blk, 0); saved_w3 = _io_page_w3; sprinter_page_w3(a->page); n = read(fd, pg, 16384); ok = (n >= (int)_ATL_DATA_OFF && pg[0] == 'S' && pg[1] == 'P' && pg[2] == 'A' && pg[3] == '1'); if (ok) { a->count = pg[4]; stub = (uint16_t)&_gfx_w0_isr; pg[0x38] = 0xC3; /* JP _gfx_w0_isr */ pg[0x39] = (uint8_t)(stub & 0xFF); pg[0x3A] = (uint8_t)(stub >> 8); pg[0x66] = 0xED; /* RETN (NMI) */ pg[0x67] = 0x45; } sprinter_page_w3(saved_w3); close(fd); if (!ok) { mem_free_block(blk); a->page = 0; errno = EINVAL; return -1; } return 0; }