60373930fb
- <dos.h>: getdate/gettime/setdate/settime (структуры Turbo-C, обёртки над getdatetime), getdisk/setdisk (ESTEX $02/$01), absread/abswrite (BIOS $55/$56, rst 8 — номера найдены в solid-c DOS.ASM; сектор 0 = boot логического диска) - scanf/fscanf/sscanf: своё C-ядро _scanf_core (%d %u %x %o %c %s, модификатор l, ширина, подавление '*', %%); в SDCC z80 scanf нет, asm solid-c не портируем из-за чужого ABI; 22 хост-теста ядра - хвост П2: fdopen/freopen/fclosall/fgetpos/fsetpos поверх таблицы FILE; парсер режима и выдача слота вынесены в _file_mode/_file_slot - rename() — ESTEX RENAME $10; isatty(fd) = fd <= 0 (tty только псевдо-fd 0/-1/-2: из CLI DSS манипуляторы идут с 1 — verified, fd 1 не резерв, под Flex Navigator его держит навигатор) - errno.h: Solid-C имена ошибок (EZERO/EINVFNC/ENOFILE/...) как алиасы - <sprinter_solid.h> — зонтичный заголовок для портирования; ltell/_setargv в sprinter_compat.h; div/ldiv — из SDCC (проверено) - tests/solidt — smoke всех П3/П4 API, зелёный в MAME (вкл. absread boot-сектора с сигнатурой 55AA) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
161 lines
8.8 KiB
Markdown
161 lines
8.8 KiB
Markdown
# Solid-C compatibility — gap analysis
|
||
|
||
**Goal:** if a function exists in Solid-C, it must exist in our libc (with the same name). If we deliberately use a different name, document the difference here.
|
||
|
||
Solid-C source (`third_party/solid-c/INCLUDE/*.H`) provides these functions. SDCC's z80.lib auto-includes most of the standard C library. This document tracks the remaining gaps.
|
||
|
||
## Already covered (no work needed)
|
||
|
||
**From our libc directly:**
|
||
atexit, chdir, clearerr, close, clrscr, cprintf, cputs, creat, ctime, asctime,
|
||
exit, _exit, fclose, feof, ferror, fflush, fgetc, fgets, ffirst, fnext,
|
||
fopen, fputc, fputs, fread, fseek, fstat, ftell, fwrite, getch, getchar,
|
||
getche, getcwd, getenv, gotoxy, kbhit, longjmp, lseek, mkdir, open, perror,
|
||
printf, putch, putchar, putenv, puts, read, rewind, rmdir, setjmp, sleep,
|
||
sprintf, stat, textattr, textbackground, textcolor, unlink, vprintf,
|
||
vsprintf, write, wherex, wherey, set_videomode, get_videomode,
|
||
mouse_{init,show,hide,read,goto,bounds_x,bounds_y,refresh,text_cursor,
|
||
load_cursor,get_cursor,get_sensitivity_x,get_sensitivity_y,set_sensitivity,
|
||
video_mode_changed}.
|
||
|
||
**Free from SDCC's z80.lib (auto-linked):**
|
||
abs, atof, atoi, atol, bsearch, calloc, free, isalpha, isdigit, islower,
|
||
isupper, isspace, iscntrl, isgraph, isprint, ispunct, isalnum, isxdigit,
|
||
malloc, memchr, memcmp, memcpy, memmove, memset, qsort, rand, realloc,
|
||
srand, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp,
|
||
strncpy, strpbrk, strrchr, strspn, strstr, strtok, strtol, strtoul,
|
||
tolower, toupper.
|
||
|
||
## REAL gaps — to implement
|
||
|
||
### Category A: trivial (one-liner aliases or small wrappers)
|
||
|
||
| Solid-C | Status | Notes |
|
||
|---|---|---|
|
||
| `getc(fd)` | macro alias | `#define getc(fp) fgetc(fp)` |
|
||
| `putc(c, fp)` | macro alias | `#define putc(c,fp) fputc(c,fp)` |
|
||
| `remove(name)` | alias | `#define remove(n) unlink(n)` (POSIX semantic match) |
|
||
| `seek(fd, off)` | alias | `int seek(fd, off) { return lseek(fd, off, SEEK_SET); }` |
|
||
| `tell(fd)` | alias | `int tell(fd) { return lseek(fd, 0, SEEK_CUR); }` |
|
||
| `ltell(fd, &lpos)` | wrapper | wrap our `lseek` (32-bit) |
|
||
| `home()` | macro alias | `#define home() gotoxy(0,0)` |
|
||
| `_setargv()` | crt0 does this | provide stub or doc that crt0 covers it |
|
||
| `_ffirst()` | alias | already have `ffirst` with same semantic — alias macro |
|
||
| `setmem(p, n, b)` | alias | `#define setmem(p,n,b) memset(p,b,n)` |
|
||
| `movmem(s, d, n)` | alias | `#define movmem(s,d,n) memcpy(d,s,n)` (note arg order!) |
|
||
| `min(a,b)`, `max(a,b)` | macros | `#define min(a,b) ((a)<(b)?(a):(b))` etc. |
|
||
| `isascii(c)` | macro | `#define isascii(c) ((unsigned)(c) < 128)` |
|
||
| `abort()` | wrapper | `void abort(void) { _exit(0xFF); }` |
|
||
| `strerr(n)` | alias | rename existing `strerror` or alias |
|
||
| `sysenv()` | wrapper | already have env API, just alias |
|
||
|
||
### Category B: small new implementations
|
||
|
||
| Solid-C | Notes |
|
||
|---|---|
|
||
| `dec8/dec16/dec32` | print uint8/16/32 as decimal — use sprintf("%u") internally |
|
||
| `hex8/hex16/hex32` | print uint8/16/32 as hex — we have `print_hex`, just add hex16 and hex32 |
|
||
| `strlwr(s)` | in-place lowercase the string (returns s) |
|
||
| `strupr(s)` | in-place uppercase the string |
|
||
| `div(num, den)` | returns `div_t { quot, rem }` — trivial wrapper over `/` and `%` |
|
||
| `getc/putc/ungetc` | one-byte putback for streams; `ungetc` needs 1-char buffer in FILE* |
|
||
| `gets(buf)` | dangerous-but-Solid-C-has-it, simple fgets-wrapper |
|
||
| `cgets(buf)` | line input via conio (no echo control — wrap getche loop) |
|
||
| `inp(port)` / `outp(port,val)` | direct port I/O — Z80 IN/OUT, can be __sfr or inline asm wrappers |
|
||
| `enable()` / `disable()` | `__asm ei __endasm` / `__asm di __endasm` |
|
||
| `getdisk()` / `setdisk(d)` | ESTEX $02 CURDISK / $01 CHDISK |
|
||
|
||
### Category C: requires research / non-trivial work
|
||
|
||
| Solid-C | Notes |
|
||
|---|---|
|
||
| `fdopen(fd, mode)` / `freopen` | needs FILE* expansion — currently we have unbuffered FILE; mid-effort |
|
||
| `fclosall()` | iterate over all open FILE*'s and close them — depends on FILE table refactor |
|
||
| `fgetpos(fp, &pos)` / `fsetpos` | wrappers over ftell/fseek with `fpos_t` type |
|
||
| `bdos(a, hl)` / `bdosh(...)` / `intdos(®s)` | Solid-C exposes raw ESTEX call interface. Our convention is typed wrappers — we may **document** the difference and skip these. |
|
||
| `absread(disk, n, sect, buf)` / `abswrite` | absolute disk sector I/O — need ESTEX READ_SECT / WRITE_SECT (need to find function numbers) |
|
||
| `_ffirst` raw vs `ffirst` cooked | Solid-C has two — raw "FilenameExt" format and cooked. Investigate if we want both. |
|
||
| `ioctl(fd, ...)` | terminal control — Solid-C scope unclear, may skip |
|
||
| `isatty(fd)` | trivial (always returns 0 — we have no tty handle), but check our FD numbers |
|
||
| `brk(addr)` / `sbrk(n)` | classical Unix heap pointer manipulation; our heap is managed by SDCC `_sbrk` already? Investigate alias. |
|
||
| `scanf` / `sscanf` / `fscanf` | parser — SDCC may have it in stdlib if requested. Check or add stub. |
|
||
| `getdate` / `gettime` / `setdate` / `settime` | we have `getdatetime`/`setdatetime`; Solid-C splits into date/time structs. Build wrappers. |
|
||
|
||
### Category D: Mouse aliases — Solid-C `ms_*` names
|
||
|
||
Solid-C uses short names: `ms_init/show/hide/stat/spos/ybnd/xbnd/scur/tcur/gcur/gsen/ssen/hard/vmod/ref` + `msgstat`/`mssgpos`. All have the same semantics as our `mouse_*` functions.
|
||
|
||
**Plan:** add aliases via header macros so both names work:
|
||
|
||
```c
|
||
#define ms_init mouse_init
|
||
#define ms_show mouse_show
|
||
/* ... etc */
|
||
```
|
||
|
||
Also Solid-C wraps state into `MSSTAT` (8-bit coords) and `MSGSTAT` (16-bit coords) structs. Our `mouse_state_t` already matches `MSGSTAT` semantics — add a typedef alias.
|
||
|
||
## Documented differences (will NOT match Solid-C exactly)
|
||
|
||
These will be in `docs/solid_c_diff.md`:
|
||
|
||
- **`bdos` / `bdosh` / `intdos`** — we don't expose raw ESTEX call interface; use typed wrappers
|
||
- **`FILE*` model** — ours is unbuffered (currently); Solid-C may use buffered streams
|
||
- **Error code constants** — Solid-C's `EZERO/EINVFNC/etc.` vs our `errno` table. Will provide compat aliases in `errno.h`.
|
||
|
||
## Implementation plan
|
||
|
||
**Phase 1 — trivial aliases/macros** (~1 hour):
|
||
- conio.h additions: `home`, `inp`, `outp`, `enable`, `disable`
|
||
- stdio.h: `getc`, `putc`, `remove`, `gets`
|
||
- string.h: `setmem`, `movmem`, `strlwr`, `strupr`, `strerr`
|
||
- stdlib.h: `min`, `max`, `div`, `abort`, `sysenv`, `dec8/16/32`, `hex8/16/32`
|
||
- ctype.h: `isascii`
|
||
- io.h: `seek`, `tell`, `ltell`, `_setargv` stub
|
||
- dir.h: `_ffirst`
|
||
- mouse.h: `ms_*` aliases + `MSSTAT`/`MSGSTAT` typedefs
|
||
- types.h: provide compat `BOOL`/`uint`/`WORD`/`f_point` types
|
||
|
||
**Phase 2 — new impls** (~2-3 hours):
|
||
- ungetc, gets, cgets
|
||
- getdisk/setdisk
|
||
- getdate/gettime/setdate/settime (split datetime struct)
|
||
|
||
**Phase 3 — investigate / decide** (research first):
|
||
- absread/abswrite (sector I/O)
|
||
- scanf family (SDCC has it?)
|
||
- brk/sbrk vs SDCC heap
|
||
|
||
## Compatibility header
|
||
|
||
To make porting easier, add a single `<sprinter_solid.h>` that includes all the standard headers (`stdio.h`, `string.h`, `conio.h`, etc.) — Solid-C programs can `#include <sprinter_solid.h>` and have most functions available.
|
||
|
||
## Status 2026-07-06 — Phase 1/2/3 ЗАКРЫТЫ
|
||
|
||
Всё из категорий A/B/C реализовано или закрыто решением:
|
||
|
||
- **A (алиасы)**: все на месте в sprinter_compat.h (+ ltell, _setargv
|
||
добавлены 2026-07-06); div/ldiv — из SDCC z80.lib (проверено).
|
||
- **B**: getdisk/setdisk (ESTEX $02/$01, libc/io), getdate/gettime/
|
||
setdate/settime (обёртки над getdatetime, структуры Turbo-C в
|
||
<dos.h>), остальное было готово ранее.
|
||
- **C**: fdopen/freopen/fclosall/fgetpos/fsetpos — реализованы поверх
|
||
таблицы FILE v2 (libc/file); ungetc — есть (FILE v2);
|
||
**absread/abswrite — BIOS $55/$56** (rst 8, A=диск, HL:IX=сектор,
|
||
DE=буфер, B=счётчик; найдено в solid-c DOS.ASM) — реализованы в
|
||
libc/io; **scanf/fscanf/sscanf — реализованы** (своё C-ядро
|
||
_scanf_core с семантикой Solid-C: %d %u %x %o %c %s, l, ширина, %*;
|
||
в SDCC z80 scanf нет); isatty — fd < 2 (см. memory/dss_fd_limit).
|
||
bdos/bdosh/intdos — НЕ экспонируем (решение: типизированные
|
||
обёртки); brk/sbrk — НЕ нужны (heap SDCC); ioctl — скип.
|
||
- **errno**: Solid-C имена (EZERO/EINVFNC/ENOFILE/…) — алиасы в errno.h.
|
||
- **Зонтичный заголовок**: <sprinter_solid.h>.
|
||
- Тест: tests/solidt (MAME).
|
||
|
||
## History
|
||
|
||
- 2026-07-06 — Phase 1/2/3 закрыты: dos.h (даты/диски/сектора),
|
||
scanf-семейство, fdopen/freopen/fclosall/fgetpos/fsetpos,
|
||
rename/isatty (П4), errno-алиасы, sprinter_solid.h, тест solidt
|
||
- 2026-06-01 — initial gap analysis vs Solid-C v2004
|