diff --git a/.gitignore b/.gitignore
index fa15163..651e592 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,7 @@
# ===========================================================================
# `build/` directories anywhere in the tree
-# (top-level build/, lib/build/, toolchain/*/build/, ...)
+# (top-level build/, libc/build/, libbgi/build/, toolchain/*/build/, ...)
build/
# sprinter-cc per-example intermediate directory
@@ -40,7 +40,7 @@ tests/*/*.cdb
tests/*/*.mem
tests/*/*.rst
-# libc archive (built from libc/, see lib/Makefile)
+# libc + libbgi archives (built by libc/Makefile + libbgi/Makefile)
lib/*.lib
# Host-built mkexe binary + test outputs (input fixtures *.bin/*.ihx kept)
diff --git a/CLAUDE.md b/CLAUDE.md
index bbdc742..baec71d 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -6,20 +6,26 @@ Target-слой SDCC 4.5 (z80) для компьютера Sprinter Sp2000: crt0
## Сборка и проверка
```
-make # tools + lib + все тесты (43) + examples
-make -C lib # только libc → lib/sprinter.lib
+make # tools + lib + libbgi + все тесты (45) + examples
+make -C libc # только libc → lib/sprinter.lib
+make -C libbgi # только BGI → lib/bgi256.lib (и bgi16.lib в Фазе 2)
make floppy # упаковать все .exe в mame/v306/IMG/mc.img
make size-check # размерный регресс: _CODE vs docs/size_baseline.tsv
make size-baseline # принять текущие размеры эталоном
```
+Графика (BGI) — отдельная библиотека libbgi/ (см. ниже). Программа,
+использующая graphics.h, собирается с `--gfx 256` (или `--gfx 16` в
+Фазе 2): sprinter-cc подлинкует lib/bgi256.lib и добавит -I libbgi/include.
+
Одиночный тест: `cd tests/<имя> && make run` (пакует ТОЛЬКО этот exe
+ EXTRA_DATA на дискету и запускает MAME). Тесты в MAME гоняет
пользователь — готовь дискету и проси прогнать.
-После правок libc: пересборка от чистого листа (`make -C lib clean`)
-не обязательна — stale .rel чистятся автоматически; `make size-check`
-обязателен (рост _CODE без причины — регрессия).
+После правок libc/libbgi: пересборка от чистого листа (`make -C libc clean`
+/ `make -C libbgi clean`) не обязательна — stale .rel чистятся
+автоматически; `make size-check` обязателен (рост _CODE без причины —
+регрессия).
## Правила libc
@@ -29,7 +35,7 @@ make size-baseline # принять текущие размеры эталон
(`_`-префикс); общие статики — в отдельные data-модули
(`_xxx_state.c`); internal-заголовки (`_file.h`, `_gfx.h`, …) —
рядом с исходниками, НЕ в libc/include.
-- Имя файла = имя функции. lib/Makefile собирает wildcard'ом —
+- Имя файла = имя функции. libc/Makefile собирает wildcard'ом —
ничего регистрировать не надо.
- Комментарии — на русском; шапка модуля объясняет что/зачем + ABI.
- File-scope переменные НЕ инициализировать `= 0` (crt0 зануляет
@@ -54,12 +60,13 @@ make size-baseline # принять текущие размеры эталон
лимит 8 файловых манипуляторов, 9-й OPEN ВЕШАЕТ DSS (_fd_guard);
ENV $46: A=0 = NOT FOUND.
- Перед обвинением компилятора/железа — подтвердить артефактом
- (сгенерированный .asm в lib/build/, дамп, репро) — см.
+ (сгенерированный .asm в libc/build/ или libbgi/build/, дамп, репро) — см.
memory/defer_unexplained_quirks.
## Структура
-- `libc//*.c` — модули libc; `libc/include/` — публичные заголовки
+- `libc//*.c` — модули libc (ядро, БЕЗ графики); `libc/include/` — публичные заголовки libc
+- `libbgi/` — графика BGI (отдельная библиотека): `common/` — mode-agnostic (один исходник, .rel в обеих driver-библиотеках), `bgi256/` + `bgi16/` — mode-specific leaf'ы (реальные реализации, без обёрток); `include/` — graphics.h + gfx.h; `_bgi.h` — внутренний заголовок. Собирает `lib/bgi256.lib` (и `bgi16.lib` в Фазе 2). Выбор режима линковкой: `--gfx 256` / `--gfx 16`.
- `runtime/` — crt0-семейство, heap, bank (bank.s собирается per-build)
- `bin/sprinter-cc` — обёртка компилятора; `toolchain/mkexe` — упаковщик
- `tests/` — по одному API/фиче; `examples/` — реальные приложения
diff --git a/Makefile b/Makefile
index d243ba7..6ef56cf 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
#
# make build host tools, libc archive, all tests, all apps
# make tools build only host tools (mkexe)
-# make lib build lib/sprinter.lib (libc archive used by sprinter-cc)
+# make lib build lib/sprinter.lib (libc) + lib/bgi256.lib (libbgi)
# make tests build all libc feature tests under tests/
# make examples build all real applications under examples/
# make floppy package every .exe + test fixtures into mame/v306/IMG/mc.img
@@ -18,8 +18,9 @@ TESTS := hello hello2 simple banked bankedbg banktest strtest cat seek \
attrprob timedir mouse banklocl stdlib assrtest ptime stattest \
filetest fdmax fbench solidt irqtest cbltest cblwav dec_test gets stest2 winrest \
bios_text text_palette \
- gfx_demo gfx_d16 gfx_text gfx_mous gfx_dbuf
-
+ gfx_demo gfx_dbuf
+# gfx_d16 / gfx_text / gfx_mous — 16-цветные; убраны до Фазы 2 (bgi16.lib
+# ещё не собирается). Вернуть мигрированными на BGI --gfx 16.
# Larger end-user applications under examples/.
APPS := mdview mdview2
@@ -46,7 +47,8 @@ tools:
$(MAKE) -C toolchain/mkexe
lib:
- $(MAKE) -C lib
+ $(MAKE) -C libc
+ $(MAKE) -C libbgi
check: tools
$(MAKE) -C toolchain/mkexe check
@@ -81,7 +83,8 @@ size-baseline:
clean:
$(MAKE) -C toolchain/mkexe clean
- $(MAKE) -C lib clean
+ $(MAKE) -C libc clean
+ $(MAKE) -C libbgi clean
@for t in $(TESTS); do $(MAKE) -C tests/$$t clean; done
@for a in $(APPS); do $(MAKE) -C examples/$$a clean; done
diff --git a/app.mk b/app.mk
index 3b59957..f65e918 100644
--- a/app.mk
+++ b/app.mk
@@ -62,8 +62,13 @@ $(EXAMPLE).exe: $(SOURCES) $(MKEXE) $(LIB) $(RUNTIME_DEPS)
$(MKEXE):
$(MAKE) -C $(PROJ_ROOT)/toolchain/mkexe
+# $(LIB) = lib/sprinter.lib (libc). Графика (bgi256.lib) собирает
+# libbgi/Makefile; гоним и его — иначе standalone `make` в тесте с
+# --gfx 256 не найдёт bgi256.lib при линковке. Оба инкрементальные,
+# на повторном запуске ничего не пересобирают.
$(LIB):
- $(MAKE) -C $(PROJ_ROOT)/lib
+ $(MAKE) -C $(PROJ_ROOT)/libc
+ $(MAKE) -C $(PROJ_ROOT)/libbgi
clean:
rm -rf .sprinter-cc-* $(EXAMPLE).exe
diff --git a/bin/sprinter-cc b/bin/sprinter-cc
index b8a46a0..51e102f 100755
--- a/bin/sprinter-cc
+++ b/bin/sprinter-cc
@@ -64,6 +64,7 @@ CHECK_BANKS="$PROJ_ROOT/toolchain/check_banks.py"
RUNTIME="$PROJ_ROOT/runtime"
LIB_DIR="$PROJ_ROOT/lib"
INC_DIR="$PROJ_ROOT/libc/include"
+BGI_INC_DIR="$PROJ_ROOT/libbgi/include" # gfx.h, graphics.h (BGI)
# ------- Defaults ------------------------------------------------------------
OUT=""
@@ -129,7 +130,7 @@ done
GFX_LD=()
case "$GFX_MODE" in
"") ;; # graphics.h не используется
- 256) GFX_LD=("-lsprinter_gfx256");;
+ 256) GFX_LD=("-lbgi256");; # libbgi/bgi256 → lib/bgi256.lib
16) echo "sprinter-cc: --gfx 16 ещё не реализован (пока только 256)" >&2; exit 1;;
*) echo "sprinter-cc: --gfx: ожидается 256 (или 16), дано: $GFX_MODE" >&2; exit 1;;
esac
@@ -288,7 +289,7 @@ run "$SDASZ80" -o "$HEAP_TOP_REL" "$HEAP_TOP_SRC"
# 2. user sources → .rel (HOME)
USER_RELS=()
-CC_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size -I "$INC_DIR" "${USER_INCS[@]}")
+CC_FLAGS=(-mz80 --no-std-crt0 --std-c99 --opt-code-size -I "$INC_DIR" -I "$BGI_INC_DIR" "${USER_INCS[@]}")
[[ $DEBUG_RT -eq 1 ]] && CC_FLAGS+=(-DDEBUG_RT)
[[ -n "$MAX_ALLOCS" ]] && CC_FLAGS+=(--max-allocs-per-node "$MAX_ALLOCS")
for src in "${SOURCES[@]}"; do
diff --git a/docs/libc-headers.md b/docs/libc-headers.md
index 49ccf2b..60a20aa 100644
--- a/docs/libc-headers.md
+++ b/docs/libc-headers.md
@@ -32,9 +32,15 @@ SDCC-версию) и дальше только добавляет Sprinter-ра
## 3. Свои заголовки (SDCC-аналога нет — затенения нет)
-conio.h, dir.h, dos.h, errno.h, fcntl.h, gfx.h, mouse.h, palette.h,
+conio.h, dir.h, dos.h, errno.h, fcntl.h, mouse.h, palette.h,
sprinter*.h, unistd.h, bios/*.
+Графика вынесена из libc в отдельную библиотеку libbgi/: её публичные
+заголовки gfx.h (mode-agnostic BGI_GFX) и graphics.h (BGI API) живут в
+libbgi/include/ и пробрасываются через -I libbgi/include (sprinter-cc
+добавляет его автоматически). Внутренний заголовок графики —
+libbgi/_bgi.h (слияние старых libc/gfx/_gfx.h и libc/bgi/_bgi.h).
+
## Правила
- новый стандартный заголовок — сначала пробовать паттерн 1
@@ -42,5 +48,7 @@ sprinter*.h, unistd.h, bios/*.
реализацию (как puts/putchar на ESTEX);
- в заголовках паттерна 2 — комментарий, какие декларации обслуживают
z80.lib;
-- internal-заголовки libc (`_conio.h`, `_file.h`, `_gfx.h`, …) живут
- РЯДОМ с исходниками в libc//, не в libc/include.
+- internal-заголовки libc (`_conio.h`, `_file.h`, …) живут
+ РЯДОМ с исходниками в libc//, не в libc/include. Internal
+ графики — в libbgi/_bgi.h (корень libbgi/, подключается из common/ и
+ bgi256/bgi16/ как `#include "../_bgi.h"`).
diff --git a/docs/libc-reference.md b/docs/libc-reference.md
index 47b88f6..6bf493f 100644
--- a/docs/libc-reference.md
+++ b/docs/libc-reference.md
@@ -180,7 +180,13 @@ wrchar rdchar`; режимы `gettextmode/settextmode` (0x02=40×32,
`bios_fillchar/fillattr/fillcharattr`, `bios_clearwin[_ch]`,
`bios_scrollwin`. Строка s — в #4000–#BFFF; place продвигается.
-## — графика (0x81: 320×256×256; 0x82: 640×256×16)
+## — графика, mode-agnostic API (BGI_GFX); живёт в libbgi/include
+
+Рисование (putpixel/line/bar/circle/…) вынесено в BGI — см. ``
+и driver-библиотеки lib/bgi256.lib / lib/bgi16.lib (выбор режима линковкой:
+`sprinter-cc --gfx 256` / `--gfx 16`). В gfx.h остались только функции
+БЕЗ BGI-аналога (mode-agnostic, живут в libbgi/common/, .rel в обеих
+ driver-библиотеках):
Setup: `gfx_init(mode,page)→prev`, `gfx_done(prev)`.
Страницы/банк: `gfx_set/get_visible_page`, `gfx_set/get_draw_page`
@@ -199,14 +205,13 @@ Setup: `gfx_init(mode,page)→prev`, `gfx_done(prev)`.
использования с реальным CBL-звуком. Фолбэк на одно кадровое
прерывание (`halt`), если бит не ведёт себя как ожидается за разумное
число попыток.
-Примитивы (суффикс _256 / _16): `clear putpixel hline vline line
-rect fill_rect` — через акселератор (hline/vline burst до 256 байт;
-в 0x82 vline через RMW). Координаты int, клиппинг по краям.
-Текст: `gfx_putchar256/16, gfx_text256/16` (8×8, fg/bg; в 0x82 x —
-чётный), `gfx_load_default_font`, `gfx_set_font(ptr)` (interleaved
-font[row*256+char]).
+Шрифт: `gfx_load_default_font`, `gfx_set_font(ptr)` (interleaved
+font[row*256+char]) — грузится лениво при первом использовании BGI-текста.
Палитра: `gfx_pal_load/set/get/get_color/reset` (страницы 0..3).
-`gfx_getpixel256(x,y)→color` — чтение пикселя (0x81).
+
+Константы режимов: `GFX_MODE_320x256x256` (0x81), `GFX_MODE_640x256x16`
+(0x82); размеры `GFX_WIDTH/HEIGHT` (320/256), `GFX_WIDTH_16/HEIGHT_16`
+(640/256). Рисование через `` (BGI).
## — Turbo-C BGI (функц. совместимость), Фаза 1, режим 256
@@ -237,9 +242,15 @@ drawpoly.
Стиль текста (Ф2d): `settextstyle(font,dir,size)`/`gettextsettings`,
`textwidth`/`textheight` — масштаб 1..10, HORIZ/VERT, прозрачный фон
(только DEFAULT_FONT 8×8).
-Реализация: libc/bgi/*.c (math) + libc/bgi/drv256/*.c (leaf →
-sprinter_gfx256.lib). Пакетные примитивы — одна W3-скобка на примитив;
-тригонометрия/эллипсы целочисленные (Q7/isqrt, БЕЗ 32-бит).
+Реализация: libbgi/common/*.c (mode-agnostic math + BGI public API +
+BGI_GFX) + libbgi/bgi256/*.c (256-цветные leaf'ы) → lib/bgi256.lib
+(Фаза 2 добавит libbgi/bgi16/*.c → lib/bgi16.lib; common .rel одни и
+те же в обоих архивах). Leaf'ы — реальные реализации (БЕЗ обёрток:
+putpixel/getpixel полностью inline, _bgi_plot_raw/_bgi_hspan_raw/...
+поглощают акселераторный asm). Пакетные примитивы — одна W3-скобка
+на примитив; тригонометрия/эллипсы целочисленные (Q7/isqrt, БЕЗ 32-бит).
+Cross-lib: libbgi всегда линкуется с libc; _cbl_port_ref/unref
+объявлены extern в libbgi/_bgi.h (сверять с libc/cbl/_cbl.h).
Ф2d (осталось): setviewport/клиппинг, settextjustify, setaspectratio —
см. docs/TODO.md.
diff --git a/docs/libc-roadmap.md b/docs/libc-roadmap.md
index 3e33cff..205f074 100644
--- a/docs/libc-roadmap.md
+++ b/docs/libc-roadmap.md
@@ -75,7 +75,7 @@ fgetpos/fsetpos (хвост П2). bdos/brk/ioctl — отказ решение
(stdio.h, time.h — обязаны дублировать сигнатуры z80.lib);
из sprinter_compat.h убраны макросы min/max (конфликтовали с
функциями из stdlib.h; в Solid-C это тоже функции)
-- [x] lib/Makefile: stale .rel чистятся сверкой списка перед упаковкой;
+- [x] libc/Makefile: stale .rel чистятся сверкой списка перед упаковкой;
штамп .modules триггерит перелинковку при смене состава (и сносит
архив — mtime на exFAT грубый)
- [x] Все extra-тесты в top-level TESTS (43 программы: + hello2, simple,
diff --git a/docs/size_baseline.tsv b/docs/size_baseline.tsv
index b016a5c..3a26e4b 100644
--- a/docs/size_baseline.tsv
+++ b/docs/size_baseline.tsv
@@ -6,6 +6,7 @@ banked 1056
bankedbg 1067
banklocl 4832
banktest 3767
+bgi_img 6218
bgitest 4196
bios_text 4470
cat 915
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index eace06d..0000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,104 +0,0 @@
-# Build lib/libsprinter.lib — the Sprinter target libc archive.
-#
-# Includes all libc/*.c modules plus the runtime helpers that get
-# auto-pulled by SDCC's codegen (heap for malloc, bank trampolines for
-# __banked). The crt0 family is NOT in the lib — they are always
-# explicitly linked, never DCE-eligible.
-#
-# Each .c file becomes its own .rel inside the archive. The linker
-# pulls only those .rel files whose exported symbols are referenced,
-# giving free dead-code elimination at module granularity.
-
-PROJ_ROOT := $(abspath $(CURDIR)/..)
-SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin
-SDCC := $(SDCC_BIN)/sdcc
-SDAR := $(SDCC_BIN)/sdar
-SDASZ80 := $(SDCC_BIN)/sdasz80
-
-INC := -I$(PROJ_ROOT)/libc/include
-CC_FLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC)
-
-BUILD := $(PROJ_ROOT)/lib/build
-
-# All libc C modules — every .c under libc// becomes its own .rel.
-# One PUBLIC function per file (see docs/libc-split-asm-cases.md): the
-# linker pulls whole .rel modules, so file granularity == DCE granularity.
-# Внимание: `libc/*/*.c` — ровно ОДИН уровень вложенности, поэтому
-# ловит mode-agnostic BGI-математику libc/bgi/*.c (идёт в sprinter.lib),
-# но НЕ ловит driver-leaf'ы libc/bgi/drv256/*.c (два уровня) — они
-# собираются в ОТДЕЛЬНЫЙ архив sprinter_gfx256.lib (выбор режима
-# линковкой; см. memory/bgi_two_lib_design).
-LIBC_C := $(patsubst $(PROJ_ROOT)/%,%,$(wildcard $(PROJ_ROOT)/libc/*/*.c))
-
-# Driver-leaf'ы 256-цветного BGI → sprinter_gfx256.lib.
-GFX256_C := $(patsubst $(PROJ_ROOT)/%,%,$(wildcard $(PROJ_ROOT)/libc/bgi/drv256/*.c))
-
-# Runtime modules to bundle (pulled by symbol references from libc-using code).
-# NOTE: runtime/bank.s is NOT bundled — its trampoline depends on the banking
-# window (W1 for BIG, W3 for HUGE) which is decided per-build by sprinter-cc.
-# That tool assembles bank.s on each banked build with the right BANK_W1 flag.
-RUNTIME_S := runtime/heap.s
-
-LIBC_RELS := $(patsubst libc/%.c,$(BUILD)/%.rel,$(LIBC_C))
-GFX256_RELS := $(patsubst libc/%.c,$(BUILD)/%.rel,$(GFX256_C))
-RUNTIME_RELS := $(patsubst runtime/%.s,$(BUILD)/%.rel,$(RUNTIME_S))
-
-# Члены основной sprinter.lib.
-ALL_RELS := $(LIBC_RELS) $(RUNTIME_RELS)
-# Всё, что вообще собираем (для штампа и чистки stale — иначе .rel'ы
-# драйвера сочтутся «осиротевшими» и будут удалены).
-KNOWN_RELS := $(ALL_RELS) $(GFX256_RELS)
-
-# Штамп списка модулей: обновляется при любом изменении состава
-# (добавление/удаление/переименование исходника) — иначе удаление
-# исходника не триггерит перелинковку и stale .rel остаётся в архиве.
-# Сразу сносим и архив: на exFAT (SAM8) гранулярность mtime грубая,
-# и «список изменился» через сравнение времён можно проглядеть.
-MODLIST := $(BUILD)/.modules
-ifneq ($(shell cat $(MODLIST) 2>/dev/null),$(KNOWN_RELS))
-_ := $(shell mkdir -p $(BUILD); echo "$(KNOWN_RELS)" > $(MODLIST); rm -f sprinter.lib sprinter_gfx256.lib)
-endif
-
-LIB := sprinter.lib
-GFX256_LIB := sprinter_gfx256.lib
-
-all: $(LIB) $(GFX256_LIB)
-
-# Pattern rule for C modules — preserves the libc/io|mem|stdio path
-# so .rel members keep their natural names inside the archive.
-$(BUILD)/%.rel: $(PROJ_ROOT)/libc/%.c
- @mkdir -p $(dir $@)
- $(SDCC) $(CC_FLAGS) -c -o $@ $<
-
-# Runtime .s → .rel
-$(BUILD)/%.rel: $(PROJ_ROOT)/runtime/%.s
- @mkdir -p $(dir $@)
- $(SDASZ80) -o $@ $<
-
-# Archive — sdar with `rcs` = replace/create/symtab.
-# Перед упаковкой удаляем stale .rel: wildcard не знает об удалённых/
-# переименованных исходниках, и осиротевший .rel из build/ иначе жил бы
-# вечно (уже кусало: старый file.rel после сплита).
-$(LIB): $(ALL_RELS) $(MODLIST)
- @find $(BUILD) -name '*.rel' -print | sort > $(BUILD)/.have
- @printf '%s\n' $(KNOWN_RELS) | sort > $(BUILD)/.want
- @comm -23 $(BUILD)/.have $(BUILD)/.want | while read f; do \
- echo " stale: $$f (исходник удалён) — rm"; \
- rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \
- done
- rm -f $@
- $(SDAR) -rcs $@ $(ALL_RELS)
- @echo
- @echo " Built $@ with $(words $(ALL_RELS)) modules:"
- @$(SDAR) -t $@ | sed 's/^/ /'
-
-# Driver-архив 256-цветного BGI: только leaf'ы drv256/.
-$(GFX256_LIB): $(GFX256_RELS) $(MODLIST)
- rm -f $@
- $(SDAR) -rcs $@ $(GFX256_RELS)
- @echo " Built $@ with $(words $(GFX256_RELS)) modules."
-
-clean:
- rm -rf $(BUILD) $(LIB) $(GFX256_LIB)
-
-.PHONY: all clean
diff --git a/libbgi/Makefile b/libbgi/Makefile
new file mode 100644
index 0000000..8513c83
--- /dev/null
+++ b/libbgi/Makefile
@@ -0,0 +1,79 @@
+# Build lib/bgi256.lib — Sprinter BGI graphics driver (320×256×256).
+#
+# libbgi/ — самостоятельная графическая библиотека, отделённая от libc.
+# Две driver-библиотеки собираются из одной исходной базы:
+# bgi256.lib = common/*.rel + bgi256/*.rel (эта — Фаза 1)
+# bgi16.lib = common/*.rel + bgi16/*.rel (Фаза 2; пока не собирается)
+# common/ — mode-agnostic: .rel компилируется ОДИН раз и кладётся в ОБА
+# архива (один исходник для функций, общих 256- и 16-цветной версиям).
+# bgi256/ — mode-specific leaf'ы (реальные реализации, без обёрток).
+#
+# Каждый .c — отдельный .rel в архиве (1 публичная функция = 1 модуль);
+# линкер тянет только нужные .rel → DCE на уровне файлов. См. план
+# «Рефакторинг GFX → BGI» и memory/bgi_two_lib_design.
+#
+# make build lib/bgi256.lib
+# make clean remove build/ + lib/bgi256.lib
+#
+# (Фаза 2 добавит bgi16.lib = common + bgi16; common .rel переиспользуются.)
+
+PROJ_ROOT := $(abspath $(CURDIR)/..)
+SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin
+SDCC := $(SDCC_BIN)/sdcc
+SDAR := $(SDCC_BIN)/sdar
+
+# -I libbgi/include (gfx.h, graphics.h) + -I libc/include (palette.h,
+# sprinter_exit.h — публичные заголовки libc; libbgi всегда линкуется с
+# libc). SDCC stdint и пр. — из собственного include-пути SDCC.
+INC := -I$(CURDIR)/include -I$(PROJ_ROOT)/libc/include
+CC_FLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC)
+
+BUILD := $(CURDIR)/build
+
+COMMON_C := $(wildcard $(CURDIR)/common/*.c)
+BGI256_C := $(wildcard $(CURDIR)/bgi256/*.c)
+# BGI16_C := $(wildcard $(CURDIR)/bgi16/*.c) # Фаза 2
+
+COMMON_RELS := $(patsubst $(CURDIR)/common/%.c,$(BUILD)/common/%.rel,$(COMMON_C))
+BGI256_RELS := $(patsubst $(CURDIR)/bgi256/%.c,$(BUILD)/bgi256/%.rel,$(BGI256_C))
+KNOWN_RELS := $(COMMON_RELS) $(BGI256_RELS)
+
+LIB_DIR := $(PROJ_ROOT)/lib
+LIB256 := $(LIB_DIR)/bgi256.lib
+
+# Штамп списка модулей — иначе удаление/переименование исходника не
+# триггерит перелинковку и stale .rel остаётся в архиве. На exFAT
+# грубая mtime — сравниваем по списку, не по времени.
+MODLIST := $(BUILD)/.modules
+ifneq ($(shell cat $(MODLIST) 2>/dev/null),$(KNOWN_RELS))
+_ := $(shell mkdir -p $(BUILD); echo "$(KNOWN_RELS)" > $(MODLIST); rm -f $(LIB256))
+endif
+
+all: $(LIB256)
+
+# Pattern rule для common/ и bgi256/ (один уровень под build/).
+$(BUILD)/common/%.rel: $(CURDIR)/common/%.c
+ @mkdir -p $(dir $@)
+ $(SDCC) $(CC_FLAGS) -c -o $@ $<
+
+$(BUILD)/bgi256/%.rel: $(CURDIR)/bgi256/%.c
+ @mkdir -p $(dir $@)
+ $(SDCC) $(CC_FLAGS) -c -o $@ $<
+
+# Archive — sdar rcs = replace/create/symtab. Перед упаковкой удаляем
+# stale .rel (wildcard не знает об удалённых исходниках).
+$(LIB256): $(COMMON_RELS) $(BGI256_RELS) $(MODLIST)
+ @find $(BUILD) -name '*.rel' -print | sort > $(BUILD)/.have
+ @printf '%s\n' $(KNOWN_RELS) | sort > $(BUILD)/.want
+ @comm -23 $(BUILD)/.have $(BUILD)/.want | while read f; do \
+ echo " stale: $$f (исходник удалён) — rm"; \
+ rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \
+ done
+ rm -f $@
+ $(SDAR) -rcs $@ $(COMMON_RELS) $(BGI256_RELS)
+ @echo " Built $@ with $(words $(COMMON_RELS)) common + $(words $(BGI256_RELS)) bgi256 modules."
+
+clean:
+ rm -rf $(BUILD) $(LIB256)
+
+.PHONY: all clean
diff --git a/libbgi/_bgi.h b/libbgi/_bgi.h
new file mode 100644
index 0000000..554bbb5
--- /dev/null
+++ b/libbgi/_bgi.h
@@ -0,0 +1,197 @@
+/*
+ * _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
+#include
+#include /* GFX_MODE_*, размеры — для внутренних таблиц */
+
+/* ---- Состояние BGI (_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 / 639) */
+extern int _bgi_maxy; /* нижняя граница (255) */
+extern int _bgi_maxcolor; /* макс. индекс цвета (255 / 15) */
+extern uint8_t _bgi_prevmode; /* видеорежим до initgraph */
+extern int _bgi_result; /* код graphresult */
+
+/* ---- Общее gfx-состояние (common/_gfx_state.c) ------------------ *
+ * Пишут gfx_set_visible_page / gfx_set_draw_page /
+ * gfx_set_bank; читают все mode-специфичные примитивы. */
+
+extern uint8_t _gfx_visible_page;
+extern uint8_t _gfx_draw_page;
+
+/* Байт страницы W3 (0x50..0x5F) — какой видеобанк мапится при записи.
+ * См. memory/sprinter_vram_transparency.md (0x50 normal, 0x54 temp,
+ * 0x58 transparent, 0x5C оба). */
+extern uint8_t _gfx_bank;
+
+/* 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);
+void _bgi_end(void);
+
+/* ---- 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); /* войти в режим + палитра + границы */
+
+void _bgi_plot_raw (int x, int y, uint8_t color); /* точка, без скобки */
+uint8_t _bgi_read_raw (int x, int y); /* чтение, без скобки */
+void _bgi_hspan_raw(int x, int y, int len, uint8_t color); /* H-отрезок, без скобки */
+void _bgi_vspan_raw(int x, int y, int len, uint8_t color); /* V-отрезок, без скобки */
+void _bgi_clear_raw(uint8_t color); /* заливка экрана, без скобки */
+
+/* Self-bracket версии (begin + raw + end) — для разовых вызовов из
+ * математики, которой не нужен пакетный режим (floodfill, cleardevice).
+ * _bgi_read возвращает цвет пикселя как unsigned (в SDCC __sdcccall(1)
+ * 8-битный возврат идёт в A, расширяется до int). */
+unsigned _bgi_read (int x, int y);
+void _bgi_hspan (int x, int y, int len, uint8_t color);
+void _bgi_clearall(uint8_t color);
+
+/* ---- Скретч акселератора 256 (bgi256/_gfx_acc256.c) -------------- *
+ * Общий для hspan/vspan/clear; однопоточно, IRQ выключены между
+ * _bgi_begin/_bgi_end. */
+extern uint8_t _gfx_acc_color;
+extern uint8_t _gfx_acc_y;
+extern uint8_t _gfx_acc_len; /* 0 = 256 — конвенция акселератора */
+extern uint16_t _gfx_acc_addr;
+
+/* Горизонтальный Fill-burst: _gfx_acc_len байт с _gfx_acc_addr на
+ * строке _gfx_acc_y (W3 замаплен, DI активен). */
+void _gfx_hfill256_chunk(void);
+
+/* ---- Скретч 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 в обоих
+ * режимах), см. . */
+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
diff --git a/libc/gfx/_gfx_clear16_raw.c b/libbgi/bgi16/_bgi_clear_raw.c
similarity index 76%
rename from libc/gfx/_gfx_clear16_raw.c
rename to libbgi/bgi16/_bgi_clear_raw.c
index 94ddf97..c561091 100644
--- a/libc/gfx/_gfx_clear16_raw.c
+++ b/libbgi/bgi16/_bgi_clear_raw.c
@@ -1,11 +1,11 @@
/*
- * _gfx_clear16_raw — залить всё поле 640×256 цветом color, mode 0x82.
+ * _bgi_clear_raw — залить всё поле 640×256 цветом color, mode 0x82.
* Построчный hfill: 256 строк × 2 burst'а (256 + 64 байта). W3-naive.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
-void _gfx_clear16_raw(uint8_t color)
+void _bgi_clear_raw(uint8_t color)
{
_gfx_g16_byte = (uint8_t)((color & 0x0F) | ((color & 0x0F) << 4));
for (int y = 0; y < GFX_HEIGHT_16; y++) {
diff --git a/libc/gfx/_gfx_hline16_raw.c b/libbgi/bgi16/_bgi_hspan_raw.c
similarity index 90%
rename from libc/gfx/_gfx_hline16_raw.c
rename to libbgi/bgi16/_bgi_hspan_raw.c
index 83b95dd..12811df 100644
--- a/libc/gfx/_gfx_hline16_raw.c
+++ b/libbgi/bgi16/_bgi_hspan_raw.c
@@ -1,12 +1,12 @@
/*
- * _gfx_hline16_raw — горизонтальная линия len пикселей от (x,y),
+ * _bgi_hspan_raw — горизонтальная линия len пикселей от (x,y),
* mode 0x82: невыровненные крайние ниблы через RMW, середина —
* Fill-burst'ами акселератора по целым байтам. W3-naive.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
-void _gfx_hline16_raw(int x, int y, int len, uint8_t color)
+void _bgi_hspan_raw(int x, int y, int len, uint8_t color)
{
if ((unsigned)y >= GFX_HEIGHT_16) return;
if (x < 0) { len += x; x = 0; }
diff --git a/libc/gfx/_gfx_putpixel16_raw.c b/libbgi/bgi16/_bgi_plot_raw.c
similarity index 80%
rename from libc/gfx/_gfx_putpixel16_raw.c
rename to libbgi/bgi16/_bgi_plot_raw.c
index 46a84b4..cfe2c99 100644
--- a/libc/gfx/_gfx_putpixel16_raw.c
+++ b/libbgi/bgi16/_bgi_plot_raw.c
@@ -1,12 +1,12 @@
/*
- * _gfx_putpixel16_raw — пиксель (x,y) цветом 0..15, mode 0x82.
+ * _bgi_plot_raw — пиксель (x,y) цветом 0..15, mode 0x82.
* Байт по адресу _gfx_addr_base + x/2 держит два пикселя: high nibble =
* ЛЕВЫЙ (чётный x), low = ПРАВЫЙ (нечётный). W3-naive.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
-void _gfx_putpixel16_raw(int x, int y, uint8_t color)
+void _bgi_plot_raw(int x, int y, uint8_t color)
{
if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return;
_gfx_g16_y = (uint8_t)y;
diff --git a/libc/gfx/_gfx_vline16_raw.c b/libbgi/bgi16/_bgi_vspan_raw.c
similarity index 84%
rename from libc/gfx/_gfx_vline16_raw.c
rename to libbgi/bgi16/_bgi_vspan_raw.c
index ea61ba6..edd96be 100644
--- a/libc/gfx/_gfx_vline16_raw.c
+++ b/libbgi/bgi16/_bgi_vspan_raw.c
@@ -1,13 +1,13 @@
/*
- * _gfx_vline16_raw — вертикальная линия len пикселей от (x,y),
+ * _bgi_vspan_raw — вертикальная линия len пикселей от (x,y),
* mode 0x82. Вертикального accel-пути нет: байт покрывает два
* горизонтальных пикселя, Fill затёр бы соседний нибл — поэтому
* RMW на каждую строку. W3-naive.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
-void _gfx_vline16_raw(int x, int y, int len, uint8_t color)
+void _bgi_vspan_raw(int x, int y, int len, uint8_t color)
{
if ((unsigned)x >= GFX_WIDTH_16) return;
if (y < 0) { len += y; y = 0; }
diff --git a/libc/gfx/_gfx_g16_state.c b/libbgi/bgi16/_gfx_g16_state.c
similarity index 96%
rename from libc/gfx/_gfx_g16_state.c
rename to libbgi/bgi16/_gfx_g16_state.c
index 008191b..6a7155a 100644
--- a/libc/gfx/_gfx_g16_state.c
+++ b/libbgi/bgi16/_gfx_g16_state.c
@@ -4,7 +4,7 @@
* между W3-begin/end.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t _gfx_g16_y;
uint8_t _gfx_g16_byte; /* nibble | (nibble<<4) — цвет в обе половины */
diff --git a/libc/gfx/_gfx_hfill16.c b/libbgi/bgi16/_gfx_hfill16.c
similarity index 98%
rename from libc/gfx/_gfx_hfill16.c
rename to libbgi/bgi16/_gfx_hfill16.c
index dfa3162..f00ab1d 100644
--- a/libc/gfx/_gfx_hfill16.c
+++ b/libbgi/bgi16/_gfx_hfill16.c
@@ -10,7 +10,7 @@
* как новый размер блока.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void _gfx_hfill16_chunk(void) __naked
{
diff --git a/libc/gfx/_gfx_rmw16.c b/libbgi/bgi16/_gfx_rmw16.c
similarity index 98%
rename from libc/gfx/_gfx_rmw16.c
rename to libbgi/bgi16/_gfx_rmw16.c
index f3a179c..1ce7102 100644
--- a/libc/gfx/_gfx_rmw16.c
+++ b/libbgi/bgi16/_gfx_rmw16.c
@@ -6,7 +6,7 @@
* Pre: W3 замаплен, DI активен.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void _gfx_rmw16_pixel(void) __naked
{
diff --git a/libc/gfx/_gfx_clear256_raw.c b/libbgi/bgi256/_bgi_clear_raw.c
similarity index 78%
rename from libc/gfx/_gfx_clear256_raw.c
rename to libbgi/bgi256/_bgi_clear_raw.c
index f15b442..5d557a7 100644
--- a/libc/gfx/_gfx_clear256_raw.c
+++ b/libbgi/bgi256/_bgi_clear_raw.c
@@ -1,12 +1,12 @@
/*
- * _gfx_clear256_raw — залить всё поле 320×256 цветом color, mode 0x81.
+ * _bgi_clear_raw — залить всё поле 320×256 цветом color, mode 0x81.
* Построчный hfill: 256 строк × 2 burst'а (256 + 64 байта) = 512.
* W3-naive: вызывающий обрамляет begin/end.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
-void _gfx_clear256_raw(uint8_t color)
+void _bgi_clear_raw(uint8_t color)
{
_gfx_acc_color = color;
for (int y = 0; y < GFX_HEIGHT; y++) {
diff --git a/libc/gfx/_gfx_hline256_raw.c b/libbgi/bgi256/_bgi_hspan_raw.c
similarity index 80%
rename from libc/gfx/_gfx_hline256_raw.c
rename to libbgi/bgi256/_bgi_hspan_raw.c
index 87e852f..8b702ac 100644
--- a/libc/gfx/_gfx_hline256_raw.c
+++ b/libbgi/bgi256/_bgi_hspan_raw.c
@@ -1,12 +1,12 @@
/*
- * _gfx_hline256_raw — горизонтальная линия len пикселей от (x,y),
+ * _bgi_hspan_raw — горизонтальная линия len пикселей от (x,y),
* mode 0x81, через Fill-burst'ы акселератора (до 256 байт за выстрел).
* W3-naive: вызывающий обрамляет begin/end.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
-void _gfx_hline256_raw(int x, int y, int len, uint8_t color)
+void _bgi_hspan_raw(int x, int y, int len, uint8_t color)
{
if ((unsigned)y >= GFX_HEIGHT) return;
if (x < 0) { len += x; x = 0; }
diff --git a/libc/bgi/drv256/_bgi_mode_set.c b/libbgi/bgi256/_bgi_mode_set.c
similarity index 90%
rename from libc/bgi/drv256/_bgi_mode_set.c
rename to libbgi/bgi256/_bgi_mode_set.c
index 8dfd0fc..597e938 100644
--- a/libc/bgi/drv256/_bgi_mode_set.c
+++ b/libbgi/bgi256/_bgi_mode_set.c
@@ -31,7 +31,11 @@ static const uint8_t _bgi_ega_pal[16 * 4] = {
uint8_t _bgi_mode_set(void)
{
- uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
+ uint8_t prev = _videomode_raw_get();
+ _videomode_raw_set(GFX_MODE_320x256x256);
+ _gfx_bank = 0x50;
+ gfx_set_visible_page(0);
+ gfx_set_draw_page(0);
gfx_pal_load(0, 0, 16, _bgi_ega_pal);
_bgi_maxx = GFX_WIDTH - 1;
_bgi_maxy = GFX_HEIGHT - 1;
diff --git a/libc/gfx/_gfx_putpixel256_raw.c b/libbgi/bgi256/_bgi_plot_raw.c
similarity index 84%
rename from libc/gfx/_gfx_putpixel256_raw.c
rename to libbgi/bgi256/_bgi_plot_raw.c
index 6c60d61..83ee5fe 100644
--- a/libc/gfx/_gfx_putpixel256_raw.c
+++ b/libbgi/bgi256/_bgi_plot_raw.c
@@ -1,5 +1,5 @@
/*
- * _gfx_putpixel256_raw — пиксель (x,y) цветом color, mode 0x81.
+ * _bgi_plot_raw — пиксель (x,y) цветом color, mode 0x81.
*
* "Raw" = W3-naive: вызывающий уже сделал _gfx_w3_video_begin (W3 на
* видеобанке, DI). Адресация: CPU _gfx_addr_base + x, Port_Y (0x89) = y.
@@ -8,13 +8,13 @@
* Брезенхэма не топтал внешнее состояние акселератора.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
static uint8_t _gfx_pp_y;
static uint16_t _gfx_pp_addr;
static uint8_t _gfx_pp_color;
-void _gfx_putpixel256_raw(int x, int y, uint8_t color)
+void _bgi_plot_raw(int x, int y, uint8_t color)
{
if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return;
_gfx_pp_y = (uint8_t)y;
diff --git a/libc/gfx/_gfx_getpixel256_raw.c b/libbgi/bgi256/_bgi_read_raw.c
similarity index 81%
rename from libc/gfx/_gfx_getpixel256_raw.c
rename to libbgi/bgi256/_bgi_read_raw.c
index 172bc0d..bffc51a 100644
--- a/libc/gfx/_gfx_getpixel256_raw.c
+++ b/libbgi/bgi256/_bgi_read_raw.c
@@ -1,17 +1,17 @@
/*
- * _gfx_getpixel256_raw — прочитать пиксель (x,y) БЕЗ своей W3-скобки
+ * _bgi_read_raw — прочитать пиксель (x,y) БЕЗ своей W3-скобки
* (вызывающий уже сделал _gfx_w3_video_begin). Для блиттинга image:
* getimage/putimage читают тысячи пикселей в одной скобке.
* За пределами экрана возвращает 0.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
static uint8_t _gfx_gpr_y;
static uint16_t _gfx_gpr_addr;
static uint8_t _gfx_gpr_color;
-uint8_t _gfx_getpixel256_raw(int x, int y)
+uint8_t _bgi_read_raw(int x, int y)
{
if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return 0;
_gfx_gpr_y = (uint8_t)y;
diff --git a/libc/gfx/_gfx_vline256_raw.c b/libbgi/bgi256/_bgi_vspan_raw.c
similarity index 90%
rename from libc/gfx/_gfx_vline256_raw.c
rename to libbgi/bgi256/_bgi_vspan_raw.c
index 9c71cb0..ed5a64e 100644
--- a/libc/gfx/_gfx_vline256_raw.c
+++ b/libbgi/bgi256/_bgi_vspan_raw.c
@@ -1,10 +1,10 @@
/*
- * _gfx_vline256_raw — вертикальная линия len пикселей от (x,y),
+ * _bgi_vspan_raw — вертикальная линия len пикселей от (x,y),
* mode 0x81. Вертикальный Fill акселератора сам инкрементирует Port_Y,
* так что вся колонка (высота 256) — один burst. W3-naive.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
/* Вертикальный Fill: _gfx_acc_len пикселей в колонке _gfx_acc_addr,
* верхняя строка _gfx_acc_y. Про SMC и правила FSM акселератора —
@@ -33,7 +33,7 @@ static void vfill_chunk(void) __naked
__endasm;
}
-void _gfx_vline256_raw(int x, int y, int len, uint8_t color)
+void _bgi_vspan_raw(int x, int y, int len, uint8_t color)
{
if ((unsigned)x >= GFX_WIDTH) return;
if (y < 0) { len += y; y = 0; }
diff --git a/libc/gfx/_gfx_acc256.c b/libbgi/bgi256/_gfx_acc256.c
similarity index 95%
rename from libc/gfx/_gfx_acc256.c
rename to libbgi/bgi256/_gfx_acc256.c
index 5c1ad77..f7a9e80 100644
--- a/libc/gfx/_gfx_acc256.c
+++ b/libbgi/bgi256/_gfx_acc256.c
@@ -4,7 +4,7 @@
* GFX работает с выключенными прерываниями между W3-begin/end.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t _gfx_acc_color;
uint8_t _gfx_acc_y;
diff --git a/libc/gfx/_gfx_hfill256.c b/libbgi/bgi256/_gfx_hfill256.c
similarity index 99%
rename from libc/gfx/_gfx_hfill256.c
rename to libbgi/bgi256/_gfx_hfill256.c
index 09a0a29..d8a108b 100644
--- a/libc/gfx/_gfx_hfill256.c
+++ b/libbgi/bgi256/_gfx_hfill256.c
@@ -15,7 +15,7 @@
* как новый размер блока.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void _gfx_hfill256_chunk(void) __naked
{
diff --git a/libbgi/bgi256/getpixel.c b/libbgi/bgi256/getpixel.c
new file mode 100644
index 0000000..f1c52fb
--- /dev/null
+++ b/libbgi/bgi256/getpixel.c
@@ -0,0 +1,33 @@
+/*
+ * getpixel (bgi256) — цвет пикселя (x,y), mode 0x81. Полностью inline
+ * (bounds + W3-скобка + чтение пикселя), без вызовов _bgi_read/raw.
+ * Возвращает 0 вне экрана.
+ */
+#include "../_bgi.h"
+
+static uint8_t _gp_y;
+static uint16_t _gp_addr;
+static uint8_t _gp_color;
+
+unsigned getpixel(int x, int y)
+{
+ if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return 0;
+ _gp_y = (uint8_t)y;
+ _gp_addr = (uint16_t)(_gfx_addr_base + (unsigned)x);
+ __asm
+ di
+ in a, (#0xE2)
+ ld (__gfx_saved_w3), a
+ ld a, (__gfx_bank)
+ out (#0xE2), a
+ ld a, (_gp_y)
+ out (#0x89), a
+ ld hl, (_gp_addr)
+ ld a, (hl)
+ ld (_gp_color), a
+ ld a, (__gfx_saved_w3)
+ out (#0xE2), a
+ ei
+ __endasm;
+ return _gp_color;
+}
diff --git a/libbgi/bgi256/putpixel.c b/libbgi/bgi256/putpixel.c
new file mode 100644
index 0000000..414e648
--- /dev/null
+++ b/libbgi/bgi256/putpixel.c
@@ -0,0 +1,39 @@
+/*
+ * putpixel (bgi256) — точка (x,y) цветом color, mode 0x81.
+ * ПОЛНОСТЬЬЮ inline: bounds + W3-скобка + запись пикселя в теле, БЕЗ
+ * вызовов _bgi_plot / gfx_putpixel256 / _bgi_plot_raw (устранены
+ * прокладки старой цепочки putpixel→_bgi_plot→gfx_putpixel256→raw).
+ * Адресация: CPU _gfx_addr_base + x, Port_Y (0x89) = y; W3 мапится на
+ * _gfx_bank, сейв восстанавливается. Bounds — compile-time GFX_WIDTH/
+ * HEIGHT (меньше/быстрее, ≡ runtime _bgi_maxx/_bgi_maxy).
+ */
+#include "../_bgi.h"
+
+/* File-static скретч (как в _bgi_plot_raw, но свой — putpixel не должен
+ * топтать скретч акселератора/plot_raw, если звать вперемешку). */
+static uint8_t _pp_y;
+static uint16_t _pp_addr;
+static uint8_t _pp_color;
+
+void putpixel(int x, int y, int color)
+{
+ if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return;
+ _pp_y = (uint8_t)y;
+ _pp_addr = (uint16_t)(_gfx_addr_base + (unsigned)x);
+ _pp_color = (uint8_t)color;
+ __asm
+ di
+ in a, (#0xE2)
+ ld (__gfx_saved_w3), a
+ ld a, (__gfx_bank)
+ out (#0xE2), a
+ ld a, (_pp_y)
+ out (#0x89), a
+ ld hl, (_pp_addr)
+ ld a, (_pp_color)
+ ld (hl), a
+ ld a, (__gfx_saved_w3)
+ out (#0xE2), a
+ ei
+ __endasm;
+}
diff --git a/libc/bgi/_bgi_arc_draw.c b/libbgi/common/_bgi_arc_draw.c
similarity index 98%
rename from libc/bgi/_bgi_arc_draw.c
rename to libbgi/common/_bgi_arc_draw.c
index 5b2754d..123bf95 100644
--- a/libc/bgi/_bgi_arc_draw.c
+++ b/libbgi/common/_bgi_arc_draw.c
@@ -10,7 +10,7 @@
* эллипс через (long)…>>8 рисовался прямоугольником).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void _bgi_ellipse_arc(int cx, int cy, int stangle, int endangle,
int xr, int yr, uint8_t color)
diff --git a/libbgi/common/_bgi_begin.c b/libbgi/common/_bgi_begin.c
new file mode 100644
index 0000000..e138f6a
--- /dev/null
+++ b/libbgi/common/_bgi_begin.c
@@ -0,0 +1,24 @@
+/*
+ * _bgi_begin — открыть W3-сессию для пакетного рисования: DI, сохранить
+ * текущую страницу W3 и замапить _gfx_bank (видеобанк 0x50..0x5F).
+ * Композитные примитивы обрамляют одной парой _bgi_begin/_bgi_end весь
+ * внутренний цикл — W3-танец оплачивается один раз на операцию, а не
+ * на пиксель. НЕ реентерабельно (сейв в _gfx_saved_w3): между begin и
+ * end IRQ выключены.
+ *
+ * Real код (поглощён из старого libc/gfx/_gfx_w3_video_begin.c) — не
+ * обёртка. Mode-agnostic: использует только _gfx_bank/_gfx_saved_w3.
+ */
+#include "../_bgi.h"
+
+void _bgi_begin(void) __naked
+{
+ __asm
+ di
+ in a, (#0xE2)
+ ld (__gfx_saved_w3), a
+ ld a, (__gfx_bank)
+ out (#0xE2), a
+ ret
+ __endasm;
+}
diff --git a/libbgi/common/_bgi_clearall.c b/libbgi/common/_bgi_clearall.c
new file mode 100644
index 0000000..59fc151
--- /dev/null
+++ b/libbgi/common/_bgi_clearall.c
@@ -0,0 +1,13 @@
+/*
+ * _bgi_clearall — залить весь экран цветом, self-bracket (своя W3-скобка).
+ * cleardevice зовёт это фоновым цветом. Реальная композиция
+ * _bgi_begin + _bgi_clear_raw + _bgi_end.
+ */
+#include "../_bgi.h"
+
+void _bgi_clearall(uint8_t color)
+{
+ _bgi_begin();
+ _bgi_clear_raw(color);
+ _bgi_end();
+}
diff --git a/libc/bgi/_bgi_draw_scaled.c b/libbgi/common/_bgi_draw_scaled.c
similarity index 98%
rename from libc/bgi/_bgi_draw_scaled.c
rename to libbgi/common/_bgi_draw_scaled.c
index 10c703c..e9ae53d 100644
--- a/libc/bgi/_bgi_draw_scaled.c
+++ b/libbgi/common/_bgi_draw_scaled.c
@@ -7,7 +7,7 @@
* Каждый «пиксель» глифа — блок size×size из raw-плотов, всё в одной
* W3-скобке.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void _bgi_draw_scaled(int x, int y, const char *s)
{
diff --git a/libbgi/common/_bgi_end.c b/libbgi/common/_bgi_end.c
new file mode 100644
index 0000000..25b1adb
--- /dev/null
+++ b/libbgi/common/_bgi_end.c
@@ -0,0 +1,15 @@
+/*
+ * _bgi_end — закрыть W3-сессию: восстановить сохранённую страницу W3 и
+ * EI. Real код (поглощён из старого libc/gfx/_gfx_w3_video_end.c).
+ */
+#include "../_bgi.h"
+
+void _bgi_end(void) __naked
+{
+ __asm
+ ld a, (__gfx_saved_w3)
+ out (#0xE2), a
+ ei
+ ret
+ __endasm;
+}
diff --git a/libc/bgi/_bgi_fill_span.c b/libbgi/common/_bgi_fill_span.c
similarity index 98%
rename from libc/bgi/_bgi_fill_span.c
rename to libbgi/common/_bgi_fill_span.c
index 6f051cd..b58868a 100644
--- a/libc/bgi/_bgi_fill_span.c
+++ b/libbgi/common/_bgi_fill_span.c
@@ -6,7 +6,7 @@
* Клип по экрану внутри. ВЫЗЫВАТЬ между _bgi_begin/_bgi_end.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
/* Стандартные 8×8-паттерны Borland, индексы LINE_FILL..CLOSE_DOT_FILL. */
static const uint8_t _bgi_pat[10][8] = {
diff --git a/libc/bgi/_bgi_fill_state.c b/libbgi/common/_bgi_fill_state.c
similarity index 93%
rename from libc/bgi/_bgi_fill_state.c
rename to libbgi/common/_bgi_fill_state.c
index 6bc8589..81055fa 100644
--- a/libc/bgi/_bgi_fill_state.c
+++ b/libbgi/common/_bgi_fill_state.c
@@ -4,7 +4,7 @@
* Без инициализации (crt0 зануляет _DATA).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
uint8_t _bgi_fill_pattern;
uint8_t _bgi_fill_color;
diff --git a/libbgi/common/_bgi_font_rows.c b/libbgi/common/_bgi_font_rows.c
new file mode 100644
index 0000000..0775afb
--- /dev/null
+++ b/libbgi/common/_bgi_font_rows.c
@@ -0,0 +1,20 @@
+/*
+ * _bgi_font_rows — 8 байт строк глифа символа c (mode-agnostic: просто
+ * читает шрифт через _gfx_font_ptr). Шрифт системный, interleaved:
+ * offset = row*256 + char (MSB-first), см. memory/sprinter_font_format.
+ * Грузится лениво (_gfx_font_ensure) при первом использовании.
+ *
+ * Раньше жил в drv256/ по недосмотру — перенесён в common/, т.к. логика
+ * не зависит от видеорежима (один и тот же .rel в bgi256.lib и bgi16.lib).
+ */
+#include "../_bgi.h"
+
+void _bgi_font_rows(unsigned char c, uint8_t *rows8)
+{
+ const uint8_t *f;
+ int r;
+ _gfx_font_ensure();
+ f = _gfx_font_ptr;
+ for (r = 0; r < 8; r++)
+ rows8[r] = f[r * 256 + c];
+}
diff --git a/libbgi/common/_bgi_hspan.c b/libbgi/common/_bgi_hspan.c
new file mode 100644
index 0000000..01f3b33
--- /dev/null
+++ b/libbgi/common/_bgi_hspan.c
@@ -0,0 +1,13 @@
+/*
+ * _bgi_hspan — горизонтальный отрезок len пикселей от (x,y), self-bracket
+ * (своя W3-скобка). Для floodfill (заливка строки вне пакетной сессии).
+ * Реальная композиция _bgi_begin + _bgi_hspan_raw + _bgi_end.
+ */
+#include "../_bgi.h"
+
+void _bgi_hspan(int x, int y, int len, uint8_t color)
+{
+ _bgi_begin();
+ _bgi_hspan_raw(x, y, len, color);
+ _bgi_end();
+}
diff --git a/libc/bgi/_bgi_isqrt.c b/libbgi/common/_bgi_isqrt.c
similarity index 94%
rename from libc/bgi/_bgi_isqrt.c
rename to libbgi/common/_bgi_isqrt.c
index e58a6bf..666bb44 100644
--- a/libc/bgi/_bgi_isqrt.c
+++ b/libbgi/common/_bgi_isqrt.c
@@ -4,7 +4,7 @@
* без float и 32-бит.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
int _bgi_isqrt(int n)
{
diff --git a/libc/bgi/_bgi_line_state.c b/libbgi/common/_bgi_line_state.c
similarity index 92%
rename from libc/bgi/_bgi_line_state.c
rename to libbgi/common/_bgi_line_state.c
index f66ad51..f8e44b4 100644
--- a/libc/bgi/_bgi_line_state.c
+++ b/libbgi/common/_bgi_line_state.c
@@ -2,7 +2,7 @@
* _bgi_line_state — текущий стиль/толщина/маска линий BGI.
* initgraph ставит SOLID_LINE / NORM / 0xFFFF. Без инициализации.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
uint8_t _bgi_line_style;
uint8_t _bgi_line_thick;
diff --git a/libbgi/common/_bgi_lineseg.c b/libbgi/common/_bgi_lineseg.c
new file mode 100644
index 0000000..222fb05
--- /dev/null
+++ b/libbgi/common/_bgi_lineseg.c
@@ -0,0 +1,49 @@
+/*
+ * _bgi_lineseg — отрезок (x0,y0)->(x1,y1) БЕЗ стиля/толщины (SOLID+NORM).
+ * Real логика (поглощена из старого libc/gfx/gfx_line256.c), не обёртка.
+ *
+ * Ортогональные отрезки уходят на driver-leaf'ы _bgi_hspan_raw /
+ * _bgi_vspan_raw (акселератор); наклонные — Брезенхэм поточечно через
+ * _bgi_plot_raw. Каждый путь ставит свою W3-скобку (_bgi_begin/_bgi_end)
+ * — вызывать _bgi_lineseg ВНЕ чужой скобки (W3-сейв не реентерабелен).
+ * Вызывают: _bgi_styled_line (SOLID+NORM), _bgi_arc_draw, fillpoly,
+ * sector — все вне скобки.
+ */
+#include "../_bgi.h"
+
+void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color)
+{
+ /* Горизонталь — один H-burst. */
+ if (y0 == y1) {
+ int x = x0 <= x1 ? x0 : x1;
+ int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1;
+ _bgi_begin();
+ _bgi_hspan_raw(x, y0, w, color);
+ _bgi_end();
+ return;
+ }
+ /* Вертикаль — один V-burst (256) или RMW-цикл (16). */
+ if (x0 == x1) {
+ int y = y0 <= y1 ? y0 : y1;
+ int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1;
+ _bgi_begin();
+ _bgi_vspan_raw(x0, y, h, color);
+ _bgi_end();
+ return;
+ }
+
+ /* Наклонный — Брезенхэм в одной W3-скобке. */
+ int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx;
+ int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy;
+ int err = (dx > dy ? dx : -dy) / 2;
+ int x = x0, y = y0;
+ _bgi_begin();
+ for (;;) {
+ _bgi_plot_raw(x, y, color);
+ if (x == x1 && y == y1) break;
+ int e2 = err;
+ if (e2 > -dx) { err -= dy; x += sx; }
+ if (e2 < dy) { err += dx; y += sy; }
+ }
+ _bgi_end();
+}
diff --git a/libc/bgi/_bgi_poly_edge.c b/libbgi/common/_bgi_poly_edge.c
similarity index 97%
rename from libc/bgi/_bgi_poly_edge.c
rename to libbgi/common/_bgi_poly_edge.c
index e382773..63f8455 100644
--- a/libc/bgi/_bgi_poly_edge.c
+++ b/libbgi/common/_bgi_poly_edge.c
@@ -5,7 +5,7 @@
* пропускаются. Заливка потом идёт от min до max по строке.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void _bgi_poly_edge(int x0, int y0, int x1, int y1)
{
diff --git a/libc/bgi/_bgi_poly_state.c b/libbgi/common/_bgi_poly_state.c
similarity index 95%
rename from libc/bgi/_bgi_poly_state.c
rename to libbgi/common/_bgi_poly_state.c
index d1044fe..a3e70d3 100644
--- a/libc/bgi/_bgi_poly_state.c
+++ b/libbgi/common/_bgi_poly_state.c
@@ -5,7 +5,7 @@
* однопоточно (рисование не реентерабельно).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
int _bgi_span_min[GFX_HEIGHT];
int _bgi_span_max[GFX_HEIGHT];
diff --git a/libbgi/common/_bgi_read.c b/libbgi/common/_bgi_read.c
new file mode 100644
index 0000000..d29ebe1
--- /dev/null
+++ b/libbgi/common/_bgi_read.c
@@ -0,0 +1,16 @@
+/*
+ * _bgi_read — цвет пикселя (x,y), self-bracket (своя W3-скобка).
+ * Для разовых чтений из математики, которой не нужен пакетный режим
+ * (floodfill). getpixel тоже зовёт это. Реальная композиция
+ * _bgi_begin + _bgi_read_raw + _bgi_end — не обёртка над обёрткой.
+ */
+#include "../_bgi.h"
+
+unsigned _bgi_read(int x, int y)
+{
+ unsigned c;
+ _bgi_begin();
+ c = _bgi_read_raw(x, y);
+ _bgi_end();
+ return c;
+}
diff --git a/libc/bgi/_bgi_state.c b/libbgi/common/_bgi_state.c
similarity index 95%
rename from libc/bgi/_bgi_state.c
rename to libbgi/common/_bgi_state.c
index a5e9ffc..4d25fd1 100644
--- a/libc/bgi/_bgi_state.c
+++ b/libbgi/common/_bgi_state.c
@@ -6,7 +6,7 @@
* выставляет initgraph().
*/
-#include "_bgi.h"
+#include "../_bgi.h"
uint8_t _bgi_fg;
uint8_t _bgi_bg;
diff --git a/libc/bgi/_bgi_styled_line.c b/libbgi/common/_bgi_styled_line.c
similarity index 98%
rename from libc/bgi/_bgi_styled_line.c
rename to libbgi/common/_bgi_styled_line.c
index 415f649..8c2b812 100644
--- a/libc/bgi/_bgi_styled_line.c
+++ b/libbgi/common/_bgi_styled_line.c
@@ -6,7 +6,7 @@
* дублированием перпендикулярно основной оси (±1). Всё raw в одной
* W3-скобке.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
/* Маски стандартных стилей (SOLID/DOTTED/CENTER/DASHED). */
static const uint16_t _bgi_line_pat[4] = { 0xFFFF, 0xCCCC, 0xFF18, 0xF8F8 };
diff --git a/libc/bgi/_bgi_text_state.c b/libbgi/common/_bgi_text_state.c
similarity index 91%
rename from libc/bgi/_bgi_text_state.c
rename to libbgi/common/_bgi_text_state.c
index 5c4e664..fa7c1d8 100644
--- a/libc/bgi/_bgi_text_state.c
+++ b/libbgi/common/_bgi_text_state.c
@@ -2,7 +2,7 @@
* _bgi_text_state — направление и масштаб текста BGI.
* initgraph ставит HORIZ_DIR / size 1. Без инициализации.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
uint8_t _bgi_text_dir;
uint8_t _bgi_text_size;
diff --git a/libc/bgi/_bgi_trig.c b/libbgi/common/_bgi_trig.c
similarity index 98%
rename from libc/bgi/_bgi_trig.c
rename to libbgi/common/_bgi_trig.c
index 6b84c47..5ac287d 100644
--- a/libc/bgi/_bgi_trig.c
+++ b/libbgi/common/_bgi_trig.c
@@ -9,7 +9,7 @@
* (см. memory/avoid_32bit_arith_z80; ловили эллипс-в-прямоугольник).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
/* sin(0°..90°) × 128. */
static const int _bgi_sintab[91] = {
diff --git a/libc/gfx/_gfx_font_ensure.c b/libbgi/common/_gfx_font_ensure.c
similarity index 95%
rename from libc/gfx/_gfx_font_ensure.c
rename to libbgi/common/_gfx_font_ensure.c
index 26863e8..e48e61d 100644
--- a/libc/gfx/_gfx_font_ensure.c
+++ b/libbgi/common/_gfx_font_ensure.c
@@ -4,7 +4,7 @@
* использовании (чисто графическая программа BIOS-вызов не платит).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void _gfx_font_ensure(void)
{
diff --git a/libc/gfx/_gfx_font_state.c b/libbgi/common/_gfx_font_state.c
similarity index 97%
rename from libc/gfx/_gfx_font_state.c
rename to libbgi/common/_gfx_font_state.c
index 4225c0a..3c23f84 100644
--- a/libc/gfx/_gfx_font_state.c
+++ b/libbgi/common/_gfx_font_state.c
@@ -9,7 +9,7 @@
* _gfx_font_ensure(); программы могут подменить шрифт gfx_set_font().
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t _gfx_font_buf[_GFX_FONT_BYTES];
const uint8_t *_gfx_font_ptr = _gfx_font_buf;
diff --git a/libc/gfx/_gfx_state.c b/libbgi/common/_gfx_state.c
similarity index 89%
rename from libc/gfx/_gfx_state.c
rename to libbgi/common/_gfx_state.c
index b98d68f..60ec462 100644
--- a/libc/gfx/_gfx_state.c
+++ b/libbgi/common/_gfx_state.c
@@ -1,11 +1,11 @@
/*
* _gfx_state — общее состояние графики (модуль только с данными).
*
- * Пишут gfx_init / gfx_set_visible_page / gfx_set_draw_page /
+ * Пишут gfx_set_visible_page / gfx_set_draw_page /
* gfx_set_bank; читают все mode-специфичные примитивы.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t _gfx_visible_page;
uint8_t _gfx_draw_page;
diff --git a/libc/gfx/_gfx_w3_state.c b/libbgi/common/_gfx_w3_state.c
similarity index 94%
rename from libc/gfx/_gfx_w3_state.c
rename to libbgi/common/_gfx_w3_state.c
index 7ff33a6..650cdd9 100644
--- a/libc/gfx/_gfx_w3_state.c
+++ b/libbgi/common/_gfx_w3_state.c
@@ -5,6 +5,6 @@
* прерывания выключенными между _gfx_w3_video_begin и _end.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t _gfx_saved_w3;
diff --git a/libc/bgi/arc.c b/libbgi/common/arc.c
similarity index 92%
rename from libc/bgi/arc.c
rename to libbgi/common/arc.c
index f07840c..b7fd122 100644
--- a/libc/bgi/arc.c
+++ b/libbgi/common/arc.c
@@ -1,5 +1,5 @@
/* arc — дуга окружности радиуса r от stangle до endangle (градусы). */
-#include "_bgi.h"
+#include "../_bgi.h"
void arc(int x, int y, int stangle, int endangle, int radius)
{
diff --git a/libc/bgi/bar.c b/libbgi/common/bar.c
similarity index 96%
rename from libc/bgi/bar.c
rename to libbgi/common/bar.c
index d1b8601..72595ed 100644
--- a/libc/bgi/bar.c
+++ b/libbgi/common/bar.c
@@ -2,7 +2,7 @@
* bar — залитый прямоугольник (left,top)-(right,bottom) включительно
* ТЕКУЩИМ стилем заливки (setfillstyle), без рамки — как в Turbo-C.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void bar(int left, int top, int right, int bottom)
{
diff --git a/libc/bgi/bar3d.c b/libbgi/common/bar3d.c
similarity index 98%
rename from libc/bgi/bar3d.c
rename to libbgi/common/bar3d.c
index 2e9128c..0209533 100644
--- a/libc/bgi/bar3d.c
+++ b/libbgi/common/bar3d.c
@@ -3,7 +3,7 @@
* заливки, рёбра — текущим цветом рисования. depth — глубина (вправо-
* вверх), topflag != 0 рисует верхнюю грань.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void bar3d(int left, int top, int right, int bottom, int depth, int topflag)
{
diff --git a/libc/bgi/circle.c b/libbgi/common/circle.c
similarity index 98%
rename from libc/bgi/circle.c
rename to libbgi/common/circle.c
index 3318b16..21db215 100644
--- a/libc/bgi/circle.c
+++ b/libbgi/common/circle.c
@@ -6,7 +6,7 @@
* raw-плот — иначе скобка на каждый пиксель делает большие окружности
* мучительно медленными (тысячи DI/EI).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void circle(int cx, int cy, int r)
{
diff --git a/libc/bgi/cleardevice.c b/libbgi/common/cleardevice.c
similarity index 90%
rename from libc/bgi/cleardevice.c
rename to libbgi/common/cleardevice.c
index 4724dbf..a218b8c 100644
--- a/libc/bgi/cleardevice.c
+++ b/libbgi/common/cleardevice.c
@@ -1,5 +1,5 @@
/* cleardevice — очистить экран фоновым цветом, вернуть CP в (0,0). */
-#include "_bgi.h"
+#include "../_bgi.h"
void cleardevice(void)
{
diff --git a/libbgi/common/closegraph.c b/libbgi/common/closegraph.c
new file mode 100644
index 0000000..56b637d
--- /dev/null
+++ b/libbgi/common/closegraph.c
@@ -0,0 +1,8 @@
+/* closegraph — вернуть текстовый режим, действовавший до initgraph.
+ * _bgi_mode_done удалён — _videomode_raw_set (mode-agnostic) */
+#include "../_bgi.h"
+
+void closegraph(void)
+{
+ _videomode_raw_set(_bgi_prevmode);
+}
diff --git a/libc/bgi/drawpoly.c b/libbgi/common/drawpoly.c
similarity index 96%
rename from libc/bgi/drawpoly.c
rename to libbgi/common/drawpoly.c
index 9f0ec46..f29e12d 100644
--- a/libc/bgi/drawpoly.c
+++ b/libbgi/common/drawpoly.c
@@ -3,7 +3,7 @@
* текущим цветом. Как в Turbo-C, контур НЕ замыкается автоматически:
* чтобы получить замкнутый полигон, повторите первую точку последней.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void drawpoly(int numpoints, const int *polypoints)
{
diff --git a/libc/bgi/ellipse.c b/libbgi/common/ellipse.c
similarity index 94%
rename from libc/bgi/ellipse.c
rename to libbgi/common/ellipse.c
index f6fbdc9..3f9fa3b 100644
--- a/libc/bgi/ellipse.c
+++ b/libbgi/common/ellipse.c
@@ -2,7 +2,7 @@
* ellipse — контур эллипса/эллиптической дуги с полуосями xradius,
* yradius от stangle до endangle. Полный эллипс: stangle=0,endangle=360.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void ellipse(int x, int y, int stangle, int endangle,
int xradius, int yradius)
diff --git a/libc/bgi/fillellipse.c b/libbgi/common/fillellipse.c
similarity index 97%
rename from libc/bgi/fillellipse.c
rename to libbgi/common/fillellipse.c
index ae7b4d1..a9b1ac4 100644
--- a/libc/bgi/fillellipse.c
+++ b/libbgi/common/fillellipse.c
@@ -6,7 +6,7 @@
* _bgi_isqrt). ry²,dy² ≤ ~180² < 32767, rx*s ≤ rx*ry < 32767 — без
* 32-бит (см. memory/avoid_32bit_arith_z80).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void fillellipse(int cx, int cy, int rx, int ry)
{
diff --git a/libc/bgi/fillpoly.c b/libbgi/common/fillpoly.c
similarity index 98%
rename from libc/bgi/fillpoly.c
rename to libbgi/common/fillpoly.c
index d17372d..d7bc3ea 100644
--- a/libc/bgi/fillpoly.c
+++ b/libbgi/common/fillpoly.c
@@ -8,7 +8,7 @@
* оболочка по строкам (упрощение). Крайние X даёт брезенхэмовский
* проход рёбер (_bgi_poly_edge) — без 32-бит арифметики.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void fillpoly(int numpoints, const int *polypoints)
{
diff --git a/libc/bgi/floodfill.c b/libbgi/common/floodfill.c
similarity index 99%
rename from libc/bgi/floodfill.c
rename to libbgi/common/floodfill.c
index df1bec1..96aa892 100644
--- a/libc/bgi/floodfill.c
+++ b/libbgi/common/floodfill.c
@@ -15,7 +15,7 @@
* фигурах) — компромисс по памяти.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
#define FF_STACK 300
static int ff_sx[FF_STACK];
diff --git a/libc/bgi/getbkcolor.c b/libbgi/common/getbkcolor.c
similarity index 83%
rename from libc/bgi/getbkcolor.c
rename to libbgi/common/getbkcolor.c
index c907e85..67e74cb 100644
--- a/libc/bgi/getbkcolor.c
+++ b/libbgi/common/getbkcolor.c
@@ -1,5 +1,5 @@
/* getbkcolor — текущий фоновый цвет. */
-#include "_bgi.h"
+#include "../_bgi.h"
int getbkcolor(void)
{
diff --git a/libc/bgi/getcolor.c b/libbgi/common/getcolor.c
similarity index 83%
rename from libc/bgi/getcolor.c
rename to libbgi/common/getcolor.c
index e0c2b0d..65cf2c7 100644
--- a/libc/bgi/getcolor.c
+++ b/libbgi/common/getcolor.c
@@ -1,5 +1,5 @@
/* getcolor — текущий цвет рисования. */
-#include "_bgi.h"
+#include "../_bgi.h"
int getcolor(void)
{
diff --git a/libc/bgi/getfillsettings.c b/libbgi/common/getfillsettings.c
similarity index 92%
rename from libc/bgi/getfillsettings.c
rename to libbgi/common/getfillsettings.c
index f7eda81..2c39883 100644
--- a/libc/bgi/getfillsettings.c
+++ b/libbgi/common/getfillsettings.c
@@ -1,5 +1,5 @@
/* getfillsettings — прочитать текущий паттерн и цвет заливки. */
-#include "_bgi.h"
+#include "../_bgi.h"
void getfillsettings(struct fillsettingstype *fillinfo)
{
diff --git a/libc/bgi/getimage.c b/libbgi/common/getimage.c
similarity index 97%
rename from libc/bgi/getimage.c
rename to libbgi/common/getimage.c
index 982dd31..176c71d 100644
--- a/libc/bgi/getimage.c
+++ b/libbgi/common/getimage.c
@@ -3,7 +3,7 @@
* Формат: uint16 width, uint16 height, затем w*h байт (по строкам).
* Чтение raw в одной W3-скобке.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void getimage(int left, int top, int right, int bottom, void *bitmap)
{
diff --git a/libc/bgi/getlinesettings.c b/libbgi/common/getlinesettings.c
similarity index 93%
rename from libc/bgi/getlinesettings.c
rename to libbgi/common/getlinesettings.c
index 7a5b74c..8d428f2 100644
--- a/libc/bgi/getlinesettings.c
+++ b/libbgi/common/getlinesettings.c
@@ -1,5 +1,5 @@
/* getlinesettings — прочитать текущий стиль/маску/толщину линий. */
-#include "_bgi.h"
+#include "../_bgi.h"
void getlinesettings(struct linesettingstype *lineinfo)
{
diff --git a/libc/bgi/getmaxcolor.c b/libbgi/common/getmaxcolor.c
similarity index 88%
rename from libc/bgi/getmaxcolor.c
rename to libbgi/common/getmaxcolor.c
index d862c74..f011be4 100644
--- a/libc/bgi/getmaxcolor.c
+++ b/libbgi/common/getmaxcolor.c
@@ -1,5 +1,5 @@
/* getmaxcolor — максимальный индекс цвета (255 в 256-цветном режиме). */
-#include "_bgi.h"
+#include "../_bgi.h"
int getmaxcolor(void)
{
diff --git a/libc/bgi/getmaxx.c b/libbgi/common/getmaxx.c
similarity index 86%
rename from libc/bgi/getmaxx.c
rename to libbgi/common/getmaxx.c
index 0e326e5..830042e 100644
--- a/libc/bgi/getmaxx.c
+++ b/libbgi/common/getmaxx.c
@@ -1,5 +1,5 @@
/* getmaxx — максимальная координата X (ширина-1). */
-#include "_bgi.h"
+#include "../_bgi.h"
int getmaxx(void)
{
diff --git a/libc/bgi/getmaxy.c b/libbgi/common/getmaxy.c
similarity index 86%
rename from libc/bgi/getmaxy.c
rename to libbgi/common/getmaxy.c
index b7f63c0..a018431 100644
--- a/libc/bgi/getmaxy.c
+++ b/libbgi/common/getmaxy.c
@@ -1,5 +1,5 @@
/* getmaxy — максимальная координата Y (высота-1). */
-#include "_bgi.h"
+#include "../_bgi.h"
int getmaxy(void)
{
diff --git a/libc/bgi/gettextsettings.c b/libbgi/common/gettextsettings.c
similarity index 94%
rename from libc/bgi/gettextsettings.c
rename to libbgi/common/gettextsettings.c
index 1d0217b..d0ad6fe 100644
--- a/libc/bgi/gettextsettings.c
+++ b/libbgi/common/gettextsettings.c
@@ -1,5 +1,5 @@
/* gettextsettings — текущий стиль текста (justify не реализован → 0). */
-#include "_bgi.h"
+#include "../_bgi.h"
void gettextsettings(struct textsettingstype *textinfo)
{
diff --git a/libc/bgi/getx.c b/libbgi/common/getx.c
similarity index 80%
rename from libc/bgi/getx.c
rename to libbgi/common/getx.c
index b1cf7a3..5635ae3 100644
--- a/libc/bgi/getx.c
+++ b/libbgi/common/getx.c
@@ -1,5 +1,5 @@
/* getx — текущая позиция X. */
-#include "_bgi.h"
+#include "../_bgi.h"
int getx(void)
{
diff --git a/libc/bgi/gety.c b/libbgi/common/gety.c
similarity index 80%
rename from libc/bgi/gety.c
rename to libbgi/common/gety.c
index 35dc83d..7a17b14 100644
--- a/libc/bgi/gety.c
+++ b/libbgi/common/gety.c
@@ -1,5 +1,5 @@
/* gety — текущая позиция Y. */
-#include "_bgi.h"
+#include "../_bgi.h"
int gety(void)
{
diff --git a/libc/gfx/gfx_get_bank.c b/libbgi/common/gfx_get_bank.c
similarity index 86%
rename from libc/gfx/gfx_get_bank.c
rename to libbgi/common/gfx_get_bank.c
index a7cbc79..8ce444f 100644
--- a/libc/gfx/gfx_get_bank.c
+++ b/libbgi/common/gfx_get_bank.c
@@ -2,7 +2,7 @@
* gfx_get_bank — текущий байт страницы W3 (0x50..0x5F).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t gfx_get_bank(void)
{
diff --git a/libc/gfx/gfx_get_draw_page.c b/libbgi/common/gfx_get_draw_page.c
similarity index 89%
rename from libc/gfx/gfx_get_draw_page.c
rename to libbgi/common/gfx_get_draw_page.c
index a67e9a8..c5340e6 100644
--- a/libc/gfx/gfx_get_draw_page.c
+++ b/libbgi/common/gfx_get_draw_page.c
@@ -2,7 +2,7 @@
* gfx_get_draw_page — кэшированный номер рисуемой страницы (0/1).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t gfx_get_draw_page(void)
{
diff --git a/libc/gfx/gfx_get_visible_page.c b/libbgi/common/gfx_get_visible_page.c
similarity index 89%
rename from libc/gfx/gfx_get_visible_page.c
rename to libbgi/common/gfx_get_visible_page.c
index e54fd4b..46d0a14 100644
--- a/libc/gfx/gfx_get_visible_page.c
+++ b/libbgi/common/gfx_get_visible_page.c
@@ -2,7 +2,7 @@
* gfx_get_visible_page — кэшированный номер видимой страницы (0/1).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
uint8_t gfx_get_visible_page(void)
{
diff --git a/libc/gfx/gfx_load_default_font.c b/libbgi/common/gfx_load_default_font.c
similarity index 97%
rename from libc/gfx/gfx_load_default_font.c
rename to libbgi/common/gfx_load_default_font.c
index 5e28f3d..0799cf8 100644
--- a/libc/gfx/gfx_load_default_font.c
+++ b/libbgi/common/gfx_load_default_font.c
@@ -3,7 +3,7 @@
* через BIOS WIN_GET_ZG (fn 0xB8) в _gfx_font_buf и включить его.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
/* BIOS WIN_GET_ZG (0xB8): DE = приёмник, возвращает 2 КБ. */
static void bios_get_zg(uint8_t *dest) __naked
diff --git a/libc/gfx/gfx_pal_get.c b/libbgi/common/gfx_pal_get.c
similarity index 94%
rename from libc/gfx/gfx_pal_get.c
rename to libbgi/common/gfx_pal_get.c
index d9419e9..883cabe 100644
--- a/libc/gfx/gfx_pal_get.c
+++ b/libbgi/common/gfx_pal_get.c
@@ -3,7 +3,7 @@
* обёртка над pal_get (libc/video) — не на горячем пути.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
#include
void gfx_pal_get(uint8_t pal_num, uint8_t start, uint8_t count,
diff --git a/libc/gfx/gfx_pal_get_color.c b/libbgi/common/gfx_pal_get_color.c
similarity index 95%
rename from libc/gfx/gfx_pal_get_color.c
rename to libbgi/common/gfx_pal_get_color.c
index b958794..99888a1 100644
--- a/libc/gfx/gfx_pal_get_color.c
+++ b/libbgi/common/gfx_pal_get_color.c
@@ -3,7 +3,7 @@
* R/G/B (любой указатель может быть NULL); обёртка над pal_get_color.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
#include
void gfx_pal_get_color(uint8_t pal_num, uint8_t idx,
diff --git a/libc/gfx/gfx_pal_load.c b/libbgi/common/gfx_pal_load.c
similarity index 98%
rename from libc/gfx/gfx_pal_load.c
rename to libbgi/common/gfx_pal_load.c
index d7e32d7..c25eedc 100644
--- a/libc/gfx/gfx_pal_load.c
+++ b/libbgi/common/gfx_pal_load.c
@@ -8,7 +8,7 @@
* палитру (следующая печать в текстовом режиме вешалась).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
#include
static uint8_t gpl_num_;
diff --git a/libc/gfx/gfx_pal_reset.c b/libbgi/common/gfx_pal_reset.c
similarity index 91%
rename from libc/gfx/gfx_pal_reset.c
rename to libbgi/common/gfx_pal_reset.c
index 67a52f0..27b5624 100644
--- a/libc/gfx/gfx_pal_reset.c
+++ b/libbgi/common/gfx_pal_reset.c
@@ -3,7 +3,7 @@
* (BIOS $A6, type = PAL_GRAPH).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
#include
void gfx_pal_reset(void)
diff --git a/libc/gfx/gfx_pal_set.c b/libbgi/common/gfx_pal_set.c
similarity index 95%
rename from libc/gfx/gfx_pal_set.c
rename to libbgi/common/gfx_pal_set.c
index 7546b3d..036945c 100644
--- a/libc/gfx/gfx_pal_set.c
+++ b/libbgi/common/gfx_pal_set.c
@@ -3,7 +3,7 @@
* четвёрку (B, G, R, 0) и зовёт gfx_pal_load(pal_num, idx, 1, ...).
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void gfx_pal_set(uint8_t pal_num, uint8_t idx,
uint8_t r, uint8_t g, uint8_t b)
diff --git a/libc/gfx/gfx_set_bank.c b/libbgi/common/gfx_set_bank.c
similarity index 88%
rename from libc/gfx/gfx_set_bank.c
rename to libbgi/common/gfx_set_bank.c
index 5c0ae44..914af9f 100644
--- a/libc/gfx/gfx_set_bank.c
+++ b/libbgi/common/gfx_set_bank.c
@@ -2,7 +2,7 @@
* gfx_set_bank — задать байт страницы W3 (0x50..0x5F) для gfx-записей.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void gfx_set_bank(uint8_t bank)
{
diff --git a/libc/gfx/gfx_set_draw_page.c b/libbgi/common/gfx_set_draw_page.c
similarity index 96%
rename from libc/gfx/gfx_set_draw_page.c
rename to libbgi/common/gfx_set_draw_page.c
index c7e10be..04d9b30 100644
--- a/libc/gfx/gfx_set_draw_page.c
+++ b/libbgi/common/gfx_set_draw_page.c
@@ -3,7 +3,7 @@
* _gfx_addr_base, который читают все примитивы.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void gfx_set_draw_page(uint8_t page)
{
diff --git a/libc/gfx/gfx_set_font.c b/libbgi/common/gfx_set_font.c
similarity index 93%
rename from libc/gfx/gfx_set_font.c
rename to libbgi/common/gfx_set_font.c
index f665bab..19fe523 100644
--- a/libc/gfx/gfx_set_font.c
+++ b/libbgi/common/gfx_set_font.c
@@ -3,7 +3,7 @@
* storage должен жить, пока шрифт активен). Формат см. _gfx.h.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void gfx_set_font(const uint8_t *font)
{
diff --git a/libc/gfx/gfx_set_visible_page.c b/libbgi/common/gfx_set_visible_page.c
similarity index 97%
rename from libc/gfx/gfx_set_visible_page.c
rename to libbgi/common/gfx_set_visible_page.c
index c29c88a..5434e86 100644
--- a/libc/gfx/gfx_set_visible_page.c
+++ b/libbgi/common/gfx_set_visible_page.c
@@ -6,7 +6,7 @@
* (один из свопов показывается чёрным). Через syscall DSS доволен.
*/
-#include "_gfx.h"
+#include "../_bgi.h"
void gfx_set_visible_page(uint8_t page)
{
diff --git a/libc/gfx/gfx_wait_vsync.c b/libbgi/common/gfx_wait_vsync.c
similarity index 98%
rename from libc/gfx/gfx_wait_vsync.c
rename to libbgi/common/gfx_wait_vsync.c
index 469d8df..400ed5a 100644
--- a/libc/gfx/gfx_wait_vsync.c
+++ b/libbgi/common/gfx_wait_vsync.c
@@ -19,8 +19,7 @@
* зависнуть намертво.
*/
-#include "_gfx.h"
-#include "../cbl/_cbl.h"
+#include "../_bgi.h"
#include
static uint8_t vsync_ready;
diff --git a/libc/bgi/graphresult.c b/libbgi/common/graphresult.c
similarity index 90%
rename from libc/bgi/graphresult.c
rename to libbgi/common/graphresult.c
index c7f4511..4975dad 100644
--- a/libc/bgi/graphresult.c
+++ b/libbgi/common/graphresult.c
@@ -1,5 +1,5 @@
/* graphresult — код последней ошибки; вызов сбрасывает его в grOk. */
-#include "_bgi.h"
+#include "../_bgi.h"
int graphresult(void)
{
diff --git a/libc/bgi/imagesize.c b/libbgi/common/imagesize.c
similarity index 97%
rename from libc/bgi/imagesize.c
rename to libbgi/common/imagesize.c
index 81635e8..56ff444 100644
--- a/libc/bgi/imagesize.c
+++ b/libbgi/common/imagesize.c
@@ -6,7 +6,7 @@
* Произведение w*h считаем в unsigned — для валидных (<64 КБ) образов
* умещается точно; без 32-бит.
*/
-#include "_bgi.h"
+#include "../_bgi.h"
unsigned imagesize(int left, int top, int right, int bottom)
{
diff --git a/libc/bgi/initgraph.c b/libbgi/common/initgraph.c
similarity index 97%
rename from libc/bgi/initgraph.c
rename to libbgi/common/initgraph.c
index 27b6bd0..c884129 100644
--- a/libc/bgi/initgraph.c
+++ b/libbgi/common/initgraph.c
@@ -5,7 +5,7 @@
* 320×256×256). По умолчанию: цвет WHITE, фон BLACK, позиция (0,0).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void initgraph(void)
{
diff --git a/libc/bgi/line.c b/libbgi/common/line.c
similarity index 90%
rename from libc/bgi/line.c
rename to libbgi/common/line.c
index c9a0b42..45313a6 100644
--- a/libc/bgi/line.c
+++ b/libbgi/common/line.c
@@ -1,5 +1,5 @@
/* line — отрезок (x1,y1)->(x2,y2) текущим цветом; CP не меняется. */
-#include "_bgi.h"
+#include "../_bgi.h"
void line(int x1, int y1, int x2, int y2)
{
diff --git a/libc/bgi/linerel.c b/libbgi/common/linerel.c
similarity index 92%
rename from libc/bgi/linerel.c
rename to libbgi/common/linerel.c
index bbb0c27..9cb1f70 100644
--- a/libc/bgi/linerel.c
+++ b/libbgi/common/linerel.c
@@ -1,5 +1,5 @@
/* linerel — линия от CP до CP+(dx,dy); CP сдвигается в конец. */
-#include "_bgi.h"
+#include "../_bgi.h"
void linerel(int dx, int dy)
{
diff --git a/libc/bgi/lineto.c b/libbgi/common/lineto.c
similarity index 90%
rename from libc/bgi/lineto.c
rename to libbgi/common/lineto.c
index 7fe6291..ad7295e 100644
--- a/libc/bgi/lineto.c
+++ b/libbgi/common/lineto.c
@@ -1,5 +1,5 @@
/* lineto — линия от CP до (x,y) текущим цветом; CP := (x,y). */
-#include "_bgi.h"
+#include "../_bgi.h"
void lineto(int x, int y)
{
diff --git a/libc/bgi/moverel.c b/libbgi/common/moverel.c
similarity index 88%
rename from libc/bgi/moverel.c
rename to libbgi/common/moverel.c
index b3dd510..273236b 100644
--- a/libc/bgi/moverel.c
+++ b/libbgi/common/moverel.c
@@ -1,5 +1,5 @@
/* moverel — сдвинуть текущую позицию относительно. */
-#include "_bgi.h"
+#include "../_bgi.h"
void moverel(int dx, int dy)
{
diff --git a/libc/bgi/moveto.c b/libbgi/common/moveto.c
similarity index 86%
rename from libc/bgi/moveto.c
rename to libbgi/common/moveto.c
index 8a3b7fa..8c592da 100644
--- a/libc/bgi/moveto.c
+++ b/libbgi/common/moveto.c
@@ -1,5 +1,5 @@
/* moveto — задать текущую позицию (CP). */
-#include "_bgi.h"
+#include "../_bgi.h"
void moveto(int x, int y)
{
diff --git a/libc/bgi/outtext.c b/libbgi/common/outtext.c
similarity index 95%
rename from libc/bgi/outtext.c
rename to libbgi/common/outtext.c
index 9d433b4..0b43aa5 100644
--- a/libc/bgi/outtext.c
+++ b/libbgi/common/outtext.c
@@ -2,7 +2,7 @@
* outtext — строка в текущей позиции (CP) текущим стилем текста; CP
* сдвигается на textwidth (гориз.) или вверх на textheight (верт.).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void outtext(const char *text)
{
diff --git a/libc/bgi/outtextxy.c b/libbgi/common/outtextxy.c
similarity index 92%
rename from libc/bgi/outtextxy.c
rename to libbgi/common/outtextxy.c
index e87f11e..d7df3af 100644
--- a/libc/bgi/outtextxy.c
+++ b/libbgi/common/outtextxy.c
@@ -1,6 +1,6 @@
/* outtextxy — строка в (x,y) текущим стилем текста (масштаб/направление,
* прозрачный фон); CP не меняет. */
-#include "_bgi.h"
+#include "../_bgi.h"
void outtextxy(int x, int y, const char *text)
{
diff --git a/libc/bgi/pieslice.c b/libbgi/common/pieslice.c
similarity index 91%
rename from libc/bgi/pieslice.c
rename to libbgi/common/pieslice.c
index f150b41..a900af1 100644
--- a/libc/bgi/pieslice.c
+++ b/libbgi/common/pieslice.c
@@ -1,5 +1,5 @@
/* pieslice — залитый сектор круга радиуса r (частный случай sector). */
-#include "_bgi.h"
+#include "../_bgi.h"
void pieslice(int x, int y, int stangle, int endangle, int radius)
{
diff --git a/libc/bgi/putimage.c b/libbgi/common/putimage.c
similarity index 98%
rename from libc/bgi/putimage.c
rename to libbgi/common/putimage.c
index fb31b57..37d8a58 100644
--- a/libc/bgi/putimage.c
+++ b/libbgi/common/putimage.c
@@ -5,7 +5,7 @@
* COPY — пишем src; XOR/OR/AND — комбинируем с экраном (нужно raw-
* чтение); NOT — пишем ~src. Всё в одной W3-скобке (raw-плот/чтение).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void putimage(int left, int top, const void *bitmap, int op)
{
diff --git a/libc/bgi/rectangle.c b/libbgi/common/rectangle.c
similarity index 95%
rename from libc/bgi/rectangle.c
rename to libbgi/common/rectangle.c
index 96523bb..e8de20d 100644
--- a/libc/bgi/rectangle.c
+++ b/libbgi/common/rectangle.c
@@ -1,5 +1,5 @@
/* rectangle — контур прямоугольника по углам (left,top)-(right,bottom). */
-#include "_bgi.h"
+#include "../_bgi.h"
void rectangle(int left, int top, int right, int bottom)
{
diff --git a/libc/bgi/sector.c b/libbgi/common/sector.c
similarity index 98%
rename from libc/bgi/sector.c
rename to libbgi/common/sector.c
index 9819d74..df55d53 100644
--- a/libc/bgi/sector.c
+++ b/libbgi/common/sector.c
@@ -9,7 +9,7 @@
* «выемку» (min/max по строке не различает 4 пересечения).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
/* точка на эллипсе под углом a (Q7-тригонометрия). */
static int se_x(int cx, int xr, int a) { return cx + ((xr * _bgi_cos128(a)) >> 7); }
diff --git a/libc/bgi/setbkcolor.c b/libbgi/common/setbkcolor.c
similarity index 88%
rename from libc/bgi/setbkcolor.c
rename to libbgi/common/setbkcolor.c
index 05a26be..7c54f07 100644
--- a/libc/bgi/setbkcolor.c
+++ b/libbgi/common/setbkcolor.c
@@ -1,5 +1,5 @@
/* setbkcolor — задать фоновый цвет (cleardevice, фон текста). */
-#include "_bgi.h"
+#include "../_bgi.h"
void setbkcolor(int color)
{
diff --git a/libc/bgi/setcolor.c b/libbgi/common/setcolor.c
similarity index 86%
rename from libc/bgi/setcolor.c
rename to libbgi/common/setcolor.c
index d416ae5..61c3100 100644
--- a/libc/bgi/setcolor.c
+++ b/libbgi/common/setcolor.c
@@ -1,5 +1,5 @@
/* setcolor — задать текущий цвет рисования. */
-#include "_bgi.h"
+#include "../_bgi.h"
void setcolor(int color)
{
diff --git a/libc/bgi/setfillstyle.c b/libbgi/common/setfillstyle.c
similarity index 91%
rename from libc/bgi/setfillstyle.c
rename to libbgi/common/setfillstyle.c
index 14d4fd6..3e9b1fa 100644
--- a/libc/bgi/setfillstyle.c
+++ b/libbgi/common/setfillstyle.c
@@ -1,5 +1,5 @@
/* setfillstyle — задать паттерн и цвет заливки (bar/fillpoly/…). */
-#include "_bgi.h"
+#include "../_bgi.h"
void setfillstyle(int pattern, int color)
{
diff --git a/libc/bgi/setlinestyle.c b/libbgi/common/setlinestyle.c
similarity index 94%
rename from libc/bgi/setlinestyle.c
rename to libbgi/common/setlinestyle.c
index 9fc98e0..47e7a3d 100644
--- a/libc/bgi/setlinestyle.c
+++ b/libbgi/common/setlinestyle.c
@@ -1,5 +1,5 @@
/* setlinestyle — задать стиль, пользовательскую маску и толщину линий. */
-#include "_bgi.h"
+#include "../_bgi.h"
void setlinestyle(int linestyle, unsigned upattern, int thickness)
{
diff --git a/libc/bgi/settextstyle.c b/libbgi/common/settextstyle.c
similarity index 95%
rename from libc/bgi/settextstyle.c
rename to libbgi/common/settextstyle.c
index f105a0f..9b932b4 100644
--- a/libc/bgi/settextstyle.c
+++ b/libbgi/common/settextstyle.c
@@ -2,7 +2,7 @@
* settextstyle — шрифт (поддержан только DEFAULT_FONT), направление и
* масштаб текста. font игнорируется (всегда растровый 8×8).
*/
-#include "_bgi.h"
+#include "../_bgi.h"
void settextstyle(int font, int direction, int charsize)
{
diff --git a/libc/bgi/textheight.c b/libbgi/common/textheight.c
similarity index 93%
rename from libc/bgi/textheight.c
rename to libbgi/common/textheight.c
index 55b6376..d87dceb 100644
--- a/libc/bgi/textheight.c
+++ b/libbgi/common/textheight.c
@@ -1,5 +1,5 @@
/* textheight — высота строки как она будет нарисована (масштаб/направление). */
-#include "_bgi.h"
+#include "../_bgi.h"
#include
int textheight(const char *text)
diff --git a/libc/bgi/textwidth.c b/libbgi/common/textwidth.c
similarity index 94%
rename from libc/bgi/textwidth.c
rename to libbgi/common/textwidth.c
index b24a1d3..e2ad879 100644
--- a/libc/bgi/textwidth.c
+++ b/libbgi/common/textwidth.c
@@ -1,6 +1,6 @@
/* textwidth — ширина строки как она будет нарисована (с учётом
* масштаба и направления). */
-#include "_bgi.h"
+#include "../_bgi.h"
#include
int textwidth(const char *text)
diff --git a/libbgi/include/gfx.h b/libbgi/include/gfx.h
new file mode 100644
index 0000000..d8ffa55
--- /dev/null
+++ b/libbgi/include/gfx.h
@@ -0,0 +1,74 @@
+/*
+ * gfx.h — Sprinter graphics: mode-agnostic API (BGI_GFX).
+ *
+ * Рисование (putpixel/line/bar/circle/…) вынесено в BGI — см.
+ * и driver-библиотеки bgi256.lib / bgi16.lib (выбор режима
+ * линковкой: sprinter-cc --gfx 256 | --gfx 16). Здесь остались только
+ * функции БЕЗ BGI-аналога: вход/выход в режим, страницы, банк, vsync,
+ * палитра, шрифт. Они mode-agnostic и живут в libbgi/common/ (один
+ * исходник, .rel в обеих driver-библиотеках).
+ *
+ * Адресация (для не-BGI программ, использующих эти примитивы напрямую:
+ * пиксель (x,y) — CPU 0xC000 + (x или x/2) с Port_Y (0x89) = y;
+ * gfx-код мапит 16 КБ VRAM-страницу в W3 при записи.
+ * Для double-buffering страница 1 начинается на 320 байт дальше (0xC140).
+ *
+ * Палитра: BIOS $A4 (RST 8); 4 байта на запись — B, G, R, pad.
+ */
+#ifndef GFX_H
+#define GFX_H
+
+#include
+
+/* ESTEX SETVMOD codes — same values as the SETVMOD `A` register. */
+#define GFX_MODE_TEXT_40x32 0x02
+#define GFX_MODE_TEXT_80x32 0x03
+#define GFX_MODE_320x256x256 0x81
+#define GFX_MODE_640x256x16 0x82
+
+/* Pixel dimensions of mode 0x81 (320×256, 256 colours). */
+#define GFX_WIDTH 320
+#define GFX_HEIGHT 256
+
+/* Pixel dimensions of mode 0x82 (640×256, 16 colours). Each byte at
+ * 0xC000+x_byte holds two pixels: high nibble = LEFT (even-x), low
+ * nibble = RIGHT (odd-x) — see memory/sprinter_graphics.md. */
+#define GFX_WIDTH_16 640
+#define GFX_HEIGHT_16 256
+#define GFX_COLORS_16 16
+
+/* ---- Page selection (double-buffering) and bank control ---------- */
+void gfx_set_visible_page(uint8_t page); /* 0 or 1 */
+uint8_t gfx_get_visible_page(void);
+void gfx_set_draw_page(uint8_t page); /* 0 or 1 */
+uint8_t gfx_get_draw_page(void);
+void gfx_set_bank(uint8_t bank); /* 0x50..0x5F */
+uint8_t gfx_get_bank(void);
+
+/* Block until the next frame (50 Hz). Типичный double-buffer:
+ * gfx_set_draw_page(hidden); draw_frame(); gfx_wait_vsync();
+ * gfx_set_visible_page(hidden); // tear-free flip */
+void gfx_wait_vsync(void);
+
+/* ---- Bitmap-font text -------------------------------------------- *
+ * Шрифт 256 глифов × 8 рядов × 1 байт (ZX-Spectrum формат), 2 КБ.
+ * Грузится лениво при первом использовании BGI-текста; gfx_set_font
+ * подменяет указатель (storage должен жить, пока шрифт активен). */
+void gfx_load_default_font(void);
+void gfx_set_font(const uint8_t *font);
+
+/* ---- Palette ----------------------------------------------------- *
+ * Каждая графическая страница имеет свою палитру (page 0 → palette 0,
+ * page 1 → palette 1). Для seamless double-buffering грузить одну
+ * палитру в обе. */
+void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count,
+ const uint8_t *data);
+void gfx_pal_set (uint8_t pal_num, uint8_t idx,
+ uint8_t r, uint8_t g, uint8_t b);
+void gfx_pal_get (uint8_t pal_num, uint8_t start, uint8_t count,
+ uint8_t *data);
+void gfx_pal_get_color(uint8_t pal_num, uint8_t idx,
+ uint8_t *r, uint8_t *g, uint8_t *b);
+void gfx_pal_reset(void);
+
+#endif
diff --git a/libc/include/graphics.h b/libbgi/include/graphics.h
similarity index 100%
rename from libc/include/graphics.h
rename to libbgi/include/graphics.h
diff --git a/libc/Makefile b/libc/Makefile
new file mode 100644
index 0000000..501beec
--- /dev/null
+++ b/libc/Makefile
@@ -0,0 +1,89 @@
+# Build lib/sprinter.lib — the Sprinter target libc archive.
+#
+# libc/ — ядро библиотеки (БЕЗ графики; графика вынесена в libbgi/).
+# Каждый .c под libc// — отдельный .rel в архиве (1 публичная
+# функция = 1 модуль); линкер тянет только нужные .rel → DCE на уровне
+# файлов. Плюс runtime-хелперы, которые автотянутся кодогеном SDCC
+# (heap для malloc). crt0-семейство НЕ в архиве — оно всегда явно
+# линкуется, не DCE-eligible. См. docs/libc-split-asm-cases.md.
+#
+# make build lib/sprinter.lib
+# make clean remove build/ + lib/sprinter.lib
+#
+# Симметрично libbgi/Makefile: исходники и build/ рядом, результат
+# ложится в общий каталог lib/ (откуда его линкует sprinter-cc).
+
+PROJ_ROOT := $(abspath $(CURDIR)/..)
+SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin
+SDCC := $(SDCC_BIN)/sdcc
+SDAR := $(SDCC_BIN)/sdar
+SDASZ80 := $(SDCC_BIN)/sdasz80
+
+INC := -I$(CURDIR)/include
+CC_FLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC)
+
+BUILD := $(CURDIR)/build
+
+# All libc C modules — every .c under libc// becomes its own .rel.
+# `libc/*/*.c` — ровно ОДИН уровень вложенности; графика (gfx/bgi) сюда
+# не попадает (вынесена в libbgi/). Один PUBLIC-символ на файл.
+LIBC_C := $(wildcard $(CURDIR)/*/*.c)
+
+# Runtime modules to bundle (pulled by symbol references from libc-using
+# code). bank.s НЕ bundled — его трамплин зависит от banking-окна (W1
+# для BIG, W3 для HUGE), что решается per-build в sprinter-cc; он
+# ассемблирует bank.s с нужным BANK_W1 флагом на каждый banked-build.
+RUNTIME_S := $(PROJ_ROOT)/runtime/heap.s
+
+LIBC_RELS := $(patsubst $(CURDIR)/%.c,$(BUILD)/%.rel,$(LIBC_C))
+RUNTIME_RELS := $(patsubst $(PROJ_ROOT)/runtime/%.s,$(BUILD)/%.rel,$(RUNTIME_S))
+
+ALL_RELS := $(LIBC_RELS) $(RUNTIME_RELS)
+KNOWN_RELS := $(ALL_RELS)
+
+# Штамп списка модулей: обновляется при любом изменении состава
+# (добавление/удаление/переименование исходника) — иначе удаление
+# исходника не триггерит перелинковку и stale .rel остаётся в архиве.
+# Сразу сносим и архив: на exFAT (SAM8) гранулярность mtime грубая,
+# и «список изменился» через сравнение времён можно проглядеть.
+MODLIST := $(BUILD)/.modules
+ifneq ($(shell cat $(MODLIST) 2>/dev/null),$(KNOWN_RELS))
+_ := $(shell mkdir -p $(BUILD); echo "$(KNOWN_RELS)" > $(MODLIST); rm -f $(LIB))
+endif
+
+LIB_DIR := $(PROJ_ROOT)/lib
+LIB := $(LIB_DIR)/sprinter.lib
+
+all: $(LIB)
+
+# Pattern rule для C-модулей libc//file.c → build//file.rel
+# (сохраняет путь io|mem|stdio внутри архива).
+$(BUILD)/%.rel: $(CURDIR)/%.c
+ @mkdir -p $(dir $@)
+ $(SDCC) $(CC_FLAGS) -c -o $@ $<
+
+# Runtime .s → .rel (runtime/ вне libc/, но heap.s бандлится в архив).
+$(BUILD)/%.rel: $(PROJ_ROOT)/runtime/%.s
+ @mkdir -p $(dir $@)
+ $(SDASZ80) -o $@ $<
+
+# Archive — sdar rcs = replace/create/symtab. Перед упаковкой удаляем
+# stale .rel: wildcard не знает об удалённых/переименованных исходниках,
+# и осиротевший .rel из build/ иначе жил бы вечно.
+$(LIB): $(ALL_RELS) $(MODLIST)
+ @find $(BUILD) -name '*.rel' -print | sort > $(BUILD)/.have
+ @printf '%s\n' $(KNOWN_RELS) | sort > $(BUILD)/.want
+ @comm -23 $(BUILD)/.have $(BUILD)/.want | while read f; do \
+ echo " stale: $$f (исходник удалён) — rm"; \
+ rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \
+ done
+ rm -f $@
+ $(SDAR) -rcs $@ $(ALL_RELS)
+ @echo
+ @echo " Built $@ with $(words $(ALL_RELS)) modules:"
+ @$(SDAR) -t $@ | sed 's/^/ /'
+
+clean:
+ rm -rf $(BUILD) $(LIB)
+
+.PHONY: all clean
diff --git a/libc/bgi/_bgi.h b/libc/bgi/_bgi.h
deleted file mode 100644
index c735fee..0000000
--- a/libc/bgi/_bgi.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * _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
-#include
-#include /* GFX_WIDTH/HEIGHT для внутренних таблиц */
-
-/* ---- Состояние (_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);
-
-/* ---- Тригонометрия для дуг (_bgi_trig.c) ------------------------- *
- * Угол в градусах; результат sin/cos × 128 (Q7 — чтобы радиус×значение
- * влезало в int без 32-бит арифметики). */
-int _bgi_sin128(int deg);
-int _bgi_cos128(int deg);
-
-/* Общий рисователь дуги/контура эллипса (_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 (_bgi_isqrt.c). */
-int _bgi_isqrt(int n);
-
-/* ---- Состояние линий (_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 */
-
-/* Отрезок текущим стилем/толщиной линии (_bgi_styled_line.c). */
-void _bgi_styled_line(int x0, int y0, int x1, int y1, uint8_t color);
-
-/* ---- Состояние заливки (_bgi_fill_state.c) ----------------------- */
-extern uint8_t _bgi_fill_pattern; /* *_FILL */
-extern uint8_t _bgi_fill_color;
-
-/* Raw horizontal span (без своей W3-скобки; клип делает сам gfx-raw). */
-void _bgi_hspan_raw(int x, int y, int len, uint8_t color);
-
-/* Raw чтение пикселя (без своей W3-скобки) — для getimage/putimage. */
-unsigned _bgi_read_raw(int x, int y);
-
-/* ---- Стиль текста (_bgi_text_state.c) ---------------------------- */
-extern uint8_t _bgi_text_dir; /* HORIZ_DIR / VERT_DIR */
-extern uint8_t _bgi_text_size; /* масштаб 1..10 */
-
-/* Заполнить 8 байт строк глифа символа c (грузит шрифт при первом
- * использовании) — drv256/_bgi_font_rows.c. */
-void _bgi_font_rows(unsigned char c, uint8_t *rows8);
-
-/* Нарисовать строку s в (x,y) текущим стилем текста (масштаб/направление,
- * цвет _bgi_fg, прозрачный фон) — _bgi_draw_scaled.c. */
-void _bgi_draw_scaled(int x, int y, const char *s);
-
-/* Залить строку [x0..x1] на y ТЕКУЩИМ стилем заливки (паттерн+цвет),
- * с клипом по экрану. Вызывать между _bgi_begin/_bgi_end. */
-void _bgi_fill_span(int x0, int x1, int y);
-
-/* Скан-таблицы min/max X по строкам для fillpoly (_bgi_poly_state.c). */
-extern int _bgi_span_min[GFX_HEIGHT];
-extern int _bgi_span_max[GFX_HEIGHT];
-
-/* Прогнать ребро (Брезенхэм) обновляя _bgi_span_min/max (_bgi_poly_edge.c). */
-void _bgi_poly_edge(int x0, int y0, int x1, int y1);
-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
diff --git a/libc/bgi/closegraph.c b/libc/bgi/closegraph.c
deleted file mode 100644
index 7e155d4..0000000
--- a/libc/bgi/closegraph.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* closegraph — вернуть текстовый режим, действовавший до initgraph. */
-#include "_bgi.h"
-
-void closegraph(void)
-{
- _bgi_mode_done(_bgi_prevmode);
-}
diff --git a/libc/bgi/drv256/_bgi_begin.c b/libc/bgi/drv256/_bgi_begin.c
deleted file mode 100644
index b4c2346..0000000
--- a/libc/bgi/drv256/_bgi_begin.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_begin (drv256) — открыть W3-сессию для пакетного рисования. */
-#include "../_bgi.h"
-#include "../../gfx/_gfx.h"
-
-void _bgi_begin(void)
-{
- _gfx_w3_video_begin();
-}
diff --git a/libc/bgi/drv256/_bgi_clearall.c b/libc/bgi/drv256/_bgi_clearall.c
deleted file mode 100644
index 2aea0d9..0000000
--- a/libc/bgi/drv256/_bgi_clearall.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_clearall (drv256) — залить весь экран цветом. */
-#include "../_bgi.h"
-#include
-
-void _bgi_clearall(uint8_t color)
-{
- gfx_clear256(color);
-}
diff --git a/libc/bgi/drv256/_bgi_drawtext.c b/libc/bgi/drv256/_bgi_drawtext.c
deleted file mode 100644
index 1608977..0000000
--- a/libc/bgi/drv256/_bgi_drawtext.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_drawtext (drv256) — строка шрифтом 8×8 цветами fg/bg в (x,y). */
-#include "../_bgi.h"
-#include
-
-void _bgi_drawtext(int x, int y, const char *s, uint8_t fg, uint8_t bg)
-{
- gfx_text256(x, y, s, fg, bg);
-}
diff --git a/libc/bgi/drv256/_bgi_end.c b/libc/bgi/drv256/_bgi_end.c
deleted file mode 100644
index eb43be2..0000000
--- a/libc/bgi/drv256/_bgi_end.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_end (drv256) — закрыть W3-сессию пакетного рисования. */
-#include "../_bgi.h"
-#include "../../gfx/_gfx.h"
-
-void _bgi_end(void)
-{
- _gfx_w3_video_end();
-}
diff --git a/libc/bgi/drv256/_bgi_fillrect.c b/libc/bgi/drv256/_bgi_fillrect.c
deleted file mode 100644
index b94f704..0000000
--- a/libc/bgi/drv256/_bgi_fillrect.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_fillrect (drv256) — залитый прямоугольник w×h из (x,y). */
-#include "../_bgi.h"
-#include
-
-void _bgi_fillrect(int x, int y, int w, int h, uint8_t color)
-{
- gfx_fill_rect256(x, y, w, h, color);
-}
diff --git a/libc/bgi/drv256/_bgi_font_rows.c b/libc/bgi/drv256/_bgi_font_rows.c
deleted file mode 100644
index bd9e627..0000000
--- a/libc/bgi/drv256/_bgi_font_rows.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * _bgi_font_rows (drv256) — 8 байт строк глифа символа c.
- * Шрифт системный, interleaved: offset = row*256 + char (MSB-first),
- * см. memory/sprinter_font_format. Грузится лениво (_gfx_font_ensure).
- */
-#include "../_bgi.h"
-#include "../../gfx/_gfx.h"
-
-void _bgi_font_rows(unsigned char c, uint8_t *rows8)
-{
- const uint8_t *f;
- int r;
- _gfx_font_ensure();
- f = _gfx_font_ptr;
- for (r = 0; r < 8; r++)
- rows8[r] = f[r * 256 + c];
-}
diff --git a/libc/bgi/drv256/_bgi_hspan.c b/libc/bgi/drv256/_bgi_hspan.c
deleted file mode 100644
index ad8bbd2..0000000
--- a/libc/bgi/drv256/_bgi_hspan.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_hspan (drv256) — горизонтальный отрезок len пикселей. */
-#include "../_bgi.h"
-#include
-
-void _bgi_hspan(int x, int y, int len, uint8_t color)
-{
- gfx_hline256(x, y, len, color);
-}
diff --git a/libc/bgi/drv256/_bgi_hspan_raw.c b/libc/bgi/drv256/_bgi_hspan_raw.c
deleted file mode 100644
index 3dcb6ae..0000000
--- a/libc/bgi/drv256/_bgi_hspan_raw.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * _bgi_hspan_raw (drv256) — горизонтальный отрезок без своей W3-скобки
- * (вызывать между _bgi_begin/_bgi_end). Клип делает сам raw-примитив.
- */
-#include "../_bgi.h"
-#include "../../gfx/_gfx.h"
-
-void _bgi_hspan_raw(int x, int y, int len, uint8_t color)
-{
- _gfx_hline256_raw(x, y, len, color);
-}
diff --git a/libc/bgi/drv256/_bgi_lineseg.c b/libc/bgi/drv256/_bgi_lineseg.c
deleted file mode 100644
index 02c7e17..0000000
--- a/libc/bgi/drv256/_bgi_lineseg.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_lineseg (drv256) — отрезок (x0,y0)->(x1,y1) (использует accel-line). */
-#include "../_bgi.h"
-#include
-
-void _bgi_lineseg(int x0, int y0, int x1, int y1, uint8_t color)
-{
- gfx_line256(x0, y0, x1, y1, color);
-}
diff --git a/libc/bgi/drv256/_bgi_mode_done.c b/libc/bgi/drv256/_bgi_mode_done.c
deleted file mode 100644
index 0b6c74b..0000000
--- a/libc/bgi/drv256/_bgi_mode_done.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_mode_done (drv256) — вернуть видеорежим, бывший до initgraph. */
-#include "../_bgi.h"
-#include
-
-void _bgi_mode_done(uint8_t prev_mode)
-{
- gfx_done(prev_mode);
-}
diff --git a/libc/bgi/drv256/_bgi_plot.c b/libc/bgi/drv256/_bgi_plot.c
deleted file mode 100644
index 6041ba7..0000000
--- a/libc/bgi/drv256/_bgi_plot.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_plot (drv256) — одиночный пиксель текущим цветом. */
-#include "../_bgi.h"
-#include
-
-void _bgi_plot(int x, int y, uint8_t color)
-{
- gfx_putpixel256(x, y, color);
-}
diff --git a/libc/bgi/drv256/_bgi_plot_raw.c b/libc/bgi/drv256/_bgi_plot_raw.c
deleted file mode 100644
index 0ce530f..0000000
--- a/libc/bgi/drv256/_bgi_plot_raw.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * _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);
-}
diff --git a/libc/bgi/drv256/_bgi_read.c b/libc/bgi/drv256/_bgi_read.c
deleted file mode 100644
index 8303807..0000000
--- a/libc/bgi/drv256/_bgi_read.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* _bgi_read (drv256) — цвет пикселя (x,y). */
-#include "../_bgi.h"
-#include
-
-unsigned _bgi_read(int x, int y)
-{
- return gfx_getpixel256(x, y);
-}
diff --git a/libc/bgi/drv256/_bgi_read_raw.c b/libc/bgi/drv256/_bgi_read_raw.c
deleted file mode 100644
index f667e17..0000000
--- a/libc/bgi/drv256/_bgi_read_raw.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * _bgi_read_raw (drv256) — чтение пикселя без своей W3-скобки
- * (между _bgi_begin/_bgi_end). Для getimage/putimage.
- */
-#include "../_bgi.h"
-#include "../../gfx/_gfx.h"
-
-unsigned _bgi_read_raw(int x, int y)
-{
- return _gfx_getpixel256_raw(x, y);
-}
diff --git a/libc/bgi/getpixel.c b/libc/bgi/getpixel.c
deleted file mode 100644
index 1a56540..0000000
--- a/libc/bgi/getpixel.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* getpixel — цвет пикселя (x,y). */
-#include "_bgi.h"
-
-unsigned getpixel(int x, int y)
-{
- return _bgi_read(x, y);
-}
diff --git a/libc/bgi/putpixel.c b/libc/bgi/putpixel.c
deleted file mode 100644
index f1d6996..0000000
--- a/libc/bgi/putpixel.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/* putpixel — точка (x,y) заданным цветом (не трогает текущий цвет/CP). */
-#include "_bgi.h"
-
-void putpixel(int x, int y, int color)
-{
- _bgi_plot(x, y, (uint8_t)color);
-}
diff --git a/libc/gfx/_gfx.h b/libc/gfx/_gfx.h
deleted file mode 100644
index 4d85a85..0000000
--- a/libc/gfx/_gfx.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * _gfx.h — внутренности графической подсистемы (НЕ публичный заголовок).
- *
- * Общее состояние лежит в data-модулях (_gfx_state.c, _gfx_w3_state.c,
- * _gfx_acc256.c, _gfx_g16_state.c, _gfx_font_state.c), helpers — в
- * отдельных internal-модулях; см. docs/libc-split-asm-cases.md.
- */
-#ifndef _GFX_INTERNAL_H
-#define _GFX_INTERNAL_H
-
-#include
-
-/* ---- Общее состояние (_gfx_state.c) ------------------------------ */
-
-/* Кэш SELPAGE: видимая и рисуемая страницы (0/1). */
-extern uint8_t _gfx_visible_page;
-extern uint8_t _gfx_draw_page;
-
-/* Байт страницы W3 (0x50..0x5F) — какой видеобанк мапится при записи. */
-extern uint8_t _gfx_bank;
-
-/* CPU-адрес колонки 0 текущей draw-страницы: 0xC000 (page 0) или
- * 0xC140 (page 1); каждый примитив использует его вместо константы. */
-extern uint16_t _gfx_addr_base;
-
-/* ---- Низкоуровневый видеорежим (video/videomode_raw.c) ----------- */
-
-uint8_t _videomode_raw_get(void);
-int _videomode_raw_set(uint8_t mode);
-
-/* ---- W3-скобки (_gfx_w3_video_begin/end.c, _gfx_w3_state.c) ------ *
- * begin: DI + сохранить текущий W3 и замапить _gfx_bank;
- * end: восстановить W3 + EI. Не реентерабельно (сейв в статике). */
-
-extern uint8_t _gfx_saved_w3;
-
-void _gfx_w3_video_begin(void);
-void _gfx_w3_video_end(void);
-
-/* ---- Raw-примитивы 256 цветов (mode 0x81) ------------------------- *
- * "Raw" = W3-naive: вызывающий обязан обернуть последовательность в
- * одну пару _gfx_w3_video_begin/_gfx_w3_video_end. */
-
-void _gfx_putpixel256_raw(int x, int y, uint8_t color);
-uint8_t _gfx_getpixel256_raw(int x, int y);
-void _gfx_hline256_raw (int x, int y, int len, uint8_t color);
-void _gfx_vline256_raw (int x, int y, int len, uint8_t color);
-void _gfx_clear256_raw (uint8_t color);
-
-/* Скретч акселератора (_gfx_acc256.c) — общий для hline/vline/clear;
- * однопоточно, IRQ выключены между begin/end. */
-extern uint8_t _gfx_acc_color;
-extern uint8_t _gfx_acc_y;
-extern uint8_t _gfx_acc_len; /* 0 = 256 — конвенция акселератора */
-extern uint16_t _gfx_acc_addr;
-
-/* Горизонтальный Fill-burst: _gfx_acc_len байт с _gfx_acc_addr на
- * строке _gfx_acc_y (W3 замаплен, DI активен). */
-void _gfx_hfill256_chunk(void);
-
-/* ---- Raw-примитивы 16 цветов (mode 0x82) -------------------------- */
-
-void _gfx_putpixel16_raw(int x, int y, uint8_t color);
-void _gfx_hline16_raw (int x, int y, int len, uint8_t color);
-void _gfx_vline16_raw (int x, int y, int len, uint8_t color);
-void _gfx_clear16_raw (uint8_t color);
-
-/* Скретч 16-цветных примитивов (_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 (_gfx_hfill16.c). */
-void _gfx_hfill16_chunk(void);
-
-/* RMW одного нибла по (_gfx_g16_addr, _gfx_g16_y) (_gfx_rmw16.c). */
-void _gfx_rmw16_pixel(void);
-
-/* ---- Шрифт (_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);
-
-/* ---- Текст 16 цветов: общая машинерия ----------------------------- *
- * Данные в _gfx_t16_state.c, рендер ряда в _gfx_render_row16.c,
- * pair-таблица в _gfx_t16_pair_build.c. */
-
-extern uint8_t _gfx_t16_y;
-extern uint8_t _gfx_t16_row; /* битовый паттерн ряда глифа */
-extern uint16_t _gfx_t16_addr; /* VRAM-адрес ряда */
-extern uint8_t _gfx_t16_pair[4]; /* LEFT*2+RIGHT → (LEFT<<4)|RIGHT */
-
-/* Отрисовать один 8-пиксельный ряд по pair-таблице (4 записи байт). */
-void _gfx_render_row16(void);
-
-/* Заполнить pair-таблицу для пары цветов fg/bg. */
-void _gfx_t16_pair_build(uint8_t fg, uint8_t bg);
-
-#endif
diff --git a/libc/gfx/_gfx_render_row16.c b/libc/gfx/_gfx_render_row16.c
deleted file mode 100644
index 257a1cd..0000000
--- a/libc/gfx/_gfx_render_row16.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * _gfx_render_row16 — один 8-пиксельный ряд глифа в mode 0x82
- * (640×256×16): 4 выходных байта, каждый пакует два соседних пикселя
- * как (LEFT<<4) | RIGHT через прекомпилированную _gfx_t16_pair —
- * 2-битный паттерн источника (LEFT*2 + RIGHT) сразу даёт выходной
- * байт, без mask/OR на пиксель. Сам делает DI / W3 save+restore —
- * вызывать можно из любого контекста без скобок.
- */
-
-#include "_gfx.h"
-
-void _gfx_render_row16(void) __naked
-{
- __asm
- di
- in a, (#0xE2)
- push af
- ld a, #0x50
- out (#0xE2), a
- ld a, (__gfx_t16_y)
- out (#0x89), a
-
- ld hl, (__gfx_t16_addr)
- ld a, (__gfx_t16_row)
- ld c, a ; C = сдвигаемые биты источника
- ld b, #4 ; 4 выходных байта
- rr16_loop:
- ;; Два верхних бита C в индекс A = LEFT*2 + RIGHT.
- sla c ; CY = бит LEFT; C <<= 1
- ld a, #0
- adc a, a ; A = LEFT
- sla c ; CY = бит RIGHT; C <<= 1
- adc a, a ; A = LEFT*2 + RIGHT (0..3)
-
- ;; A = _gfx_t16_pair[A]; HL сохраняем через стек.
- push hl
- ld e, a
- ld d, #0
- ld hl, #__gfx_t16_pair
- add hl, de
- ld a, (hl)
- pop hl
-
- ld (hl), a
- inc hl
- djnz rr16_loop
-
- pop af
- out (#0xE2), a
- ei
- ret
- __endasm;
-}
diff --git a/libc/gfx/_gfx_t16_pair_build.c b/libc/gfx/_gfx_t16_pair_build.c
deleted file mode 100644
index 31726a2..0000000
--- a/libc/gfx/_gfx_t16_pair_build.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * _gfx_t16_pair_build — заполнить pair-таблицу текстового рендера
- * mode 0x82 для пары цветов fg/bg.
- */
-
-#include "_gfx.h"
-
-void _gfx_t16_pair_build(uint8_t fg, uint8_t bg)
-{
- uint8_t f = fg & 0x0F;
- uint8_t b = bg & 0x0F;
- /* HIGH nibble = LEFT, LOW = RIGHT (конвенция sprinter_graphics). */
- _gfx_t16_pair[0] = (uint8_t)((b << 4) | b); /* 00 BG BG */
- _gfx_t16_pair[1] = (uint8_t)((b << 4) | f); /* 01 BG FG */
- _gfx_t16_pair[2] = (uint8_t)((f << 4) | b); /* 10 FG BG */
- _gfx_t16_pair[3] = (uint8_t)((f << 4) | f); /* 11 FG FG */
-}
diff --git a/libc/gfx/_gfx_t16_state.c b/libc/gfx/_gfx_t16_state.c
deleted file mode 100644
index 3c9d80d..0000000
--- a/libc/gfx/_gfx_t16_state.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * _gfx_t16_state — скретч текстового рендера mode 0x82 (только данные).
- * Пишут gfx_putchar16/gfx_text16 и _gfx_t16_pair_build, читает
- * _gfx_render_row16.
- */
-
-#include "_gfx.h"
-
-uint8_t _gfx_t16_y;
-uint8_t _gfx_t16_row;
-uint16_t _gfx_t16_addr;
-
-/* index = LEFT*2 + RIGHT, value = (LEFT<<4)|RIGHT. */
-uint8_t _gfx_t16_pair[4];
diff --git a/libc/gfx/_gfx_w3_video_begin.c b/libc/gfx/_gfx_w3_video_begin.c
deleted file mode 100644
index 4a6e271..0000000
--- a/libc/gfx/_gfx_w3_video_begin.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * _gfx_w3_video_begin — DI, сохранить текущую страницу W3 и замапить
- * _gfx_bank (видеобанк 0x50..0x5F). Композитные примитивы обрамляют
- * одной парой begin/end весь внутренний цикл — W3-танец оплачивается
- * один раз на операцию, а не на пиксель.
- */
-
-#include "_gfx.h"
-
-void _gfx_w3_video_begin(void) __naked
-{
- __asm
- di
- in a, (#0xE2)
- ld (__gfx_saved_w3), a
- ld a, (__gfx_bank)
- out (#0xE2), a
- ret
- __endasm;
-}
diff --git a/libc/gfx/_gfx_w3_video_end.c b/libc/gfx/_gfx_w3_video_end.c
deleted file mode 100644
index 2cf90ac..0000000
--- a/libc/gfx/_gfx_w3_video_end.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * _gfx_w3_video_end — восстановить сохранённую страницу W3 и EI.
- */
-
-#include "_gfx.h"
-
-void _gfx_w3_video_end(void) __naked
-{
- __asm
- ld a, (__gfx_saved_w3)
- out (#0xE2), a
- ei
- ret
- __endasm;
-}
diff --git a/libc/gfx/gfx_clear16.c b/libc/gfx/gfx_clear16.c
deleted file mode 100644
index 62925b5..0000000
--- a/libc/gfx/gfx_clear16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * gfx_clear16 — залить экран цветом (mode 0x82); одна W3-скобка.
- */
-
-#include "_gfx.h"
-
-void gfx_clear16(uint8_t color)
-{
- _gfx_w3_video_begin();
- _gfx_clear16_raw(color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_clear256.c b/libc/gfx/gfx_clear256.c
deleted file mode 100644
index 4c00ab8..0000000
--- a/libc/gfx/gfx_clear256.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * gfx_clear256 — залить экран цветом (mode 0x81); одна W3-скобка.
- */
-
-#include "_gfx.h"
-
-void gfx_clear256(uint8_t color)
-{
- _gfx_w3_video_begin();
- _gfx_clear256_raw(color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_done.c b/libc/gfx/gfx_done.c
deleted file mode 100644
index 953c453..0000000
--- a/libc/gfx/gfx_done.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * gfx_done — восстановить ранее сохранённый видеорежим (из gfx_init).
- */
-
-#include "_gfx.h"
-
-void gfx_done(uint8_t mode)
-{
- _videomode_raw_set(mode);
-}
diff --git a/libc/gfx/gfx_fill_rect16.c b/libc/gfx/gfx_fill_rect16.c
deleted file mode 100644
index 93a3ee2..0000000
--- a/libc/gfx/gfx_fill_rect16.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * gfx_fill_rect16 — залитый прямоугольник w×h от (x,y) (mode 0x82).
- * Поколоночные vlines (per-row RMW в каждой колонке); внешняя
- * begin/end-скобка мапит W3 один раз на весь прямоугольник.
- */
-
-#include "_gfx.h"
-
-void gfx_fill_rect16(int x, int y, int w, int h, uint8_t color)
-{
- if (w <= 0 || h <= 0) return;
- _gfx_w3_video_begin();
- for (int xx = 0; xx < w; xx++)
- _gfx_vline16_raw(x + xx, y, h, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_fill_rect256.c b/libc/gfx/gfx_fill_rect256.c
deleted file mode 100644
index fdbd849..0000000
--- a/libc/gfx/gfx_fill_rect256.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * gfx_fill_rect256 — залитый прямоугольник w×h от (x,y) (mode 0x81).
- */
-
-#include "_gfx.h"
-
-void gfx_fill_rect256(int x, int y, int w, int h, uint8_t color)
-{
- if (w <= 0 || h <= 0) return;
-
- /* Ориентация с меньшим числом accel-burst'ов. Один burst красит
- * до 256 смежных байт (горизонталь) или до 256 пикселей колонки.
- * построчно (hlines): h × ceil(w/256) burst'ов
- * поколоночно (vlines): w × ceil(h/256) — при h ≤ 256 это w
- * Вертикаль выигрывает на высоких узких, горизонталь — на низких
- * широких. */
- int h_bursts = h * ((w + 255) >> 8);
- int v_bursts = w * ((h + 255) >> 8);
- _gfx_w3_video_begin();
- if (h_bursts <= v_bursts) {
- for (int yy = 0; yy < h; yy++)
- _gfx_hline256_raw(x, y + yy, w, color);
- } else {
- for (int xx = 0; xx < w; xx++)
- _gfx_vline256_raw(x + xx, y, h, color);
- }
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_getpixel256.c b/libc/gfx/gfx_getpixel256.c
deleted file mode 100644
index 8ea4137..0000000
--- a/libc/gfx/gfx_getpixel256.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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;
-}
diff --git a/libc/gfx/gfx_hline16.c b/libc/gfx/gfx_hline16.c
deleted file mode 100644
index 0e16f91..0000000
--- a/libc/gfx/gfx_hline16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * gfx_hline16 — горизонтальная линия (mode 0x82) в W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_hline16(int x, int y, int len, uint8_t color)
-{
- _gfx_w3_video_begin();
- _gfx_hline16_raw(x, y, len, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_hline256.c b/libc/gfx/gfx_hline256.c
deleted file mode 100644
index 36d9e20..0000000
--- a/libc/gfx/gfx_hline256.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * gfx_hline256 — горизонтальная линия (mode 0x81) в W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_hline256(int x, int y, int len, uint8_t color)
-{
- _gfx_w3_video_begin();
- _gfx_hline256_raw(x, y, len, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_init.c b/libc/gfx/gfx_init.c
deleted file mode 100644
index ad76c7c..0000000
--- a/libc/gfx/gfx_init.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * gfx_init — переключиться в графический режим `mode`, вернуть прежний.
- *
- * `page` (0/1) — стартовая страница: и видимая, и рисуемая; банк W3
- * сбрасывается в 0x50 (канонический видимый видеобанк). Идёт через
- * _videomode_raw_set — минуя text-only валидацию conio.
- */
-
-#include "_gfx.h"
-
-uint8_t gfx_init(uint8_t mode, uint8_t page)
-{
- uint8_t prev = _videomode_raw_get();
- _videomode_raw_set(mode);
- _gfx_bank = 0x50;
- gfx_set_visible_page(page);
- gfx_set_draw_page(page);
- return prev;
-}
diff --git a/libc/gfx/gfx_line16.c b/libc/gfx/gfx_line16.c
deleted file mode 100644
index 8620af2..0000000
--- a/libc/gfx/gfx_line16.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * gfx_line16 — линия (x0,y0)-(x1,y1) (mode 0x82). Ортогональные —
- * через hline/vline; наклонные — Брезенхэм с одной W3-скобкой.
- */
-
-#include "_gfx.h"
-
-void gfx_line16(int x0, int y0, int x1, int y1, uint8_t color)
-{
- if (y0 == y1) {
- int x = x0 <= x1 ? x0 : x1;
- int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1;
- gfx_hline16(x, y0, w, color);
- return;
- }
- if (x0 == x1) {
- int y = y0 <= y1 ? y0 : y1;
- int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1;
- gfx_vline16(x0, y, h, color);
- return;
- }
- int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx;
- int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy;
- int err = (dx > dy ? dx : -dy) / 2;
- int x = x0, y = y0;
- _gfx_w3_video_begin();
- for (;;) {
- _gfx_putpixel16_raw(x, y, color);
- if (x == x1 && y == y1) break;
- int e2 = err;
- if (e2 > -dx) { err -= dy; x += sx; }
- if (e2 < dy) { err += dx; y += sy; }
- }
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_line256.c b/libc/gfx/gfx_line256.c
deleted file mode 100644
index b3e0e1c..0000000
--- a/libc/gfx/gfx_line256.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * gfx_line256 — линия (x0,y0)-(x1,y1) (mode 0x81). Ортогональные
- * уходят на акселератор; наклонные — Брезенхэм с одной W3-скобкой
- * вокруг всего цикла.
- */
-
-#include "_gfx.h"
-
-void gfx_line256(int x0, int y0, int x1, int y1, uint8_t color)
-{
- if (y0 == y1) {
- int x = x0 <= x1 ? x0 : x1;
- int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1;
- gfx_hline256(x, y0, w, color);
- return;
- }
- if (x0 == x1) {
- int y = y0 <= y1 ? y0 : y1;
- int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1;
- gfx_vline256(x0, y, h, color);
- return;
- }
-
- int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx;
- int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy;
- int err = (dx > dy ? dx : -dy) / 2;
- int x = x0, y = y0;
- _gfx_w3_video_begin();
- for (;;) {
- _gfx_putpixel256_raw(x, y, color);
- if (x == x1 && y == y1) break;
- int e2 = err;
- if (e2 > -dx) { err -= dy; x += sx; }
- if (e2 < dy) { err += dx; y += sy; }
- }
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_putchar16.c b/libc/gfx/gfx_putchar16.c
deleted file mode 100644
index fb78947..0000000
--- a/libc/gfx/gfx_putchar16.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * gfx_putchar16 — символ шрифтом 8×8 в (x,y), mode 0x82.
- * x должен быть ЧЁТНЫМ (байтовое выравнивание); нечётный молча
- * игнорируется — текстовые сетки обычно выровнены.
- */
-
-#include "_gfx.h"
-
-void gfx_putchar16(int x, int y, char c, uint8_t fg, uint8_t bg)
-{
- _gfx_font_ensure();
- if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return;
- if (x & 1) return;
-
- _gfx_t16_pair_build(fg, bg);
- uint8_t cc = (uint8_t)c;
- uint16_t base = (uint16_t)(_gfx_addr_base + ((unsigned)x >> 1));
-
- for (int r = 0; r < 8; r++) {
- int yy = y + r;
- if ((unsigned)yy >= GFX_HEIGHT_16) break;
- _gfx_t16_y = (uint8_t)yy;
- _gfx_t16_addr = base;
- _gfx_t16_row = _gfx_font_ptr[r * 256 + cc];
- _gfx_render_row16();
- }
-}
diff --git a/libc/gfx/gfx_putchar256.c b/libc/gfx/gfx_putchar256.c
deleted file mode 100644
index dc53d14..0000000
--- a/libc/gfx/gfx_putchar256.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * gfx_putchar256 — символ шрифтом 8×8 в (x,y), mode 0x81 (байт на
- * пиксель). На ряд глифа (8 пикселей) пишем 8 байт: FG где бит 1,
- * BG где 0. Рендер ряда сам делает DI / W3 save+restore — вызывать
- * можно из любого контекста без скобок.
- */
-
-#include "_gfx.h"
-
-/* Скретч рендера ряда — только этого модуля. */
-static uint8_t txt_y;
-static uint8_t txt_row; /* битовый паттерн текущего ряда глифа */
-static uint8_t txt_fg;
-static uint8_t txt_bg;
-static uint16_t txt_addr; /* VRAM-адрес ряда */
-
-static void render_row_256(void) __naked
-{
- __asm
- di
- in a, (#0xE2)
- push af
- ld a, #0x50
- out (#0xE2), a
- ld a, (_txt_y)
- out (#0x89), a
-
- ld hl, (_txt_addr)
- ld a, (_txt_fg)
- ld d, a
- ld a, (_txt_bg)
- ld e, a
- ld a, (_txt_row)
- ld b, #8 ; 8 пикселей в ряду
- rr256_loop:
- rla ; CY = старший бит, A <<= 1
- jr nc, rr256_bg
- ld (hl), d ; FG
- jr rr256_next
- rr256_bg:
- ld (hl), e ; BG
- rr256_next:
- inc hl
- djnz rr256_loop
-
- pop af
- out (#0xE2), a
- ei
- ret
- __endasm;
-}
-
-void gfx_putchar256(int x, int y, char c, uint8_t fg, uint8_t bg)
-{
- _gfx_font_ensure();
- if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return;
-
- txt_fg = fg;
- txt_bg = bg;
- uint8_t cc = (uint8_t)c;
- uint16_t base = (uint16_t)(_gfx_addr_base + (unsigned)x);
-
- for (int r = 0; r < 8; r++) {
- int yy = y + r;
- if ((unsigned)yy >= GFX_HEIGHT) break;
- txt_y = (uint8_t)yy;
- txt_addr = base;
- /* Interleaved-раскладка: ряд r глифа cc — font[r*256 + cc]. */
- txt_row = _gfx_font_ptr[r * 256 + cc];
- render_row_256();
- }
-}
diff --git a/libc/gfx/gfx_putpixel16.c b/libc/gfx/gfx_putpixel16.c
deleted file mode 100644
index 47294ef..0000000
--- a/libc/gfx/gfx_putpixel16.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * gfx_putpixel16 — пиксель (x,y) цветом 0..15 (mode 0x82);
- * одиночный вызов в собственной W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_putpixel16(int x, int y, uint8_t color)
-{
- if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return;
- _gfx_w3_video_begin();
- _gfx_putpixel16_raw(x, y, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_putpixel256.c b/libc/gfx/gfx_putpixel256.c
deleted file mode 100644
index 34e64b9..0000000
--- a/libc/gfx/gfx_putpixel256.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * gfx_putpixel256 — пиксель (x,y) цветом color (mode 0x81);
- * одиночный вызов в собственной W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_putpixel256(int x, int y, uint8_t color)
-{
- if ((unsigned)x >= GFX_WIDTH || (unsigned)y >= GFX_HEIGHT) return;
- _gfx_w3_video_begin();
- _gfx_putpixel256_raw(x, y, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_rect16.c b/libc/gfx/gfx_rect16.c
deleted file mode 100644
index 7de60c7..0000000
--- a/libc/gfx/gfx_rect16.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * gfx_rect16 — рамка w×h от (x,y) (mode 0x82); все четыре стороны
- * в одной W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_rect16(int x, int y, int w, int h, uint8_t color)
-{
- if (w <= 0 || h <= 0) return;
- _gfx_w3_video_begin();
- _gfx_hline16_raw(x, y, w, color);
- _gfx_hline16_raw(x, y + h - 1, w, color);
- if (h > 2) {
- _gfx_vline16_raw(x, y + 1, h - 2, color);
- _gfx_vline16_raw(x + w - 1, y + 1, h - 2, color);
- }
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_rect256.c b/libc/gfx/gfx_rect256.c
deleted file mode 100644
index c2e3d47..0000000
--- a/libc/gfx/gfx_rect256.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * gfx_rect256 — рамка w×h от (x,y) (mode 0x81); все четыре стороны
- * в одной W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_rect256(int x, int y, int w, int h, uint8_t color)
-{
- if (w <= 0 || h <= 0) return;
- _gfx_w3_video_begin();
- _gfx_hline256_raw(x, y, w, color);
- _gfx_hline256_raw(x, y + h - 1, w, color);
- if (h > 2) {
- _gfx_vline256_raw(x, y + 1, h - 2, color);
- _gfx_vline256_raw(x + w - 1, y + 1, h - 2, color);
- }
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_text16.c b/libc/gfx/gfx_text16.c
deleted file mode 100644
index 6f14666..0000000
--- a/libc/gfx/gfx_text16.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * gfx_text16 — строка шрифтом 8×8 от (x,y), mode 0x82; x чётный,
- * растёт на 8 на символ. Pair-таблица строится один раз на всю
- * строку (FG/BG не меняются) — поэтому не через gfx_putchar16.
- */
-
-#include "_gfx.h"
-
-void gfx_text16(int x, int y, const char *s, uint8_t fg, uint8_t bg)
-{
- _gfx_font_ensure();
- if (x & 1) return;
- _gfx_t16_pair_build(fg, bg);
- for (; *s; s++) {
- if (x >= GFX_WIDTH_16) break;
- if ((unsigned)y >= GFX_HEIGHT_16) break;
- uint8_t cc = (uint8_t)*s;
- uint16_t base = (uint16_t)(_gfx_addr_base + ((unsigned)x >> 1));
- for (int r = 0; r < 8; r++) {
- int yy = y + r;
- if ((unsigned)yy >= GFX_HEIGHT_16) break;
- _gfx_t16_y = (uint8_t)yy;
- _gfx_t16_addr = base;
- _gfx_t16_row = _gfx_font_ptr[r * 256 + cc];
- _gfx_render_row16();
- }
- x += 8;
- }
-}
diff --git a/libc/gfx/gfx_text256.c b/libc/gfx/gfx_text256.c
deleted file mode 100644
index 4ba8ee5..0000000
--- a/libc/gfx/gfx_text256.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * gfx_text256 — строка шрифтом 8×8 от (x,y), mode 0x81; x растёт
- * на 8 на символ.
- */
-
-#include "_gfx.h"
-
-void gfx_text256(int x, int y, const char *s, uint8_t fg, uint8_t bg)
-{
- for (; *s; s++) {
- if (x >= GFX_WIDTH) break;
- gfx_putchar256(x, y, *s, fg, bg);
- x += 8;
- }
-}
diff --git a/libc/gfx/gfx_vline16.c b/libc/gfx/gfx_vline16.c
deleted file mode 100644
index 34406e8..0000000
--- a/libc/gfx/gfx_vline16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * gfx_vline16 — вертикальная линия (mode 0x82) в W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_vline16(int x, int y, int len, uint8_t color)
-{
- _gfx_w3_video_begin();
- _gfx_vline16_raw(x, y, len, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/gfx/gfx_vline256.c b/libc/gfx/gfx_vline256.c
deleted file mode 100644
index 594f00b..0000000
--- a/libc/gfx/gfx_vline256.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * gfx_vline256 — вертикальная линия (mode 0x81) в W3-скобке.
- */
-
-#include "_gfx.h"
-
-void gfx_vline256(int x, int y, int len, uint8_t color)
-{
- _gfx_w3_video_begin();
- _gfx_vline256_raw(x, y, len, color);
- _gfx_w3_video_end();
-}
diff --git a/libc/include/gfx.h b/libc/include/gfx.h
deleted file mode 100644
index 197a004..0000000
--- a/libc/include/gfx.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * gfx.h — Sprinter graphics primitives.
- *
- * Two main modes:
- * GFX_MODE_320x256x256 (0x81) — one byte per pixel, palette of 256
- * entries. API functions suffixed _256.
- * GFX_MODE_640x256x16 (0x82) — 4 bits per pixel, palette of 16.
- * API functions suffixed _16.
- *
- * Common API (no suffix) covers things that are mode-agnostic:
- * gfx_init / gfx_done
- * gfx_set_visible_page / gfx_set_draw_page / gfx_set_bank
- * gfx_wait_vsync
- * gfx_pal_load / gfx_pal_set
- * gfx_load_default_font / gfx_set_font
- *
- * Addressing reminder:
- * pixel (x, y) lives at CPU 0xC000 + (x or x/2) with Port_Y (0x89) = y;
- * the gfx code maps a 16 KB VRAM page into W3 around every write.
- * For double-buffering, page 1 starts 320 bytes later (0xC140).
- *
- * Palette: BIOS $A4 (RST 8); 4 bytes per entry — B, G, R, pad.
- */
-
-#ifndef GFX_H
-#define GFX_H
-
-#include
-
-/* ESTEX SETVMOD codes — same values as the SETVMOD `A` register. */
-#define GFX_MODE_TEXT_40x32 0x02
-#define GFX_MODE_TEXT_80x32 0x03
-#define GFX_MODE_320x256x256 0x81
-#define GFX_MODE_640x256x16 0x82
-
-/* Pixel dimensions of mode 0x81 (320×256, 256 colours). */
-#define GFX_WIDTH 320
-#define GFX_HEIGHT 256
-
-/* Pixel dimensions of mode 0x82 (640×256, 16 colours). Each byte at
- * 0xC000+x_byte holds two pixels: high nibble = LEFT (even-x), low
- * nibble = RIGHT (odd-x) — see memory/sprinter_graphics.md. */
-#define GFX_WIDTH_16 640
-#define GFX_HEIGHT_16 256
-#define GFX_COLORS_16 16
-
-/* ---- Setup / teardown -------------------------------------------- *
- *
- * Switch to `mode`, returning the previous mode for restore. `page`
- * (0 or 1) selects the initial graphics screen — both the visible and
- * the draw page are set to it, and the W3 bank is reset to 0x50 (the
- * canonical visible video page). Programs that don't double-buffer
- * just pass 0. */
-uint8_t gfx_init(uint8_t mode, uint8_t page);
-
-/* Restore a previously-saved video mode. */
-void gfx_done(uint8_t mode);
-
-/* ---- Page selection (double-buffering) and bank control ---------- *
- *
- * The Sprinter hardware holds two graphics screens. The VISIBLE page
- * is what's shown on screen; the DRAW page is where the gfx_* writes
- * land. Render the next frame into the hidden page and flip when ready.
- *
- * "Bank" is the W3 page byte (0x50..0x5F) — bits 2,3 select
- * normal/temp/transparent display modes. All gfx_* primitives map
- * THIS bank into W3 before touching 0xC000+. Default is 0x50. */
-
-void gfx_set_visible_page(uint8_t page); /* 0 or 1 */
-uint8_t gfx_get_visible_page(void);
-
-void gfx_set_draw_page(uint8_t page); /* 0 or 1 */
-uint8_t gfx_get_draw_page(void);
-
-void gfx_set_bank(uint8_t bank); /* 0x50..0x5F */
-uint8_t gfx_get_bank(void);
-
-/* Block until the next frame interrupt (50 Hz on Sprinter). Uses
- * `EI; HALT` — the Z80 sleeps until the next IM2 tick that DSS programs
- * for keyboard / cursor handling. Typical use:
- *
- * gfx_set_draw_page(hidden);
- * draw_frame(...);
- * gfx_wait_vsync(); // wait for vretrace
- * gfx_set_visible_page(hidden); // tear-free flip
- */
-void gfx_wait_vsync(void);
-
-/* ---- 320×256×256 (mode 0x81) drawing API -------------------------- *
- * Colour args are palette indices 0..255. */
-
-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);
-void gfx_rect256 (int x, int y, int w, int h, uint8_t color);
-void gfx_fill_rect256(int x, int y, int w, int h, uint8_t color);
-
-/* ---- 640×256×16 (mode 0x82) drawing API --------------------------- *
- * Colour args are palette indices 0..15. The accelerator works
- * byte-wise so vline16 falls back to per-row RMW (a byte spans two
- * horizontal pixels). */
-
-void gfx_clear16 (uint8_t color);
-void gfx_putpixel16 (int x, int y, uint8_t color);
-void gfx_hline16 (int x, int y, int len, uint8_t color);
-void gfx_vline16 (int x, int y, int len, uint8_t color);
-void gfx_line16 (int x0, int y0, int x1, int y1, uint8_t color);
-void gfx_rect16 (int x, int y, int w, int h, uint8_t color);
-void gfx_fill_rect16(int x, int y, int w, int h, uint8_t color);
-
-/* ---- Bitmap-font text -------------------------------------------- *
- * Font is 256 glyphs × 8 rows × 1 byte (ZX-Spectrum format), 2 KB.
- * On first use the default system font is fetched via BIOS WIN_GET_ZG
- * (fn 0xB8). gfx_set_font() lets you swap in a custom font (the
- * pointer is held — keep the storage alive). */
-
-void gfx_load_default_font(void);
-void gfx_set_font(const uint8_t *font);
-
-/* 320×256×256 text: one byte per pixel; advances x by 8 per char. */
-void gfx_putchar256(int x, int y, char c, uint8_t fg, uint8_t bg);
-void gfx_text256 (int x, int y, const char *s, uint8_t fg, uint8_t bg);
-
-/* 640×256×16 text: 4 bits per pixel; x must be EVEN (byte-aligned). */
-void gfx_putchar16 (int x, int y, char c, uint8_t fg, uint8_t bg);
-void gfx_text16 (int x, int y, const char *s, uint8_t fg, uint8_t bg);
-
-/* ---- Palette ----------------------------------------------------- *
- * Each graphics page has its own palette page (page 0 → palette 0,
- * page 1 → palette 1). For seamless double-buffering, load the same
- * palette into both. */
-
-/* Load a contiguous block of palette entries.
- * pal_num: 0..3 (graphics palettes)
- * start: first colour slot (0..255)
- * count: number of slots (0 → 256)
- * data: pointer to count entries, each formatted (B, G, R, 0). */
-void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count,
- const uint8_t *data);
-
-/* Convenience: set one palette entry from RGB. Internally builds the
- * BGR+pad triple and calls gfx_pal_load(pal_num, idx, 1, ...). */
-void gfx_pal_set (uint8_t pal_num, uint8_t idx,
- uint8_t r, uint8_t g, uint8_t b);
-
-/* Read a contiguous block of entries back from a graphics palette. */
-void gfx_pal_get (uint8_t pal_num, uint8_t start, uint8_t count,
- uint8_t *data);
-
-/* Read one entry into R, G, B pointers (any may be NULL). */
-void gfx_pal_get_color(uint8_t pal_num, uint8_t idx,
- uint8_t *r, uint8_t *g, uint8_t *b);
-
-/* Restore the system default graphics palette (BIOS $A6, type=1). */
-void gfx_pal_reset(void);
-
-#endif
diff --git a/tests/bgi_img/Makefile b/tests/bgi_img/Makefile
new file mode 100644
index 0000000..bc36d30
--- /dev/null
+++ b/tests/bgi_img/Makefile
@@ -0,0 +1,4 @@
+PROJ_ROOT := $(abspath $(CURDIR)/../..)
+EXAMPLE := bgi_img
+EXTRA_FLAGS := --gfx 256
+include $(PROJ_ROOT)/app.mk
diff --git a/tests/bgi_img/bgi_img.c b/tests/bgi_img/bgi_img.c
new file mode 100644
index 0000000..07ff492
--- /dev/null
+++ b/tests/bgi_img/bgi_img.c
@@ -0,0 +1,114 @@
+/*
+ * bgi_img — тест спрайтов BGI: getimage / putimage / imagesize
+ * (режим 320×256×256, --gfx 256).
+ *
+ * Что проверяем:
+ * 1. imagesize() совпадает с реальным размером буфера (self-check —
+ * при расхождении рисуется красная плашка "SIZE MISMATCH").
+ * 2. getimage() снимает прямоугольник экрана в буфер (заголовок
+ * w,h + w*h байт).
+ * 3. putimage() кладёт образ всеми пятью операциями COPY/XOR/OR/AND/
+ * NOT поверх серого фона — визуально видно разницу операций.
+ * 4. XOR дважды по одному месту восстанавливает фон (классический
+ * признак корректного спрайтового XOR).
+ *
+ * Прогон в MAME визуальный: см. что источник и его COPY-копия
+ * идентичны (в т.ч. красный маркер в левом-верхнем углу — ловит
+ * зеркалирование), а XOR-дважды не оставляет следа на фоне.
+ */
+
+#include
+#include
+
+/* Габариты спрайта-источника. Из них же считаем и рект, и буфер —
+ * так imagesize() и sizeof(buf) обязаны сойтись. */
+#define SPR_L 16
+#define SPR_T 28
+#define SPR_W 40
+#define SPR_H 32
+
+/* Буфер образа: 4 байта заголовка (w,h) + по байту на пиксель. */
+static uint8_t sprite[4 + SPR_W * SPR_H];
+
+/* Нарисовать узнаваемый ассиметричный образ в (SPR_L,SPR_T). */
+static void draw_source(void)
+{
+ int l = SPR_L, t = SPR_T;
+ int r = l + SPR_W - 1, b = t + SPR_H - 1;
+
+ setfillstyle(SOLID_FILL, LIGHTBLUE);
+ bar(l, t, r, b); /* фон образа */
+
+ setcolor(YELLOW);
+ circle(l + SPR_W / 2, t + SPR_H / 2, 10);
+
+ setcolor(WHITE);
+ line(l, t, r, b); /* диагональ */
+
+ /* Красный маркер в левом-верхнем углу — детектор ориентации. */
+ setfillstyle(SOLID_FILL, LIGHTRED);
+ bar(l, t, l + 5, t + 5);
+
+ setcolor(WHITE);
+ rectangle(l - 1, t - 1, r + 1, b + 1); /* рамка вокруг источника */
+}
+
+int main(void)
+{
+ static const int ops[5] = { COPY_PUT, XOR_PUT, OR_PUT, AND_PUT, NOT_PUT };
+ static const char *names[5] = { "COPY", "XOR", "OR", "AND", "NOT" };
+ int i, x;
+ int sl = SPR_L, st = SPR_T;
+ int sr = SPR_L + SPR_W - 1, sb = SPR_T + SPR_H - 1;
+
+ initgraph();
+ cleardevice();
+
+ setcolor(WHITE);
+ settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
+ outtextxy(80, 6, "getimage/putimage test");
+
+ /* --- источник --- */
+ outtextxy(SPR_L, 18, "src");
+ draw_source();
+
+ /* --- imagesize() self-check --- */
+ if (imagesize(sl, st, sr, sb) != (unsigned)sizeof(sprite)) {
+ setfillstyle(SOLID_FILL, LIGHTRED);
+ bar(80, 90, 240, 100);
+ setcolor(WHITE);
+ outtextxy(84, 92, "SIZE MISMATCH");
+ }
+
+ /* --- снимаем образ --- */
+ getimage(sl, st, sr, sb, sprite);
+
+ /* --- пять операций putimage поверх серого фона --- */
+ for (i = 0; i < 5; i++) {
+ x = 16 + i * 60;
+ setcolor(WHITE);
+ outtextxy(x, 108, names[i]);
+
+ setfillstyle(SOLID_FILL, LIGHTGRAY); /* общий фон под все ops */
+ bar(x, 120, x + SPR_W - 1, 120 + SPR_H - 1);
+
+ putimage(x, 120, sprite, ops[i]);
+ }
+
+ /* --- XOR дважды = восстановление фона --- */
+ setcolor(WHITE);
+ outtextxy(16, 176, "XOR x2 -> restores bg (patch stays clean):");
+
+ setfillstyle(SOLID_FILL, GREEN);
+ bar(16, 190, 16 + SPR_W - 1, 190 + SPR_H - 1);
+ putimage(16, 190, sprite, XOR_PUT); /* наложили */
+ putimage(16, 190, sprite, XOR_PUT); /* сняли */
+
+ /* Рядом — тот же зелёный фон нетронутым, для сравнения. */
+ setfillstyle(SOLID_FILL, GREEN);
+ bar(80, 190, 80 + SPR_W - 1, 190 + SPR_H - 1);
+ setcolor(WHITE);
+ outtextxy(130, 202, "<- these two must match ->");
+
+ for (;;) { }
+}
diff --git a/tests/gfx_dbuf/Makefile b/tests/gfx_dbuf/Makefile
index c6c92f4..3702dd4 100644
--- a/tests/gfx_dbuf/Makefile
+++ b/tests/gfx_dbuf/Makefile
@@ -1,3 +1,4 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
-EXAMPLE := gfx_dbuf
+EXAMPLE := gfx_dbuf
+EXTRA_FLAGS := --gfx 256
include $(PROJ_ROOT)/app.mk
diff --git a/tests/gfx_dbuf/gfx_dbuf.c b/tests/gfx_dbuf/gfx_dbuf.c
index 0a092ff..80341e6 100644
--- a/tests/gfx_dbuf/gfx_dbuf.c
+++ b/tests/gfx_dbuf/gfx_dbuf.c
@@ -1,29 +1,26 @@
/*
- * gfx_dbuf — double-buffering demo.
+ * gfx_dbuf — double-buffering demo (BGI, bgi256.lib).
*
- * Renders a moving rectangle by alternating between page 0 and page 1:
- * - Each frame: draw to the HIDDEN page, then flip visible to it.
- * - The page currently being displayed is never written to, so the
- * user only sees fully-rendered frames (no half-drawn artefacts,
- * no flicker from the per-frame clear).
+ * Рендерит движущийся прямоугольник, чередуя страницу 0 и 1:
+ * - Каждый кадр: рисуем на СКРЫТОЙ странице, затем делаем её видимой.
+ * - Видимая страница никогда не пишется → пользователь видит только
+ * целые кадры (без артефактов, без мерцания от per-frame clear).
*
- * Indicators help verify the swap is actually happening:
- * - A small colour swatch in the top-right alternates each frame:
- * one shade when page 0 is shown, another when page 1. If the
- * box motion looks smooth and the swatch flickers between the two
- * shades at the animation rate, the swap is working.
+ * Переключение страниц и 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.
*
- * NOTE: each graphics screen has its OWN palette page (screen 0 →
- * palette 0, screen 1 → palette 1). We load the same palette into
- * both so the colours look identical regardless of which page is
- * currently visible. See memory/sprinter_graphics.md.
- *
- * Press any key to exit.
+ * Индикатор страницы (маленький swatch сверху-справа) меняет оттенок
+ * каждый кадр — если бокс движется плавно, а swatch мигает между двумя
+ * оттенками, своп работает. Press any key to exit.
*/
#include
#include
-#include
+#include
+#include /* double-buffering + vsync (mode-agnostic) */
#include
static uint8_t palette[256 * 4];
@@ -48,42 +45,44 @@ static void make_palette(void)
static void draw_frame(int box_x, int box_y, uint8_t page_indicator)
{
- gfx_clear256(COL_BG);
+ setbkcolor(COL_BG); cleardevice();
/* Static decoration — identical on both pages so the swap doesn't
* flicker the chrome. */
- gfx_fill_rect256(0, 0, GFX_WIDTH, 8, COL_STRIPE);
- gfx_fill_rect256(0, GFX_HEIGHT - 8, GFX_WIDTH, 8, COL_STRIPE);
+ setfillstyle(SOLID_FILL, COL_STRIPE);
+ bar(0, 0, GFX_WIDTH - 1, 7);
+ bar(0, GFX_HEIGHT - 8, GFX_WIDTH - 1, GFX_HEIGHT - 1);
- gfx_text256(8, 16, "double-buffering demo", COL_TEXT, COL_BG);
- gfx_text256(8, GFX_HEIGHT - 24,
- "press a key to exit", COL_TEXT, COL_BG);
+ setcolor(COL_TEXT);
+ outtextxy(8, 16, "double-buffering demo");
+ outtextxy(8, GFX_HEIGHT - 24, "press a key to exit");
- /* Page indicator — different shade for each page so a flickering
- * box here proves the swap is happening. */
- gfx_fill_rect256(GFX_WIDTH - 24, 16, 12, 12,
- page_indicator ? COL_PAGE1 : COL_PAGE0);
+ /* 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. */
- gfx_fill_rect256(box_x, box_y, 40, 30, COL_BOX);
- gfx_rect256 (box_x, box_y, 40, 30, COL_BLACK);
+ 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();
- uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
+ initgraph();
- /* Each graphics screen has its own palette page (0→pal 0, 1→pal 1).
- * Load the same data into both so the visual swap is seamless. */
+ /* Каждая графическая страница имеет свою палитру (0→pal 0, 1→pal 1).
+ * Грузим одну и ту же в обе — визуальный своп бесшовный. */
gfx_pal_load(0, 0, 0, palette);
gfx_pal_load(1, 0, 0, palette);
- /* Clear both pages so the very first flip doesn't reveal garbage. */
- gfx_set_draw_page(0);
- gfx_clear256(COL_BG);
- gfx_set_draw_page(1);
- gfx_clear256(COL_BG);
+ /* Очистить обе страницы, чтобы первый флип не вскрыл мусор. */
+ setbkcolor(COL_BG);
+ gfx_set_draw_page(0); cleardevice();
+ gfx_set_draw_page(1); cleardevice();
/* Bouncing rect state. */
int box_x = 10;
@@ -98,9 +97,8 @@ int main(void)
draw_frame(box_x, box_y, hidden);
- /* Wait for the next frame interrupt before flipping, so the
- * page swap lands during vertical retrace and the user never
- * sees a half-drawn frame. */
+ /* Ждать следующий кадр перед флипом — своп падает в vblank,
+ * пользователь не видит полунарисованный кадр. */
gfx_wait_vsync();
gfx_set_visible_page(hidden);
@@ -114,7 +112,7 @@ int main(void)
}
(void)getch();
- gfx_done(prev);
+ closegraph();
puts("done");
return 0;
}
diff --git a/tests/gfx_demo/Makefile b/tests/gfx_demo/Makefile
index 7324b8d..3352578 100644
--- a/tests/gfx_demo/Makefile
+++ b/tests/gfx_demo/Makefile
@@ -1,3 +1,4 @@
PROJ_ROOT := $(abspath $(CURDIR)/../..)
-EXAMPLE := gfx_demo
+EXAMPLE := gfx_demo
+EXTRA_FLAGS := --gfx 256
include $(PROJ_ROOT)/app.mk
diff --git a/tests/gfx_demo/gfx_demo.c b/tests/gfx_demo/gfx_demo.c
index 0a88638..aa1945d 100644
--- a/tests/gfx_demo/gfx_demo.c
+++ b/tests/gfx_demo/gfx_demo.c
@@ -1,15 +1,23 @@
/*
- * gfx_demo — exercises the libc/gfx primitives. Shows:
- * 1. accelerator-backed gfx_clear256 / gfx_hline256 / gfx_vline256 / gfx_fill_rect256
- * 2. gfx_rect256 outline, gfx_line256 diagonals (Bresenham via putpixel)
- * 3. a grey-ramp palette
+ * gfx_demo — exercises the BGI primitives (bgi256.lib). Shows:
+ * 1. cleardevice / line (orthogonal frame via horizontal/vertical lines)
+ * 2. rectangle outlines, line diagonals (Bresenham)
+ * 3. bar filled-rect colour bars (accelerator-backed)
+ * 4. a grey-ramp palette
+ *
+ * Migrated с низкоуровневого gfx.h drawing-API на BGI (graphics.h).
+ * Режим 0x81 (320×256×256) выбирается линковкой: EXTRA_FLAGS=--gfx 256
+ * (см. Makefile). Палитура грузится через gfx_pal_load (mode-agnostic,
+ * остался в gfx.h) — BGI initgraph уже загрузил EGA-палитру, мы её
+ * подменяем серым клином.
*
* Press a key to advance through each stage.
*/
#include
#include
-#include
+#include
+#include /* GFX_WIDTH/HEIGHT, gfx_pal_load (mode-agnostic) */
#include
static uint8_t palette_data[256 * 4];
@@ -32,69 +40,74 @@ int main(void)
palette_data[i * 4 + 3] = 0;
}
- uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
+ initgraph();
gfx_pal_load(0, 0, 0, palette_data);
- /* --- Stage 1: orthogonal frame via hline / vline ----------------- */
- gfx_clear256(0x40);
- gfx_hline256(1, 1, GFX_WIDTH - 2, 0xFF);
- gfx_hline256(1, GFX_HEIGHT - 2, GFX_WIDTH - 2, 0xFF);
- gfx_vline256(1, 2, GFX_HEIGHT - 4, 0xFF);
- gfx_vline256(GFX_WIDTH - 2, 2, GFX_HEIGHT - 4, 0xFF);
+ /* --- Stage 1: orthogonal frame via horizontal/vertical lines ------ */
+ setbkcolor(0x40); cleardevice();
+ setcolor(0xFF);
+ line(1, 1, GFX_WIDTH - 2, 1); /* top */
+ line(1, GFX_HEIGHT - 2, GFX_WIDTH - 2, GFX_HEIGHT - 2); /* bottom */
+ line(1, 2, 1, GFX_HEIGHT - 4); /* left */
+ line(GFX_WIDTH - 2, 2, GFX_WIDTH - 2, GFX_HEIGHT - 4); /* right */
wait_key();
- /* --- Stage 2: nested rectangles -------------------------------- */
- gfx_clear256(0x20);
- for (int i = 0; i < 16; i++)
- gfx_rect256(i * 10, i * 8,
- GFX_WIDTH - i * 20,
- GFX_HEIGHT - i * 16,
- (uint8_t)(0x40 + i * 8));
- wait_key();
-
- /* --- Stage 3: filled-rect colour bars --------------------------- */
- gfx_clear256(0);
- /* Tall-narrow rects (w=20, h=128) — heuristic picks vertical orient. */
+ /* --- Stage 2: nested rectangles --------------------------------- */
+ setbkcolor(0x20); cleardevice();
for (int i = 0; i < 16; i++) {
- gfx_fill_rect256(i * 20, 0, 20, 128, (uint8_t)(i * 16));
- gfx_fill_rect256(i * 20 + 0, 128, 20, 128, (uint8_t)(255 - i * 16));
+ setcolor((uint8_t)(0x40 + i * 8));
+ rectangle(i * 10, i * 8,
+ GFX_WIDTH - i * 20,
+ GFX_HEIGHT - i * 16);
}
wait_key();
- /* --- Stage 3b: wide-short rects + a grid of small squares -------- */
- gfx_clear256(0x08);
- /* Wide-short stripes (w=320, h=16) — heuristic picks horizontal. */
- for (int i = 0; i < 8; i++)
- gfx_fill_rect256(0, i * 32, GFX_WIDTH, 16, (uint8_t)(0x40 + i * 24));
- /* 8×8 small squares grid (w=h, heuristic picks either — same cost). */
- for (int row = 0; row < 4; row++)
- for (int col = 0; col < 16; col++)
- gfx_fill_rect256(col * 20 + 4, 256 - 80 + row * 20, 12, 12,
- (uint8_t)((row * 16 + col) * 4));
+ /* --- Stage 3: filled-rect colour bars (bar = залитый прямоугольник) */
+ setbkcolor(0); cleardevice();
+ for (int i = 0; i < 16; i++) {
+ setfillstyle(SOLID_FILL, (uint8_t)(i * 16));
+ bar(i * 20, 0, i * 20 + 19, 127);
+ setfillstyle(SOLID_FILL, (uint8_t)(255 - i * 16));
+ bar(i * 20, 128, i * 20 + 19, 255);
+ }
wait_key();
- /* --- Stage 4: diagonal lines via Bresenham ---------------------- */
- gfx_clear256(0x18);
- /* "Star" of lines from centre to a circle of endpoints. */
+ /* --- Stage 3b: wide-short stripes + a grid of small squares ------ */
+ setbkcolor(0x08); cleardevice();
+ for (int i = 0; i < 8; i++) {
+ setfillstyle(SOLID_FILL, (uint8_t)(0x40 + i * 24));
+ bar(0, i * 32, GFX_WIDTH - 1, i * 32 + 15);
+ }
+ for (int row = 0; row < 4; row++)
+ for (int col = 0; col < 16; col++) {
+ setfillstyle(SOLID_FILL, (uint8_t)((row * 16 + col) * 4));
+ bar(col * 20 + 4, 256 - 80 + row * 20,
+ col * 20 + 4 + 11, 256 - 80 + row * 20 + 11);
+ }
+ wait_key();
+
+ /* --- Stage 4: diagonal lines via Bresenham ----------------------- */
+ setbkcolor(0x18); cleardevice();
int cx = GFX_WIDTH / 2, cy = GFX_HEIGHT / 2;
for (int i = 0; i < 16; i++) {
int ex = i * (GFX_WIDTH - 1) / 15;
- gfx_line256(cx, cy, ex, 0, 0xFF);
- gfx_line256(cx, cy, ex, GFX_HEIGHT - 1, 0xC0);
+ setcolor(0xFF); line(cx, cy, ex, 0);
+ setcolor(0xC0); line(cx, cy, ex, GFX_HEIGHT - 1);
}
for (int i = 0; i < 16; i++) {
int ey = i * (GFX_HEIGHT - 1) / 15;
- gfx_line256(cx, cy, 0, ey, 0x80);
- gfx_line256(cx, cy, GFX_WIDTH - 1, ey, 0x40);
+ setcolor(0x80); line(cx, cy, 0, ey);
+ setcolor(0x40); line(cx, cy, GFX_WIDTH - 1, ey);
}
- /* Box outline using gfx_line256. */
- gfx_line256(0, 0, GFX_WIDTH - 1, 0, 0xFF);
- gfx_line256(0, GFX_HEIGHT - 1, GFX_WIDTH - 1, GFX_HEIGHT - 1, 0xFF);
- gfx_line256(0, 0, 0, GFX_HEIGHT - 1, 0xFF);
- gfx_line256(GFX_WIDTH - 1, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1, 0xFF);
+ /* Box outline. */
+ setcolor(0xFF);
+ line(0, 0, GFX_WIDTH - 1, 0);
+ line(0, GFX_HEIGHT - 1, GFX_WIDTH - 1, GFX_HEIGHT - 1);
+ line(0, 0, 0, GFX_HEIGHT - 1);
+ line(GFX_WIDTH - 1, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1);
wait_key();
- gfx_done(prev);
+ closegraph();
puts("done");
return 0;
}