Files
Sprinter-SDCC/docs/libc-reference.md
T
snark13 7187752b29 docs: справочник libc API, правила проекта в CLAUDE.md, актуализация TODO (П7)
- docs/libc-reference.md — сводный справочник по всем заголовкам:
  сигнатуры + описание + особенности ABI и квирки
- CLAUDE.md — сборка/проверка (make, size-check, MAME-workflow),
  правила libc (1 функция = 1 модуль, internal _-модули, русские
  комментарии, без = 0, asm-связки), ABI-шпаргалка, структура репо
- docs/TODO.md переписан: открытые задачи наверху (MAME/железо,
  auto-banking, v2: BGI/IM2/audio, gfx-расширения, Port_Y),
  закрытые этапы 5-10 сжаты в «Историю»; снят протухший пункт
  «FILE API rewrite для v2» (сделан в v1), fprintf/fscanf и др.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 20:47:33 +03:00

195 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# libc — справочник API (2026-07-06)
Сводка по заголовкам: сигнатура + одна строка + особенности ABI.
Детали дизайна: docs/libc-headers.md (контракт затенения SDCC),
docs/file-buffering-design.md (FILE*), docs/solid_c_compatibility.md.
Общие соглашения:
- ошибки: возврат -1/NULL/EOF + `errno` (код DSS as-is, см. errno.h);
- SDCC `__sdcccall(1)`: 1-й аргумент HL (8-битный — A), 2-й — DE,
остальные на стеке; **int/указатель возвращается в DE**;
- строки для BIOS-вызовов (rst 8) должны лежать в #4000#BFFF;
- стек при любых ESTEX/BIOS-вызовах — в W2 (обеспечено crt0).
## <stdio.h> — полная замена SDCC (контракт: printf-семейство из z80.lib)
Из SDCC z80.lib: `printf sprintf vprintf vsprintf`.
Консоль (ESTEX, без атрибутов — быстрый путь; цветной вывод — conio):
| Сигнатура | Описание |
|---|---|
| `int putchar(int c)` | символ через PUTCHAR $5B; '\n'→CR LF |
| `int getchar(void)` | блокирующий WAITKEY $30, ASCII |
| `char puts(const char *s)` | строка + '\n' (посимвольно через putchar) |
| `char *gets(char *buf)` | строка с консоли, без контроля длины |
| `void dec8/dec16/dec32(v)` | десятичная печать без ведущих нулей |
| `void hex8/hex16/hex32(v)` | hex-печать фиксированной ширины |
FILE* (буферизованный, вариант B+ — единый ленивый буфер BUFSIZ=512
на чтение/запись с автопереключением; таблица `OPEN_MAX=8` слотов;
exit() сбрасывает всё через atexit; **ошибки записи отложенные —
проверять fclose**):
| Сигнатура | Описание |
|---|---|
| `FILE *fopen(path, mode)` | "r/w/a" + '+', 'b/t' игнорируются |
| `FILE *fdopen(fd, mode)` | завернуть готовый fd (закрывать fclose!) |
| `FILE *freopen(path, mode, fp)` | переоткрыть тот же FILE* |
| `int fclose(FILE*)` / `void fclosall(void)` | сброс+закрытие / все потоки |
| `int fflush(FILE*)` | сброс записи / откат readahead; NULL = все |
| `int fgetc/fputc(...)` | горячий путь на asm; getc/putc — макро-алиасы |
| `char *fgets(buf, n, fp)` | до '\n' (сохраняется); блочный LDI-сканер |
| `int fputs(s, fp)` | без '\n'; через fwrite |
| `size_t fread/fwrite(p, sz, n, fp)` | блоки ≥ 512 идут мимо буфера |
| `int ungetc(c, fp)` | 1 байт putback (и на stdin) |
| `int fseek(fp, off, whence)` / `long ftell(fp)` | ftell без побочных эффектов |
| `void rewind(fp)` | fseek(0) + сброс EOF/ERROR |
| `int fgetpos/fsetpos(fp, &pos)` | fpos_t = long |
| `int feof/ferror(fp)`, `void clearerr(fp)` | флаги потока |
| `int fprintf/vfprintf(fp, fmt, ...)` | vsprintf в статический буфер 256 |
| `int scanf/fscanf/sscanf(...)` | %d %u %x %o %c %s, `l`, ширина, %*, %% |
| `int rename(old, new)` | ESTEX RENAME $10 |
`stdin/stdout/stderr` — консольные псевдопотоки (fd 0/-1/-2), не
буферизуются; freopen на них меняет только FILE*-операции (printf
идёт в ESTEX напрямую).
## <stdlib.h> — include_next + добавки
Из SDCC: malloc/free/calloc/realloc (heap в W2), atoi/atol/strtol/
strtoul, rand/srand, qsort/bsearch, abs/labs, div/ldiv, exit-типы.
Наше: `int16_t min(a,b)`, `int16_t max(a,b)` (функции, как в Solid-C).
## <string.h> — include_next + добавки
Из SDCC: mem*/str* полностью. Наше: `char *strlwr/strupr(char *s)`
in-place регистр, латиница + кириллица CP866.
## <time.h> — полная замена (struct tm в SDCC-ABI, __TIME_UNSIGNED=1)
| Сигнатура | Описание |
|---|---|
| `void getdatetime(datetime_t*)` | RTC как есть (ESTEX SYSTIME $21) |
| `int setdatetime(const datetime_t*)` | установка RTC ($22) |
| `time_t time(time_t*)` | Unix-эпоха из RTC |
| `mktime/gmtime/localtime/asctime/ctime` | POSIX поверх RTC (без TZ) |
`datetime_t`: day/month/year(полный)/hour/minute/second/dow (1=Вс).
## <unistd.h>, <fcntl.h> — fd-уровень (манипуляторы DSS)
| Сигнатура | Описание |
|---|---|
| `int open(path, flags)` | O_RDONLY/WRONLY/RDWR + O_CREAT/TRUNC/EXCL/APPEND (ESTEX $11/$0A/$0B) |
| `int creat(path, mode)` | open(W|CREAT|TRUNC); mode игнорируется |
| `int read/write(fd, buf, n)` | ESTEX $13/$14. **Квирк WRITE: DE-возврат ненадёжен, успех = CF=0&A=0** (см. memory/estex_write_de_quirk) |
| `int close(fd)` | ESTEX $12 |
| `long lseek(fd, off, whence)` | 32-битная позиция (MOVE_FP $15) |
| `int unlink(path)` | удалить (DELETE $0E) |
| `int isatty(fd)` | fd <= 0 (файловые манипуляторы DSS с 1) |
| `int mkdir/rmdir/chdir(path)` | ESTEX $1B/$1C/$1D |
| `char *getcwd(buf, size)` | буфер 256 байт, size игнорируется |
| `void sleep(seconds)` | 50 halt/с по кадровому IRQ |
**Лимит: 8 одновременных манипуляторов**; 9-й OPEN вешает DSS —
libc отказывает сама (EMFILE, предохранитель _fd_guard).
## <errno.h>
`errno` (int), коды = коды DSS (EOK..EUNKERR) + POSIX-имена
(ENOENT/EBADF/EMFILE/…) + алиасы Solid-C (EZERO/EINVFNC/ENOFILE/…).
`const char *strerror(int)`, `void perror(const char*)`.
## <dos.h> — DOS-слой Solid-C
| Сигнатура | Описание |
|---|---|
| `void getdate/gettime(&d)` | struct date/time (Turbo-C; ti_hund=0) |
| `int setdate/settime(&d)` | RMW полного datetime |
| `uint8_t getdisk(void)` | текущий диск, 0=A (ESTEX $02) |
| `int setdisk(uint8_t)` | смена диска; возврат = число дисков ($01) |
| `int absread/abswrite(disk, sect, cnt, buf)` | секторы ЛОГИЧЕСКОГО диска (BIOS $55/$56); буфер в #4000#BFFF; abswrite минует ФС! |
## <dir.h>
`int ffirst(pattern, ffblk_t*, attrib)` / `int fnext(ffblk_t*)`
поиск по шаблону (ESTEX $19/$1A). Квирк: "."/".." находятся только
итерацией "*.*" (memory/estex_ffirst_dotdot). FA_*-атрибуты.
## <sys/stat.h>
`int stat(path, struct stat*)` / `int fstat(fd, ...)` — st_mode
(S_ISREG/S_ISDIR), st_size, st_mtime (Unix-эпоха).
## <conio.h> — текстовый экран с атрибутами (Turbo-C стиль)
Клавиатура: `kbhit getch getche getkey` (+KEY_* коды позиций),
`char *cgets(buf)`.
Вывод с атрибутом: `putch cputs cprintf` (~10× медленнее stdio-пути;
'\n' НЕ транслируется — писать "\r\n").
Атрибуты: `textcolor textbackground textattr`, `set/get_text_attr`,
COLOR_*-enum, `COLOR(fg,bg)`, COLOR_BLINK; `set/get_putch_raw_mode`.
Экран: `clrscr clrscr_attr gotoxy home() wherex wherey wherexy scroll
wrchar rdchar`; режимы `gettextmode/settextmode` (0x02=40×32,
0x03=80×32).
Порты/IRQ: `inp outp enable() disable()`.
Текстовая палитра: `text_pal_load/set_color/get/get_color/reset`
(план 0..3 → страница BIOS 4..7).
## <bios/text.h> — быстрый BIOS-вывод (rst 8, place-based)
`bios_set_place/get_place`, `bios_write[attr][_until|_stop]`,
`bios_fillchar/fillattr/fillcharattr`, `bios_clearwin[_ch]`,
`bios_scrollwin`. Строка s — в #4000#BFFF; place продвигается.
## <gfx.h> — графика (0x81: 320×256×256; 0x82: 640×256×16)
Setup: `gfx_init(mode,page)→prev`, `gfx_done(prev)`.
Страницы/банк: `gfx_set/get_visible_page`, `gfx_set/get_draw_page`
(double buffering), `gfx_set/get_bank` (0x50..0x5F, 0x58 = FF-
прозрачность), `gfx_wait_vsync()`.
Примитивы (суффикс _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_pal_load/set/get/get_color/reset` (страницы 0..3).
## <palette.h> — низкий уровень (BIOS $A4/$A6)
`pal_load pal_get pal_set_color pal_get_color` (страница 0..7,
записи B,G,R,0), `pal_reset(type)` / `pal_reset_at(type,page,graph)`;
PAL_GRAPH/PAL_SINCLAIR/PAL_CGA.
## <mouse.h> — драйвер RST 30h
`mouse_init show hide refresh read(mouse_state_t*) goto bounds_x/y
text_cursor load_cursor/get_cursor(mouse_cursor_t*) set_sensitivity
get_sensitivity_x/y video_mode_changed`. Sensitivity = делитель
(меньше = быстрее). Solid-C алиасы ms_* включены.
## <sprinter.h> — платформа
Константы портов (PORT_PAGE_W0..W3, PORT_RGADR, PORT_RGMOD), номера
всех ESTEX-функций (ESTEX_*), BIOS EMM ($C0..$C7); `__sfr`-доступ и
inline `sprinter_page_w0..w3(page)`; ENV: `getenv putenv sysenv`.
## <sprinter_mem.h> — EMM-страницы и банковый I/O
`mem_alloc_pages(n)→blk_id, mem_free_block, mem_get_page(blk,idx),
mem_info(&total,&free)` (реализации _bios/_estex; макро-выбор
MEM_MANAGE_MODE_*). HOME-резидентный доступ к чужим страницам:
`bank_load_byte/store_byte/read/write` (своп W3 внутри; *_w1 —
вариант через окно W1).
## <sprinter_exit.h>
`atexit` (LIFO, 8 слотов), `exit` (хендлеры+сброс FILE), `_exit`.
## <sprinter_compat.h> / <sprinter_solid.h>
Типы (BYTE/BOOL/WORD/uint/FD/f_point), TRUE/FALSE/OK/ERROR,
`setmem movmem` (порядок аргументов!), `strerr seek tell ltell
remove _ffirst _setargv abort()`, isascii. `<sprinter_solid.h>`
зонтичный: один include для портирования Solid-C программ.