/* * 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 #include /* ---- Стандартные EGA/VGA цвета (индексы палитры 0..15) ------------ */ enum { BLACK = 0, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE }; /* 8-битный цвет (индекс палитры). При смене формата достаточно поменять * один typedef — все public-функции используют этот тип. */ typedef uint8_t color_t; /* ---- Коды graphresult() ------------------------------------------ */ #define grOk 0 #define grNoInitGraph (-1) #define grError (-11) /* ---- Внутреннее состояние BGI ------------------------------------- * * НЕ трогать напрямую — только через функции ниже. Объявлено здесь, * чтобы тривиальные аксессоры были inline (без call/ret и без * .rel-модуля на каждый геттер). Именно `inline` БЕЗ static: SDCC * инлайнит вызов и НЕ эмитит standalone-тело (static inline эмитил бы * мёртвую копию в каждый включивший модуль — проверено 2026-07-10); * если SDCC когда-нибудь откажется инлайнить — будет громкая ошибка * линковки, не тихая деградация. Хранилище — libbgi/common/ * _bgi_state.c и _bgi_fill_state.c. */ extern uint8_t _bgi_fg, _bgi_bg; extern int _bgi_cx, _bgi_cy; extern int _bgi_maxx, _bgi_maxy, _bgi_maxcolor; extern int _bgi_result; extern uint8_t _bgi_fill_pattern, _bgi_fill_color; /* ---- Setup / teardown -------------------------------------------- */ /* Перейти в графический режим (для этой либы — 320×256×256), загрузить * EGA-палитру, сбросить состояние: цвет = WHITE, фон = BLACK, текущая * позиция = (0,0). Предыдущий видеорежим запоминается для closegraph. */ void initgraph(void); /* Вернуться в текстовый режим, действовавший до initgraph(). */ void closegraph(void); /* Код последней ошибки; вызов сбрасывает его в grOk (как в BGI). */ inline int graphresult(void) { int r = _bgi_result; _bgi_result = grOk; return r; } /* Очистить экран фоновым цветом и вернуть позицию в (0,0). */ void cleardevice(void); /* ---- Границы и цвета --------------------------------------------- */ inline int getmaxx(void) { return _bgi_maxx; } /* 319 */ inline int getmaxy(void) { return _bgi_maxy; } /* 255 */ inline color_t getmaxcolor(void) { return (color_t)_bgi_maxcolor; } /* 255 */ /* текущий цвет рисования */ inline void setcolor(color_t color) { _bgi_fg = (uint8_t)color; } inline color_t getcolor(void) { return _bgi_fg; } /* фоновый цвет (для cleardevice/текста) */ inline void setbkcolor(color_t color) { _bgi_bg = (uint8_t)color; } inline color_t getbkcolor(void) { return _bgi_bg; } /* ---- Точки ------------------------------------------------------- */ void putpixel(int x, int y, color_t color); color_t getpixel(int x, int y); /* ---- Текущая позиция и линии ------------------------------------- */ /* задать текущую позицию (CP) */ inline void moveto(int x, int y) { _bgi_cx = x; _bgi_cy = y; } /* сдвинуть CP относительно */ inline void moverel(int dx, int dy) { _bgi_cx += dx; _bgi_cy += dy; } inline int getx(void) { return _bgi_cx; } inline int gety(void) { return _bgi_cy; } 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); /* окружность */ /* Дуги/эллипсы: угол в градусах, 0°=восток, против часовой стрелки. * Полный эллипс — ellipse(x,y,0,360,xr,yr). */ void arc(int x, int y, int stangle, int endangle, int radius); void ellipse(int x, int y, int stangle, int endangle, int xradius, int yradius); /* Ломаная по numpoints точкам {x0,y0,x1,y1,…}; НЕ замыкается сама. */ void drawpoly(int numpoints, const int *polypoints); /* ---- Стиль линий ------------------------------------------------- * * Действует на line/lineto/linerel/rectangle/drawpoly. USERBIT_LINE * использует 16-битный upattern. thickness: NORM_WIDTH или THICK_WIDTH. * (Окружности/дуги пока всегда сплошные 1px — упрощение.) */ enum { SOLID_LINE = 0, DOTTED_LINE, CENTER_LINE, DASHED_LINE, USERBIT_LINE }; #define NORM_WIDTH 1 #define THICK_WIDTH 3 struct linesettingstype { int linestyle; unsigned upattern; int thickness; }; void setlinestyle(int linestyle, unsigned upattern, int thickness); void getlinesettings(struct linesettingstype *lineinfo); /* ---- Заливки ----------------------------------------------------- * * Стиль заливки — паттерн (8×8) + цвет; действует на bar/bar3d/ * fillpoly/fillellipse. SOLID_FILL заполняет сплошняком, EMPTY_FILL — * фоновым цветом. USER_FILL пока трактуется как SOLID. */ enum { EMPTY_FILL = 0, SOLID_FILL, LINE_FILL, LTSLASH_FILL, SLASH_FILL, BKSLASH_FILL, LTBKSLASH_FILL, HATCH_FILL, XHATCH_FILL, INTERLEAVE_FILL, WIDE_DOT_FILL, CLOSE_DOT_FILL, USER_FILL }; struct fillsettingstype { int pattern; color_t color; }; inline void setfillstyle(int pattern, color_t color) { _bgi_fill_pattern = (uint8_t)pattern; _bgi_fill_color = (uint8_t)color; } void getfillsettings(struct fillsettingstype *fillinfo); /* bar — залитый прямоугольник (текущий стиль заливки, без рамки). */ /* bar3d — 3D-брусок: перёд залит стилем заливки, рёбра — тек. цветом; * topflag != 0 рисует верхнюю грань. */ void bar3d(int left, int top, int right, int bottom, int depth, int topflag); /* fillpoly — залитый многоугольник (авто-замыкается); контур тек. * цветом, нутро — стилем заливки. Вогнутые заполняются по выпуклой * оболочке строк (min/max X на строку) — упрощение. */ void fillpoly(int numpoints, const int *polypoints); /* fillellipse — залитый эллипс (полуоси xradius,yradius). */ void fillellipse(int x, int y, int xradius, int yradius); /* floodfill — заливка области, содержащей (x,y), текущим стилем до * границы цвета border. Заливка сплошная цветом заливки (паттерн в * floodfill пока не применяется — упрощение). */ void floodfill(int x, int y, int border); /* pieslice — залитый сектор круга; sector — эллиптический сектор. * Контур (дуга + два радиуса) тек. цветом, нутро — стилем заливки. * Для секторов >180° возможен перелив в «выемку» (min/max по строке). */ void pieslice(int x, int y, int stangle, int endangle, int radius); void sector(int x, int y, int stangle, int endangle, int xradius, int yradius); /* ---- Растровые образы (спрайты) ---------------------------------- * * Формат буфера: 2×uint16 (ширина, высота в пикселях) + пиксели * построчно (1 байт/пиксель в режиме 256). Буфер выделяет вызывающий * размером imagesize(). */ enum { COPY_PUT = 0, XOR_PUT, OR_PUT, AND_PUT, NOT_PUT }; /* Байт под образ прямоугольника (left,top)-(right,bottom) включительно. * ВНИМАНИЕ: результат — 16-бит unsigned; образы ≥64 КБ не поддержаны. */ unsigned imagesize(int left, int top, int right, int bottom); /* Сохранить прямоугольник экрана в bitmap (размер = imagesize()). */ void getimage(int left, int top, int right, int bottom, void *bitmap); /* Вывести образ левым-верхним углом в (left,top) операцией op * (COPY/XOR/OR/AND/NOT_PUT). */ void putimage(int left, int top, const void *bitmap, int op); /* ---- Текст ------------------------------------------------------- * * Шрифт 8×8 (системный). Рисуется текущим цветом на фоновом. */ void outtextxy(int x, int y, const char *text); /* в (x,y), CP не меняет */ void outtext(const char *text); /* в CP; CP сдвигается вправо */ /* ---- Стиль текста ------------------------------------------------ * * Поддержан только DEFAULT_FONT (8×8, растровый); charsize 1..10 — * целочисленный масштаб; direction — HORIZ_DIR или VERT_DIR (поворот * 90° против часовой). Фон текста прозрачный (рисуется только цвет). */ enum { DEFAULT_FONT = 0, TRIPLEX_FONT, SMALL_FONT, SANS_SERIF_FONT, GOTHIC_FONT }; enum { HORIZ_DIR = 0, VERT_DIR = 1 }; struct textsettingstype { int font; int direction; int charsize; int horiz; int vert; }; void settextstyle(int font, int direction, int charsize); void gettextsettings(struct textsettingstype *textinfo); int textwidth(const char *text); int textheight(const char *text); #endif