libc: graphics.h — Turbo-C BGI-слой, Фаза 1 (режим 256)

Функционально-совместимый с Turbo-C <graphics.h> поверх gfx.h.
Архитектура: mode-agnostic математика (libc/bgi/*.c → sprinter.lib) +
driver-leaf'ы per-режим (libc/bgi/drv256/*.c → sprinter_gfx256.lib).
Режим выбирается линковкой: sprinter-cc --gfx 256 (16 — позже, тем же
leaf-split'ом). Один код работает в любом режиме без правок.

API: initgraph/closegraph/graphresult/cleardevice, set/get color+bkcolor,
getmaxx/y/color, put/getpixel, moveto/moverel/getx/gety, line/lineto/
linerel, rectangle, bar, circle, outtext/outtextxy. initgraph грузит
EGA-палитру 0..15. Пакетные примитивы (circle) — одна W3-скобка на
примитив (иначе на порядок медленнее). Проверено в MAME (tests/bgitest).

Попутно: gfx_getpixel256 в libc/gfx. size-check без регресса, baseline
обновлён. Детали: memory/bgi_two_lib_design, docs/TODO.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 15:40:49 +03:00
parent 72466f7cad
commit e761d21505
49 changed files with 721 additions and 15 deletions
+93
View File
@@ -0,0 +1,93 @@
/*
* graphics.h — Turbo-C-совместимый (функционально) BGI-слой для Sprinter.
*
* Слой поверх низкоуровневого gfx.h. Состояние (текущий цвет, позиция,
* границы экрана) хранится внутри — как в оригинальном BGI, где функции
* рисуют «текущим» цветом от «текущей» позиции.
*
* РЕЖИМ фиксируется на этапе ЛИНКОВКИ выбором driver-библиотеки:
* sprinter-cc --gfx 256 → 320×256×256 (эта версия)
* (--gfx 16 → 640×256×16 будет позже; API идентичен, менять код не надо)
* Одновременно два режима использовать нельзя.
*
* Отличия от Turbo-C (функциональная, а не буквальная совместимость):
* - initgraph() без аргументов-указателей на драйвер: драйвер задан
* линковкой, грузить .bgi-файл с диска не нужно.
* - в 256-режиме initgraph() загружает EGA-совместимые цвета 0..15 в
* палитру, так что setcolor(RED) и т.п. работают как в Turbo-C;
* индексы 16..255 свободны под свои цвета (getmaxcolor() = 255).
* - fill-паттерны/стили линий/стили текста — Фаза 2 (пока bar/bar-подобное
* заливается текущим цветом, линии сплошные, текст 8×8).
*/
#ifndef GRAPHICS_H
#define GRAPHICS_H
/* ---- Стандартные EGA/VGA цвета (индексы палитры 0..15) ------------ */
enum {
BLACK = 0, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY,
DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA,
YELLOW, WHITE
};
/* ---- Коды graphresult() ------------------------------------------ */
#define grOk 0
#define grNoInitGraph (-1)
#define grError (-11)
/* ---- Setup / teardown -------------------------------------------- */
/* Перейти в графический режим (для этой либы — 320×256×256), загрузить
* EGA-палитру, сбросить состояние: цвет = WHITE, фон = BLACK, текущая
* позиция = (0,0). Предыдущий видеорежим запоминается для closegraph. */
void initgraph(void);
/* Вернуться в текстовый режим, действовавший до initgraph(). */
void closegraph(void);
/* Код последней ошибки; вызов сбрасывает его в grOk (как в BGI). */
int graphresult(void);
/* Очистить экран фоновым цветом и вернуть позицию в (0,0). */
void cleardevice(void);
/* ---- Границы и цвета --------------------------------------------- */
int getmaxx(void); /* 319 */
int getmaxy(void); /* 255 */
int getmaxcolor(void); /* 255 */
void setcolor(int color); /* текущий цвет рисования */
int getcolor(void);
void setbkcolor(int color); /* фоновый цвет (для cleardevice/текста) */
int getbkcolor(void);
/* ---- Точки ------------------------------------------------------- */
void putpixel(int x, int y, int color);
unsigned getpixel(int x, int y);
/* ---- Текущая позиция и линии ------------------------------------- */
void moveto(int x, int y); /* задать текущую позицию (CP) */
void moverel(int dx, int dy); /* сдвинуть CP относительно */
int getx(void);
int gety(void);
void lineto(int x, int y); /* линия CP→(x,y), CP := (x,y) */
void linerel(int dx, int dy); /* линия CP→CP+(dx,dy), CP сдвигается */
void line(int x1, int y1, int x2, int y2); /* линия, CP не меняет */
/* ---- Фигуры ------------------------------------------------------ */
void rectangle(int left, int top, int right, int bottom); /* контур */
void bar(int left, int top, int right, int bottom); /* заливка */
void circle(int x, int y, int radius); /* окружность */
/* ---- Текст ------------------------------------------------------- *
* Шрифт 8×8 (системный). Рисуется текущим цветом на фоновом. */
void outtextxy(int x, int y, const char *text); /* в (x,y), CP не меняет */
void outtext(const char *text); /* в CP; CP сдвигается вправо */
#endif