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:
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* _bgi.h — внутренности BGI-слоя (НЕ публичный заголовок).
|
||||
*
|
||||
* Математика примитивов (circle/line/bar/…) — mode-agnostic, лежит в
|
||||
* каталоге libc/bgi (файлы .c) и попадает в основную sprinter.lib.
|
||||
* Различающиеся по видеорежиму LEAF-операции (`_bgi_*`) реализованы в
|
||||
* отдельных driver-каталогах libc/bgi/drv256 и drv16 (каждый — свой архив, выбирается
|
||||
* линковкой; см. memory/bgi_two_lib_design). Публичные символы leaf'ов
|
||||
* одинаковы в обоих драйверах, поэтому math не знает режима.
|
||||
*/
|
||||
#ifndef _BGI_INTERNAL_H
|
||||
#define _BGI_INTERNAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <graphics.h>
|
||||
|
||||
/* ---- Состояние (_bgi_state.c) ------------------------------------ */
|
||||
extern uint8_t _bgi_fg; /* текущий цвет рисования */
|
||||
extern uint8_t _bgi_bg; /* фоновый цвет */
|
||||
extern int _bgi_cx; /* текущая позиция X (CP) */
|
||||
extern int _bgi_cy; /* текущая позиция Y */
|
||||
extern int _bgi_maxx; /* правая граница (319) */
|
||||
extern int _bgi_maxy; /* нижняя граница (255) */
|
||||
extern int _bgi_maxcolor; /* макс. индекс цвета (255) */
|
||||
extern uint8_t _bgi_prevmode; /* видеорежим до initgraph */
|
||||
extern int _bgi_result; /* код graphresult */
|
||||
|
||||
/* ---- LEAF-операции драйвера (каталоги drv256 или drv16) ----------- *
|
||||
* Каждая self-contained (сама оборачивает W3-скобку через gfx_*).
|
||||
* mode_set: войти в граф.режим, загрузить палитру, заполнить
|
||||
* _bgi_maxx/_bgi_maxy/_bgi_maxcolor; вернуть предыдущий видеорежим. */
|
||||
uint8_t _bgi_mode_set(void);
|
||||
void _bgi_mode_done(uint8_t prev_mode);
|
||||
|
||||
void _bgi_plot(int x, int y, uint8_t color);
|
||||
unsigned _bgi_read(int x, int y);
|
||||
|
||||
/* Пакетное рисование: одна W3-скобка на весь примитив вместо скобки на
|
||||
* каждый пиксель (для circle/ellipse/fill — тысячи точек). Между
|
||||
* _bgi_begin и _bgi_end IRQ выключены; плот делать только _bgi_plot_raw
|
||||
* (без своей скобки, с клипом по краю экрана). */
|
||||
void _bgi_begin(void);
|
||||
void _bgi_end(void);
|
||||
void _bgi_plot_raw(int x, int y, uint8_t color);
|
||||
void _bgi_hspan(int x, int y, int len, uint8_t color);
|
||||
void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color);
|
||||
void _bgi_fillrect(int x, int y, int w, int h, uint8_t color);
|
||||
void _bgi_clearall(uint8_t color);
|
||||
void _bgi_drawtext(int x, int y, const char *s, uint8_t fg, uint8_t bg);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* _bgi_state.c — общее состояние BGI-слоя.
|
||||
*
|
||||
* File-scope переменные НЕ инициализируются (crt0 зануляет _DATA;
|
||||
* см. memory/sdcc_static_storage_gotcha). Осмысленные значения
|
||||
* выставляет initgraph().
|
||||
*/
|
||||
|
||||
#include "_bgi.h"
|
||||
|
||||
uint8_t _bgi_fg;
|
||||
uint8_t _bgi_bg;
|
||||
int _bgi_cx;
|
||||
int _bgi_cy;
|
||||
int _bgi_maxx;
|
||||
int _bgi_maxy;
|
||||
int _bgi_maxcolor;
|
||||
uint8_t _bgi_prevmode;
|
||||
int _bgi_result;
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* bar — залитый прямоугольник (left,top)-(right,bottom) включительно.
|
||||
*
|
||||
* В Turbo-C цвет/паттерн заливки задаётся setfillstyle; пока (Фаза 1)
|
||||
* заливаем текущим цветом рисования сплошняком.
|
||||
*/
|
||||
#include "_bgi.h"
|
||||
|
||||
void bar(int left, int top, int right, int bottom)
|
||||
{
|
||||
int w = right - left + 1;
|
||||
int h = bottom - top + 1;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
_bgi_fillrect(left, top, w, h, _bgi_fg);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* circle — окружность (midpoint) с центром (cx,cy) радиуса r,
|
||||
* текущим цветом. Целочисленный алгоритм, 8 октантов за шаг.
|
||||
*
|
||||
* Вся окружность рисуется в ОДНОЙ W3-скобке (_bgi_begin/_bgi_end) +
|
||||
* raw-плот — иначе скобка на каждый пиксель делает большие окружности
|
||||
* мучительно медленными (тысячи DI/EI).
|
||||
*/
|
||||
#include "_bgi.h"
|
||||
|
||||
void circle(int cx, int cy, int r)
|
||||
{
|
||||
int x, y, d;
|
||||
uint8_t c = _bgi_fg;
|
||||
|
||||
if (r < 0) return;
|
||||
|
||||
x = 0;
|
||||
y = r;
|
||||
d = 1 - r;
|
||||
_bgi_begin();
|
||||
while (x <= y) {
|
||||
_bgi_plot_raw(cx + x, cy + y, c);
|
||||
_bgi_plot_raw(cx - x, cy + y, c);
|
||||
_bgi_plot_raw(cx + x, cy - y, c);
|
||||
_bgi_plot_raw(cx - x, cy - y, c);
|
||||
_bgi_plot_raw(cx + y, cy + x, c);
|
||||
_bgi_plot_raw(cx - y, cy + x, c);
|
||||
_bgi_plot_raw(cx + y, cy - x, c);
|
||||
_bgi_plot_raw(cx - y, cy - x, c);
|
||||
if (d < 0) {
|
||||
d += 2 * x + 3;
|
||||
} else {
|
||||
d += 2 * (x - y) + 5;
|
||||
y--;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
_bgi_end();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* cleardevice — очистить экран фоновым цветом, вернуть CP в (0,0). */
|
||||
#include "_bgi.h"
|
||||
|
||||
void cleardevice(void)
|
||||
{
|
||||
_bgi_clearall(_bgi_bg);
|
||||
_bgi_cx = 0;
|
||||
_bgi_cy = 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* closegraph — вернуть текстовый режим, действовавший до initgraph. */
|
||||
#include "_bgi.h"
|
||||
|
||||
void closegraph(void)
|
||||
{
|
||||
_bgi_mode_done(_bgi_prevmode);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_begin (drv256) — открыть W3-сессию для пакетного рисования. */
|
||||
#include "../_bgi.h"
|
||||
#include "../../gfx/_gfx.h"
|
||||
|
||||
void _bgi_begin(void)
|
||||
{
|
||||
_gfx_w3_video_begin();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_clearall (drv256) — залить весь экран цветом. */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_clearall(uint8_t color)
|
||||
{
|
||||
gfx_clear256(color);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_drawtext (drv256) — строка шрифтом 8×8 цветами fg/bg в (x,y). */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_drawtext(int x, int y, const char *s, uint8_t fg, uint8_t bg)
|
||||
{
|
||||
gfx_text256(x, y, s, fg, bg);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_end (drv256) — закрыть W3-сессию пакетного рисования. */
|
||||
#include "../_bgi.h"
|
||||
#include "../../gfx/_gfx.h"
|
||||
|
||||
void _bgi_end(void)
|
||||
{
|
||||
_gfx_w3_video_end();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_fillrect (drv256) — залитый прямоугольник w×h из (x,y). */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_fillrect(int x, int y, int w, int h, uint8_t color)
|
||||
{
|
||||
gfx_fill_rect256(x, y, w, h, color);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_hspan (drv256) — горизонтальный отрезок len пикселей. */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_hspan(int x, int y, int len, uint8_t color)
|
||||
{
|
||||
gfx_hline256(x, y, len, color);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_lineseg (drv256) — отрезок (x0,y0)->(x1,y1) (использует accel-line). */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color)
|
||||
{
|
||||
gfx_line256(x0, y0, x1, y1, color);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_mode_done (drv256) — вернуть видеорежим, бывший до initgraph. */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_mode_done(uint8_t prev_mode)
|
||||
{
|
||||
gfx_done(prev_mode);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* _bgi_mode_set (drv256) — вход в графический режим 320×256×256.
|
||||
*
|
||||
* Загружает EGA-совместимые цвета 0..15 в палитру 0, чтобы setcolor(RED)
|
||||
* и прочие BGI-константы давали ожидаемый цвет. Заполняет границы
|
||||
* экрана в состоянии BGI. Возвращает предыдущий видеорежим.
|
||||
*/
|
||||
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
/* 16 EGA-цветов, формат записи палитры (B, G, R, pad). */
|
||||
static const uint8_t _bgi_ega_pal[16 * 4] = {
|
||||
0, 0, 0, 0, /* 0 BLACK */
|
||||
168, 0, 0, 0, /* 1 BLUE */
|
||||
0, 168, 0, 0, /* 2 GREEN */
|
||||
168, 168, 0, 0, /* 3 CYAN */
|
||||
0, 0, 168, 0, /* 4 RED */
|
||||
168, 0, 168, 0, /* 5 MAGENTA */
|
||||
0, 84, 168, 0, /* 6 BROWN */
|
||||
168, 168, 168, 0, /* 7 LIGHTGRAY */
|
||||
84, 84, 84, 0, /* 8 DARKGRAY */
|
||||
255, 84, 84, 0, /* 9 LIGHTBLUE */
|
||||
84, 255, 84, 0, /* 10 LIGHTGREEN */
|
||||
255, 255, 84, 0, /* 11 LIGHTCYAN */
|
||||
84, 84, 255, 0, /* 12 LIGHTRED */
|
||||
255, 84, 255, 0, /* 13 LIGHTMAGENTA */
|
||||
84, 255, 255, 0, /* 14 YELLOW */
|
||||
255, 255, 255, 0, /* 15 WHITE */
|
||||
};
|
||||
|
||||
uint8_t _bgi_mode_set(void)
|
||||
{
|
||||
uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
|
||||
gfx_pal_load(0, 0, 16, _bgi_ega_pal);
|
||||
_bgi_maxx = GFX_WIDTH - 1;
|
||||
_bgi_maxy = GFX_HEIGHT - 1;
|
||||
_bgi_maxcolor = 255;
|
||||
return prev;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_plot (drv256) — одиночный пиксель текущим цветом. */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
void _bgi_plot(int x, int y, uint8_t color)
|
||||
{
|
||||
gfx_putpixel256(x, y, color);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* _bgi_plot_raw (drv256) — пиксель без своей W3-скобки (вызывать между
|
||||
* _bgi_begin/_bgi_end). Клип по краю экрана делает сам raw-примитив.
|
||||
*/
|
||||
#include "../_bgi.h"
|
||||
#include "../../gfx/_gfx.h"
|
||||
|
||||
void _bgi_plot_raw(int x, int y, uint8_t color)
|
||||
{
|
||||
_gfx_putpixel256_raw(x, y, color);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* _bgi_read (drv256) — цвет пикселя (x,y). */
|
||||
#include "../_bgi.h"
|
||||
#include <gfx.h>
|
||||
|
||||
unsigned _bgi_read(int x, int y)
|
||||
{
|
||||
return gfx_getpixel256(x, y);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getbkcolor — текущий фоновый цвет. */
|
||||
#include "_bgi.h"
|
||||
|
||||
int getbkcolor(void)
|
||||
{
|
||||
return _bgi_bg;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getcolor — текущий цвет рисования. */
|
||||
#include "_bgi.h"
|
||||
|
||||
int getcolor(void)
|
||||
{
|
||||
return _bgi_fg;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getmaxcolor — максимальный индекс цвета (255 в 256-цветном режиме). */
|
||||
#include "_bgi.h"
|
||||
|
||||
int getmaxcolor(void)
|
||||
{
|
||||
return _bgi_maxcolor;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getmaxx — максимальная координата X (ширина-1). */
|
||||
#include "_bgi.h"
|
||||
|
||||
int getmaxx(void)
|
||||
{
|
||||
return _bgi_maxx;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getmaxy — максимальная координата Y (высота-1). */
|
||||
#include "_bgi.h"
|
||||
|
||||
int getmaxy(void)
|
||||
{
|
||||
return _bgi_maxy;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getpixel — цвет пикселя (x,y). */
|
||||
#include "_bgi.h"
|
||||
|
||||
unsigned getpixel(int x, int y)
|
||||
{
|
||||
return _bgi_read(x, y);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* getx — текущая позиция X. */
|
||||
#include "_bgi.h"
|
||||
|
||||
int getx(void)
|
||||
{
|
||||
return _bgi_cx;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* gety — текущая позиция Y. */
|
||||
#include "_bgi.h"
|
||||
|
||||
int gety(void)
|
||||
{
|
||||
return _bgi_cy;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* graphresult — код последней ошибки; вызов сбрасывает его в grOk. */
|
||||
#include "_bgi.h"
|
||||
|
||||
int graphresult(void)
|
||||
{
|
||||
int r = _bgi_result;
|
||||
_bgi_result = grOk;
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* initgraph — перейти в графический режим и сбросить состояние BGI.
|
||||
*
|
||||
* Режим определяется driver-библиотекой (для sprinter_gfx256 —
|
||||
* 320×256×256). По умолчанию: цвет WHITE, фон BLACK, позиция (0,0).
|
||||
*/
|
||||
|
||||
#include "_bgi.h"
|
||||
|
||||
void initgraph(void)
|
||||
{
|
||||
_bgi_prevmode = _bgi_mode_set();
|
||||
_bgi_fg = WHITE;
|
||||
_bgi_bg = BLACK;
|
||||
_bgi_cx = 0;
|
||||
_bgi_cy = 0;
|
||||
_bgi_result = grOk;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* line — отрезок (x1,y1)->(x2,y2) текущим цветом; CP не меняется. */
|
||||
#include "_bgi.h"
|
||||
|
||||
void line(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
_bgi_lineseg(x1, y1, x2, y2, _bgi_fg);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* linerel — линия от CP до CP+(dx,dy); CP сдвигается в конец. */
|
||||
#include "_bgi.h"
|
||||
|
||||
void linerel(int dx, int dy)
|
||||
{
|
||||
int nx = _bgi_cx + dx;
|
||||
int ny = _bgi_cy + dy;
|
||||
_bgi_lineseg(_bgi_cx, _bgi_cy, nx, ny, _bgi_fg);
|
||||
_bgi_cx = nx;
|
||||
_bgi_cy = ny;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* lineto — линия от CP до (x,y) текущим цветом; CP := (x,y). */
|
||||
#include "_bgi.h"
|
||||
|
||||
void lineto(int x, int y)
|
||||
{
|
||||
_bgi_lineseg(_bgi_cx, _bgi_cy, x, y, _bgi_fg);
|
||||
_bgi_cx = x;
|
||||
_bgi_cy = y;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* moverel — сдвинуть текущую позицию относительно. */
|
||||
#include "_bgi.h"
|
||||
|
||||
void moverel(int dx, int dy)
|
||||
{
|
||||
_bgi_cx += dx;
|
||||
_bgi_cy += dy;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* moveto — задать текущую позицию (CP). */
|
||||
#include "_bgi.h"
|
||||
|
||||
void moveto(int x, int y)
|
||||
{
|
||||
_bgi_cx = x;
|
||||
_bgi_cy = y;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* outtext — строка в текущей позиции (CP) текущим цветом; CP сдвигается
|
||||
* вправо на ширину строки (шрифт 8×8, 8 пикселей на символ).
|
||||
*/
|
||||
#include "_bgi.h"
|
||||
#include <string.h>
|
||||
|
||||
void outtext(const char *text)
|
||||
{
|
||||
_bgi_drawtext(_bgi_cx, _bgi_cy, text, _bgi_fg, _bgi_bg);
|
||||
_bgi_cx += (int)strlen(text) * 8;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* outtextxy — строка шрифтом 8×8 в (x,y) текущим цветом; CP не меняет. */
|
||||
#include "_bgi.h"
|
||||
|
||||
void outtextxy(int x, int y, const char *text)
|
||||
{
|
||||
_bgi_drawtext(x, y, text, _bgi_fg, _bgi_bg);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* putpixel — точка (x,y) заданным цветом (не трогает текущий цвет/CP). */
|
||||
#include "_bgi.h"
|
||||
|
||||
void putpixel(int x, int y, int color)
|
||||
{
|
||||
_bgi_plot(x, y, (uint8_t)color);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* rectangle — контур прямоугольника по углам (left,top)-(right,bottom). */
|
||||
#include "_bgi.h"
|
||||
|
||||
void rectangle(int left, int top, int right, int bottom)
|
||||
{
|
||||
uint8_t c = _bgi_fg;
|
||||
_bgi_lineseg(left, top, right, top, c); /* верх */
|
||||
_bgi_lineseg(right, top, right, bottom, c); /* право */
|
||||
_bgi_lineseg(right, bottom, left, bottom, c); /* низ */
|
||||
_bgi_lineseg(left, bottom, left, top, c); /* лево */
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* setbkcolor — задать фоновый цвет (cleardevice, фон текста). */
|
||||
#include "_bgi.h"
|
||||
|
||||
void setbkcolor(int color)
|
||||
{
|
||||
_bgi_bg = (uint8_t)color;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* setcolor — задать текущий цвет рисования. */
|
||||
#include "_bgi.h"
|
||||
|
||||
void setcolor(int color)
|
||||
{
|
||||
_bgi_fg = (uint8_t)color;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* gfx_getpixel256 — прочитать цвет пикселя (x,y) в режиме 0x81.
|
||||
*
|
||||
* Одиночный вызов в собственной W3-скобке. Адресация та же, что у
|
||||
* _gfx_putpixel256_raw: CPU _gfx_addr_base + x, Port_Y (0x89) = y.
|
||||
* За пределами экрана возвращает 0.
|
||||
*/
|
||||
|
||||
#include "_gfx.h"
|
||||
|
||||
static uint8_t _gfx_gp_y;
|
||||
static uint16_t _gfx_gp_addr;
|
||||
static uint8_t _gfx_gp_color;
|
||||
|
||||
uint8_t gfx_getpixel256(int x, int y)
|
||||
{
|
||||
if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return 0;
|
||||
_gfx_gp_y = (uint8_t)y;
|
||||
_gfx_gp_addr = (uint16_t)(_gfx_addr_base + (unsigned)x);
|
||||
_gfx_w3_video_begin();
|
||||
__asm
|
||||
ld a, (__gfx_gp_y)
|
||||
out (#0x89), a
|
||||
ld hl, (__gfx_gp_addr)
|
||||
ld a, (hl)
|
||||
ld (__gfx_gp_color), a
|
||||
__endasm;
|
||||
_gfx_w3_video_end();
|
||||
return _gfx_gp_color;
|
||||
}
|
||||
@@ -91,6 +91,7 @@ void gfx_wait_vsync(void);
|
||||
|
||||
void gfx_clear256 (uint8_t color);
|
||||
void gfx_putpixel256 (int x, int y, uint8_t color);
|
||||
uint8_t gfx_getpixel256 (int x, int y);
|
||||
void gfx_hline256 (int x, int y, int len, uint8_t color);
|
||||
void gfx_vline256 (int x, int y, int len, uint8_t color);
|
||||
void gfx_line256 (int x0, int y0, int x1, int y1, uint8_t color);
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user