libbgi: W0-атласы спрайтов — загрузчик, движок, упаковщик (все проверки PASS)
Реализация §3.1/§9в: атлас = один .atl-файл = одна EMM-страница, подключаемая в W0 на время блита. - atlas_load: read() файла целиком в страницу через W3 + патч ISR-стаба (0x38: JP _gfx_w0_isr; 0x66: RETN); atlas_free/atlas_image/ atlas_sprite_init; gfx_w0_map/unmap для ручных вызовов. - _gfx_w0_isr (стаб из tests/w0page): свап на ядро DSS → честный 0x38 → restore спрайт-страницы; покрывает IM1 и IM2-чейн. - sprite_t.page (0 = обычная память); sprite_update в блит-проходе мапит страницу по смене (один OUT на атлас), эпилог возвращает DSS (+52 Б на движок — цена фичи). - toolchain/mkatlas.py: PNG (indexed) / raw → .atl; заголовок 0x100, каталог 0x68 (19 лент), файл-офсет == офсет страницы == W0-адрес. - Сплит _gfx_sprite_fns → _gfx_blit_fn.c + _gfx_heal_fn.c (1 указатель = 1 модуль): putsprite-only программа не тянет heal-ядро (spriteclip ловил +292 Б; теперь −68 Б от эталона). tests/atlas (MAME dev, PASS): загрузка (count/страница), каталог и данные по W0-адресам (заголовок ленты через gfx_w0_map), 3 спрайта из двух лент через движок — пиксели проверены read_vram побайтно (0x10/0x12/0x21, прозрачный угол = фон). docs: §9г — предложение авто-анимации (кадровая ±step без умножений, tween-Брезенхэм порциями, тикер через funcptr) — ОБСУЖДАЕТСЯ. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* atlas — тест W0-атласов (sprite.h: atlas_load/atlas_image/
|
||||
* atlas_sprite_init + спрайтовый движок с полем page).
|
||||
*
|
||||
* atlas.atl (генерят gen_frames.py + mkatlas.py):
|
||||
* лента 0: 16×16, 4 кадра вертикально — кадр k: заливка 0x10+k,
|
||||
* рамка 0x04, углы 0xFF (прозрачные);
|
||||
* лента 1: 24×24, 2 кадра — заливка 0x20+k, рамка 0x0E.
|
||||
*
|
||||
* Стадии:
|
||||
* A atlas_load: count == 2.
|
||||
* B каталог/W0: getimage-заголовок ленты 0 (w=16, h=64) читается
|
||||
* через указатель atlas_image при gfx_w0_map — проверка, что
|
||||
* офсеты каталога и данные легли по своим W0-адресам.
|
||||
* C движок: 3 спрайта из двух лент (кадры 0/2 ленты 0, кадр 1
|
||||
* ленты 1) на зелёном фоне — sprite_update сам мапит страницу.
|
||||
* Экран write-only → корректность пикселей проверяется скриншотом/
|
||||
* read_vram: (108,68)=0x10, (148,68)=0x12, (188,72)=0x21,
|
||||
* угол (100,60)=0x02 (фон сквозь прозрачный угол).
|
||||
*
|
||||
* Запуск через MAME-мост; Enter между стадиями.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <graphics.h>
|
||||
#include <gfx.h>
|
||||
#include <sprite.h>
|
||||
|
||||
static atlas_t at;
|
||||
static sprite_t sp[3];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const uint8_t *im;
|
||||
uint8_t okA, okB, okC;
|
||||
|
||||
puts("ATLAS: .atl load + W0 sprite engine");
|
||||
|
||||
/* ---- A: загрузка ------------------------------------------------ */
|
||||
if (atlas_load(&at, "atlas.atl") != 0 &&
|
||||
atlas_load(&at, "a:\\atlas.atl") != 0) {
|
||||
puts("A atlas_load: FAIL (open/format)");
|
||||
return 1;
|
||||
}
|
||||
okA = (at.count == 2);
|
||||
printf("A load: %s (page=%u count=%u)\n",
|
||||
okA ? "PASS" : "FAIL", at.page, at.count);
|
||||
|
||||
/* ---- B: каталог + данные по W0-адресам -------------------------- */
|
||||
im = (const uint8_t *)atlas_image(&at, 0);
|
||||
gfx_w0_map(at.page);
|
||||
okB = (im[0] == 16 && im[1] == 0 && im[2] == 64 && im[3] == 0) &&
|
||||
(im[4] == 0xFF) && /* угол кадра 0 — прозрачный */
|
||||
(im[4 + 17] == 0x10); /* (1,1) кадра 0 — заливка */
|
||||
gfx_w0_unmap();
|
||||
printf("B W0 dir/data: %s (img=%04x)\n",
|
||||
okB ? "PASS" : "FAIL", (unsigned)im);
|
||||
puts("Enter -> gfx");
|
||||
(void)getchar();
|
||||
|
||||
/* ---- C: движок со спрайтами из атласа --------------------------- */
|
||||
initgraph();
|
||||
cleardevice();
|
||||
setfillstyle(SOLID_FILL, GREEN);
|
||||
bar(90, 50, 220, 100);
|
||||
|
||||
atlas_sprite_init(&sp[0], &at, 0); /* лента 0, кадр 0 */
|
||||
sp[0].x = 100; sp[0].y = 60;
|
||||
sprite_show(&sp[0]);
|
||||
|
||||
atlas_sprite_init(&sp[1], &at, 0); /* лента 0, кадр 2 */
|
||||
sp[1].x = 140; sp[1].y = 60;
|
||||
sprite_frame(&sp[1], 0, 2 * 16);
|
||||
sprite_show(&sp[1]);
|
||||
|
||||
atlas_sprite_init(&sp[2], &at, 1); /* лента 1, кадр 1 */
|
||||
sp[2].x = 180; sp[2].y = 60;
|
||||
sprite_frame(&sp[2], 0, 24);
|
||||
sprite_show(&sp[2]);
|
||||
|
||||
sprite_update(sp, 3);
|
||||
|
||||
/* ESTEX снова доступен: sprite_update вернул страницу ядра DSS. */
|
||||
okC = 1; /* пиксели — скриншотом/read_vram */
|
||||
setcolor(WHITE);
|
||||
outtextxy(4, 4, "ATLAS: 3 sprites from .atl page (W0)");
|
||||
outtextxy(4, 200, okA && okB ? "A/B PASS; C: check pixels"
|
||||
: "A/B FAIL");
|
||||
outtextxy(4, 210, "Enter to exit");
|
||||
(void)getchar();
|
||||
|
||||
closegraph();
|
||||
printf("done (A=%u B=%u C=%u)\n", okA, okB, okC);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user