libc: Solid-C совместимость (П3) + rename/isatty (П4); scanf-семейство
- <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>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* dos.h — DOS-подобный слой Solid-C поверх ESTEX/BIOS: диски,
|
||||
* дата/время в Turbo-C-структурах, абсолютное чтение/запись секторов.
|
||||
*
|
||||
* Структуры совместимы с Solid-C DOS.H (и Turbo C):
|
||||
* struct time { ti_min, ti_hour, ti_hund, ti_sec }
|
||||
* struct date { da_year, da_day, da_mon (1 = январь) }
|
||||
* ti_hund (сотые секунды) не поддержан RTC Sprinter — всегда 0.
|
||||
*/
|
||||
|
||||
#ifndef DOS_H
|
||||
#define DOS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct time {
|
||||
unsigned char ti_min; /* минуты */
|
||||
unsigned char ti_hour; /* часы */
|
||||
unsigned char ti_hund; /* сотые доли секунды (не используются) */
|
||||
unsigned char ti_sec; /* секунды */
|
||||
};
|
||||
|
||||
struct date {
|
||||
int da_year; /* год (полный, напр. 2026) */
|
||||
char da_day; /* день месяца */
|
||||
char da_mon; /* месяц (1 = январь) */
|
||||
};
|
||||
|
||||
/* Чтение/установка даты и времени (обёртки над getdatetime/
|
||||
* setdatetime — set* делает read-modify-write полного datetime_t). */
|
||||
void getdate(struct date *d);
|
||||
int setdate(const struct date *d);
|
||||
void gettime(struct time *t);
|
||||
int settime(const struct time *t);
|
||||
|
||||
/* Текущий диск: 0=A, 1=B, ... setdisk возвращает число дисков или
|
||||
* -1 + errno. */
|
||||
uint8_t getdisk(void);
|
||||
int setdisk(uint8_t drive);
|
||||
|
||||
/* Абсолютное чтение/запись секторов ЛОГИЧЕСКОГО диска (BIOS $55/$56,
|
||||
* rst 8; сектор 0 = boot-сектор, с 1 — первая FAT и т.д.).
|
||||
* Возврат 0 или -1 + errno (EREAD/EWRITE, как у Solid-C).
|
||||
* Буфер должен лежать в #4000-#BFFF (требование BIOS). */
|
||||
int absread (uint8_t disk, uint16_t nsect, uint8_t count, void *buffer);
|
||||
int abswrite(uint8_t disk, uint16_t nsect, uint8_t count,
|
||||
const void *buffer);
|
||||
|
||||
#endif
|
||||
@@ -55,6 +55,27 @@ extern int errno;
|
||||
* Folded onto the closest existing code so error strings stay sane. */
|
||||
#define EINVAL EUNKOP /* "Invalid argument" → "Unknown operation" */
|
||||
|
||||
/* ---- Solid-C aliases (ERRNO.H из Solid-C v2004) -------------------
|
||||
* Те же числовые коды DSS, только имена другие — портируемые
|
||||
* программы работают без правок. */
|
||||
#define EZERO EOK
|
||||
#define EINVFNC EINVFN
|
||||
#define EINVDRV ENODRV
|
||||
#define ENOFILE ENOENT
|
||||
#define EINVHND EBADF
|
||||
#define EROFILE EROFS
|
||||
#define EROOT EROOTFULL
|
||||
#define ENOSPACE ENOSPC
|
||||
#define ENOEMPTY ENOTEMPTY
|
||||
#define ECURDIR EBUSY
|
||||
#define EINVMED EMEDIA
|
||||
#define EOPER EUNKOP
|
||||
#define EEXISDIR EISDIR
|
||||
#define EINVFNAM EINAME
|
||||
#define ENSUPEXE ENOEXEC
|
||||
#define ENORDY ENOTREADY
|
||||
#define EWRTPRT EWRPROT
|
||||
|
||||
/* C99 perror / strerror surface. */
|
||||
const char *strerror(int err);
|
||||
void perror (const char *prefix);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dir.h>
|
||||
#include <dos.h> /* getdate/gettime, getdisk, absread */
|
||||
#include <sprinter_exit.h> /* _exit, atexit */
|
||||
|
||||
/* ---- Solid-C types ----------------------------------------------- */
|
||||
@@ -98,8 +99,12 @@ char *strupr(char *s);
|
||||
/* ---- io.h aliases (Solid-C fd shortcuts) ------------------------- */
|
||||
#define seek(fd, off) lseek((fd), (long)(off), SEEK_SET)
|
||||
#define tell(fd) ((uint16_t)lseek((fd), 0, SEEK_CUR))
|
||||
#define ltell(fd) lseek((fd), 0L, SEEK_CUR)
|
||||
#define remove(name) unlink(name)
|
||||
|
||||
/* crt0 разбирает argv сам — заглушка для портируемого кода. */
|
||||
#define _setargv() 0
|
||||
|
||||
/* ---- dir.h alias ------------------------------------------------- */
|
||||
#define _ffirst ffirst
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* sprinter_solid.h — зонтичный заголовок для портирования программ
|
||||
* Solid-C: подключает все стандартные заголовки + compat-алиасы.
|
||||
* Программа Solid-C может заменить свои include на один этот.
|
||||
*
|
||||
* Известные отличия от Solid-C (см. docs/solid_c_compatibility.md):
|
||||
* - bdos/bdosh/intdos (сырой интерфейс ESTEX) не экспонируются —
|
||||
* использовать типизированные обёртки libc;
|
||||
* - lseek/ltell возвращают long, а не struct fpoint*;
|
||||
* - FILE* буферизован (Solid-C тоже, семантика совместима).
|
||||
*/
|
||||
|
||||
#ifndef SPRINTER_SOLID_H
|
||||
#define SPRINTER_SOLID_H
|
||||
|
||||
#include <sprinter_compat.h> /* включает stdio/stdlib/string/conio/
|
||||
ctype/errno/fcntl/unistd/dir/dos/
|
||||
mouse + типы и алиасы Solid-C */
|
||||
#include <time.h>
|
||||
#include <sprinter.h>
|
||||
|
||||
#endif
|
||||
+22
-3
@@ -83,9 +83,15 @@ extern FILE *const stderr;
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
FILE *fopen (const char *path, const char *mode);
|
||||
int fclose(FILE *fp);
|
||||
int fflush(FILE *fp);
|
||||
/* Тип позиции файла для fgetpos/fsetpos. */
|
||||
typedef long fpos_t;
|
||||
|
||||
FILE *fopen (const char *path, const char *mode);
|
||||
FILE *fdopen (int fd, const char *mode);
|
||||
FILE *freopen(const char *path, const char *mode, FILE *fp);
|
||||
int fclose (FILE *fp);
|
||||
void fclosall(void);
|
||||
int fflush (FILE *fp); /* fflush(NULL) — все потоки */
|
||||
|
||||
int fputc (int c, FILE *fp);
|
||||
int fgetc (FILE *fp);
|
||||
@@ -96,12 +102,25 @@ int ungetc(int c, FILE *fp);
|
||||
int fprintf (FILE *fp, const char *fmt, ...);
|
||||
int vfprintf(FILE *fp, const char *fmt, va_list ap);
|
||||
|
||||
/* scanf-семейство (семантика Solid-C, реализация своя — в SDCC z80
|
||||
* его нет). Конверсии: %d %u %x %o %c %s (+ модификатор l, ширина,
|
||||
* подавление '*', %%). Возврат: число присвоенных полей, EOF если
|
||||
* ввод кончился до первого совпадения. */
|
||||
int scanf (const char *fmt, ...);
|
||||
int fscanf(FILE *fp, const char *fmt, ...);
|
||||
int sscanf(const char *s, const char *fmt, ...);
|
||||
|
||||
/* Переименование файла (ESTEX RENAME $10). */
|
||||
int rename(const char *oldpath, const char *newpath);
|
||||
|
||||
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *fp);
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp);
|
||||
|
||||
int fseek (FILE *fp, long off, int whence);
|
||||
long ftell (FILE *fp);
|
||||
void rewind(FILE *fp);
|
||||
int fgetpos(FILE *fp, fpos_t *pos);
|
||||
int fsetpos(FILE *fp, const fpos_t *pos);
|
||||
|
||||
int feof (FILE *fp);
|
||||
int ferror(FILE *fp);
|
||||
|
||||
@@ -28,6 +28,10 @@ long lseek(int fd, long offset, int whence);
|
||||
/* Block the calling task for `seconds` seconds (50 Hz IRQ-based timer). */
|
||||
void sleep(unsigned int seconds);
|
||||
|
||||
/* 1, если fd — консоль (наши псевдо-fd 0/-1/-2), 0 — файл (любой
|
||||
* положительный манипулятор DSS; из командной строки они идут с 1). */
|
||||
int isatty(int fd);
|
||||
|
||||
/* Directory operations (ESTEX $1B-$1E). All return 0 on success and -1
|
||||
* with errno set on failure; getcwd returns the buffer on success or NULL.
|
||||
* size is ignored — ESTEX always wants a 256-byte buffer. */
|
||||
|
||||
Reference in New Issue
Block a user