5f0c46f0ea
При узкой стороне <= 8 линий chunked-rectfill проигрывает циклу _bgi_hspan_raw/_bgi_vspan_raw (подготовка ~340Т впустую, break-even n~9): либо fast-path в диспетчере, либо рецепт для пользователя — решать по профилю. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
222 lines
14 KiB
Markdown
222 lines
14 KiB
Markdown
# TODO / Roadmap
|
||
|
||
Открытые задачи в порядке убывания приоритета; закрытые этапы — в
|
||
«Истории» внизу. Текущий срез libc-работ: docs/libc-roadmap.md.
|
||
|
||
## Ближайшее
|
||
|
||
- [ ] **П6/железо**: MAME-смоук всех тестов после libc-сплита (conio,
|
||
ptime, stattest, mouse, gfx_demo/gfx_d16/gfx_text/gfx_mous —
|
||
трогался asm акселератора); затем прогон на реальном Sprinter
|
||
(mdview2 + FILE* v2 + fdmax — подтвердить лимит 8 манипуляторов
|
||
и зависание DSS на 9-м OPEN)
|
||
- [ ] Мигрировать оставшиеся examples на sprinter-cc вместо ручных
|
||
Makefile (косметика)
|
||
- [ ] check_banks.py: разбивка size = code + const + bss per bank
|
||
|
||
## Auto-banking (memory/banking_roadmap.md)
|
||
|
||
Phase 1 — file-level bin-packing (`toolchain/auto_bank.py`) — когда
|
||
проект перерастёт ~30 KB кода: парсинг размеров из .rel/.map,
|
||
first-fit-decreasing, уважение `#pragma codeseg BANKn`, перелинковка,
|
||
печать плана. Phase 2-5 (rebalance, banks.toml, function-level) —
|
||
по потребности.
|
||
|
||
## ОБЯЗАТЕЛЬНОЕ ДЛЯ V2
|
||
|
||
### Turbo-C-style graphics API (BGI-like) — Фаза 1 ГОТОВА (256, 2026-07-08)
|
||
|
||
Архитектура: `graphics.h` — mode-agnostic слой (libc/bgi/*.c в
|
||
sprinter.lib), режим задаёт driver-архив; выбор линковкой через
|
||
`sprinter-cc --gfx 256` (16 — позже, тем же leaf-split'ом; см.
|
||
memory/bgi_two_lib_design).
|
||
|
||
**Фаза 1 (256, реализовано и проверено в MAME — tests/bgitest):**
|
||
initgraph/closegraph/graphresult/cleardevice, setcolor/getcolor/
|
||
setbkcolor/getbkcolor, getmaxx/getmaxy/getmaxcolor, putpixel/getpixel,
|
||
moveto/moverel/getx/gety, line/lineto/linerel, rectangle, bar, circle,
|
||
outtext/outtextxy. initgraph грузит EGA-палитру 0..15. Пакетные
|
||
примитивы (circle) — одна W3-скобка на весь примитив (raw-плот), иначе
|
||
на порядок медленнее.
|
||
|
||
**Фаза 2a/2b/2c ГОТОВЫ (2026-07-08, проверено в MAME tests/bgitest):**
|
||
- 2a: arc, ellipse, drawpoly (Q7-тригонометрия, БЕЗ 32-бит).
|
||
- 2b: setfillstyle/getfillsettings + 10 паттернов Borland, bar (с
|
||
паттерном), bar3d, fillpoly (scanline min/max), fillellipse (isqrt).
|
||
- 2c: floodfill (scanline span; медленный — self-bracket чтение, но
|
||
корректный), pieslice, sector.
|
||
|
||
**Фаза 2d-1/2/3 ГОТОВЫ (2026-07-08, MAME tests/bgitest):**
|
||
- 2d-1: getimage/putimage/imagesize (COPY/XOR/OR/AND/NOT_PUT), raw-блит
|
||
в одной W3-скобке (_gfx_getpixel256_raw).
|
||
- 2d-2: setlinestyle/getlinesettings (SOLID/DOTTED/CENTER/DASHED/USERBIT
|
||
+ NORM/THICK) — line/lineto/linerel/rectangle/drawpoly.
|
||
- 2d-3: settextstyle/gettextsettings/textwidth/textheight — масштаб
|
||
1..10, HORIZ/VERT, прозрачный фон (свой scaled-рендер поверх 8×8).
|
||
|
||
**Фаза 2d (осталось):** setviewport/clearviewport + клиппинг (инвазивно —
|
||
трогает все примитивы), settextjustify, setaspectratio (пиксели 320×256
|
||
неквадратные — круги визуально эллиптичны), setfillpattern (USER_FILL),
|
||
setactivepage/setvisualpage (2 страницы в gfx уже есть). Оптимизации:
|
||
floodfill на raw-чтении; ellipse/arc в одной W3-сессии. Потом drv16 +
|
||
sprinter_gfx16.lib (--gfx 16).
|
||
Acceptance: типичная BGI-программа переносится без существенных
|
||
правок. Референс: Turbo C 2.x BGIDEMO.
|
||
|
||
### IM2 Interrupt Handlers — Phase 1 ГОТОВ (2026-07-06, libc/irq, tests/irqtest; Phase 2: CBL/ISA/цепочки)
|
||
|
||
User-ISR через IM 2 — timer ticks, музыка (AY/COVOX), real-time
|
||
игры, async input. Phase 1 реализован БЕЗ отдельного memory mode:
|
||
libc/irq (<irq.h>: irq_install/irq_remove), таблица в BSS с runtime-
|
||
выравниванием, jp-заглушка внутри таблицы, чейн к DSS всегда;
|
||
работает в tiny/big, в small/huge — EINVAL. Детали и отличия от
|
||
исходного плана: docs/im2_isr_design.md.
|
||
|
||
### Прочее v2
|
||
|
||
- [ ] **Audio API** — AY-3-8910 + COVOX (требует IM2)
|
||
- [ ] **ISA-8 slot support** — ZX-Bus карты (требует IM2)
|
||
|
||
## GFX: расширения по accelerator_doc.txt
|
||
|
||
Quick wins:
|
||
- [ ] block-size через `LD A,(nn)` вместо SMC (док разрешает LD A,(HL/BC/DE))
|
||
- [ ] кэширование block-size между burst'ами (accel помнит размер)
|
||
|
||
Новые возможности:
|
||
- [ ] **пакетное чтение/запись массива байт через акселератор** —
|
||
отдельные ф-ии, которые в ОДНОМ вызове читают/пишут строку или
|
||
столбец пикселей (гориз./верт.), а не по пикселю через
|
||
_bgi_read_raw/_bgi_plot_raw. Аналогично тому, как сейчас рисуются
|
||
линии (_bgi_hspan_raw/_bgi_vspan_raw задают Port_Y и адрес один раз,
|
||
далее burst). Цель — ускорить блиттинг: getimage/putimage сейчас
|
||
зовут _bgi_read_raw/_gfx_getpixel256_raw по-пиксельно, из-за чего на
|
||
каждый пиксель повторяются out Port_Y + ld bc,(base) + bounds-check
|
||
(см. разбор _bgi_read_raw). Дать `_bgi_hread_raw`/`_bgi_hwrite_raw`
|
||
(+ vertical) с ABI как у fill-сегментов (HL=addr, B=len, E=y, буфер
|
||
в DE) и перевести getimage/putimage на них.
|
||
- [ ] `gfx_blit` / `gfx_blit_transparent` — block copy (LD L,L / LD A,A),
|
||
прозрачность через bank 0x58 («FF is transparent»)
|
||
- [ ] `gfx_xor_rect` / `gfx_or_rect` / `gfx_and_rect` / `gfx_invert_rect`
|
||
- [ ] шрифты ≠ 8×8: gfx_set_font_data(ptr,w,h,advance), proportional,
|
||
8×16/16×16, отдельный font_id API; font-quad для 640×256
|
||
(per-cell палитра через дескрипторы 0x0300..0x039F)
|
||
|
||
Оптимизации (не сейчас):
|
||
- [ ] gfx_line через accel для пологих диагоналей (runs ≥ 4-5 px)
|
||
- [ ] композитные примитивы с одним W3-swap на операцию
|
||
- [ ] **span-примитивы для узких прямоугольников**: при узкой стороне
|
||
≤ 8 линий chunked-rectfill проигрывает простому циклу
|
||
_bgi_hspan_raw/_bgi_vspan_raw (подготовка+precompute ~340Т уходят
|
||
впустую; break-even n≈9 — docs/accel-fill-budget.md). Варианты:
|
||
fast-path в диспетчере _gfx_rectfill256 («узкая сторона ≤ 8 →
|
||
цикл span'ов») или просто задокументировать рецепт для
|
||
пользователя. Делать по результатам профиля — если узкие
|
||
прямоугольники реально встречаются в горячем коде.
|
||
|
||
## Прочий backlog
|
||
|
||
- [ ] factoring parse_argv из crt0/crt0_banked в общий argv.s
|
||
- [ ] `restore SP on EXIT` (паттерн z88dk +pps) — проверить нужность
|
||
- [x] ~~CI: MAME с -aviwrite для screenshot-сравнения без человека~~ —
|
||
`toolchain/mame_interactive.py`: авто-запуск .exe вводом с
|
||
эмуляцией клавиатуры + Lua-таймер для скриншотов/выхода; сравнение
|
||
визуальное (Claude читает скриншот), не автоматический diff.
|
||
Полный справочник: docs/mame-autotest.md.
|
||
- [ ] linker duplicate-symbol warnings: сейчас фильтруются в
|
||
sprinter-cc (наши overrides _puts/___sdcc_heap/_asctime/…);
|
||
радикально — --nostdlib с ручным списком модулей z80.lib
|
||
- [ ] ZX Spectrum-совместимый target; ZX-Bus драйверы; PGO-tools
|
||
|
||
## Проверить на реальном железе
|
||
|
||
- [ ] **Port_Y banking trick** (адреса 0xC000+0x400*N → строки
|
||
Y..Y+15): в MAME 0.283 НЕ работает (2026-06-01). На железе:
|
||
dual-write тест → если работает, кэшировать Port_Y в putpixel
|
||
(~8× меньше OUT для Брезенхэма); если нет — вычистить из доков.
|
||
- [ ] fdmax: лимит манипуляторов и зависание 9-го OPEN — MAME vs железо.
|
||
- [ ] CBL: щелчок перед первым проигрыванием звука за сессию (tests/
|
||
cbltest, tests/cblwav) — воспроизводится ТОЛЬКО на первом запуске
|
||
программы за сессию MAME, не зависит от содержимого потока
|
||
(тон/тишина/речь одинаково). Похоже на разовый прогрев звуковой
|
||
подсистемы MAME при первой активации канала — на реальном железе
|
||
скорее всего отсутствует. Проверить и закрыть либо описать как
|
||
реальный аппаратный эффект.
|
||
- [ ] **CBL: помехи в звуке при движении мыши** (tests/cblstream,
|
||
2026-07-07) — при потоковом воспроизведении движение мыши даёт
|
||
слышимые артефакты. Гипотеза (НЕ подтверждена): мышь может
|
||
делить SIO-канал/детект-бит с клавиатурой (порт 0x19 бит 0,
|
||
см. _irq_tramp.c), и трамплин классифицирует байты мыши как
|
||
«клавиатура» → сразу chain на DSS (0x0038), пропуская проверку
|
||
CBL-хука для ЭТОГО прерывания — при движении мыши часть тиков,
|
||
которые должны были обслужить CBL-насос, уходят мимо, кольцо
|
||
недоливается. Нужно исследование (MAME-дамп/лог трамплина).
|
||
|
||
## Known quirks (зафиксированы, обходы в libc)
|
||
|
||
- ESTEX $46 ENV: A=0 это NOT FOUND (док врёт) — memory/sprinter_platform
|
||
- ESTEX WRITE $14: на успехе DE=0, не счётчик; успех = CF=0 & A=0 —
|
||
memory/estex_write_de_quirk
|
||
- DSS: 8 манипуляторов, 9-й OPEN вешает систему; _fd_guard в libc —
|
||
memory/dss_fd_limit
|
||
- SDCC z80 `if(n!=g)g=n;` пишет (n-g) — memory/sdcc_z80_cmp_store_a_bug
|
||
|
||
---
|
||
|
||
# История — закрытые этапы
|
||
|
||
## Этап 10 — libc: сплит + FILE v2 + Solid-C (2026-07-05/06) ✅
|
||
|
||
Полный план/итоги: docs/libc-roadmap.md. Кратко:
|
||
- вся libc разложена «1 функция = 1 модуль» (~250 модулей, wildcard-
|
||
сборка, DCE на уровне файлов): gfx_text −4.4 КБ, timedir/ls/stattest
|
||
−3 КБ и т.д.; правила asm-связок: docs/libc-split-asm-cases.md
|
||
- **FILE* v2 (B+)**: ленивый буфер 512 на чтение/запись с
|
||
автопереключением, таблица OPEN_MAX=8, flush-on-exit, ungetc,
|
||
fprintf/vfprintf, fdopen/freopen/fclosall/fgetpos/fsetpos; горячие
|
||
пути fgetc/fputc/fgets на asm (fgets 100 КБ: 144с unbuffered-оценка
|
||
→ ~1 с). Дизайн: docs/file-buffering-design.md
|
||
- **scanf/fscanf/sscanf** — своё C-ядро (в SDCC z80 нет)
|
||
- **Solid-C совместимость закрыта**: <dos.h> (даты/диски/absread),
|
||
errno-алиасы, <sprinter_solid.h> — docs/solid_c_compatibility.md
|
||
- гигиена: stale .rel чистка, все 43 теста в make all, размерный
|
||
регресс (make size-check), контракт заголовков docs/libc-headers.md
|
||
- справочник API: docs/libc-reference.md
|
||
|
||
## Этап 9 — memory modes (tiny/small/big/huge/manual) ✅ 2026-05-30
|
||
|
||
`--memory MODE` в sprinter-cc; crt0-семейство (crt0/minimal/small/
|
||
banked); small: ESTEX GETMEM+SETWIN2 до gsinit, auto-detect W2 по
|
||
порту 0xC2; big/huge: параметризация crt0_banked/bank.s через
|
||
BANK_W1; --debug, --stack-size. Детали: memory/memory_modes_
|
||
implemented, memory/sprinter_memory_modes.
|
||
|
||
Дизайн-решения: одна sprinter.lib на все режимы (DCE per-member);
|
||
gfx.lib отдельно не нужен; libc_banked + sprinter_home.lib — идея
|
||
на потом (триггер: HOME забит user-кодом).
|
||
|
||
## Этап 8 — графика ✅
|
||
|
||
320×256×256 + 640×256×16, акселератор (Fill h/v, SMC block-size),
|
||
Брезенхэм, bitmap font (WIN_GET_ZG, interleaved), gfx_text.
|
||
memory/sprinter_graphics*, sprinter_accelerator, sprinter_font_format.
|
||
|
||
## Bank-local data ✅
|
||
|
||
--codeseg/--constseg/--dataseg BANKn + mkexe -p 0; фикс трамплина
|
||
(pop bc/out (c),b — сохраняет A); malloc из банка прозрачен (heap в
|
||
W2). memory/bank_local_data_pattern.
|
||
|
||
## Этапы 5-7 и ранняя libc ✅
|
||
|
||
- malloc/free (SDCC + runtime/heap.s в W2), page allocator
|
||
(mem_alloc_pages, ESTEX $3C-$3E + BIOS $C4), bank_read/bank_write
|
||
- crt0 argv-парсинг (IX-prefix, CP/M-space quirk, APPINFO basename),
|
||
sprinter-cc wrapper со всеми опциями
|
||
- errno+strerror/perror, open state-machine, atexit, setjmp/longjmp,
|
||
sleep, ENV API ($46), ffirst/fnext, getdatetime/setdatetime,
|
||
chdir/getcwd/mkdir/rmdir, conio (полный), mouse (RST 30h, 14 ф-й),
|
||
POSIX time API, sys/stat, assert
|
||
- text I/O split (stdio fast / conio attr) — memory/text_output_api_split
|
||
- SDCC stdlib НЕ переписываем — memory/sdcc_stdlib_works
|