setcolor/getcolor/setbkcolor/getbkcolor/getmaxx/getmaxy/getmaxcolor/
getx/gety/moveto/moverel/setfillstyle/graphresult (graphics.h) и
gfx_get_bank/gfx_set_bank/gfx_get_draw_page/gfx_get_visible_page
(gfx.h) определены inline в публичных заголовках; state-переменные
объявлены там же (хранилище прежнее — _bgi_state.c/_gfx_state.c).
Именно `inline` БЕЗ static: проверено артефактами (.asm) — SDCC 4.5
инлайнит вызов при всех наших флагах (--opt-code-size/--opt-code-speed/
--max-allocs) и не эмитит standalone-тело; `static inline` эмитил бы
мёртвую копию каждого аксессора в КАЖДЫЙ включивший модуль. Отказ
инлайнить = громкая ошибка линковки (все 47 программ слинковались).
Экономия ~30-40Т на вызов, минус 17 .rel; по _CODE размер-нейтрально
(сайт вызова ≈ телу). size_baseline: bgitest +267/accfill +528 — это
НЕ inline, а run-рендер текста из ba09c0b (draw_scaled потянул
vspan_raw+vfill256 и сам вырос) — цена за ~2-6× скорость текста.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Строка глифа сканируется на прогоны единичных битов; прогон n битов =
прямоугольник n*size×size → hspan/vspan-примитивы (одиночный пиксель —
plot_raw). Координаты инкрементальные (+= size за бит) — умножений на
пиксель нет. Прогон клипится до span'а — клип теперь работает и в
fast-сборке (span-raw диапазон не клипят). ~2× на size=1, ~6× на
size=4. Проверено в MAME (bgitest: масштабы 1..4 + VERT — пиксель в
пиксель).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
plot/read/hspan/vspan_raw читают D/E (y в DE), но не пишут — аннотация
задокументирована в _bgi.h. Честное измерение (полная пересборка с/без,
diff всех .asm в common/ и bgi256/): кодогенерация SDCC 4.5 НЕ меняется —
вызывающие держат локали в IX-фрейме и перезагружают DE перед каждым
вызовом, спасений DE вокруг вызовов не было. Оставлено как контракт на
будущее (изменение вызывающих/компилятора); при правке asm сверять
клоббер-лист.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bar(): rectfill-ветки выходили ранним return без _bgi_end() — W3
оставался замаплен на видеобанк после каждого bar() со сплошной
заливкой.
_bgi_read дублировал getpixel (та же композиция begin+read_raw+end);
единственный потребитель floodfill переведён на getpixel, модуль
удалён. getpixel.c: убраны мёртвые статики _gp_* (остались от
до-register версии).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs/accel-fill-budget.md: полный разбор v3 (подготовка ~340Т на
прямоугольник, 46Т на чанк 16 линий, 53Т/51Т на линию, ~107 байт/leaf)
против per-line di/ei вариантов (djnz 72Т/линию ~63 байта; 16-бит IX
206Т/линию); break-even n≈9 линий, тотализатор, решение остаться на v3.
Краткие выжимки — в шапки _gfx_rect*fill256.
Идеи на будущее (там же): ограничить контракт стороной <=256 (широкие
прямоугольники пользователь выводит в два приёма); реализовать оба
варианта (поблочный/построчный) с переключением опцией сборки в духе
GFX_NOCHECK.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Семантика FSM акселератора вскрыта по драйверу MAME (sprinter.cpp) и
подтверждена экспериментами в MAME (tests/accfill): армирование живёт до
следующего accel-опкода (мульти-триггер работает); под армированием
триггерит ЛЮБОЙ non-M1 доступ к памяти (fetch операнда djnz/out!);
вертикальный Fill двигает Port_Y и не возвращает; размер блока переживает
LD B,B. Детали: memory/accel_multitrigger_fill.
- _bgi_clear_raw: 20 DI-скобок по 16 колонок вместо полного брекета на
каждую из 320 колонок; армирование размера один раз на скобку.
- _gfx_rectfill256 разделён: диспетчер (проверка ориентации ~160-245Т,
break-even |w-h| >= ~4) + leaf'ы _gfx_recthfill256/_gfx_rectvfill256
для прямого вызова, когда форма известна заранее.
- Leaf'ы: чанки <=16 линий одной скобкой (~54-56Т/линию против ~250Т у
per-line варианта); счётчик чанков precompute'ится в байт-регистр
(dec e/jr nz ~46Т/чанк вместо 16-бит арифметики в IX-слотах
~173Т/чанк); хвост — отдельная скобка со своим армированием (CBL-ISR
в окне EI армирует акселератор своим размером — не выносить).
- getpixel/putpixel/_bgi_read: уборка мёртвого закомментированного кода.
- tests/accfill: регресс chunked-заливок (B0 clear, B1 vert 1+3 чанка,
B2 horz чанк+хвост, полноширинный bar 320x8 — путь w>=256).
Прежние реализации сохранены под #if 0 для отката/сравнения.
Проверено в MAME (все PASS); семантика эмуляции — перепроверить на
реальном Sprinter. size-baseline: accfill добавлен, gfx_demo +54 Б
(обвязка диспетчера), остальные без роста.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_bgi_vspan_raw: safe-версия (без GFX_NOCHECK) больше НЕ клиппит диапазон
y+len и не обрабатывает y<0 — проверяется только валидность x/y (как в
_bgi_hspan_raw). Сознательный компромисс: safe ловит грубый выход за
экран по координате, но не частичный отрезок; y+len<=256 — обязанность
вызывающего.
Оба span'а: в safe добавлена проверка len==0 → return (иначе B=0 по
конвенции акселератора рисует «256»). В fast (GFX_NOCHECK) проверка
вырезается — поведение прежнее (256 точек), задокументировано в шапках.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- удалён глобальный скретч акселератора (_gfx_acc256.c); fill-сегменты
(_gfx_hfill256/_gfx_vfill256) принимают аргументы в регистрах HL/C/B/E,
вызываются только из asm raw-примитивов
- новый _gfx_rectfill256: заливка прямоугольника через Horizontal_Size
- raw-примитивы (plot/read/hspan/vspan/clear) переписаны под новый ABI
- graphics.h: typedef color_t (uint8_t) для всех public color-функций
- sprinter-cc: флаг --safe (линковка *_safe.lib при наличии)
- CLAUDE.md/mame_interactive: авто-прогон тестов в MAME
- gfx_demo: демонстрация rectfill
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Графика вынесена из libc/ в новую библиотеку libbgi/:
- common/ — mode-agnostic математика и состояние (один исходник,
.rel попадает в оба driver-архива);
- bgi256/ + bgi16/ — mode-specific leaf'ы (raw-плот/чтение/спаны);
- include/ — graphics.h + gfx.h; _bgi.h — внутренний заголовок.
Собираются lib/bgi256.lib (и bgi16.lib в Фазе 2); выбор режима
линковкой через sprinter-cc --gfx 256|16. libc/ теперь без графики.
tests/bgi_img — тест спрайтов getimage/putimage/imagesize (5 операций
COPY/XOR/OR/AND/NOT + XOR-round-trip + self-check imagesize).
Проверен автотестом в MAME.
Примечание: make size-check пока красный (gfx_dbuf/gfx_demo выросли
после реорга) — закрыть по завершении миграции libbgi.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>