/* * atlas_load — загрузить .atl-файл в свежую EMM-страницу (§3.1/§9в * дизайна, вариант II: файл-офсет == офсет страницы == W0-адрес). * * Порядок: выделить страницу → bank_load_file() → проверить магию 'SPA1' * → gfx_w0_page_prepare(). Никакого пересчёта офсетов: каталог и ленты * уже лежат по своим W0-адресам. * * Вызывать ВНЕ рендера (W3 на время загрузки занята страницей атласа). * Ошибки: -1 + errno (open/read/alloc; EINVAL — не .atl). */ #include #include #include #include "../_bgi.h" int atlas_load(atlas_t *a, const char *path) { uint8_t blk, ok, count, h[5]; int n; blk = mem_alloc_pages(1); if (!blk) return -1; a->blk = blk; a->page = mem_get_page(blk, 0); n = bank_load_file(a->page, 0, path, 16384); if (n >= 5) bank_read(a->page, 0, h, sizeof(h)); ok = (n >= (int)_ATL_DATA_OFF && h[0] == 'S' && h[1] == 'P' && h[2] == 'A' && h[3] == '1'); count = 0; if (ok) { count = h[4]; gfx_w0_page_prepare(a->page); } /* Восстановить W3 ДО записи в *a: если atlas_t лежит в банковской * памяти (её адрес тоже резолвится через W3), запись при ещё * замапленной странице атласа ушла бы не в тот физический банк * (найдено 2026-07-15 — PoP room.c держит tile_atlas[] в --bank 1, * a->count оставался мусором, room_draw читал пиксели не с того * оффсета). a->blk/a->page выше пишутся ДО ремапа — их это не * касалось, только a->count. */ if (!ok) { mem_free_block(blk); a->page = 0; errno = EINVAL; return -1; } a->count = count; return 0; }