# Sprinter C-Compiler — правила проекта Target-слой SDCC 4.5 (z80) для компьютера Sprinter Sp2000: crt0, линковка, libc, mkexe. Общение и комментарии — на русском. ## Сборка и проверка ``` 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/libbgi: пересборка от чистого листа (`make -C libc clean` / `make -C libbgi clean`) не обязательна — stale .rel чистятся автоматически; `make size-check` обязателен (рост _CODE без причины — регрессия). ## Правила libc - **1 публичная функция = 1 .c-модуль** (линкер тянет .rel целиком — гранулярность файлов = гранулярность DCE). Никакой группировки «используются вместе». Internal-хелперы — тоже по одному на модуль (`_`-префикс); общие статики — в отдельные data-модули (`_xxx_state.c`); internal-заголовки (`_file.h`, `_gfx.h`, …) — рядом с исходниками, НЕ в libc/include. - Имя файла = имя функции. libc/Makefile собирает wildcard'ом — ничего регистрировать не надо. - Комментарии — на русском; шапка модуля объясняет что/зачем + ABI. - File-scope переменные НЕ инициализировать `= 0` (crt0 зануляет _DATA; см. memory/sdcc_static_storage_gotcha). - asm-связки между модулями: `call/jp _global` — ок; `jr/djnz` через границу и fall-through — НЕЛЬЗЯ (docs/libc-split-asm-cases.md). - Заголовки: сначала пробовать include_next-паттерн; полная замена SDCC-заголовка обязана дублировать его контракт (docs/libc-headers.md). - Справочник API — docs/libc-reference.md (обновлять при добавлении функций). ## ABI и платформа (кратко; детали в memory/) - SDCC `__sdcccall(1)`: arg1 → HL (8-бит → A), arg2 → DE, остальные на стеке (callee-pops в __naked); **возврат int/ptr в DE**, uint8 в A. IX callee-saved (в __naked с IX — push/pop обязательны). - ESTEX (rst #0x10): CF=1 — ошибка, код в A → `call __errno_set`; все регистры клобберятся (IX сохранять); стек обязан быть в W2. - BIOS (rst #0x08): строки/буферы в #4000-#BFFF. - Квирки: ESTEX WRITE возвращает DE=0 на успехе (судить по CF/A); лимит 8 файловых манипуляторов, 9-й OPEN ВЕШАЕТ DSS (_fd_guard); ENV $46: A=0 = NOT FOUND. - Перед обвинением компилятора/железа — подтвердить артефактом (сгенерированный .asm в libc/build/ или libbgi/build/, дамп, репро) — см. memory/defer_unexplained_quirks. ## Структура - `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/` — реальные приложения - `docs/` — дизайн-доки; `docs/TODO.md` — roadmap - `third_party/solid-c/` — нативный Sprinter C (референс, CP866; их ABI несовместим — только как образец)