Files
Sprinter-SDCC/libbgi/_bgi.h
T
snark13 5de2f06cfb libbgi: тривиальные аксессоры → inline в заголовках (17 модулей удалено)
setcolor/getcolor/setbkcolor/getbkcolor/getmaxx/getmaxy/getmaxcolor/
getx/gety/moveto/moverel/setfillstyle/graphresult (graphics.h) и
gfx_get_bank/gfx_set_bank/gfx_get_draw_page/gfx_get_visible_page
(gfx.h) определены inline в публичных заголовках; state-переменные
объявлены там же (хранилище прежнее — _bgi_state.c/_gfx_state.c).

Именно `inline` БЕЗ static: проверено артефактами (.asm) — SDCC 4.5
инлайнит вызов при всех наших флагах (--opt-code-size/--opt-code-speed/
--max-allocs) и не эмитит standalone-тело; `static inline` эмитил бы
мёртвую копию каждого аксессора в КАЖДЫЙ включивший модуль.  Отказ
инлайнить = громкая ошибка линковки (все 47 программ слинковались).

Экономия ~30-40Т на вызов, минус 17 .rel; по _CODE размер-нейтрально
(сайт вызова ≈ телу).  size_baseline: bgitest +267/accfill +528 — это
НЕ inline, а run-рендер текста из ba09c0b (draw_scaled потянул
vspan_raw+vfill256 и сам вырос) — цена за ~2-6× скорость текста.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 21:21:26 +03:00

201 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* _bgi.h — внутренности графической подсистемы BGI (НЕ публичный заголовок).
*
* Слияние старых libc/bgi/_bgi.h и libc/gfx/_gfx.h. Графика вынесена из
* libc в самостоятельную библиотеку libbgi/ (см. docs + memory
* bgi_two_lib_design). Из libbgi собираются две driver-библиотеки
* (каждый .c → отдельный .rel):
* bgi256.lib ← common/ + bgi256/ (320×256×256, mode 0x81)
* bgi16.lib ← common/ + bgi16/ (640×256×16, mode 0x82)
* common/ — mode-agnostic: .rel компилируется ОДИН раз и кладётся в
* ОБА архива (один исходник для функций, общих 256- и 16-цветной
* версиям). bgi256/ и bgi16/ — mode-specific leaf'ы (реальные
* реализации, БЕЗ обёрток-делегатов). Режим выбирается линковкой
* (--gfx 256 / --gfx 16), одновременно один.
*
* Публичные leaf-символы (_bgi_plot_raw, _bgi_hspan_raw, _bgi_read_raw,
* _bgi_vspan_raw, _bgi_clear_raw, _bgi_mode_set) одинаково объявлены в
* обоих driver-каталогах, поэтому common-математика не знает режима —
* нужный .rel тянет линкер из выбранной библиотеки.
*/
#ifndef _BGI_INTERNAL_H
#define _BGI_INTERNAL_H
#include <stdint.h>
#include <graphics.h>
#include <gfx.h> /* GFX_MODE_*, размеры — для внутренних таблиц */
/* ---- Состояние BGI (_bgi_state.c) -------------------------------- *
* _bgi_fg/_bgi_bg/_bgi_cx/_bgi_cy/_bgi_maxx/_bgi_maxy/_bgi_maxcolor/
* _bgi_result объявлены в ПУБЛИЧНОМ graphics.h (нужны static inline
* аксессорам: setcolor/moveto/getmaxx/…, 2026-07-10);
* _gfx_visible_page/_gfx_draw_page/_gfx_bank — в публичном gfx.h.
* Байт _gfx_bank (0x50..0x5F): какой видеобанк мапится при записи —
* 0x50 normal, 0x54 temp, 0x58 transparent, 0x5C оба. */
extern uint8_t _bgi_prevmode; /* видеорежим до initgraph */
/* CPU-адрес колонки 0 текущей draw-страницы: 0xC000 (page 0) или
* 0xC140 (page 1); каждый примитив использует его вместо константы. */
extern uint16_t _gfx_addr_base;
/* ---- Низкоуровневый видеорежим (libc/video) ---------------------- */
uint8_t _videomode_raw_get(void);
int _videomode_raw_set(uint8_t mode);
/* ---- W3-скобки (common/_bgi_begin.c, _bgi_end.c) ----------------- *
* begin: DI + сохранить текущий W3 и замапить _gfx_bank;
* end: восстановить W3 + EI. Не реентерабельно (сейв в статике). */
extern uint8_t _gfx_saved_w3;
void _bgi_begin(void) __preserves_regs(b,c,d,e,h,l);
void _bgi_end(void) __preserves_regs(b,c,d,e,h,l);
/* ---- LEAF-операции драйвера (bgi256/ или bgi16/) ----------------- *
* Каждая self-contained: raw-варианты НЕ ставят свою W3-скобку
* (вызывающий обязан обернуть в _bgi_begin/_bgi_end); self-bracket
* (_bgi_read/_bgi_hspan/_bgi_clearall) ставят скобку сами. */
uint8_t _bgi_mode_set(void); /* войти в режим + палитра + границы */
/* __preserves_regs(d,e): проверено по asm — эти примитивы читают D/E
* (y приходит в DE), но НЕ пишут; SDCC не обязан спасать DE вокруг
* вызова (экономит push/pop в горячих циклах Брезенхэма/блита).
* При правке asm сверять клоббер-лист заново! */
void _bgi_plot_raw (int x, int y, uint8_t color) __preserves_regs(d,e); /* точка, без скобки */
uint8_t _bgi_read_raw (int x, int y) __preserves_regs(d,e); /* чтение, без скобки */
void _bgi_hspan_raw(int x, int y, int len, uint8_t color) __preserves_regs(d,e); /* H-отрезок, без скобки */
void _bgi_vspan_raw(int x, int y, int len, uint8_t color) __preserves_regs(d,e); /* V-отрезок, без скобки */
void _bgi_clear_raw(uint8_t color); /* заливка экрана, без скобки (клоббер всех) */
/* Self-bracket версии (begin + raw + end) — для разовых вызовов из
* математики, которой не нужен пакетный режим (floodfill, cleardevice).
* Разовое чтение пикселя — публичный getpixel (та же композиция;
* бывший дубликат _bgi_read удалён 2026-07-10). */
void _bgi_hspan (int x, int y, int len, uint8_t color);
void _bgi_clearall(uint8_t color);
/* ---- Fill-burst'ы акселератора 256 (register-ABI, asm-only) ------ *
* Вызываются ТОЛЬКО из asm raw-примитивов; аргументы в регистрах, без
* глобального скретча в _DATA:
* HL = CPU-адрес (base + x), C = color,
* B = длина (0 = 256), E = y (строка для Port_Y).
* Клоббер A/F; сохраняют BC/DE/HL/IX/IY. Pre: W3 замаплен, IRQ гасятся
* внутри вокруг одного выстрела. Прототип void(void) — только чтобы
* линкер видел символ (реальный ABI регистровый, см. bgi256/_gfx_*fill256.c). */
/* Горизонтальный Fill-burst (bgi256/_gfx_hfill256.c). */
void _gfx_hfill256_segment(void);
/* Вертикальный Fill-burst (bgi256/_gfx_vfill256.c). */
void _gfx_vfill256_segment(void);
/* Заливка прямоугольника цветом: x, y, w, h, color.
* _gfx_rectfill256 — диспетчер: выбирает ориентацию с меньшим числом
* выстрелов (~160-245Т на проверку) и tail-jump'ит в leaf. Если форма
* известна заранее или |w-h| < ~4, выгоднее звать leaf напрямую:
* _gfx_recthfill256 — h горизонтальных строк, ТРЕБУЕТ 1 <= w <= 256;
* _gfx_rectvfill256 — w вертикальных колонок, ТРЕБУЕТ 1 <= h <= 256.
* Контракты/расчёт break-even — в шапках bgi256/_gfx_rect*fill256.c. */
void _gfx_rectfill256(int x, int y, int w, int h, uint8_t color);
void _gfx_recthfill256(int x, int y, int w, int h, uint8_t color);
void _gfx_rectvfill256(int x, int y, int w, int h, uint8_t color);
/* ---- Скретч 16-цветных примитивов (bgi16/_gfx_g16_state.c) ------- */
extern uint8_t _gfx_g16_y;
extern uint8_t _gfx_g16_byte; /* nibble | (nibble<<4) */
extern uint8_t _gfx_g16_nibble; /* цвет в нужной половине байта */
extern uint8_t _gfx_g16_mask; /* маска, сохраняющая ДРУГУЮ половину */
extern uint8_t _gfx_g16_len; /* размер accel-блока (0 = 256) */
extern uint16_t _gfx_g16_addr;
/* Горизонтальный Fill-burst байтами _gfx_g16_byte (bgi16/_gfx_hfill16.c). */
void _gfx_hfill16_chunk(void);
/* RMW одного нибла по (_gfx_g16_addr, _gfx_g16_y) (bgi16/_gfx_rmw16.c). */
void _gfx_rmw16_pixel(void);
/* ---- Шрифт (common/_gfx_font_state.c, _gfx_font_ensure.c) -------- *
* Формат: 256 глифов × 8 рядов, INTERLEAVED — offset = row*256 + char;
* биты MSB-first. См. memory/sprinter_font_format. */
#define _GFX_FONT_BYTES 2048
extern uint8_t _gfx_font_buf[_GFX_FONT_BYTES];
extern const uint8_t *_gfx_font_ptr;
extern uint8_t _gfx_font_loaded;
/* Ленивая инициализация: грузит системный шрифт при первом использовании. */
void _gfx_font_ensure(void);
/* 8 байт строк глифа c (грузит шрифт при первом использовании) —
* mode-agnostic, просто читает _gfx_font_ptr. common/_bgi_font_rows.c. */
void _bgi_font_rows(unsigned char c, uint8_t *rows8);
/* ---- Тригонометрия для дуг (common/_bgi_trig.c) ------------------ *
* Угол в градусах; результат sin/cos × 128 (Q7 — чтобы радиус×значение
* влезало в int без 32-бит арифметики). */
int _bgi_sin128(int deg);
int _bgi_cos128(int deg);
/* Общий рисователь дуги/контура эллипса (common/_bgi_arc_draw.c):
* полилиния по точкам от stangle до endangle с полуосями xr,yr вокруг
* (cx,cy). */
void _bgi_ellipse_arc(int cx, int cy, int stangle, int endangle,
int xr, int yr, uint8_t color);
/* Целочисленный sqrt (0..~32767) для fillellipse (common/_bgi_isqrt.c). */
int _bgi_isqrt(int n);
/* ---- Состояние линий (common/_bgi_line_state.c) ------------------ */
extern uint8_t _bgi_line_style; /* SOLID_LINE..USERBIT_LINE */
extern uint8_t _bgi_line_thick; /* 1 (NORM) или 3 (THICK) */
extern uint16_t _bgi_line_pattern; /* маска для USERBIT_LINE */
/* Отрезок текущим стилем/толщиной линии (common/_bgi_styled_line.c). */
void _bgi_styled_line(int x0, int y0, int x1, int y1, uint8_t color);
/* Отрезок (x0,y0)->(x1,y1) БЕЗ стиля: ортогонал → hspan/vspan,
* диагональ → Брезенхэм over _bgi_plot_raw, своя W3-скобка
* (common/_bgi_lineseg.c). Реальная логика, не обёртка. */
void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color);
/* ---- Состояние заливки (common/_bgi_fill_state.c) ---------------- */
extern uint8_t _bgi_fill_pattern; /* *_FILL */
extern uint8_t _bgi_fill_color;
/* Залить строку [x0..x1] на y ТЕКУЩИМ стилем заливки (паттерн+цвет),
* с клипом по экрану. Вызывать между _bgi_begin/_bgi_end. */
void _bgi_fill_span(int x0, int x1, int y);
/* ---- Стиль текста (common/_bgi_text_state.c) --------------------- */
extern uint8_t _bgi_text_dir; /* HORIZ_DIR / VERT_DIR */
extern uint8_t _bgi_text_size; /* масштаб 1..10 */
/* Нарисовать строку s в (x,y) текущим стилем текста (масштаб/направление,
* цвет _bgi_fg, прозрачный фон) — common/_bgi_draw_scaled.c. */
void _bgi_draw_scaled(int x, int y, const char *s);
/* ---- Скан-таблицы min/max X по строкам для fillpoly -------------- *
* (common/_bgi_poly_state.c). GFX_HEIGHT — высота экрана (256 в обоих
* режимах), см. <gfx.h>. */
extern int _bgi_span_min[GFX_HEIGHT];
extern int _bgi_span_max[GFX_HEIGHT];
/* Прогнать ребро (Брезенхэм) обновляя _bgi_span_min/max
* (common/_bgi_poly_edge.c). */
void _bgi_poly_edge(int x0, int y0, int x1, int y1);
/* ---- Cross-library: внутренние символы libc/cbl ------------------ *
* libbgi ВСЕГДА линкуется вместе с libc (sprinter.lib), поэтому
* зависимость от внутренних символов libc допустима. gfx_wait_vsync
* держит bit7 порта 0x004E через рефкаунт _cbl_port_ref/unref, чтобы
* бит 5 порта 0xFE (позиция луча) был доступен.
* ВНИМАНИЕ: это ВНУТРЕННИЕ символы libc/cbl — при изменении сигнатур
* СВЕРЯТЬ с libc/cbl/_cbl.h и синхронизировать. (По тому же паттерну,
* каким здесь живут _videomode_raw_* из libc/video.) */
extern void _cbl_port_ref(void);
extern void _cbl_port_unref(void);
#endif