Files
Sprinter-SDCC/tests/gfx_dbuf/gfx_dbuf.c
T
snark13 52636a5d6e 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>
2026-07-09 14:18:33 +03:00

119 lines
4.3 KiB
C

/*
* gfx_dbuf — double-buffering demo (BGI, bgi256.lib).
*
* Рендерит движущийся прямоугольник, чередуя страницу 0 и 1:
* - Каждый кадр: рисуем на СКРЫТОЙ странице, затем делаем её видимой.
* - Видимая страница никогда не пишется → пользователь видит только
* целые кадры (без артефактов, без мерцания от per-frame clear).
*
* Переключение страниц и vsync — через mode-agnostic gfx_* (gfx.h,
* остались в BGI_GFX): gfx_set_draw_page / gfx_set_visible_page /
* gfx_get_visible_page / gfx_wait_vsync. Рисование — через BGI
* (graphics.h): cleardevice / bar / rectangle / outtextxy. Режим
* 0x81 выбирается линковкой: EXTRA_FLAGS=--gfx 256.
*
* Индикатор страницы (маленький swatch сверху-справа) меняет оттенок
* каждый кадр — если бокс движется плавно, а swatch мигает между двумя
* оттенками, своп работает. Press any key to exit.
*/
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <gfx.h> /* double-buffering + vsync (mode-agnostic) */
#include <stdint.h>
static uint8_t palette[256 * 4];
#define COL_BLACK 0x00
#define COL_BG 0x20
#define COL_STRIPE 0x60
#define COL_TEXT 0xC0
#define COL_BOX 0xFF
#define COL_PAGE0 0x40
#define COL_PAGE1 0xE0
static void make_palette(void)
{
for (int i = 0; i < 256; i++) {
palette[i*4+0] = (uint8_t)i;
palette[i*4+1] = (uint8_t)i;
palette[i*4+2] = (uint8_t)i;
palette[i*4+3] = 0;
}
}
static void draw_frame(int box_x, int box_y, uint8_t page_indicator)
{
setbkcolor(COL_BG); cleardevice();
/* Static decoration — identical on both pages so the swap doesn't
* flicker the chrome. */
setfillstyle(SOLID_FILL, COL_STRIPE);
bar(0, 0, GFX_WIDTH - 1, 7);
bar(0, GFX_HEIGHT - 8, GFX_WIDTH - 1, GFX_HEIGHT - 1);
setcolor(COL_TEXT);
outtextxy(8, 16, "double-buffering demo");
outtextxy(8, GFX_HEIGHT - 24, "press a key to exit");
/* Page indicator — different shade per page: flicker here proves
* the swap is happening. */
setfillstyle(SOLID_FILL, page_indicator ? COL_PAGE1 : COL_PAGE0);
bar(GFX_WIDTH - 24, 16, GFX_WIDTH - 24 + 11, 16 + 11);
/* The animated box. */
setfillstyle(SOLID_FILL, COL_BOX);
bar(box_x, box_y, box_x + 39, box_y + 29);
setcolor(COL_BLACK);
rectangle(box_x, box_y, box_x + 39, box_y + 29);
}
int main(void)
{
make_palette();
initgraph();
/* Каждая графическая страница имеет свою палитру (0→pal 0, 1→pal 1).
* Грузим одну и ту же в обе — визуальный своп бесшовный. */
gfx_pal_load(0, 0, 0, palette);
gfx_pal_load(1, 0, 0, palette);
/* Очистить обе страницы, чтобы первый флип не вскрыл мусор. */
setbkcolor(COL_BG);
gfx_set_draw_page(0); cleardevice();
gfx_set_draw_page(1); cleardevice();
/* Bouncing rect state. */
int box_x = 10;
int box_y = 100;
int dx = 3;
int dy = 2;
const int box_w = 40, box_h = 30;
while (!kbhit()) {
uint8_t hidden = 1 - gfx_get_visible_page();
gfx_set_draw_page(hidden);
draw_frame(box_x, box_y, hidden);
/* Ждать следующий кадр перед флипом — своп падает в vblank,
* пользователь не видит полунарисованный кадр. */
gfx_wait_vsync();
gfx_set_visible_page(hidden);
/* Step the box; bounce off all four walls. */
box_x += dx;
if (box_x < 0) { box_x = 0; dx = -dx; }
if (box_x + box_w > GFX_WIDTH) { box_x = GFX_WIDTH - box_w; dx = -dx; }
box_y += dy;
if (box_y < 8) { box_y = 8; dy = -dy; }
if (box_y + box_h > GFX_HEIGHT-8) { box_y = GFX_HEIGHT-8 - box_h; dy = -dy; }
}
(void)getch();
closegraph();
puts("done");
return 0;
}