Files
Sprinter-SDCC/docs/TODO.md
T
snark13 e761d21505 libc: graphics.h — Turbo-C BGI-слой, Фаза 1 (режим 256)
Функционально-совместимый с Turbo-C <graphics.h> поверх gfx.h.
Архитектура: mode-agnostic математика (libc/bgi/*.c → sprinter.lib) +
driver-leaf'ы per-режим (libc/bgi/drv256/*.c → sprinter_gfx256.lib).
Режим выбирается линковкой: sprinter-cc --gfx 256 (16 — позже, тем же
leaf-split'ом). Один код работает в любом режиме без правок.

API: initgraph/closegraph/graphresult/cleardevice, set/get color+bkcolor,
getmaxx/y/color, put/getpixel, moveto/moverel/getx/gety, line/lineto/
linerel, rectangle, bar, circle, outtext/outtextxy. initgraph грузит
EGA-палитру 0..15. Пакетные примитивы (circle) — одна W3-скобка на
примитив (иначе на порядок медленнее). Проверено в MAME (tests/bgitest).

Попутно: gfx_getpixel256 в libc/gfx. size-check без регресса, baseline
обновлён. Детали: memory/bgi_two_lib_design, docs/TODO.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 15:40:49 +03:00

11 KiB
Raw Blame History

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-плот), иначе на порядок медленнее.

Фаза 2 (осталось): ellipse/arc/pieslice, drawpoly/fillpoly, floodfill, setfillstyle/паттерны, bar3d, settextstyle/textwidth/ textheight (размеры/направление), imagesize/getimage/putimage (COPY/XOR/AND/OR/NOT_PUT), setviewport/клиппинг, setactivepage/ setvisualpage (2 страницы есть), setlinestyle, setaspectratio (пиксели 320×256 неквадратные — окружности визуально эллиптичны). 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 помнит размер)

Новые возможности:

  • 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 на операцию

Прочий backlog

  • factoring parse_argv из crt0/crt0_banked в общий argv.s
  • restore SP on EXIT (паттерн z88dk +pps) — проверить нужность
  • CI: MAME с -aviwrite для screenshot-сравнения без человекаtoolchain/mame_auto_test.py (2026-07-08): AUTORUN.BAT chainload + Lua-таймер для скриншотов/выхода; сравнение пока визуальное (Claude читает скриншот), не автоматический diff. Подробности: memory/mame_autotest_autorun.
  • 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