/* * bgi_img — тест спрайтов BGI: getimage / putimage / imagesize * (режим 320×256×256, --gfx 256). * * Что проверяем: * 1. imagesize() совпадает с реальным размером буфера (self-check — * при расхождении рисуется красная плашка "SIZE MISMATCH"). * 2. getimage() снимает прямоугольник экрана в буфер (заголовок * w,h + w*h байт). * 3. putimage() кладёт образ всеми пятью операциями COPY/XOR/OR/AND/ * NOT поверх серого фона — визуально видно разницу операций. * 4. XOR дважды по одному месту восстанавливает фон (классический * признак корректного спрайтового XOR). * * Прогон в MAME визуальный: см. что источник и его COPY-копия * идентичны (в т.ч. красный маркер в левом-верхнем углу — ловит * зеркалирование), а XOR-дважды не оставляет следа на фоне. * * 2026-08-11: XOR/OR/AND_PUT переведены с попиксельного цикла на блочные * операции акселератора (gfx_blit_part_op), поэтому к визуальной проверке * добавлены ДВЕ БАЙТОВЫЕ (PASS/FAIL на экране) — глазами тут промах на * пиксель или уехавший Port_Y не поймать: * P1 COPY == источник побайтно (клип/адресация не сдвинули образ); * P2 XOR дважды == чистый фон побайтно (op-burst читает ровно тот байт * приёмника, поверх которого потом пишет). * Механика самих блочных операций проверяется отдельно — tests/accop. */ #include #include /* Габариты спрайта-источника. Из них же считаем и рект, и буфер — * так imagesize() и sizeof(buf) обязаны сойтись. */ #define SPR_L 16 #define SPR_T 28 #define SPR_W 40 #define SPR_H 32 /* Буфер образа: 4 байта заголовка (w,h) + по байту на пиксель. */ static uint8_t sprite[4 + SPR_W * SPR_H]; /* Нарисовать узнаваемый ассиметричный образ в (SPR_L,SPR_T). */ static void draw_source(void) { int l = SPR_L, t = SPR_T; int r = l + SPR_W - 1, b = t + SPR_H - 1; setfillstyle(SOLID_FILL, LIGHTBLUE); bar(l, t, r, b); /* фон образа */ setcolor(YELLOW); circle(l + SPR_W / 2, t + SPR_H / 2, 10); setcolor(WHITE); line(l, t, r, b); /* диагональ */ /* Красный маркер в левом-верхнем углу — детектор ориентации. */ setfillstyle(SOLID_FILL, LIGHTRED); bar(l, t, l + 5, t + 5); setcolor(WHITE); rectangle(l - 1, t - 1, r + 1, b + 1); /* рамка вокруг источника */ } /* Прямоугольник (x0,y0,w,h) совпадает с прямоугольником (x1,y1,w,h)? */ static uint8_t rect_eq(int x0, int y0, int x1, int y1, int w, int h) { int cx, cy; for (cy = 0; cy < h; cy++) for (cx = 0; cx < w; cx++) if (getpixel(x0 + cx, y0 + cy) != getpixel(x1 + cx, y1 + cy)) return 0; return 1; } static void say(int x, int y, const char *s, uint8_t ok) { setcolor(ok ? LIGHTGREEN : LIGHTRED); outtextxy(x, y, s); outtextxy(x + textwidth((char *)s) + 4, y, ok ? "PASS" : "FAIL"); } int main(void) { static const int ops[5] = { COPY_PUT, XOR_PUT, OR_PUT, AND_PUT, NOT_PUT }; static const char *names[5] = { "COPY", "XOR", "OR", "AND", "NOT" }; uint8_t p_copy, p_xor2; int i, x; int sl = SPR_L, st = SPR_T; int sr = SPR_L + SPR_W - 1, sb = SPR_T + SPR_H - 1; initgraph(); cleardevice(); setcolor(WHITE); settextstyle(DEFAULT_FONT, HORIZ_DIR, 1); outtextxy(80, 6, "getimage/putimage test"); /* --- источник --- */ outtextxy(SPR_L, 18, "src"); draw_source(); /* --- imagesize() self-check --- */ if (imagesize(sl, st, sr, sb) != (unsigned)sizeof(sprite)) { setfillstyle(SOLID_FILL, LIGHTRED); bar(80, 90, 240, 100); setcolor(WHITE); outtextxy(84, 92, "SIZE MISMATCH"); } /* --- снимаем образ --- */ getimage(sl, st, sr, sb, sprite); /* --- пять операций putimage поверх серого фона --- */ for (i = 0; i < 5; i++) { x = 16 + i * 60; setcolor(WHITE); outtextxy(x, 108, names[i]); setfillstyle(SOLID_FILL, LIGHTGRAY); /* общий фон под все ops */ bar(x, 120, x + SPR_W - 1, 120 + SPR_H - 1); putimage(x, 120, sprite, ops[i]); } /* P1: COPY-копия (x = 16, первая в ряду) обязана совпасть с источником * побайтно — ловит сдвиг на пиксель и зеркалирование. */ p_copy = rect_eq(16, 120, sl, st, SPR_W, SPR_H); /* --- XOR дважды = восстановление фона --- */ setcolor(WHITE); outtextxy(16, 176, "XOR x2 -> restores bg (patch stays clean):"); setfillstyle(SOLID_FILL, GREEN); bar(16, 190, 16 + SPR_W - 1, 190 + SPR_H - 1); putimage(16, 190, sprite, XOR_PUT); /* наложили */ putimage(16, 190, sprite, XOR_PUT); /* сняли */ /* Рядом — тот же зелёный фон нетронутым, для сравнения. */ setfillstyle(SOLID_FILL, GREEN); bar(80, 190, 80 + SPR_W - 1, 190 + SPR_H - 1); setcolor(WHITE); outtextxy(130, 202, "<- these two must match ->"); /* P2: наложенный и снятый XOR не оставил следа — сравниваем с * нетронутым зелёным эталоном справа. */ p_xor2 = rect_eq(16, 190, 80, 190, SPR_W, SPR_H); say(16, 228, "P1 COPY==src:", p_copy); say(16, 240, "P2 XORx2==bg:", p_xor2); for (;;) { } }