libbgi: выделить графику BGI в отдельную библиотеку + тест спрайтов

Графика вынесена из libc/ в новую библиотеку libbgi/:
  - common/  — mode-agnostic математика и состояние (один исходник,
    .rel попадает в оба driver-архива);
  - bgi256/ + bgi16/ — mode-specific leaf'ы (raw-плот/чтение/спаны);
  - include/ — graphics.h + gfx.h; _bgi.h — внутренний заголовок.
Собираются lib/bgi256.lib (и bgi16.lib в Фазе 2); выбор режима
линковкой через sprinter-cc --gfx 256|16.  libc/ теперь без графики.

tests/bgi_img — тест спрайтов getimage/putimage/imagesize (5 операций
COPY/XOR/OR/AND/NOT + XOR-round-trip + self-check imagesize).
Проверен автотестом в MAME.

Примечание: make size-check пока красный (gfx_dbuf/gfx_demo выросли
после реорга) — закрыть по завершении миграции libbgi.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 14:18:33 +03:00
parent 3bf50f7ff7
commit 52636a5d6e
164 changed files with 1072 additions and 1440 deletions
+4
View File
@@ -0,0 +1,4 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
EXAMPLE := bgi_img
EXTRA_FLAGS := --gfx 256
include $(PROJ_ROOT)/app.mk
+114
View File
@@ -0,0 +1,114 @@
/*
* 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-дважды не оставляет следа на фоне.
*/
#include <graphics.h>
#include <stdint.h>
/* Габариты спрайта-источника. Из них же считаем и рект, и буфер —
* так 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); /* рамка вокруг источника */
}
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" };
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]);
}
/* --- 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 ->");
for (;;) { }
}