/* * accfill — регресс chunked-заливок libbgi на мульти-триггере акселератора * (B0: cleardevice/_bgi_clear_raw; B1: bar → _gfx_rectvfill256, пути * «1 чанк», «2 чанка + хвост»; B2: bar → _gfx_recthfill256, «чанк + хвост»; * плюс полноширинный bar 320×8 — precompute-путь w>=256). * * Семантика FSM (из драйвера MAME src/mame/sinclair/sprinter.cpp; * согласуется с примерами docs/part2/accelerator_doc.txt; сырые * asm-эксперименты E1-E3, подтвердившие её, удалены — см. git history * 2026-07-10 и memory/accel_multitrigger_fill): * - армирование (LD C,C / LD E,E / ...) живёт до следующего accel-опкода — * мульти-триггер поддерживается; * - под армированием триггерит ЛЮБОЙ non-M1 доступ к памяти: в т.ч. fetch * immediate/displacement (djnz/jr/ld a,#n) и стек → между триггерами * допустимы ТОЛЬКО регистровые M1-опкоды, либо выключать (LD B,B); * - вертикальный Fill двигает Port_Y (+len) и НЕ возвращает; адрес * константен. Горизонтальный — двигает адрес, Port_Y на месте; * - OUT — I/O, акселератор не триггерит (но fetch операнда порта — да, * поэтому OUT делать при выключенном акселераторе); * - размер блока хранится во внутреннем регистре и переживает LD B,B — * армировать размер достаточно один раз на скобку. * * Верификация: getpixel по всем линиям прямоугольника + нетронутый фон * в 1px вокруг. Результат (PASS/FAIL) печатается на экране. */ #include /* Прямоугольник (x0,y0,w,h) залит col целиком, а 1px вокруг — фон (0)? * Сканируем все колонки в трёх строках и все строки в трёх колонках — * ловит пропуск отдельного триггера (дырку в колонке/строке). */ static uint8_t rect_ok(int x0, int y0, int w, int h, color_t col) { int i; for (i = 0; i < w; i++) { if (getpixel(x0 + i, y0) != col) return 0; if (getpixel(x0 + i, y0 + h / 2) != col) return 0; if (getpixel(x0 + i, y0 + h - 1) != col) return 0; } for (i = 0; i < h; i++) { if (getpixel(x0, y0 + i) != col) return 0; if (getpixel(x0 + w / 2, y0 + i) != col) return 0; if (getpixel(x0 + w - 1, y0 + i) != col) return 0; } /* вокруг — нетронутый фон */ if (getpixel(x0 - 1, y0) != 0) return 0; if (getpixel(x0 + w, y0) != 0) return 0; if (getpixel(x0, y0 - 1) != 0) return 0; if (getpixel(x0, y0 + h) != 0) return 0; return 1; } int main(void) { uint8_t b0; initgraph(); cleardevice(); /* B0: cleardevice (chunked _bgi_clear_raw) — углы и центр чистые */ b0 = getpixel(0, 0) == 0 && getpixel(319, 0) == 0 && getpixel(0, 255) == 0 && getpixel(319, 255) == 0 && getpixel(160, 128) == 0; setcolor(WHITE); outtextxy(8, 8, "ACCEL multi-trigger fill test v3"); /* B1: bar → вертикальная ветка rectfill: 1 чанк (16 кол.) и 3 чанка (40) */ setfillstyle(SOLID_FILL, LIGHTBLUE); bar(16, 60, 31, 123); /* 16×64 */ setfillstyle(SOLID_FILL, YELLOW); bar(230, 60, 269, 119); /* 40×60 */ /* B2: bar → горизонтальная ветка rectfill: 2 чанка (20 строк) */ setfillstyle(SOLID_FILL, LIGHTMAGENTA); bar(200, 18, 299, 37); /* 100×20 */ bar(0, 8, 319, 15); /* 320×8 */ outtextxy(8, 132, b0 ? "B0 cleardevice chunked: PASS" : "B0 cleardevice chunked: FAIL"); outtextxy(8, 144, (rect_ok(16, 60, 16, 64, LIGHTBLUE) && rect_ok(230, 60, 40, 60, YELLOW)) ? "B1 bar vert 1+3 chunks: PASS" : "B1 bar vert 1+3 chunks: FAIL"); outtextxy(8, 156, rect_ok(200, 18, 100, 20, LIGHTMAGENTA) ? "B2 bar horz 2 chunks: PASS" : "B2 bar horz 2 chunks: FAIL"); outtextxy(8, 208, "done"); for (;;) { } }