Files
Sprinter-SDCC/examples/mdview2/testfiles/BIG.MD
T
snark13 386837fc25 mdview2: целевые тестовые файлы путей обрыва (testfiles/) на диск
testfiles/gen_testfiles.py генерирует:
  BIG.MD    — ~170 КБ прозы (CP866), успешный рендер большого файла
  TABLES.MD — неровные таблицы, пробивает кап контент-кэша (Content cache exhausted)
  LINES.MD  — ~22000 коротких строк, пробивает лимит 18432 (Line limit reached)
floppy кладёт на диск TABLES.MD + LINES.MD (ASCII, напрямую из testfiles/)
вместо BIG.MD. ВРЕМЕННО для проверки лимита 256 КБ.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:55:17 +03:00

3279 lines
166 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# MDView ? à®á¬®âà騪 Markdown ¤«ï Sprinter
**MDView** ? ¯à®£à ¬¬  ¤«ï ¯à®á¬®âà  ¤®ªã¬¥­â®¢ ¢ ä®à¬ â¥ *Markdown* ­  ª®¬¯ìîâ¥à¥
Sprinter (¯à®æ¥áá®à Z80). „®ªã¬¥­â åà ­¨âáï ¢ ®â¤¥«ì­®¬ W3 ®ª­¥ ¨ ­¥ § ­¨¬ ¥â
®á­®¢­ãî RAM ¯à®£à ¬¬ë.
## ‚®§¬®¦­®áâ¨
- „®ªã¬¥­âë ¤® **128 Š** (8 áâà ­¨æ EMM ¯® 16 Š ª ¦¤ ï)
- „® **16 384** íªà ­­ëå áâப ¢ ¨­¤¥ªá¥
- €¢â®¬ â¨ç¥áª¨© ¯¥à¥­®á á«®¢ ¯® è¨à¨­¥ íªà ­  (80 á⮫¡æ®¢)
- ƒ®à¨§®­â «ì­ë© ᤢ¨£ ¤«ï è¨à®ª¨å áâப (¡«®ª¨ ª®¤ , â ¡«¨æë)
- ‘â âãá-¡ à: ¨¬ï ä ©« , ¤¨ ¯ §®­ áâப, ¯à®æ¥­â ¯à®ªàã⪨
- ‘¯¨­­¥à ¢ áâப¥ á®áâ®ï­¨ï ¢® ¢à¥¬ï § £à㧪¨ ¨ ¨­¤¥ªá æ¨¨
- ®¤¤¥à¦ª  ?¬ï£ª®£®? ᪫¥¨¢ ­¨ï áâப ¢  ¡§ æ å ¨ æ¨â â å
## ‡ ¯ãáª
```
mdview [¨¬ï_ä ©« .md]
```
…᫨ ¨¬ï ä ©«  ­¥ § ¤ ­®, § £à㦠¥âáï `README.MD`.
## “¯à ¢«¥­¨¥
```
Š« ¢¨è  „¥©á⢨¥
ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Up Down பàã⪠ ­  ®¤­ã áâப㠢¢¥àå / ¢­¨§
PgUp PgDn பàã⪠ ­  áâà ­¨æã (30 áâப)
Home  ç «® ¤®ªã¬¥­â 
End Š®­¥æ ¤®ªã¬¥­â 
Left Right ƒ®à¨§®­â «ì­ë© ᤢ¨£ (⮫쪮 nowrap-áâப¨)
F1 Žª­® á¯à ¢ª¨
F8 Š®¤¨à®¢ª : CP866 ? CP1251 ? KOI8-R ? UTF-8 ? ...
F10 / Esc ‚ë室 ¨§ ¯à®£à ¬¬ë
```
Š®¤¨à®¢ª  ®¯à¥¤¥«ï¥âáï  ¢â®¬ â¨ç¥áª¨ ¯à¨ ®âªàë⨨ (BOM + í¢à¨á⨪  ¯®
¯¥à¢ë¬ 4 Š); `F8` ¯¥à¥ª«î砥⠥ñ ¢àãç­ãî, ¥á«¨ ¤¥â¥ªæ¨ï ®è¨¡« áì.
8-¡¨â­ë¥ ª®¤¨à®¢ª¨ (CP866/CP1251/KOI8-R) ¯¥à¥ª«îç îâáï ¬£­®¢¥­­® (६ ¯ ­ 
®âà¨á®¢ª¥). ‚â®à®© ­ ¡®à ¨­¤¥ªá/ªíè  (­ ¯à¨¬¥à UTF-8) áâநâáï «¥­¨¢® ? ¯à¨
¯¥à¢®¬ ¯¥à¥ª«î祭¨¨ ¢ ­¥£® (ª®à®âª ï ¯ ã§  ᮠᯨ­­¥à®¬), ¤ «ìè¥ ¬£­®¢¥­­®.
## ‘¨­â ªá¨á Markdown
### ‡ £®«®¢ª¨
®¤¤¥à¦¨¢ îâáï ã஢­¨ H1?H4. “஢­¨ H5 ¨ H6 ®â®¡à ¦ îâáï ª ª H4.
# ‡ £®«®¢®ª ¯¥à¢®£® ã஢­ï
## ‡ £®«®¢®ª ¢â®à®£® ã஢­ï
### ‡ £®«®¢®ª âà¥â쥣® ã஢­ï
#### ‡ £®«®¢®ª ç¥â¢ñà⮣® ã஢­ï
### ’¥ªá⮢®¥ ä®à¬ â¨à®¢ ­¨¥
**†¨à­ë© ⥪áâ** ¢ë¤¥«ï¥âáï ¤¢®©­ë¬¨ §¢ñ§¤®çª ¬¨: `**⥪áâ**`
*Šãàᨢ* ¢ë¤¥«ï¥âáï ®¤¨­®ç­ë¬¨ §¢ñ§¤®çª ¬¨ `*⥪áâ*` ¨«¨ §­ ª®¬ ¯®¤çñન¢ ­¨ï `_⥪áâ_`
`‚áâ஥­­ë© ª®¤` ®¡®§­ ç ¥âáï ®¡à â­ë¬¨ ª ¢ë窠¬¨
~~‡ çñભãâë© â¥ªáâ~~ ? ¤¢®©­ë¥ ⨫ì¤ë: `~~⥪áâ~~`
### ¥­ã¬¥à®¢ ­­ë© ᯨ᮪
Œ àª¥àë `-`, `*` ¨«¨ `+`:
- ¥à¢ë© ¯ã­ªâ ᯨ᪠
- ‚â®à®© ¯ã­ªâ ᯨ᪠
- ’à¥â¨© ¯ã­ªâ á ¤®áâ â®ç­® ¤«¨­­ë¬ ⥪á⮬, ª®â®àë© ¯à¨ ­¥®¡å®¤¨¬®áâ¨
¡ã¤¥â ¯¥à¥­¥áñ­ ­  á«¥¤ãîéãî áâபã á á®åà ­¥­¨¥¬ ®âáâ㯠
### 㬥஢ ­­ë© ᯨ᮪
1. ¥à¢ë© í«¥¬¥­â
2. ‚â®à®© í«¥¬¥­â
3. ’à¥â¨© í«¥¬¥­â
### –¨â â 
> «®ª æ¨â âë ­ ç¨­ ¥âáï á ᨬ¢®«  `>`. ¥áª®«ìª® ¯®á«¥¤®¢ â¥«ì­ëå
> áâப ®¤­®© æ¨â âë ᪫¥¨¢ îâáï ¢ ¥¤¨­ë©  ¡§ æ á  ¢â®¬ â¨ç¥áª¨¬
> ¯¥à¥­®á®¬ á«®¢.
### «®ª ª®¤  (verbatim)
«®ª ª®¤  § ª«îç ¥âáï ¢ âன­ë¥ ®¡à â­ë¥ ª ¢ë窨. ‚­ãâਠ¡«®ª 
⥪á⠮⮡ࠦ ¥âáï ?ª ª ¥áâì? ¡¥§ à §¡®à  Markdown:
```
#include <stdio.h>
#include <sprinter.h>
int main(void) {
puts("Hello, Sprinter!");
return 0;
}
```
### ƒ®à¨§®­â «ì­ ï «¨­¨ï
’ਠ¨«¨ ¡®«¥¥ ᨬ¢®«®¢ `---`, `***` ¨«¨ `___` ­  ®â¤¥«ì­®© áâப¥:
---
## ’¥å­¨ç¥áª¨¥ å à ªâ¥à¨á⨪¨
- **« âä®à¬ :** Sprinter, ¯à®æ¥áá®à Z80 @ 21 Œƒæ
- **Š®¤¨à®¢ª¨:** CP866 / CP1251 / KOI8-R / UTF-8 ( ¢â®®¯à¥¤¥«¥­¨¥, `F8`)
- **Œ ªá¨¬ «ì­ë© à §¬¥à ä ©« :** 128 Š
- **Œ ªá¨¬ «ì­®¥ ç¨á«® áâப ¢ ¨­¤¥ªá¥:** 16 384
- **Œ ªá¨¬ «ì­ ï ¤«¨­  áâப¨ ¢ ७¤¥à-ªíè¥:** 255 ï祥ª (á¬. ®£à ­¨ç¥­¨¥ ­¨¦¥)
- **¥¦¨¬ ¯ ¬ïâ¨:** small
- Š®¤ ¯à®£à ¬¬ë, c⥪, ¤ ­­ë¥, ªãç  ? ®ª­a W1-W2 (32 Š,  ¤à¥á  0x4000?0xBFFF).
- ãä¥à ä ©«  ? áâà ­¨æë EMM, ®â®¡à ¦ ¥¬ë¥ ¢ W3 (0xC000?0xFFFF)
## ˆ§¢¥áâ­ë¥ ®£à ­¨ç¥­¨ï
### „«¨­  áâப¨ ¢ MD-०¨¬¥ ? 255 ï祥ª
¥­¤¥à-ªíè åà ­¨â ª ¦¤ãî «®£¨ç¥áªãî áâப㠪 ª **­¥ ¡®«¥¥ 255 ¯ à (ᨬ¢®«,  âਡãâ)**
? ª®­áâ ­â  `MAX_CACHE_LINE_LEN`. ‹¨¬¨â § ¤ ­ ⨯ ¬¨: `g_ncells` ¨
`cache_rec_t.len` ? `uint8_t`. Š á ¥âáï ¢á¥å áâப, ­® § ¬¥â­¥¥ ¢á¥£® ­ 
**£®à¨§®­â «ì­® áªà®««¨à㥬ëå** áâப å (¡«®ª¨ ª®¤  ¨ áâப¨ â ¡«¨æ, ä« £
`IF_HSCROLL`), ª®â®àë¥ ¢ MD-०¨¬¥ ¬®¦­® «¨áâ âì ¢¯à ¢®.
**—â® ¯à®¨á室¨â á ¡®«¥¥ ¤«¨­­®© áâப®©:** ¯à¨ ¨­¤¥ªá æ¨¨ `gc_put()` ¬®«ç 
®â¡à á뢠¥â ª ¦¤ãî ï祩ªã ¯®á«¥ 255-© (`if (g_ncells < MAX_CACHE_LINE_LEN)`).
‚ ªíè ¯®¯ ¤ îâ ⮫쪮 ¯¥à¢ë¥ 255 ï祥ª, ®áâ â®ª **â¥àï¥âáï** ? ¤® ­¥£® ­¥«ì§ï
¤®áªà®««¨âì ¨ **­¥â ¬ àª¥à  ®¡à¥§ª¨** ­  255-© ¯®§¨æ¨¨ (¬ àª¥à `>` ®§­ ç ¥â «¨èì
?¥áâì ¥éñ ¢ ¯à¥¤¥« å ªíè ?). ¥à¥¯®«­¥­¨ï ¡ãä¥à  ­¥â ? `gc_put` ¯à®¢¥àï¥â £à ­¨æã.
‚ ¦­®: ?255 ï祥ª? ? íâ® **®â७¤¥à¥­­ ï è¨à¨­ **, ­¥ ¡ ©âë ¨á室­¨ª . ’ ¡ë ¢
ª®¤¥ à §¢®à ç¨¢ îâáï ¢ ¯à®¡¥«ë (¤® `TAB_STOP`),   ï祩ª¨ â ¡«¨æë ¤®¡¨¢ îâáï
¯à®¡¥« ¬¨ ¤® è¨à¨­ë ª®«®­ª¨ + à ¬ª¨ `³` ? ¯®í⮬㠪 ¯ ¤®á⨣ ¥âáï à ­ìè¥, 祬
255 ?¯®«¥§­ëå? ᨬ¢®«®¢.
> **RAW-०¨¬ (`F2`) í⮣® «¨¬¨â  ­¥ ¨¬¥¥â** ? ®­ à¨áã¥â ¯àאַ ¨§ ä ©« 
> ¯®¡ ©â®¢®, ¤«¨­­ë¥ áâப¨ ¢¨¤­ë 楫¨ª®¬ (ç¥à¥§ wrap `F3` ¨«¨ £®à¨§. áªà®««).
**ˆ¤¥ï á­ïâ¨ï «¨¬¨â ** (®æ¥­ª , ­¥ ॠ«¨§®¢ ­®) ? à áè¨à¨âì ¤«¨­ã ¤® `uint16_t`:
- `cache_rec_t.len` `uint8_t?uint16_t` ? áâàãªâãà  ®áâ ñâáï **஢­® 8 ¡ ©â**
(len áꥤ ¥â ®¤¨­ pad-¡ ©â),  ¤à¥á æ¨ï `idx<<3` ­¥ ¬¥­ï¥âáï. ¥á¯« â­®.
- `g_ncells` / `g_ncells_at_space` ? `uint16_t` ? £« ¢­ ï 業  ¯® **ª®¤ã/᪮à®áâ¨**:
16-¡¨â­ ï  à¨ä¬¥â¨ª  ­  Z80 ¢ £®àï祬 `gc_put` (¢ë§®¢ ­  ª ¦¤ãî ï祩ªã) ¨ ¢
scan-横« å. Žà¨¥­â¨à: **+0.2?0.4 Š ª®¤ ** + § ¬¥¤«¥­¨¥ ¨­¤¥ªá æ¨¨.
- ãä¥à `g_cells[MAX_CACHE_LINE_LEN*2]` ¢ near-RAM (W2) ? £« ¢­ ï 業  ¯®
**¯ ¬ïâ¨**: `2 ? ª ¯` ¡ ©â. ‘¥©ç á 510 ; ª ¯ 512 ? +0.5 Š, 1024 ? +1.5 Š.
EMM-ªíè ª®­â¥­â  (1 Œ) ¤«¨­­ë¥ áâப¨ âﭥ⠫¥£ª® ? 㧪®¥ ¬¥áâ® ¨¬¥­­® near.
- `viewport_x` (¨ ª®¯¨ï ¢ `docset_t`) + ¯®â®«®ª `max_vx` (ᥩç á 248) ? `uint16_t`,
¨­ ç¥ åà ­¨âì >255 ¬®¦­®,   ¤®áªà®««¨âì ­¥«ì§ï. «îá `widths[]`/`ccx` ¢ â ¡«¨æ å/ª®¤¥.
¥ «¨áâ¨ç­ë© ª®¬¯à®¬¨áá ? ª ¯ 512?1023: 墠â¨â ¯®ç⨠¢á¥¬ «¨á⨭£ ¬/â ¡«¨æ ¬,
業  ~+0.3 Š ª®¤  ¨ +0.5?1.5 Š near-RAM. **„¥èñ¢ ï ¯®«ã¬¥à  ¡¥§ `uint16_t`** ?
áâ ¢¨âì ç¥áâ­ë© ¬ àª¥à ®¡à¥§ª¨ ­  255-© ¯®§¨æ¨¨, çâ®¡ë ¯®â¥àï ¡ë«  ¢¨¤­ .
## TODO
1. **“¢¥«¨ç¥­¨¥ à §¬¥à  ¤®ªã¬¥­â®¢.** ‘­ïâì «¨¬¨â 128 Š: „®áâ â®ç­®
à §à¥è¨âì à ¡®â âì á ¡®«ì訬 ª®«-¢®¬ áâà ­¨æ ¯ ¬ïâ¨, ¯®ª  ®ââ¥áâ¨à®¢ ­­®
­  à ¡®â¥ á 8-¬î áâà ­¨æ ¬¨ ¯® 16Š¡.
‘¤¥« ­®: ä®à¬ â¨à®¢ ­­ë¥ â ¡«¨æë á à ¬ª®©; ¯®¤¤¥à¦ª  ª®¤¨à®¢®ª
CP866 / CP1251 / KOI8-R / UTF-8 á  ¢â®®¯à¥¤¥«¥­¨¥¬ ¨ ¯¥à¥ª«î祭¨¥¬ ¯® `F8`
(¢â®à®© ­ ¡®à áâநâáï «¥­¨¢®, ¯® ¯¥à¢®¬ã ¯¥à¥ª«î祭¨î).
4. **“᪮७¨¥ ७¤¥à¨­£ .** Šíè áâப íªà ­ . Ž¯â¨¬¨§ æ¨ï 横«  ¢ë¢®¤ 
ᨬ¢®«®¢ ç¥à¥§ BIOS WRCHAR (¯ ª¥â­ë© ¢ë¢®¤, DMA).
---
*MDView v0.2 ú (c) 2026 ¥â஢ €.ƒ.*
---
# Sprinter C Compiler ? v1.0
C toolchain for **Sprinter** ? the Z80-based home computer by Peters Plus, running
ESTEX DSS. Host: macOS / Linux. Target: `.EXE` files in SprintEXE format.
Built on top of **SDCC 4.5** (vendored in `third_party/sdcc/`). This repository adds
everything Sprinter-specific: crt0, linker integration, libc wrappers over ESTEX,
banked-call trampolines, graphics & accelerator API, mouse driver wrappers, and the
`mkexe` utility for producing SprintEXE images.
## What you get
* **`bin/sprinter-cc`** ? one-line driver: `sprinter-cc -o foo.exe foo.c`
* **Memory modes**: `tiny`, `small`, `big`, `huge`, `manual` ? see below.
* **stdio + conio**: printf, puts, putchar, getchar, fopen/fread/..., cprintf, cputs, putch, textcolor/textbackground/textattr, gotoxy, kbhit/getch.
* **Graphics**: 320?256?256 and 640?256?16 modes, accelerator-backed primitives (hline / vline / rect / fill_rect / line via Bresenham, plus clear), bitmap-font text in both modes via BIOS character generator.
* **File I/O**: POSIX (`open`/`read`/`write`/`close`/`lseek`/`unlink`/`creat`), FILE\* streams (`fopen`/`fgets`/`fwrite`/...), directory listing (`ffirst`/`fnext`), `chdir`/`getcwd`/`mkdir`/`rmdir`, `stat`/`fstat`.
* **Memory**: 32 KB heap (W2-resident), banking-aware page allocator (`mem_alloc_pages`/`bank_read`/`bank_write`), explicit memory modes for sub-16 KB programs.
* **Mouse**: full Sprinter driver wrapper (14 functions including custom cursor bitmaps).
* **Environment**: `getenv`/`putenv`/`sysenv` over ESTEX `$46`.
* **Time**: `getdatetime`/`setdatetime` + POSIX `time`/`localtime`/`mktime`/`asctime`/`ctime`.
* **Misc**: `errno`/`strerror`/`perror`, `atexit`, `setjmp`/`longjmp`, `sleep`, full argv parsing in crt0.
## Quick start
```sh
git clone <this repo> sprinter-c
cd sprinter-c
make sdcc # one-time: fetch SDCC 4.5 binary (~25 MB)
make all # build mkexe + libsprinter.lib + 27 examples
make floppy # pack everything into mame/v306/IMG/mc.img
cd mame/v306 && ./run_mame.sh # boot Sprinter in MAME
```
Compile a single program:
```sh
cat > hello.c <<EOF
#include <stdio.h>
int main(void) { puts("Hello, Sprinter!"); return 0; }
EOF
bin/sprinter-cc -o hello.exe hello.c
```
That's it ? `hello.exe` is now a valid SprintEXE you can `RUN HELLO` from the ESTEX shell.
## Memory modes
Sprinter's address space is four 16 KB windows (W0 / W1 / W2 / W3). DSS allocates
pages by program size ? small programs get only one page. Pick a memory mode based
on what your program needs:
| Mode | Code lives in | Banking | Use when | Note |
|---|---|---|---|---|
| `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB | |
| `small` | W1-W2 (0x4100+) | no | code+data < 30 KB | |
| `big` | W2 + W1 banking | yes (W1) | tiny + extra code modules | |
| `huge` | W1-W2 + W3 banking | yes (W3) | small + extra code modules | |
| `manual` | user-specified | optional | special layouts | Not implemented |
```sh
sprinter-cc --memory small -o big.exe bigprog.c
sprinter-cc --memory huge -o app.exe main.c --bank 1=engine.c --bank 2=ai.c
```
Banked functions are declared with `__banked`:
```c
void engine_tick(int dt) __banked; // lives in BANK1, automatically swapped
```
## Examples (27 total)
| Example | What it demonstrates |
|---|---|
| `hello` | Hello world with stdio + conio Turbo-C-style colors |
| `argv` | argv parsing in crt0 |
| `cat` | File I/O ? read & print TEST.TXT |
| `seek` | 32-bit lseek over a 100 KB file |
| `ls` | Directory listing via ffirst/fnext |
| `filetest` | FILE\* streams (fopen/fread/...) |
| `stattest` | `stat`/`fstat` on files and directories |
| `errno` | errno / strerror / perror |
| `mem_test` | Page allocator + bank\_read/bank\_write |
| `malloc` | Heap stress test (200+ allocations) |
| `banked` | Banked code in W3 (huge mode) |
| `bankedbg` | Banked code in W1 (big mode) |
| `banklocl` | Bank-local static data and BSS |
| `mouse` | Mouse driver in text mode |
| `gfx_mous` | Mouse with custom bitmap cursor in graphics mode |
| `gfx_demo` | 320?256?256 lines / rects / accelerator |
| `gfx_d16` | 640?256?16 same primitives |
| `gfx_text` | Bitmap-font text on graphics screen |
| `timedir` | Date/time + directory listing |
| `ptime` | POSIX time API |
| `openenv` | open() flags + environment vars |
| `conio` | conio API smoke test |
| `attrprob` | Probe Sprinter text attribute byte layout |
| `strtest` | string.h test (from SDCC's z80.lib) |
| `stdlib` | stdlib.h test (qsort / rand / strtol / etc.) |
| `assrtest` | assert() |
| `rt_test` | Runtime helpers (sleep, setjmp, atexit) |
## Headers
Standard:
* `<stdio.h>` ? puts / printf / FILE\* + Sprinter-specific dec/hex helpers
* `<stdlib.h>` ? atoi / atof / malloc / qsort / ... (from SDCC z80.lib)
* `<string.h>` / `<ctype.h>` / `<math.h>` ? from SDCC z80.lib
* `<unistd.h>` ? read / write / close / lseek / unlink
* `<fcntl.h>` ? open / creat + O\_RDONLY / O\_CREAT / ...
* `<errno.h>` ? errno + error names + strerror
* `<sys/stat.h>` ? stat / fstat
* `<setjmp.h>` / `<assert.h>` ? from SDCC
Sprinter-specific:
* `<conio.h>` ? putch / cputs / cprintf, textcolor / textbackground / textattr, kbhit / getch, clrscr, gotoxy, wherex/y
* `<gfx.h>` ? gfx_init/done, palette, putpixel, hline/vline/rect/fill_rect/line, text ? for both 320 and 640 modes (gfx_\*16 variants)
* `<mouse.h>` ? full 14-function driver wrapper + mouse_cursor_t with bitmap support
* `<dir.h>` ? chdir / getcwd / mkdir / rmdir / ffirst / fnext / ffblk
* `<time.h>` ? getdatetime / setdatetime + POSIX time / localtime / etc.
* `<sprinter.h>` ? raw ports, ESTEX/BIOS function numbers, env API
* `<sprinter_exit.h>` ? exit / \_exit / atexit
* `<sprinter_mem.h>` ? mem\_alloc\_pages / mem\_free\_block / bank\_read / bank\_write
* `<sprinter_compat.h>` ? Solid-C compatibility layer (aliases + BOOL/WORD/uint types)
## Toolchain commands
```sh
make all # build mkexe + lib + every example
make floppy # repack mame/v306/IMG/mc.img with all .exe files
make check # 17 mkexe unit-tests
make clean # remove all build artefacts
make sdcc # one-time: fetch SDCC 4.5 binary
```
### sprinter-cc options
```
sprinter-cc -o foo.exe foo.c [more.c ...] [options]
--memory MODE tiny | small | big | huge | manual (default: tiny)
--memory-manual SPEC explicit placement (CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3)
--stack-size N bytes reserved for the stack (default ~1278)
--crt0=TYPE default | minimal | banked | small
--bank N=FILE.c compile FILE.c into bank N (repeatable, max 15)
--debug enable runtime diagnostics (defines DEBUG_RT)
-I PATH extra include path
-L 0xADDR / -E / -S override load / entry / stack addresses
-Wl FLAG pass FLAG to sdldz80
--mkexe FLAG pass FLAG to mkexe (e.g. --mkexe -p --mkexe 0 for bank padding)
-v verbose
```
## Status
What works in v1.0:
* Compile / link / pack to SprintEXE ? verified on all 27 examples
* Four memory modes (tiny / small / big / huge)
* Graphics (both modes) with accelerator
* Mouse (text + graphics cursor)
* File I/O, directories, environment, time
* All headers listed above
Deferred to v2.0 (see `docs/TODO.md`):
* **Turbo-C-style BGI graphics API** ? `initgraph` / `setcolor` / `circle` /
`getimage` / `putimage` / etc. on top of our `gfx_*` primitives
* Remaining Solid-C compatibility gaps (Phase 2/3) ? see `docs/solid_c_compatibility.md`
* Manual memory mode
* Rewrite FILE\* stream API (current implementation is very primitive and doesn't use buffers)
Deferred to v3.0:
* **IM2 interrupt handlers** ? research complete (`docs/im2_isr_design.md`),
implementation scheduled for v3
* **Audio API** (AY-3-8910 + COVOX) ? requires IM2
* **ISA-8 slot drivers** ? requires IM2 (???)
## Documentation
* `docs/TODO.md` ? roadmap and open work items
* `docs/solid_c_compatibility.md` ? gap analysis vs Solid-C 2004
* `docs/im2_isr_design.md` ? interrupt handler design (v2)
* `docs/converted/` ? source documentation (ESTEX, BIOS, architecture)
converted to plain text for `grep`
* `docs/reference/`, `docs/samples/`, `docs/memory management/` ? original
Russian docs and code samples from Peters Plus
## Repository layout
```
bin/sprinter-cc one-line compiler driver (bash)
toolchain/mkexe/ host-side tool: .ihx -> .exe SprintEXE
toolchain/check_banks.py post-link bank size enforcer
runtime/ crt0 variants (default, minimal, small, banked)
bank trampolines, heap, heap_top
libc/include/ headers
libc/io|stdio|mem|gfx/ C and asm sources for libsprinter.lib
lib/ Makefile that archives libsprinter.lib via sdar
examples/ 27 example programs
mame/v306/ MAME binary + Sprinter ROM/HDD images + floppy script
third_party/sdcc/ vendored SDCC 4.5 (fetched via `make sdcc`)
third_party/solid-c/ reference: original Sprinter native C (for compat target)
docs/ documentation
```
## License
This repository contains:
* Original code in `bin/`, `toolchain/`, `runtime/`, `libc/`, `lib/`, `examples/` ?
MIT-licensed.
* `third_party/sdcc/` ? SDCC 4.5 under GPLv2 with linking exception
(see `third_party/sdcc/COPYING.txt`)
* `third_party/solid-c/` ? original Sprinter Solid C, used only as a reference
## Credits
* **Sprinter / Peters Plus** ? ˆ¢ ­ Œ ª, „¬¨â਩  à¨­®¢ and the original team
* **SDCC** ? for the underlying Z80 compiler
* **MAME** ? for the Sprinter Sp2000 emulation
---
For questions / patches: see CONTRIBUTING.md (TBD) or open an issue.
---
# TODO / Roadmap
Žâªàëâë¥ § ¤ ç¨ ¢ ¯®à浪¥ ã¡ë¢ ­¨ï ¯à¨®à¨â¥â . ® ¬¥à¥ ¯®ï¢«¥­¨ï ॠ«ì­ëå ¯à®£à ¬¬ ? ¯à¨®à¨â¥âë ¡ã¤ãâ ᬥé âìáï.
## â ¯ 5 ? malloc / free + banking-aware page allocator ? ƒŽ’Ž‚Ž
- [x] SDCC's `malloc`/`free` + ­ è `runtime/heap.s` (¯®«­®áâìî § ¬¥­ï¥â library heap.rel, 14000-¡ ©â­ë© heap ¢ ®ª­¥ 2)
- [x] `libc/mem/mem_alloc.c` ? page allocator: `mem_alloc_pages`/`mem_free_block`/`mem_get_page`/`mem_info` ç¥à¥§ ESTEX `$3C/$3D/$3E` + BIOS `$C4`
- [x] `libc/mem/bank_io.c` ? HOME-१¨¤¥­â­ë¥ `bank_read`/`bank_write`/`bank_load_byte`/`bank_store_byte` ᮠ᢮¯®¬ W3 ¢­ãâà¨
- [x] `examples/malloc_test/` ? ¯à®¢¥àª  SDCC's malloc (~210 64-¡ ©â­ëå allocations ç¥à¥§ ¢áî heap)
- [x] `examples/mem_test/` ? ¯à®¢¥àª  page allocator: 3 áâà ­¨æë, à §­ë¥ ¯ ââ¥à­ë ç¥à¥§ bank_write, ¢¥à¨ä¨ª æ¨ï ç¥à¥§ bank_read
## â ¯ 6 ? argv parsing + sprinter-cc wrapper ? ƒŽ’Ž‚Ž
- [x] crt0 ¯ àá¨â ESTEX command-line ¨§ IX-prefix (inline asm ¢ `runtime/crt0.s`)
- [x] Strip leading CP/M-style space (DSS quirk)
- [x] ¥à¥¤ ç  `argc`/`argv` ¢ main() ç¥à¥§ HL/DE (SDCC __sdcccall(1) ABI)
- [x] argv[0] = basename .EXE ç¥à¥§ ESTEX APPINFO ($47 subfn 2)
- [x] `runtime/crt0_minimal.s` ? opt-out ¤«ï ®ç¥­ì ¬ «¥­ìª¨å ¯à®£à ¬¬
- [x] `runtime/crt0_banked.s` ? ⥯¥àì ⮦¥ ¯ àá¨â argv (parse_argv + get_progname ᪮¯¨à®¢ ­ë ¨§ crt0.s; ¡ã¤¥â factored ¢ argv.s ª®£¤  ¢®§ì¬ñ¬áï §  libsprinter.lib)
- [x] Bash-®¡ñà⪠ `bin/sprinter-cc`: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨©: `--memory`, `--memory-manual`, `--stack-size`, `--crt0=`, `--bank N=FILE.c`, `--debug`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
## â ¯ 8 ? £à ä¨ª  (320?256?256 + 640?256?16 + accel + bitmap font) ? ƒŽ’Ž‚Ž
- [x] **8a** Graphics core: `gfx_init`/`gfx_done`/`gfx_clear`/`gfx_putpixel`/`gfx_pal_load`/`gfx_pal_set` (libc/gfx/gfx_core.c).  «¨âà  ç¥à¥§ BIOS PIC_SET_PAL ($A4). Verified 320?256?256.
- [x] **8b** ‹¨­¨¨/¯àאַ㣮«ì­¨ª¨/fill ç¥à¥§ accelerator (libc/gfx/gfx_lines.c): `gfx_hline`/`gfx_vline` ç¥à¥§ accel Fill (LD C,C / LD E,E + SMC block-size), `gfx_rect`/`gfx_fill_rect` á heuristic ¢ë¡®à®¬ ®à¨¥­â æ¨¨ (h/v bursts count), `gfx_line` á Bresenham ¤«ï ¤¨ £®­ «¥©. `gfx_clear` ⮦¥ ¯¥à¥¯¨á ­ ­  column-major accel (~4? ¡ëáâ॥).
- [x] **8c** 640?256?16 mode (libc/gfx/gfx_16.c): `gfx_*16` API, HIGH nibble = LEFT pixel (¤®ªã¬¥­â æ¨ï misleading), per-row RMW ¤«ï vline (®¤¨­ ¡ ©â = 2 £®à¨§®­â «ì­ëå ¯¨ªá¥«ï).
- [x] **8d** Bitmap font + gfx_text (libc/gfx/gfx_text.c): èà¨äâ ç¥à¥§ BIOS WIN_GET_ZG ($B8), interleaved layout `font[row*256+char]`, `gfx_text`/`gfx_putchar` ¤«ï 320 mode, `gfx_text16`/`gfx_putchar16` ¤«ï 640 mode á pair-table lookup.
‘¬. memory/sprinter_graphics.md, sprinter_accelerator.md, sprinter_graphics_16.md, sprinter_font_format.md.
Žâªàëâë¥ ¬¥«®ç¨ (­¥ ¡«®ª¨àãîâ):
- [ ] ˜à¨äâ-quad ¤«ï 640: per-cell ¯ «¨âà  (mode 0x82 à §à¥è ¥â 1 ¨§ 4 ¯ «¨âà per 16?8 cell) ? ç¥à¥§ ¯àאַ© ¤®áâ㯠ª area-®¯¨á ­¨ï íªà ­  0x0300..0x039F
## Auto-banking (á¬. `memory/banking_roadmap.md` ¤«ï ¤¥â «¥©)
Phase 1 ? file-level bin-packing ? ॠ«¨§®¢ë¢ âì ª®£¤  ¯à®¥ªâ ¯¥à¥à áâñâ ~30 KB ª®¤ .
- [ ] `toolchain/auto_bank.py`:
-  àá¨â à §¬¥àë ¨§ `.rel`-ä ©«®¢ (¨«¨ ¨§ .map ¯®á«¥ dry-run link' )
- First-fit-decreasing bin-packing
- “¢ ¦ ¥â `#pragma codeseg BANKn` ª ª manual override
- ¥à¥«¨­ª®¢ë¢ ¥â á ­®¢ë¬¨ `-Wl-b_BANKn=...` ¯ à ¬¥âà ¬¨
- ¥ç â ¥â ¯« ­ à á¯à¥¤¥«¥­¨ï
Phase 2-5: incremental rebalance, declarative `banks.toml`, function-level, call-graph-aware. ’®«ìª® ¥á«¨/ª®£¤  ¯®­ ¤®¡¨âáï.
## Bank-local static data (mutable data ¢ ⮬ ¦¥ ¡ ­ª¥ çâ® ¨ ª®¤) ? ? ƒŽ’Ž‚Ž
- [x] ਬ¥à `examples/bank_local_data/` ? äã­ªæ¨ï ¢ BANK1 ᮠ᢮¨¬ writable BSS array + const table + malloc-â¥áâ
- [x] `mkexe -p 0` ¤«ï ­ã«¥¢®£® padding ¡ ­ª®¢ (BSS-storage ®¡­ã«ï¥âáï ¯à¨ § £à㧪¥)
- [x] Š ­®­¨ç¥áª¨© à¥æ¥¯â: `--codeseg BANK1 --constseg BANK1 --dataseg BANK1` ¤«ï bank1.c + `-Wl-b_BANK1=0x1C000` ¤«ï «¨­ª®¢ª¨. **`--dataseg BANK1` Ž’€…’** ? à ­ìè¥ ª § «®áì ®¡à â­®¥ ¨§-§  trampoline bug ª®â®àë© ¬ áª¨à®¢ « १ã«ìâ â.
- [x] **Šà¨â¨ç­ë© 䨪á trampoline'a ¢ runtime/bank.s** ? áâ àë© `pop af; out (n), a` ª«®¡¡¥à¨« A ? ¢á¥ banked-ä㭪樨 ¢®§¢à é î騥 uint8_t â¨å® ¢®§¢à é «¨ ¬ãá®à. ®¢ë© `pop bc; out (c), b` á®åà ­ï¥â A.
- [x] **malloc ¨§ banked-ä㭪樨 à ¡®â ¥â ¯à®§à ç­®** ? heap ¦¨¢ñâ ¢ W2 (HOME), W2 ­¨ª®£¤  ­¥ ᢠ¯ ¥âáï trampoline'®¬, pointer ¢ «¨¤¥­ ¨§ «î¡®£® ª®­â¥ªáâ . ‘¬. memory/bank_local_data_pattern.md.
- [x] „®ªã¬¥­â æ¨ï ¢ memory: `memory/bank_local_data_pattern.md` (¯®«­ë© à¥æ¥¯â + malloc + nuances), `memory/sdcc_banking.md` (trampoline fix)
- [ ] Ž¯æ¨®­ «ì­® ? à áè¨à¨âì `check_banks.py` çâ®¡ë ¯®ª §ë¢ âì à §¡¨¢ªã size = code + const + bss per bank (cosmetic)
‡ ç¥¬: ¤«ï ¬®¤ã«¥© á ¡®«ì訬 private state (level loader, audio engine, scene data). ª®­®¬¨â W2 heap ¤«ï ¤¨­ ¬¨ª¨,   áâ â¨ª  ®áâ ñâáï ¢ ¡íª¥.
## ®¤áª §ª¨ ¨§ solid-c (­ â¨¢­ë© Sprinter C ? `third_party/solid-c/`)
®á«¥  ­ «¨§  solid-c'®¢áª®© libc (á¬. `memory/solid_c_findings.md`) ¢ë¥­ë £®â®¢ë¥ ¯ ââ¥à­ë ¤«ï á«¥¤ãîé¨å ­¥¤®áâ îé¨å ä㭪権. ਮà¨â¥â ®â **¢ë᮪®£®** ª ­¨§ª®¬ã:
### High-priority gaps («¥£ª® ¯®àâ¨à®¢ âì, ¡®«ìè ï ¯®«ì§ )
- [x] **`errno` + `strerror`/`perror`** ? â ¡«¨çª  32 ®è¨¡®ª (libc/io/errno.c)
- [x] ** áè¨à¥­­ë© `open()`** ¤«ï O_CREAT/O_TRUNC/O_APPEND/O_EXCL state machine
- [x] **`atexit`** ? 8-callback LIFO + `exit()` + `_exit()` (libc/io/atexit.c)
- [x] **`setjmp`/`longjmp`** ? 6-¡ ©â jmp_buf={sp,ix,pc} (libc/io/setjmp.c)
- [x] **`sleep(seconds)`** ? 50Hz halt-loop (libc/io/sleep.c)
- [x] **ESTEX ENV API** ($46, getenv/putenv) ? libc/io/env.c. “竨 doc-bug: ॠ«ì­® A=0 íâ® NOT FOUND
### Medium-priority (­ã¦­® ¤«ï shell-like ã⨫¨â)
- [ ] **Mouse driver** ? `rst $30h`, 17 ä㭪権. **‘­ ç «  â¥áâ çâ® à ¡®â ¥â ¢ MAME**.
- [x] **`ffirst`/`fnext` + ffblk_t struct** ¤«ï directory listing ? ॠ«¨§®¢ ­®, demo: ls.exe
- [x] **`getdatetime`/`setdatetime`** ç¥à¥§ ESTEX $21/$22 ? libc/io/time.c, demo: time_dir_test
- [x] **`chdir`/`getcwd`/`mkdir`/`rmdir`** ? wrappers ¤«ï ESTEX $1B-$1E ? libc/io/fsdir.c
- [x] **conio: `kbhit`/`getch`/`getche`/`cputs`/`clrscr`/`gotoxy`** ? ॠ«¨§®¢ ­®
- [x] **conio extras**: `wherex`/`wherey` ($53), `wrchar`/`rdchar` ($58/$57), `textmode_get/set` ($50/$51), `clrscr_attr` ($56) + COLOR macros
### Low-priority ? ? FILE* stack ƒŽ’Ž‚Ž
- [x] **Œ¨­¨¬ «ì­ë© unbuffered FILE\*** ? `libc/stdio/file.c` + `libc/include/stdio.h`. fopen/fclose/fputs/fgets/fread/fwrite/fseek/ftell/rewind/feof/ferror/clearerr/fflush + stdin/stdout/stderr ª ª pseudo-streams. ‘¬. `memory/file_star_design.md` ¨ `examples/filetest`.
- [ ] fprintf / fscanf ? ­ã¦­  printf-ç¥à¥§-callback machinery. ®ª  ¯®«ì§®¢ â¥«ì ¬®¦¥â `sprintf(buf, ...) + fputs(buf, fp)`.
- [ ] Ž¯æ¨®­ «ì­ë© buffered mode (setvbuf, line/block buffering) ? ¥á«¨ ª®£¤ -â® ¯®­ ¤®¡¨âáï.
### POSIX time API ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/posix_time.c` ? time/localtime/gmtime/mktime/asctime/ctime ¯®¢¥àå getdatetime. SDCC's time.rel ¨§¡¥£ ¥¬ (­¥«ì§ï override _RtcRead). ‘¬. `examples/ptime`.
### sys/stat ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/stat.c` ? POSIX stat/fstat. ƒ¨¡à¨¤ open+fstat ¤«ï ä ©«®¢, ffirst+iter ¤«ï ¯ ¯®ª (¢ª«îç ï "."/".."). ‘¬. `examples/stattest` ¨ `memory/estex_ffirst_dotdot.md`.
### assert ? ? ƒŽ’Ž‚Ž (¨á¯®«ì§ã¥¬ SDCC's __assert ç¥à¥§ fallback include path)
## libc/stdlib ? ? ­¥ ­ã¦­® ¤¥« âì (á¬. memory/sdcc_stdlib_works.md)
஢¥à¥­® ç¥à¥§ `examples/stdlib_test/`: SDCC z80.lib ᮤ¥à¦¨â à ¡®â î騥 ॠ«¨§ æ¨¨:
- `atoi/atol/atof, strtol/strtoul, rand/srand, qsort/bsearch, abs/labs, div/ldiv`
- ®«­ë© `<string.h>` (memchr/cmp/set/cpy, strcat/cmp/cpy/len/chr/spn/etc.)
- `<ctype.h>` (toupper/tolower)
- `<math.h>` (sinf/cosf/sqrtf/etc.)
‹¨­ª¥à  ¢â®¬ â¨ç¥áª¨ âﭥ⠨§ z80.lib ª®£¤  ­ã¦­®. **… ¯¥à¥¯¨á뢠âì**.
 è¨ Sprinter-specific ®¡ï§ â¥«ì­ë¥ ¬®¤ã«¨ ®áâ îâáï: atexit, env, errno, setjmp, putchar/puts/getchar, conio, fsdir, time, mouse, open/read/lseek/close.
## Build-system: libsprinter.lib + sprinter-cc ? ? ƒŽ’Ž‚Ž
- [x] `lib/Makefile` ? ᮡ¨à ¥â ª ¦¤ë© libc/*.c ¢ `.rel`,  à娢¨àã¥â ç¥à¥§ sdar ¢ `lib/sprinter.lib`
- [x] ‚ª«îç ¥â runtime/bank.s ¨ runtime/heap.s (auto-pulled ¯à¨ __banked/malloc)
- [x] `bin/sprinter-cc` ? bash-wrapper: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨© `--crt0=default|minimal|banked`, `--bank N=FILE.c`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
- [x] `examples/hello_sccc/` ? ¤¥¬®: `hello.c` ᮡ¨à ¥âáï §  ®¤¨­ shell-¢ë§®¢, à §¬¥à ᮢ¯ ¤ ¥â á àãç­ë¬ Makefile (925 ¡ ©â)
- [x] Split `putchar.c` ? `putchar.c` + `puts.c` ¤«ï per-function granularity (puts override SDCC's z80.lib version)
- [x] ‚ª«îçñ­ ¢ `make all` (§ ¢¨á¨¬®áâì `lib` ¯¥à¥¤ `examples`)
‚®§¬®¦­ë¥ ã«ãç襭¨ï (®¯æ¨®­ «ì­®):
- [ ] Œ¨£à¨à®¢ âì ®áâ «ì­ë¥ examples ­  sprinter-cc ¢¬¥áâ® àãç­ëå Makefile (ª®á¬¥â¨ª )
- [ ] „ «ì­¥©è ï ¤¥ª®¬¯®§¨æ¨ï libc/*.c per-function (­® ⥪ãé ï granularity 㦥 ¤ ñâ ­ã¦­ë© à §¬¥à ? «¨­ª¥à ¯ ª¥âã¥â .rel 楫¨ª®¬, ¨ ¤«ï ¡®«ì設á⢠ ä ©«®¢ íâ® ®¤­  äã­ªæ¨ï)
## â ¯ 9 ? memory modes ¤«ï sprinter-cc
DSS ¢ë¤¥«ï¥â áâà ­¨æë ¯ ¬ï⨠¯® à §¬¥à㠯ਫ®¦¥­¨ï: < 16 KB ? ®¤­  áâà ­¨æ , ¢ ®áâ «ì­ë¥ ®ª­  ¯®¤ª«îç ¥âáï ?áâà ­¨æ  #FF? (read=0xFF, write ¨£­®à¨âáï). ˆ§-§  í⮣® CODE-¢-W1 + DATA-¢-W2 ¤«ï ¬ «¥­ìª®© ¯à®£à ¬¬ë ¬®«ç  «®¬ ¥âáï. ‘¬. [memory/sprinter_memory_modes.md](../../.claude/projects/-Volumes-SAM8-Projects-DIY-Z80-Sprinter-C-Compiler/memory/sprinter_memory_modes.md).
- [x] **`tiny`**: ¢áñ (CODE+DATA+á⥪) ¢ W2. Default. Verified hello/argv/conio/malloc/file/etc.
- [x] **`--memory MODE` ä« £ ¢ sprinter-cc**: parser + per-mode ¤¥ä®«âë CODE_LOC/DATA_LOC, override ç¥à¥§ ï¢­ë¥ `--code-loc`/`--data-loc`. tiny à ¡®â ¥â; small/big/huge ª®¬¯¨«¨àãîâáï á warning'®¬ (runtime ­¥ £®â®¢). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--memory-manual SPEC`**: ¯ àá¨â `CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`small` runtime**: `runtime/crt0_small.s` ¨á¯®«ì§ã¥â ESTEX `$3D GETMEM` + `$3A SETWIN2` çâ®¡ë ¢ë¤¥«¨âì ¨ § ¬ ¯¨âì W2-áâà ­¨æã „Ž gsinit. **…** BIOS `$C4` ? á⥪ ­  í⮬ íâ ¯¥ ¢ W1 (boot_stack ¢ HOME),   BIOS âॡã¥â á⥪ ¢ W2. ®á«¥ ¬ ¯¯¨­£  SP ¯¥à¥ª«îç ¥âáï ­  0xBFFE, ¤ «ìè¥ áâ ­¤ àâ­ë© flow. ¥ «¨§®¢ ­® 2026-05-30, verified hello.exe.
- [x] **`small` auto-detect ¤«ï >16 KB ¯à®£à ¬¬**: `crt0_small.s` ç¨â ¥â ¯®àâ `0xC2` (⥪ãé ï áâà ­¨æ  ¢ W2 ? ­¥ `0xA2`! íâ® W1). …᫨ 0xFF ? ¢ë¤¥«ï¥â page; ¨­ ç¥ DSS 㦥 ᤥ« «  íâ® (¯à®£à ¬¬  á ¬  ¢ë«¥§«  ¢ W2). ޤ¨­ crt0 ¯®ªà뢠¥â 0..30 KB. mkexe â ª¦¥ à §à¥è ¥â HOME span W1+W2 (0x4000..0xBFFF). Verified hello: small (5 KB ä ©«, SETWIN2 path) + 32 KB ä ©« (auto-skip). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`big` runtime** (tiny + banked code ¢ W1): ¯ à ¬¥âਧ®¢ «¨ `crt0_banked.s` + `bank.s` ç¥à¥§ `.ifdef BANK_W1` ? ¤à㣮© banking port (0xA2 vs 0xE2), ¤à㣮© load-addr (0x4000 vs 0xC000). sprinter-cc prepend'¨â `BANK_W1 = 1` ¯à¨ `--memory big`, ¯¥à¥¤ ñâ `mkexe -B 0x4000`. ਬ¥à `examples/banked_big/`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`huge` runtime** (small + banked code ¢ W3): merge W2-detect «®£¨ª¨ ¨§ `crt0_small.s` ¢ `crt0_banked.s`. ‘ãé¥áâ¢ãî騩 ¯à¨¬¥à `examples/banked/` ⥯¥àì ¨á¯®«ì§ã¥â MEMORY=huge. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--debug` ä« £**: prepend `DEBUG_RT = 1` ¢ crt0 + `-DDEBUG_RT` ¢ sdcc. Žâªà뢠¥â symbol `_w2_self_allocated` (uint8_t) ? runtime diagnostic ªâ®  ««®æ¨à®¢ « W2. ¥ «¨§®¢ ­® 2026-05-30.
### „¨§ ©­-à¥è¥­¨ï ¯® libc ¨ crt0
**ޤ­  `sprinter.lib`** à ¡®â ¥â ¤«ï ¢á¥å memory mode ? `.rel`-ç«¥­ë relocatable, SDLD ¤¥« ¥â dead-code elimination per-member (¡¥§ £à ä¨ª¨ ­¥ ¯®¤â¢ ¥â `gfx_core.rel` ¨ â.¤.). Verified hello vs malloc_test ç¥à¥§ map-ä ©«ë.
**`gfx.lib` ®â¤¥«ì­® ? … ­ã¦¥­**: dead-code elimination 㦥 à ¡®â ¥â.
**`libc_banked` (libc ¢ bank ¢¬¥áâ® HOME)** ? ¨¤¥ï ­  ¯®â®¬, ª®£¤  HOME (16 KB) § ¡¨â user-ª®¤®¬ + libc ¢ `huge` mode. ¥ «¨§ã¥âáï ç¥à¥§ `--codeseg BANK0` ¯à¨ ª®¬¯¨«ï樨 libc; trade-off: trampoline ~30 横«®¢ ­  ª ¦¤ë© libc-¢ë§®¢. ’ਣ£¥à: ॠ«ì­ ï ¯à®£à ¬¬  ã¯àñâáï ¢ HOME budget.
**HW-§ ¢¨á¨¬ë¥ ¬®¤ã«¨ ? `sprinter_home.lib` ®â¤¥«ì­®.** — áâì libc 䨧¨ç¥áª¨ ­¥ ¬®¦¥â ¡ëâì § ¡ ­ª®¢ ­  ¢ W3, ¯®â®¬ã çâ® ®­  Ž’€…’ á W3:
- `gfx_*` ? ¯¨è¥â ¢ ¢¨¤¥®¯ ¬ïâì `0xC000+` ¯®á«¥ swap W3 ­  video page
- `bank_io` (mem_alloc_pages/bank_read/bank_write) ? swap'¨â W3 ç¥à¥§ `OUT (0xE2)`
- ã¤ã騥 ISR ? ¯à¥à뢠­¨¥ ¬®¦¥â ¯à¨©â¨ ª®£¤  W3 ­  çñ¬ 㣮¤­®
‚ huge mode í⨠¬®¤ã«¨ „Ž‹†› ®áâ âìáï ¢ HOME (W1). Š®£¤  ¡ã¤¥¬ ¤¥« âì `libc_banked`, **®¤­®¢à¥¬¥­­®** ¢ë¤¥«ï¥¬ `sprinter_home.lib` (HOME-only) ¨§ `sprinter.lib` (bankable). ”¨­ «ì­ ï á奬 :
```
sprinter_home.lib HOME-only: gfx, bank_io, ISR shims
sprinter.lib bankable: printf, malloc, string, conio, stdio, env, ...
sprinter_banked.lib â®â ¦¥ sprinter.lib ­® --codeseg BANK0 (¤«ï huge)
```
’ਣ£¥à: ॠ«¨§ æ¨ï `--memory huge` runtime.
**crt0 ? ¯® ®¤­®¬ã ­  mode:**
- `crt0.s` ? ⥪ã騩, ¤«ï **tiny/big**: SP=0xBFFE, ¯ àá¨â argv (W2-à¥áãàá 㦥 ¢ë¤¥«¥­ DSS).
- `crt0_minimal.s` ? ⥪ã騩, ¤«ï tiny ¡¥§ argv.
- `crt0_small.s` ? **­®¢ë©, step 3**: ¤«ï **small/huge**,  ««®æ¨àã¥â W2 ç¥à¥§ `mem_alloc_pages` „Ž gsinit, ¬ ¯¯¨â ¢ ¯®àâ `0xA2`, ¯®â®¬ áâ ­¤ àâ­ë© flow.
- `crt0_banked.s` ? ⥪ã騩, ¤«ï **big**: trampoline-â ¡«¨æ  ¤«ï W3 ¡ ­ª®¢, CODE ¢ W2.
- `crt0_banked_small.s` ? **­®¢ë©**: huge = small (W2-alloc) + banked (W3 trampolines).
sprinter-cc ¯®¤¡¨à ¥â crt0 ¯® `--memory` mode (ᥩç á `--crt0=` íâ® override).
- [x] ** áâà ¨¢ ¥¬ë© à §¬¥à á⥪ **: ä« £ `sprinter-cc --stack-size BYTES`. Wrapper £¥­¥à¨àã¥â `heap_top.s` á `___sdcc_heap_end = stack_top + 1 - stack_size`, ®â¤¥«ì­ë© .rel «¨­ªã¥âáï per-program. Default ?1278 ¡ ©â (heap_top=0xBB00) ¨§ `runtime/heap_top.s`. ¥ «¨§®¢ ­® 2026-05-30.
ˆ­â¥à䥩á: `sprinter-cc --memory [tiny|small|big|huge|manual] [--memory-manual SPEC] [--stack-size N] foo.c`. `--memory-manual` ¨¬¥¥â á¬ë᫠⮫쪮 á `--memory manual`.
## Known issues / quirks
- **ESTEX $46 ENV API**: ? à ¡®â ¥â. „®ª-æ¨ï ¢ `DiskSyscalls.txt v1.6` ®è¨¡®ç­® ®¯¨á뢠¥â return-status ? A=0 íâ® NOT FOUND, ­¥ FOUND. ‡ ä¨ªá¨à®¢ ­® ¢ `memory/sprinter_platform.md`.
## ŽŸ‡€’…‹œ›… ‡€„€—ˆ „‹Ÿ V2 (¯®á«¥ ५¨§  v1)
### Turbo-C-style graphics API (BGI-like) ? **MUST ¤«ï v2**
 áè¨à¨âì ­ è `gfx_*` API ¤® ã஢­ï **Turbo-C `<graphics.h>`** (BGI) ¤«ï MS-DOS.
ணࠬ¬¨áâë ¯à¨¢ëªè¨¥ ª Turbo-C ¤®«¦­ë ¯¥à¥­®á¨âì £à ä¨ç¥áª¨© ª®¤ 1-¢-1.
**—â® ¤®«¦­® ¡ëâì** (­  ®á­®¢¥ Borland BGI):
Setup/teardown:
- `initgraph()` / `closegraph()` ? ã ­ á ᥩç á `gfx_init`/`gfx_done`, ¤®¡ ¢¨âì alias
- `getmaxx()` / `getmaxy()` ? ¬ ªà®á ­  GFX_WIDTH-1 / GFX_HEIGHT-1
- `cleardevice()` ? alias to gfx_clear
- `getgraphmode()` / `setgraphmode()` ? ã ­ á get_videomode/set_videomode
Color/palette:
- `setcolor(c)`, `getcolor()` ? current draw color
- `setbkcolor(c)`, `getbkcolor()` ? background color
- `setpalette(idx, c)` ? ¯ «¨âà  entry
- `getpalette(&info)` ? read all palette
Primitives (¬ë 㦥 ¨¬¥¥¬ íª¢¨¢ «¥­âë ? ¤®¡ ¢¨âì BGI-¨¬¥­  ª ª aliases):
- `putpixel(x, y, c)` ? ¥áâì ª ª gfx_putpixel
- `getpixel(x, y)` ? ­ã¦­® ॠ«¨§®¢ âì (RMW ®¡à â­®¥ ? IN)
- `moveto(x, y)`, `lineto(x, y)`, `linerel(dx, dy)` ? current point + line drawing
- `line(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_line
- `rectangle(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_rect (­® ¤à㣮© API: x1,y1,x2,y2 vs x,y,w,h!)
- `bar(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_fill_rect
- `bar3d(x1, y1, x2, y2, depth, topflag)` ? ­®¢®¥: rect + 3d edges
- `circle(x, y, r)`, `arc(...)`, `ellipse(...)`, `pieslice(...)` ? ­®¢ë¥ primitives
- `fillpoly()`, `drawpoly()` ? ¯®«¨£®­ë
- `floodfill(x, y, border_color)` ? § «¨¢ª 
Text on graphics screen:
- `outtext(s)` / `outtextxy(x, y, s)` ? ¥áâì ª ª gfx_text (alias)
- `settextstyle(font, dir, size)` ? multiple bitmap fonts
- `gettextsettings(&info)`
- `textwidth(s)` / `textheight(s)` ? measure
Image manipulation:
- `imagesize(x1, y1, x2, y2)` ? bytes needed for getimage
- `getimage(x1, y1, x2, y2, buf)` ? save rect to buffer
- `putimage(x, y, buf, op)` ? paste back with COPY_PUT/XOR_PUT/AND_PUT/OR_PUT/NOT_PUT
Clipping/viewport:
- `setviewport(x1, y1, x2, y2, clip)` ? drawing clip rect
- `getviewsettings(&info)`
- `clearviewport()`
- `setactivepage(p)` / `setvisualpage(p)` ? ¤¢®©­ ï ¡ãä¥à¨§ æ¨ï (Sprinter ¨¬¥¥â 2 screen)
Line style:
- `setlinestyle(style, pattern, thickness)` ? SOLID_LINE / DOTTED_LINE / etc.
- `getlinesettings(&info)`
**Acceptance:** ¯¥à¥­®á ⨯¨ç­®© Turbo-C BGI ¯à®£à ¬¬ë (à¨áãî饩 á ¨á¯®«ì§®¢ ­¨¥¬
moveto/lineto/circle/bar/setcolor) ¤®«¦¥­ à ¡®â âì ¡¥§ áãé¥á⢥­­ëå ¯à ¢®ª.
**Notes:**
- BGI fonts (TRIPLEX/SANS_SERIF/GOTHIC) ? ã ­ á ®¤¨­ BIOS font, ®áâ «ì­ë¥ ­ã¦­®
¤®¡ ¢¨âì (ª ª bitmap data ¢ lib)
- imagesize/getimage/putimage ? á ¬ë¥ ¢®áâॡ®¢ ­­ë¥ ¤«ï game/animation
- Active/visual page (¤¢®©­ ï ¡ãä¥à¨§ æ¨ï) ? Sprinter ¯®¤¤¥à¦¨¢ ¥â 2 graphics pages,
­ã¦¥­ API switching
‘¬. â ª¦¥ `examples/` Turbo C 2.x BGIDEMO ª ª reference çâ® ­ã¦­®.
### IM2 Interrupt Handlers ? **MUST ¤«ï v2**
User-§ ¤ ¢ ¥¬ë¥ ISR ç¥à¥§ Z80 IM 2 mode. ã¦­ë ¤«ï:
- Timer ticks (50 Hz frame counter, ¯« ¢­ ï  ­¨¬ æ¨ï)
- Music playback (AY, COVOX)
- Real-time games (input + game logic + render ¢ interrupt-driven)
- Async keyboard / mouse handling
**Status:** Ž’‹Ž†…Ž ¤® v2. ®«­ë© research + design ¢ `docs/im2_isr_design.md`.
**¥è¥­¨¥ ¯®  àå¨â¥ªâãà¥:** ॠ«¨§®¢ âì ª ª ®â¤¥«ì­ë© memory mode `--memory im2`
(¢¬¥á⮠⮣® çâ®¡ë «¥§âì ¢® ¢á¥ áãé¥áâ¢ãî騥 crt0). Detail'¨ ¢ design-doc.
**¥§î¬¥ research' ** (¯®«­ë© ⥪áâ ¢ `docs/im2_isr_design.md`):
- Vector 0xFF ? frame + keyboard + CBL. Disambiguation ¯® ¯®àâ ¬ 0x19 / 0xFE
- Mouse hardware-IRQ ­¥ ¯à¨å®¤¨â (­  ⥪ã饩 ¯« â¥)
- Vector table / ISR / stack ŽŸ‡€ ¡ëâì ¢ W2 (0x8000..0xBFFF)
- DSS ¨¬¥¥â ᢮© IM 2 handler ? ­ã¦­® chain'¨âìáï (¨­ ç¥ ª« ¢¨ âãà  / SYSTIME «®¬ îâáï)
### à®ç¨¥ ªàã¯­ë¥ ¯ã­ªâë ¤«ï v2
- [ ] **FILE API rewrite ? buffered streams** ? ⥪ãé ï ॠ«¨§ æ¨ï ¢
`libc/stdio/file.c` íâ® provisional unbuffered shim (ª ¦¤ë© fputc/fgetc
= ®¤¨­ read/write syscall). 㦭  ¯®«­®æ¥­­ ï buffered ᥬ ­â¨ª 
ª ª ¢ Solid-C:
```c
typedef struct {
uint flags; // +0..1 file status flags
int level; // +2..3 empty/fill level of buffer
char *curp; // +4..5 current active pointer
int fd; // +6..7 underlying low-level fd
char *buffer; // +8..9 data transfer buffer
char hold; // +10 ungetc byte if no buffer
short token; // +11..12 reserved
char dummy; // +13 reserved
} FILE;
```
stdin/stdout/stderr ? fd-¬ àª¥àë `0 / -1 / -2`. Žâà¨æ â¥«ì­ë¥ ¤«ï
stdout/stderr ¢ë¡à ­ë ­ ¬¥à¥­­®: ESTEX OPEN ¬®¦¥â ¢¥à­ãâì positive
small fd (1, 2, ?) ¤«ï ®¡ëç­®£® ä ©«  ? ¥á«¨ ¡ë stdout=1, ॠ«ì­ë©
fd=1 áâ «ª¨¢ «áï ¡ë á ¨¤¥­â¨ä¨ª â®à®¬. fd=0 ¤«ï stdin ¡¥§®¯ á­®
(ESTEX 0 ­¥ ¢®§¢à é ¥â). ‘ ¬¨ fd ­¥ ¯¥à¥¤ îâáï ¢ syscall'ë ?
¤¨á¯¥âç¥à¨§ æ¨ï ¯® ä« £ ¬ `_F_CONIN/_F_CONOUT`.
ਭâ¥à-¯®â®ª¨ (stdaux/stdprn) … ॠ«¨§ã¥¬ ? Sprinter ¯à¨­â¥à­®©
API ­¥ ¨¬¥¥â.
€«ìâ¥à­ â¨¢  ? ¢§ïâì ॠ«¨§ æ¨î ¨§ third_party/solid-c (sources ¢
`SRC/CLIB/`); â ¬ ¥áâì £®â®¢ë© buffered FILE + fopen/fread/fwrite/
fseek/setvbuf ¨ â.¤. €¤ ¯â¨à®¢ âì ª ­ è¨¬ open/read/write/lseek.
ਠrewrite § ®¤­® à¥è¨âì deferred issues stdio-review:
- `fwrite` short-write ¤®«¦¥­ áâ ¢¨âì `_F_ERROR`
- `fgets(buf, 1, fp)` ? áâ ­¤ àâ £®¢®à¨â "empty string", ¬ë ¢¥à­ã«¨ NULL
- `mode_to_flags` ? break-out ­  '+' (cosmetic)
- [ ] **Audio API** ? AY-3-8910 + COVOX ç¥à¥§ ¯à¥à뢠­¨ï (âॡã¥â IM2)
- [ ] **ISA-8 slot support** ? ZX-Bus ª àâë (sound, network, etc.) ? âॡã¥â IM2 + ç⥭¨ï port®¢
## à®ç¨¥ § ¤ ç¨ (v1 backlog, ­¥ ¡«®ª¨àãî騥)
- [x] **#9: text I/O split (Turbo-C style)** ? stdio (puts/printf/putchar) ⥯¥àì fast no-attr ç¥à¥§ PCHARS/PUTCHAR. conio (cputs/cprintf/putch) ¯à¨¬¥­ï¥â attr ç¥à¥§ textcolor/textbackground/textattr. KEEP_EXIST_ATTR ? conio fallback ­  fast path. Verified ¢ hello.exe. ‘¬. `memory/text_output_api_split.md`. ¥ «¨§®¢ ­® 2026-05-31.
- [x] **Mouse API ¯®«­ë©** (१¨¤¥­â­ë© driver, RST 30h) ? ¢á¥ 14 ä㭪権 ®¡ñà­ãâë (init/show/hide/refresh/read/goto/bounds/text_cursor/load_cursor/get_cursor/get/set_sensitivity/video_mode_changed). ‘¬. `memory/mouse_api.md`. Verified ¢ MAME 2026-05-31. Sensitivity = divider (¬¥­ìè¥ = ¡ëáâ॥).
- [ ] Interrupt handlers ? IM 2 vector table ¢ HOME ¤«ï user ISR'®¢
- [ ] ®¤¤¥à¦ª  `restore SP on EXIT` (¯ ââ¥à­ ¨§ z88dk +pps) ? ¯à®¢¥à¨âì ­ã¦­® «¨
- [ ] CI:  ¢â®¬ â¨ç¥áª¨ § ¯ã᪠âì MAME á `-aviwrite` ¤«ï screenshot-áà ¢­¥­¨ï, ç⮡ë â¥áâë ¯à¨¬¥à®¢ ¯à®å®¤¨«¨ ¡¥§ 祫®¢¥ª 
## ˆ¤¥¨ ­  ¯®â®¬
- ®¤¤¥à¦ª  `<setjmp.h>` (¥áâì ¢ SDCC stdlib ? ­ã¦­® ¯à®â¥áâ¨à®¢ âì çâ® ­ è crt0 ᮢ¬¥á⨬)
- `<time.h>` ç¥à¥§ ESTEX SYSTIME (`$21`) ¨ CMOS BIOS-ä㭪樨
- ZX Spectrum-ᮢ¬¥áâ¨¬ë© à¥¦¨¬ ª ª ®â¤¥«ì­ë© target (¤«ï ¯®àâ¨à®¢ ­¨ï ᯥªâà㬮¢áª¨å ¯à®£à ¬¬)
- ®¤¤¥à¦ª  ZX-Bus ª àâ (sound, network, etc.) ? ­ã¦­ë ¤à ©¢¥àë
- Profile-guided optimization tools (hot/cold detection) ¤«ï ªà㯭ëå ¯à®£à ¬¬
## Linker duplicate-symbol warnings (¡« £®¯à¨ïâ­ë¥, ®â䨫ìâ஢ ­ë)
Š®£¤  ¬ë á®§­ â¥«ì­® overrides'¨¬ SDCC z80.lib ä㭪樨 ᮡá⢥­­®© ¢¥àᨥ© ¢ `sprinter.lib`, `sdldz80` ¯¨è¥â `?ASlink-Warning-Definition of public symbol '...' found more than once`. ‹¨­ª¥à ¡¥àñâ ¯¥à¢®¥ ­ ©¤¥­­®¥ ®¯à¥¤¥«¥­¨¥ (­ è¥), ¯®í⮬㠯®¢¥¤¥­¨¥ ª®à४⭮¥ ? warning ⮫쪮 noise.
’¥ªã騥 overrides:
- `_puts` ? ­ è  ¢¥àá¨ï ç¥à¥§ PCHARS+\r\n vs SDCC posix puts
- `___sdcc_heap` ? ­ è heap ¢ W2 vs SDCC's áâ ­¤ àâ­ë©
- `_asctime`, `_localtime` (¨ ¢®§¬®¦­® ¤à㣨¥ ¨§ time) ? ­ è `posix_time.c` ç¥à¥§ ESTEX SYSTIME vs SDCC's `time.rel` ª®â®àë© § ¢¨á¨â ®â `_RtcRead`
**’¥ªã饥 à¥è¥­¨¥:** `bin/sprinter-cc` ®â䨫ìâ஢뢠¥â warning-¡«®ª (warning + 2 follow-up `Library:` áâப¨) ¨§ ¢ë¢®¤  `sdcc`. —¥à¥§ `-v` (verbose) ¢áñ ¯®ª §ë¢ ¥âáï. ¥ «¨§®¢ ­® ç¥à¥§ awk-pipe.
**‚®§¬®¦­ë¥ ã«ãç襭¨ï:**
- ¥à¥©â¨ ­  explicit `--nostdlib` + àãç­®© ᯨ᮪ ­ã¦­ëå ¬®¤ã«¥© ¨§ z80.lib (string, math, stdlib ¡¥§ override'­ãâëå) ? ã¡à âì ˆ‘’Ž—ˆŠ warning'®¢, ­¥ ¬ áª¨à®¢ âì
- ˆ«¨: ¯¥à¥¨¬¥­®¢ âì ­ è¨ `_puts` ? `_puts_sprinter` + alias ç¥à¥§ linker flag (­¥ 㢥७ çâ® SDCC ¯®¤¤¥à¦¨¢ ¥â)
- ˆ«¨: ®áâ ¢¨âì ª ª ᥩç á (à ¡®ç¥¥ ¨ benign) ? ¯à¨®à¨â¥â ­¨§ª¨©
## TODO: ¯à®¢¥à¨âì ­  ॠ«ì­®¬ ¦¥«¥§¥
- [ ] **Port_Y banking trick** (`docs/part2/SprinterGraphics programming.txt`):
¤®ªã ã⢥ত ¥â çâ® ¯®á«¥ `OUT (0x89), Y`  ¤à¥á  0xC000+0x400*N ¢ ®ª­¥ W3
¬ ¯¯ïâáï ­  áâப¨ Y..Y+15 (®¤­® ¯à®£à ¬¬¨à®¢ ­¨¥ ? 16 áâப).
Empirical 2026-06-01 ¢ MAME 0.283 íâ®â trick **­¥ à ¡®â ¥â** ? ¯¨ªá¥«¨
¯®  ¤à¥á ¬ ¢ëè¥ 0xC000+row_width ã室ïâ ¢ ­¥¢¨¤¨¬ãî ®¡« áâì. Š ­®­¨ç¥áª¨©
`docs/samples/plasma2.asm` ⮦¥ ­¥ ¨á¯®«ì§ã¥â banking, ¯¥à¥ãáâ ­ ¢«¨¢ ¥â
Port_Y per row.
« ­:
1. ®«ãç¨âì ¤®áâ㯠ª ॠ«ì­®¬ã Sprinter
2. ‡ ¯ãáâ¨âì â¥áâ dual-write (`_gfx_putpixel_raw` + ¢â®à®© write ¢ `0xD000+x`)
3. …᫨ ­  ¦¥«¥§¥ ¢¨¤­ë ¤¢®©­ë¥ «¨­¨¨ ? ¡ £  MAME, ®âªàëâì issue á
¬¨­¨¬ «ì­ë¬ ९à®
4. …᫨ ­  ¦¥«¥§¥ ⮦¥ ®¤­  «¨­¨ï ? ¤®ªã¬¥­â ­¥¢¥à­ë©, 㤠«¨âì 㯮¬¨­ ­¨¥
¨§ ¤®ª¨ ¨ ¯à®áâ® ®áâ ¢¨âì ⥪ãéãî ॠ«¨§ æ¨î (Port_Y per pixel)
5. …᫨ banking à ¡®â ¥â ­  ¦¥«¥§¥ ? ¢­¥¤à¨âì ªíè¨à®¢ ­¨¥ Port_Y ¢
`_gfx_putpixel_raw` (sentinel out-of-range, á¬. memory/gfx_port_y_banking.md)
‘¢ï§ ­­ë© ¢ë¨£àëè ¤«ï Bresenham (60-pixel ¤¨ £®­ «ì) ? ®ª®«® 8? ¬¥­ìè¥
OUT (0x89) ®¯¥à æ¨©, ¤«ï `gfx_fill_rect 320x256` ? 16? ¬¥­ìè¥. ¥ ¡«®ª¨àã¥â
release v1.
## GFX: à áè¨à¥­¨ï ¯® `docs/part2/accelerator_doc.txt`
®á«¥ ¯à®ç⥭¨ï ¤¥â «ì­®£® accelerator doc ¢ë¥­ë ­¥§ ªàëâë¥ ­ ¯à ¢«¥­¨ï.
‘¥©ç á ¢ ª®¤¥ ¨á¯®«ì§ã¥âáï ⮫쪮 £®à¨§®­â «ì­ë©/¢¥à⨪ «ì­ë© Fill mode.
### Quick wins ¤«ï ⥪ãé¨å primitives
- [ ] **‡ ¬¥­¨âì SMC ­  `LD A, (var)` ¤«ï block-size**. „®ªã¬¥­â ®
à §à¥è ¥â `LD A, (HL)`, `LD A, (BC)`, `LD A, (DE)` (­® ­¥ `LD A, r`).
â® ã¡¥àñâ SMC complexity ¢ `gfx_lines.c:hfill_chunk/vfill_chunk` ¨
`gfx_16.c:g16_hfill_chunk`. ‡ ¯à¥é¥­® ⮫쪮 register-to-register.
- [ ] **Šíè¨à®¢ ­¨¥ block-size**. „®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel § ¯®¬¨­ ¥â
block size ¬¥¦¤ã bursts (á¬. `Horizontal_Line_Fill`: ãáâ ­ ¢«¨¢ îâ
size + `LD B,B` ®âª«î祭¨¥, ¯®â®¬ ¢ª«îç îâ Fill mode ¨ ¨á¯®«ì§ãîâ
á®åà ­ñ­­ë© size). „«ï `gfx_fill_rect` á 100 ®¤¨­ ª®¢ë¬¨
áâப ¬¨ ? ãáâ ­®¢¨âì size 1 à §,   ­¥ 100.
### Bank-prefix modes (port 0xE2 bits)
„®ªã¬¥­â ¯®ª §ë¢ ¥â âਠ¢ à¨ ­â  ¡ ­ª  ¢¨¤¥®áâà ­¨æë ¯®¬¨¬® áâ ­¤ àâ­®£® 0x50:
| Bank byte | Effect |
|---|---|
| 0x50 | Normal write ? ¯¨è¥âáï ¢ shadow + ¢¨¤¨¬ë© |
| 0x54 | "no copy in main shadow RAM" |
| 0x58 | **"FF is transparent"** ? ¡ ©â 0xFF ¯à¨ write ®áâ ¢«ï¥â background |
| 0x5C | both |
Bank 0x58 ®¡êïá­ï¥â ¯®ç¥¬ã mouse cursor à¨áã¥âáï á 0xFF-¯à®§à ç­®áâìî.
â® ¯ãâì ª **sprite-blending ç¥à¥§ accel block copy**:
- [ ] **`gfx_set_bank_transparent(on)`** ¨«¨ ä« £ ¢ `gfx_set_bank` ¤«ï
¢ë¡®à  0x50/0x58 ¯à¨ ®âà¨á®¢ª¥ sprite'®¢
- [ ] ˆá¯®«ì§®¢ âì ¢ ­®¢®¬ `gfx_blit()` çâ®¡ë ¯® ä ªâã ¯®«ãç âì
transparent sprites ç¥à¥§ accel-ª®¯¨î
### Block copy mode (sprite blit'ë)
`LD L,L` (horizontal) ¨ `LD A,A` (vertical) ? ०¨¬ ª®¯¨à®¢ ­¨ï ¡«®ª  ç¥à¥§
256-¡ ©â­ãî accel memory. â® ¡ §¨á ¤«ï blit'®¢.
- [ ] **`gfx_blit(src_data, x, y, w, h)`** ? ª®¯¨à®¢ ­¨¥ sprite' 
(¯à®¨§¢®«ì­ë© à §¬¥à, ç¥à¥§ accel)
- [ ] **`gfx_blit_transparent(src, x, y, w, h)`** ? á ¨á¯®«ì§®¢ ­¨¥¬ bank 0x58
‘¬. `Draw_Restangle_Data` ¢ accelerator_doc.txt ª ª à¥ä¥à¥­á.
### AND / OR / XOR operations ç¥à¥§ accel
„®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel ¯®¤¤¥à¦¨¢ ¥â «®£¨ç¥áª¨¥ ®¯¥à æ¨¨ á ¡«®ª ¬¨
¤ ­­ëå. ਬ¥­¥­¨ï:
- XOR ? ¨­¢¥àá¨ï ®¡« á⨠(¢ë¤¥«¥­¨¥ selection ¢ UI)
- OR / AND ? masking, alpha-style blending
- ‘¬. ¯à¨¬¥à ¢ accelerator_doc.txt: "256 bytes block coding via XOR"
- [ ] **`gfx_xor_rect`** / **`gfx_or_rect`** / **`gfx_and_rect`** ?
¯à¨¬¨â¨¢ë «®£¨ç¥áª¨å ®¯¥à æ¨© ­ ¤ ¯àאַ㣮«ì­¨ª®¬
- [ ] **`gfx_invert_rect(x, y, w, h)`** ? alias ­  xor á 0xFF
### Bitmap fonts à §­ëå à §¬¥à®¢
‘¥©ç á `gfx_text` / `gfx_putchar` å à¤ª®¦¥­­® à ¡®â îâ á 8?8 èà¨ä⮬
(BIOS WIN_GET_ZG ¢®§¢à é ¥â 256?8 ¡ ©â). „«ï ¡ã¤ãé¨å UI / â¨âã«ì­¨ª®¢
­ã¦­ë:
- [ ] **`gfx_set_font_size(w, h)`** ? ¯¥à¥ª«îç¨âì è¨à¨­ã/¢ëá®âã glyph' 
- [ ] **`gfx_set_font_data(ptr, w, h, advance)`** ? § ¬¥­¨âì 㪠§ â¥«ì
­  ¯®«ì§®¢ â¥«ì᪨© èà¨äâ + à §¬¥àë
- [ ] ®¤¤¥à¦ª  **proportional** (advance != w) èà¨ä⮢ ? ¤®¡ ¢¨âì
array advance[256] ­  è¨à¨­ã ª ¦¤®£® glyph' 
- [ ] **Big-font ०¨¬ë**: 8?16, 16?16, 16?8 (¤«ï â¨âã«ì­¨ª®¢)
- [ ] ‚®§¬®¦­® ®â¤¥«ì­ë© API `gfx_text_ex(x, y, str, font_id)` £¤¥
font_id ¢ë¡¨à ¥â ®¤¨­ ¨§ § £à㦥­­ëå èà¨ä⮢
- [ ] **Anti-alias 2-bit èà¨äâë** (¡¨â ä®­ / ¡¨â £à ­¨æ  / 2-¡¨â alpha?)
? far future, ¤«ï smooth UI
## ”¨­ «ì­ë© íâ ¯ ®¯â¨¬¨§ æ¨© (­¥ ᥩç á)
- **`gfx_line` ç¥à¥§ accel ¤«ï ¯®«®£¨å ¤¨ £®­ «¥©** ? Bresenham ¤«ï «¨­¨¨ á |dy| << |dx| (¨«¨ ­ ®¡®à®â) ¢ë¤ ñâ ¤«¨­­ë¥ runs ®¤¨­ ª®¢®£® Y (¨«¨ X): ¯¨ªá¥«ì, ¯¨ªá¥«ì, ¯¨ªá¥«ì, è £ Y, ¯¨ªá¥«ì, ¯¨ªá¥«ì... Š ¦¤ë© â ª®© run ? íâ® £®â®¢ë©  à£ã¬¥­â ¤«ï `gfx_hline` (¨«¨ `vline`).
« ­ ¨áá«¥¤®¢ ­¨ï: ¯®áç¨â âì ¤«¨­ã runs ª ª äã­ªæ¨î ®â ­ ª«®­ ; à¥è¨âì ¬¨­¨¬ «ì­ë© run length, ¯à¨ ª®â®à®¬ ¢ë£®¤­¥¥ accel hline 祬 N?putpixel (overhead accel ~20?s, putpixel ~5?s ? accel ¢ë£®¤­¥¥ ¯à¨ run ? 4-5 px); ¤«ï ªàãâëå ¤¨ £®­ «¥© (dx ? dy) ®áâ ¢¨âì Bresenham, ¤«ï ¯®«®£¨å ? run-length-based fill.
‘¥©ç á `gfx_line` orthogonal cases 㦥 ç¥à¥§ accel ? ®¯â¨¬¨§¨à®¢ âì ⮫쪮 ª®áë¥.
- **`gfx_fill_rect` á ®¤­¨¬ W3-swap ­  ¢áî ®¯¥à æ¨î** ? ᥩç á ª ¦¤ë© ¢­ãâ७­¨© `gfx_hline`/`gfx_vline` ¤¥« ¥â ᢮© DI/save-W3/restore-W3/EI. Œ®¦­® ᤥ« âì internal `_fill_rect_inner` ª®â®àë© ¤¥à¦¨â W3 § ¬ ¯«¥­­ë¬ ¨ DI ¢¥áì æ¨ª«; ~20?s ? ª®«¨ç¥á⢮ áâப/á⮫¡æ®¢ íª®­®¬¨¨. ਬ¥­¨¬® ª® ¢á¥¬ ª®¬¯®§¨â­ë¬ ¯à¨¬¨â¨¢ ¬.
# MDView ? à®á¬®âà騪 Markdown ¤«ï Sprinter
**MDView** ? ¯à®£à ¬¬  ¤«ï ¯à®á¬®âà  ¤®ªã¬¥­â®¢ ¢ ä®à¬ â¥ *Markdown* ­  ª®¬¯ìîâ¥à¥
Sprinter (¯à®æ¥áá®à Z80). „®ªã¬¥­â åà ­¨âáï ¢ ®â¤¥«ì­®¬ W3 ®ª­¥ ¨ ­¥ § ­¨¬ ¥â
®á­®¢­ãî RAM ¯à®£à ¬¬ë.
## ‚®§¬®¦­®áâ¨
- „®ªã¬¥­âë ¤® **128 Š** (8 áâà ­¨æ EMM ¯® 16 Š ª ¦¤ ï)
- „® **16 384** íªà ­­ëå áâப ¢ ¨­¤¥ªá¥
- €¢â®¬ â¨ç¥áª¨© ¯¥à¥­®á á«®¢ ¯® è¨à¨­¥ íªà ­  (80 á⮫¡æ®¢)
- ƒ®à¨§®­â «ì­ë© ᤢ¨£ ¤«ï è¨à®ª¨å áâப (¡«®ª¨ ª®¤ , â ¡«¨æë)
- ‘â âãá-¡ à: ¨¬ï ä ©« , ¤¨ ¯ §®­ áâப, ¯à®æ¥­â ¯à®ªàã⪨
- ‘¯¨­­¥à ¢ áâப¥ á®áâ®ï­¨ï ¢® ¢à¥¬ï § £à㧪¨ ¨ ¨­¤¥ªá æ¨¨
- ®¤¤¥à¦ª  ?¬ï£ª®£®? ᪫¥¨¢ ­¨ï áâப ¢  ¡§ æ å ¨ æ¨â â å
## ‡ ¯ãáª
```
mdview [¨¬ï_ä ©« .md]
```
…᫨ ¨¬ï ä ©«  ­¥ § ¤ ­®, § £à㦠¥âáï `README.MD`.
## “¯à ¢«¥­¨¥
```
Š« ¢¨è  „¥©á⢨¥
ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Up Down பàã⪠ ­  ®¤­ã áâப㠢¢¥àå / ¢­¨§
PgUp PgDn பàã⪠ ­  áâà ­¨æã (30 áâப)
Home  ç «® ¤®ªã¬¥­â 
End Š®­¥æ ¤®ªã¬¥­â 
Left Right ƒ®à¨§®­â «ì­ë© ᤢ¨£ (⮫쪮 nowrap-áâப¨)
F1 Žª­® á¯à ¢ª¨
F8 Š®¤¨à®¢ª : CP866 ? CP1251 ? KOI8-R ? UTF-8 ? ...
F10 / Esc ‚ë室 ¨§ ¯à®£à ¬¬ë
```
Š®¤¨à®¢ª  ®¯à¥¤¥«ï¥âáï  ¢â®¬ â¨ç¥áª¨ ¯à¨ ®âªàë⨨ (BOM + í¢à¨á⨪  ¯®
¯¥à¢ë¬ 4 Š); `F8` ¯¥à¥ª«î砥⠥ñ ¢àãç­ãî, ¥á«¨ ¤¥â¥ªæ¨ï ®è¨¡« áì.
8-¡¨â­ë¥ ª®¤¨à®¢ª¨ (CP866/CP1251/KOI8-R) ¯¥à¥ª«îç îâáï ¬£­®¢¥­­® (६ ¯ ­ 
®âà¨á®¢ª¥). ‚â®à®© ­ ¡®à ¨­¤¥ªá/ªíè  (­ ¯à¨¬¥à UTF-8) áâநâáï «¥­¨¢® ? ¯à¨
¯¥à¢®¬ ¯¥à¥ª«î祭¨¨ ¢ ­¥£® (ª®à®âª ï ¯ ã§  ᮠᯨ­­¥à®¬), ¤ «ìè¥ ¬£­®¢¥­­®.
## ‘¨­â ªá¨á Markdown
### ‡ £®«®¢ª¨
®¤¤¥à¦¨¢ îâáï ã஢­¨ H1?H4. “஢­¨ H5 ¨ H6 ®â®¡à ¦ îâáï ª ª H4.
# ‡ £®«®¢®ª ¯¥à¢®£® ã஢­ï
## ‡ £®«®¢®ª ¢â®à®£® ã஢­ï
### ‡ £®«®¢®ª âà¥â쥣® ã஢­ï
#### ‡ £®«®¢®ª ç¥â¢ñà⮣® ã஢­ï
### ’¥ªá⮢®¥ ä®à¬ â¨à®¢ ­¨¥
**†¨à­ë© ⥪áâ** ¢ë¤¥«ï¥âáï ¤¢®©­ë¬¨ §¢ñ§¤®çª ¬¨: `**⥪áâ**`
*Šãàᨢ* ¢ë¤¥«ï¥âáï ®¤¨­®ç­ë¬¨ §¢ñ§¤®çª ¬¨ `*⥪áâ*` ¨«¨ §­ ª®¬ ¯®¤çñન¢ ­¨ï `_⥪áâ_`
`‚áâ஥­­ë© ª®¤` ®¡®§­ ç ¥âáï ®¡à â­ë¬¨ ª ¢ë窠¬¨
~~‡ çñભãâë© â¥ªáâ~~ ? ¤¢®©­ë¥ ⨫ì¤ë: `~~⥪áâ~~`
### ¥­ã¬¥à®¢ ­­ë© ᯨ᮪
Œ àª¥àë `-`, `*` ¨«¨ `+`:
- ¥à¢ë© ¯ã­ªâ ᯨ᪠
- ‚â®à®© ¯ã­ªâ ᯨ᪠
- ’à¥â¨© ¯ã­ªâ á ¤®áâ â®ç­® ¤«¨­­ë¬ ⥪á⮬, ª®â®àë© ¯à¨ ­¥®¡å®¤¨¬®áâ¨
¡ã¤¥â ¯¥à¥­¥áñ­ ­  á«¥¤ãîéãî áâபã á á®åà ­¥­¨¥¬ ®âáâ㯠
### 㬥஢ ­­ë© ᯨ᮪
1. ¥à¢ë© í«¥¬¥­â
2. ‚â®à®© í«¥¬¥­â
3. ’à¥â¨© í«¥¬¥­â
### –¨â â 
> «®ª æ¨â âë ­ ç¨­ ¥âáï á ᨬ¢®«  `>`. ¥áª®«ìª® ¯®á«¥¤®¢ â¥«ì­ëå
> áâப ®¤­®© æ¨â âë ᪫¥¨¢ îâáï ¢ ¥¤¨­ë©  ¡§ æ á  ¢â®¬ â¨ç¥áª¨¬
> ¯¥à¥­®á®¬ á«®¢.
### «®ª ª®¤  (verbatim)
«®ª ª®¤  § ª«îç ¥âáï ¢ âன­ë¥ ®¡à â­ë¥ ª ¢ë窨. ‚­ãâਠ¡«®ª 
⥪á⠮⮡ࠦ ¥âáï ?ª ª ¥áâì? ¡¥§ à §¡®à  Markdown:
```
#include <stdio.h>
#include <sprinter.h>
int main(void) {
puts("Hello, Sprinter!");
return 0;
}
```
### ƒ®à¨§®­â «ì­ ï «¨­¨ï
’ਠ¨«¨ ¡®«¥¥ ᨬ¢®«®¢ `---`, `***` ¨«¨ `___` ­  ®â¤¥«ì­®© áâப¥:
---
## ’¥å­¨ç¥áª¨¥ å à ªâ¥à¨á⨪¨
- **« âä®à¬ :** Sprinter, ¯à®æ¥áá®à Z80 @ 21 Œƒæ
- **Š®¤¨à®¢ª¨:** CP866 / CP1251 / KOI8-R / UTF-8 ( ¢â®®¯à¥¤¥«¥­¨¥, `F8`)
- **Œ ªá¨¬ «ì­ë© à §¬¥à ä ©« :** 128 Š
- **Œ ªá¨¬ «ì­®¥ ç¨á«® áâப ¢ ¨­¤¥ªá¥:** 16 384
- **¥¦¨¬ ¯ ¬ïâ¨:** small
- Š®¤ ¯à®£à ¬¬ë, c⥪, ¤ ­­ë¥, ªãç  ? ®ª­a W1-W2 (32 Š,  ¤à¥á  0x4000?0xBFFF).
- ãä¥à ä ©«  ? áâà ­¨æë EMM, ®â®¡à ¦ ¥¬ë¥ ¢ W3 (0xC000?0xFFFF)
## TODO
1. **“¢¥«¨ç¥­¨¥ à §¬¥à  ¤®ªã¬¥­â®¢.** ‘­ïâì «¨¬¨â 128 Š: „®áâ â®ç­®
à §à¥è¨âì à ¡®â âì á ¡®«ì訬 ª®«-¢®¬ áâà ­¨æ ¯ ¬ïâ¨, ¯®ª  ®ââ¥áâ¨à®¢ ­­®
­  à ¡®â¥ á 8-¬î áâà ­¨æ ¬¨ ¯® 16Š¡.
‘¤¥« ­®: ä®à¬ â¨à®¢ ­­ë¥ â ¡«¨æë á à ¬ª®©; ¯®¤¤¥à¦ª  ª®¤¨à®¢®ª
CP866 / CP1251 / KOI8-R / UTF-8 á  ¢â®®¯à¥¤¥«¥­¨¥¬ ¨ ¯¥à¥ª«î祭¨¥¬ ¯® `F8`
(¢â®à®© ­ ¡®à áâநâáï «¥­¨¢®, ¯® ¯¥à¢®¬ã ¯¥à¥ª«î祭¨î).
4. **“᪮७¨¥ ७¤¥à¨­£ .** Šíè áâப íªà ­ . Ž¯â¨¬¨§ æ¨ï 横«  ¢ë¢®¤ 
ᨬ¢®«®¢ ç¥à¥§ BIOS WRCHAR (¯ ª¥â­ë© ¢ë¢®¤, DMA).
---
*MDView v0.2 ú (c) 2026 ¥â஢ €.ƒ.*
---
# Sprinter C Compiler ? v1.0
C toolchain for **Sprinter** ? the Z80-based home computer by Peters Plus, running
ESTEX DSS. Host: macOS / Linux. Target: `.EXE` files in SprintEXE format.
Built on top of **SDCC 4.5** (vendored in `third_party/sdcc/`). This repository adds
everything Sprinter-specific: crt0, linker integration, libc wrappers over ESTEX,
banked-call trampolines, graphics & accelerator API, mouse driver wrappers, and the
`mkexe` utility for producing SprintEXE images.
## What you get
* **`bin/sprinter-cc`** ? one-line driver: `sprinter-cc -o foo.exe foo.c`
* **Memory modes**: `tiny`, `small`, `big`, `huge`, `manual` ? see below.
* **stdio + conio**: printf, puts, putchar, getchar, fopen/fread/..., cprintf, cputs, putch, textcolor/textbackground/textattr, gotoxy, kbhit/getch.
* **Graphics**: 320?256?256 and 640?256?16 modes, accelerator-backed primitives (hline / vline / rect / fill_rect / line via Bresenham, plus clear), bitmap-font text in both modes via BIOS character generator.
* **File I/O**: POSIX (`open`/`read`/`write`/`close`/`lseek`/`unlink`/`creat`), FILE\* streams (`fopen`/`fgets`/`fwrite`/...), directory listing (`ffirst`/`fnext`), `chdir`/`getcwd`/`mkdir`/`rmdir`, `stat`/`fstat`.
* **Memory**: 32 KB heap (W2-resident), banking-aware page allocator (`mem_alloc_pages`/`bank_read`/`bank_write`), explicit memory modes for sub-16 KB programs.
* **Mouse**: full Sprinter driver wrapper (14 functions including custom cursor bitmaps).
* **Environment**: `getenv`/`putenv`/`sysenv` over ESTEX `$46`.
* **Time**: `getdatetime`/`setdatetime` + POSIX `time`/`localtime`/`mktime`/`asctime`/`ctime`.
* **Misc**: `errno`/`strerror`/`perror`, `atexit`, `setjmp`/`longjmp`, `sleep`, full argv parsing in crt0.
## Quick start
```sh
git clone <this repo> sprinter-c
cd sprinter-c
make sdcc # one-time: fetch SDCC 4.5 binary (~25 MB)
make all # build mkexe + libsprinter.lib + 27 examples
make floppy # pack everything into mame/v306/IMG/mc.img
cd mame/v306 && ./run_mame.sh # boot Sprinter in MAME
```
Compile a single program:
```sh
cat > hello.c <<EOF
#include <stdio.h>
int main(void) { puts("Hello, Sprinter!"); return 0; }
EOF
bin/sprinter-cc -o hello.exe hello.c
```
That's it ? `hello.exe` is now a valid SprintEXE you can `RUN HELLO` from the ESTEX shell.
## Memory modes
Sprinter's address space is four 16 KB windows (W0 / W1 / W2 / W3). DSS allocates
pages by program size ? small programs get only one page. Pick a memory mode based
on what your program needs:
| Mode | Code lives in | Banking | Use when | Note |
|---|---|---|---|---|
| `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB | |
| `small` | W1-W2 (0x4100+) | no | code+data < 30 KB | |
| `big` | W2 + W1 banking | yes (W1) | tiny + extra code modules | |
| `huge` | W1-W2 + W3 banking | yes (W3) | small + extra code modules | |
| `manual` | user-specified | optional | special layouts | Not implemented |
```sh
sprinter-cc --memory small -o big.exe bigprog.c
sprinter-cc --memory huge -o app.exe main.c --bank 1=engine.c --bank 2=ai.c
```
Banked functions are declared with `__banked`:
```c
void engine_tick(int dt) __banked; // lives in BANK1, automatically swapped
```
## Examples (27 total)
| Example | What it demonstrates |
|---|---|
| `hello` | Hello world with stdio + conio Turbo-C-style colors |
| `argv` | argv parsing in crt0 |
| `cat` | File I/O ? read & print TEST.TXT |
| `seek` | 32-bit lseek over a 100 KB file |
| `ls` | Directory listing via ffirst/fnext |
| `filetest` | FILE\* streams (fopen/fread/...) |
| `stattest` | `stat`/`fstat` on files and directories |
| `errno` | errno / strerror / perror |
| `mem_test` | Page allocator + bank\_read/bank\_write |
| `malloc` | Heap stress test (200+ allocations) |
| `banked` | Banked code in W3 (huge mode) |
| `bankedbg` | Banked code in W1 (big mode) |
| `banklocl` | Bank-local static data and BSS |
| `mouse` | Mouse driver in text mode |
| `gfx_mous` | Mouse with custom bitmap cursor in graphics mode |
| `gfx_demo` | 320?256?256 lines / rects / accelerator |
| `gfx_d16` | 640?256?16 same primitives |
| `gfx_text` | Bitmap-font text on graphics screen |
| `timedir` | Date/time + directory listing |
| `ptime` | POSIX time API |
| `openenv` | open() flags + environment vars |
| `conio` | conio API smoke test |
| `attrprob` | Probe Sprinter text attribute byte layout |
| `strtest` | string.h test (from SDCC's z80.lib) |
| `stdlib` | stdlib.h test (qsort / rand / strtol / etc.) |
| `assrtest` | assert() |
| `rt_test` | Runtime helpers (sleep, setjmp, atexit) |
## Headers
Standard:
* `<stdio.h>` ? puts / printf / FILE\* + Sprinter-specific dec/hex helpers
* `<stdlib.h>` ? atoi / atof / malloc / qsort / ... (from SDCC z80.lib)
* `<string.h>` / `<ctype.h>` / `<math.h>` ? from SDCC z80.lib
* `<unistd.h>` ? read / write / close / lseek / unlink
* `<fcntl.h>` ? open / creat + O\_RDONLY / O\_CREAT / ...
* `<errno.h>` ? errno + error names + strerror
* `<sys/stat.h>` ? stat / fstat
* `<setjmp.h>` / `<assert.h>` ? from SDCC
Sprinter-specific:
* `<conio.h>` ? putch / cputs / cprintf, textcolor / textbackground / textattr, kbhit / getch, clrscr, gotoxy, wherex/y
* `<gfx.h>` ? gfx_init/done, palette, putpixel, hline/vline/rect/fill_rect/line, text ? for both 320 and 640 modes (gfx_\*16 variants)
* `<mouse.h>` ? full 14-function driver wrapper + mouse_cursor_t with bitmap support
* `<dir.h>` ? chdir / getcwd / mkdir / rmdir / ffirst / fnext / ffblk
* `<time.h>` ? getdatetime / setdatetime + POSIX time / localtime / etc.
* `<sprinter.h>` ? raw ports, ESTEX/BIOS function numbers, env API
* `<sprinter_exit.h>` ? exit / \_exit / atexit
* `<sprinter_mem.h>` ? mem\_alloc\_pages / mem\_free\_block / bank\_read / bank\_write
* `<sprinter_compat.h>` ? Solid-C compatibility layer (aliases + BOOL/WORD/uint types)
## Toolchain commands
```sh
make all # build mkexe + lib + every example
make floppy # repack mame/v306/IMG/mc.img with all .exe files
make check # 17 mkexe unit-tests
make clean # remove all build artefacts
make sdcc # one-time: fetch SDCC 4.5 binary
```
### sprinter-cc options
```
sprinter-cc -o foo.exe foo.c [more.c ...] [options]
--memory MODE tiny | small | big | huge | manual (default: tiny)
--memory-manual SPEC explicit placement (CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3)
--stack-size N bytes reserved for the stack (default ~1278)
--crt0=TYPE default | minimal | banked | small
--bank N=FILE.c compile FILE.c into bank N (repeatable, max 15)
--debug enable runtime diagnostics (defines DEBUG_RT)
-I PATH extra include path
-L 0xADDR / -E / -S override load / entry / stack addresses
-Wl FLAG pass FLAG to sdldz80
--mkexe FLAG pass FLAG to mkexe (e.g. --mkexe -p --mkexe 0 for bank padding)
-v verbose
```
## Status
What works in v1.0:
* Compile / link / pack to SprintEXE ? verified on all 27 examples
* Four memory modes (tiny / small / big / huge)
* Graphics (both modes) with accelerator
* Mouse (text + graphics cursor)
* File I/O, directories, environment, time
* All headers listed above
Deferred to v2.0 (see `docs/TODO.md`):
* **Turbo-C-style BGI graphics API** ? `initgraph` / `setcolor` / `circle` /
`getimage` / `putimage` / etc. on top of our `gfx_*` primitives
* Remaining Solid-C compatibility gaps (Phase 2/3) ? see `docs/solid_c_compatibility.md`
* Manual memory mode
* Rewrite FILE\* stream API (current implementation is very primitive and doesn't use buffers)
Deferred to v3.0:
* **IM2 interrupt handlers** ? research complete (`docs/im2_isr_design.md`),
implementation scheduled for v3
* **Audio API** (AY-3-8910 + COVOX) ? requires IM2
* **ISA-8 slot drivers** ? requires IM2 (???)
## Documentation
* `docs/TODO.md` ? roadmap and open work items
* `docs/solid_c_compatibility.md` ? gap analysis vs Solid-C 2004
* `docs/im2_isr_design.md` ? interrupt handler design (v2)
* `docs/converted/` ? source documentation (ESTEX, BIOS, architecture)
converted to plain text for `grep`
* `docs/reference/`, `docs/samples/`, `docs/memory management/` ? original
Russian docs and code samples from Peters Plus
## Repository layout
```
bin/sprinter-cc one-line compiler driver (bash)
toolchain/mkexe/ host-side tool: .ihx -> .exe SprintEXE
toolchain/check_banks.py post-link bank size enforcer
runtime/ crt0 variants (default, minimal, small, banked)
bank trampolines, heap, heap_top
libc/include/ headers
libc/io|stdio|mem|gfx/ C and asm sources for libsprinter.lib
lib/ Makefile that archives libsprinter.lib via sdar
examples/ 27 example programs
mame/v306/ MAME binary + Sprinter ROM/HDD images + floppy script
third_party/sdcc/ vendored SDCC 4.5 (fetched via `make sdcc`)
third_party/solid-c/ reference: original Sprinter native C (for compat target)
docs/ documentation
```
## License
This repository contains:
* Original code in `bin/`, `toolchain/`, `runtime/`, `libc/`, `lib/`, `examples/` ?
MIT-licensed.
* `third_party/sdcc/` ? SDCC 4.5 under GPLv2 with linking exception
(see `third_party/sdcc/COPYING.txt`)
* `third_party/solid-c/` ? original Sprinter Solid C, used only as a reference
## Credits
* **Sprinter / Peters Plus** ? ˆ¢ ­ Œ ª, „¬¨â਩  à¨­®¢ and the original team
* **SDCC** ? for the underlying Z80 compiler
* **MAME** ? for the Sprinter Sp2000 emulation
---
For questions / patches: see CONTRIBUTING.md (TBD) or open an issue.
---
# TODO / Roadmap
Žâªàëâë¥ § ¤ ç¨ ¢ ¯®à浪¥ ã¡ë¢ ­¨ï ¯à¨®à¨â¥â . ® ¬¥à¥ ¯®ï¢«¥­¨ï ॠ«ì­ëå ¯à®£à ¬¬ ? ¯à¨®à¨â¥âë ¡ã¤ãâ ᬥé âìáï.
## â ¯ 5 ? malloc / free + banking-aware page allocator ? ƒŽ’Ž‚Ž
- [x] SDCC's `malloc`/`free` + ­ è `runtime/heap.s` (¯®«­®áâìî § ¬¥­ï¥â library heap.rel, 14000-¡ ©â­ë© heap ¢ ®ª­¥ 2)
- [x] `libc/mem/mem_alloc.c` ? page allocator: `mem_alloc_pages`/`mem_free_block`/`mem_get_page`/`mem_info` ç¥à¥§ ESTEX `$3C/$3D/$3E` + BIOS `$C4`
- [x] `libc/mem/bank_io.c` ? HOME-१¨¤¥­â­ë¥ `bank_read`/`bank_write`/`bank_load_byte`/`bank_store_byte` ᮠ᢮¯®¬ W3 ¢­ãâà¨
- [x] `examples/malloc_test/` ? ¯à®¢¥àª  SDCC's malloc (~210 64-¡ ©â­ëå allocations ç¥à¥§ ¢áî heap)
- [x] `examples/mem_test/` ? ¯à®¢¥àª  page allocator: 3 áâà ­¨æë, à §­ë¥ ¯ ââ¥à­ë ç¥à¥§ bank_write, ¢¥à¨ä¨ª æ¨ï ç¥à¥§ bank_read
## â ¯ 6 ? argv parsing + sprinter-cc wrapper ? ƒŽ’Ž‚Ž
- [x] crt0 ¯ àá¨â ESTEX command-line ¨§ IX-prefix (inline asm ¢ `runtime/crt0.s`)
- [x] Strip leading CP/M-style space (DSS quirk)
- [x] ¥à¥¤ ç  `argc`/`argv` ¢ main() ç¥à¥§ HL/DE (SDCC __sdcccall(1) ABI)
- [x] argv[0] = basename .EXE ç¥à¥§ ESTEX APPINFO ($47 subfn 2)
- [x] `runtime/crt0_minimal.s` ? opt-out ¤«ï ®ç¥­ì ¬ «¥­ìª¨å ¯à®£à ¬¬
- [x] `runtime/crt0_banked.s` ? ⥯¥àì ⮦¥ ¯ àá¨â argv (parse_argv + get_progname ᪮¯¨à®¢ ­ë ¨§ crt0.s; ¡ã¤¥â factored ¢ argv.s ª®£¤  ¢®§ì¬ñ¬áï §  libsprinter.lib)
- [x] Bash-®¡ñà⪠ `bin/sprinter-cc`: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨©: `--memory`, `--memory-manual`, `--stack-size`, `--crt0=`, `--bank N=FILE.c`, `--debug`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
## â ¯ 8 ? £à ä¨ª  (320?256?256 + 640?256?16 + accel + bitmap font) ? ƒŽ’Ž‚Ž
- [x] **8a** Graphics core: `gfx_init`/`gfx_done`/`gfx_clear`/`gfx_putpixel`/`gfx_pal_load`/`gfx_pal_set` (libc/gfx/gfx_core.c).  «¨âà  ç¥à¥§ BIOS PIC_SET_PAL ($A4). Verified 320?256?256.
- [x] **8b** ‹¨­¨¨/¯àאַ㣮«ì­¨ª¨/fill ç¥à¥§ accelerator (libc/gfx/gfx_lines.c): `gfx_hline`/`gfx_vline` ç¥à¥§ accel Fill (LD C,C / LD E,E + SMC block-size), `gfx_rect`/`gfx_fill_rect` á heuristic ¢ë¡®à®¬ ®à¨¥­â æ¨¨ (h/v bursts count), `gfx_line` á Bresenham ¤«ï ¤¨ £®­ «¥©. `gfx_clear` ⮦¥ ¯¥à¥¯¨á ­ ­  column-major accel (~4? ¡ëáâ॥).
- [x] **8c** 640?256?16 mode (libc/gfx/gfx_16.c): `gfx_*16` API, HIGH nibble = LEFT pixel (¤®ªã¬¥­â æ¨ï misleading), per-row RMW ¤«ï vline (®¤¨­ ¡ ©â = 2 £®à¨§®­â «ì­ëå ¯¨ªá¥«ï).
- [x] **8d** Bitmap font + gfx_text (libc/gfx/gfx_text.c): èà¨äâ ç¥à¥§ BIOS WIN_GET_ZG ($B8), interleaved layout `font[row*256+char]`, `gfx_text`/`gfx_putchar` ¤«ï 320 mode, `gfx_text16`/`gfx_putchar16` ¤«ï 640 mode á pair-table lookup.
‘¬. memory/sprinter_graphics.md, sprinter_accelerator.md, sprinter_graphics_16.md, sprinter_font_format.md.
Žâªàëâë¥ ¬¥«®ç¨ (­¥ ¡«®ª¨àãîâ):
- [ ] ˜à¨äâ-quad ¤«ï 640: per-cell ¯ «¨âà  (mode 0x82 à §à¥è ¥â 1 ¨§ 4 ¯ «¨âà per 16?8 cell) ? ç¥à¥§ ¯àאַ© ¤®áâ㯠ª area-®¯¨á ­¨ï íªà ­  0x0300..0x039F
## Auto-banking (á¬. `memory/banking_roadmap.md` ¤«ï ¤¥â «¥©)
Phase 1 ? file-level bin-packing ? ॠ«¨§®¢ë¢ âì ª®£¤  ¯à®¥ªâ ¯¥à¥à áâñâ ~30 KB ª®¤ .
- [ ] `toolchain/auto_bank.py`:
-  àá¨â à §¬¥àë ¨§ `.rel`-ä ©«®¢ (¨«¨ ¨§ .map ¯®á«¥ dry-run link' )
- First-fit-decreasing bin-packing
- “¢ ¦ ¥â `#pragma codeseg BANKn` ª ª manual override
- ¥à¥«¨­ª®¢ë¢ ¥â á ­®¢ë¬¨ `-Wl-b_BANKn=...` ¯ à ¬¥âà ¬¨
- ¥ç â ¥â ¯« ­ à á¯à¥¤¥«¥­¨ï
Phase 2-5: incremental rebalance, declarative `banks.toml`, function-level, call-graph-aware. ’®«ìª® ¥á«¨/ª®£¤  ¯®­ ¤®¡¨âáï.
## Bank-local static data (mutable data ¢ ⮬ ¦¥ ¡ ­ª¥ çâ® ¨ ª®¤) ? ? ƒŽ’Ž‚Ž
- [x] ਬ¥à `examples/bank_local_data/` ? äã­ªæ¨ï ¢ BANK1 ᮠ᢮¨¬ writable BSS array + const table + malloc-â¥áâ
- [x] `mkexe -p 0` ¤«ï ­ã«¥¢®£® padding ¡ ­ª®¢ (BSS-storage ®¡­ã«ï¥âáï ¯à¨ § £à㧪¥)
- [x] Š ­®­¨ç¥áª¨© à¥æ¥¯â: `--codeseg BANK1 --constseg BANK1 --dataseg BANK1` ¤«ï bank1.c + `-Wl-b_BANK1=0x1C000` ¤«ï «¨­ª®¢ª¨. **`--dataseg BANK1` Ž’€…’** ? à ­ìè¥ ª § «®áì ®¡à â­®¥ ¨§-§  trampoline bug ª®â®àë© ¬ áª¨à®¢ « १ã«ìâ â.
- [x] **Šà¨â¨ç­ë© 䨪á trampoline'a ¢ runtime/bank.s** ? áâ àë© `pop af; out (n), a` ª«®¡¡¥à¨« A ? ¢á¥ banked-ä㭪樨 ¢®§¢à é î騥 uint8_t â¨å® ¢®§¢à é «¨ ¬ãá®à. ®¢ë© `pop bc; out (c), b` á®åà ­ï¥â A.
- [x] **malloc ¨§ banked-ä㭪樨 à ¡®â ¥â ¯à®§à ç­®** ? heap ¦¨¢ñâ ¢ W2 (HOME), W2 ­¨ª®£¤  ­¥ ᢠ¯ ¥âáï trampoline'®¬, pointer ¢ «¨¤¥­ ¨§ «î¡®£® ª®­â¥ªáâ . ‘¬. memory/bank_local_data_pattern.md.
- [x] „®ªã¬¥­â æ¨ï ¢ memory: `memory/bank_local_data_pattern.md` (¯®«­ë© à¥æ¥¯â + malloc + nuances), `memory/sdcc_banking.md` (trampoline fix)
- [ ] Ž¯æ¨®­ «ì­® ? à áè¨à¨âì `check_banks.py` çâ®¡ë ¯®ª §ë¢ âì à §¡¨¢ªã size = code + const + bss per bank (cosmetic)
‡ ç¥¬: ¤«ï ¬®¤ã«¥© á ¡®«ì訬 private state (level loader, audio engine, scene data). ª®­®¬¨â W2 heap ¤«ï ¤¨­ ¬¨ª¨,   áâ â¨ª  ®áâ ñâáï ¢ ¡íª¥.
## ®¤áª §ª¨ ¨§ solid-c (­ â¨¢­ë© Sprinter C ? `third_party/solid-c/`)
®á«¥  ­ «¨§  solid-c'®¢áª®© libc (á¬. `memory/solid_c_findings.md`) ¢ë¥­ë £®â®¢ë¥ ¯ ââ¥à­ë ¤«ï á«¥¤ãîé¨å ­¥¤®áâ îé¨å ä㭪権. ਮà¨â¥â ®â **¢ë᮪®£®** ª ­¨§ª®¬ã:
### High-priority gaps («¥£ª® ¯®àâ¨à®¢ âì, ¡®«ìè ï ¯®«ì§ )
- [x] **`errno` + `strerror`/`perror`** ? â ¡«¨çª  32 ®è¨¡®ª (libc/io/errno.c)
- [x] ** áè¨à¥­­ë© `open()`** ¤«ï O_CREAT/O_TRUNC/O_APPEND/O_EXCL state machine
- [x] **`atexit`** ? 8-callback LIFO + `exit()` + `_exit()` (libc/io/atexit.c)
- [x] **`setjmp`/`longjmp`** ? 6-¡ ©â jmp_buf={sp,ix,pc} (libc/io/setjmp.c)
- [x] **`sleep(seconds)`** ? 50Hz halt-loop (libc/io/sleep.c)
- [x] **ESTEX ENV API** ($46, getenv/putenv) ? libc/io/env.c. “竨 doc-bug: ॠ«ì­® A=0 íâ® NOT FOUND
### Medium-priority (­ã¦­® ¤«ï shell-like ã⨫¨â)
- [ ] **Mouse driver** ? `rst $30h`, 17 ä㭪権. **‘­ ç «  â¥áâ çâ® à ¡®â ¥â ¢ MAME**.
- [x] **`ffirst`/`fnext` + ffblk_t struct** ¤«ï directory listing ? ॠ«¨§®¢ ­®, demo: ls.exe
- [x] **`getdatetime`/`setdatetime`** ç¥à¥§ ESTEX $21/$22 ? libc/io/time.c, demo: time_dir_test
- [x] **`chdir`/`getcwd`/`mkdir`/`rmdir`** ? wrappers ¤«ï ESTEX $1B-$1E ? libc/io/fsdir.c
- [x] **conio: `kbhit`/`getch`/`getche`/`cputs`/`clrscr`/`gotoxy`** ? ॠ«¨§®¢ ­®
- [x] **conio extras**: `wherex`/`wherey` ($53), `wrchar`/`rdchar` ($58/$57), `textmode_get/set` ($50/$51), `clrscr_attr` ($56) + COLOR macros
### Low-priority ? ? FILE* stack ƒŽ’Ž‚Ž
- [x] **Œ¨­¨¬ «ì­ë© unbuffered FILE\*** ? `libc/stdio/file.c` + `libc/include/stdio.h`. fopen/fclose/fputs/fgets/fread/fwrite/fseek/ftell/rewind/feof/ferror/clearerr/fflush + stdin/stdout/stderr ª ª pseudo-streams. ‘¬. `memory/file_star_design.md` ¨ `examples/filetest`.
- [ ] fprintf / fscanf ? ­ã¦­  printf-ç¥à¥§-callback machinery. ®ª  ¯®«ì§®¢ â¥«ì ¬®¦¥â `sprintf(buf, ...) + fputs(buf, fp)`.
- [ ] Ž¯æ¨®­ «ì­ë© buffered mode (setvbuf, line/block buffering) ? ¥á«¨ ª®£¤ -â® ¯®­ ¤®¡¨âáï.
### POSIX time API ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/posix_time.c` ? time/localtime/gmtime/mktime/asctime/ctime ¯®¢¥àå getdatetime. SDCC's time.rel ¨§¡¥£ ¥¬ (­¥«ì§ï override _RtcRead). ‘¬. `examples/ptime`.
### sys/stat ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/stat.c` ? POSIX stat/fstat. ƒ¨¡à¨¤ open+fstat ¤«ï ä ©«®¢, ffirst+iter ¤«ï ¯ ¯®ª (¢ª«îç ï "."/".."). ‘¬. `examples/stattest` ¨ `memory/estex_ffirst_dotdot.md`.
### assert ? ? ƒŽ’Ž‚Ž (¨á¯®«ì§ã¥¬ SDCC's __assert ç¥à¥§ fallback include path)
## libc/stdlib ? ? ­¥ ­ã¦­® ¤¥« âì (á¬. memory/sdcc_stdlib_works.md)
஢¥à¥­® ç¥à¥§ `examples/stdlib_test/`: SDCC z80.lib ᮤ¥à¦¨â à ¡®â î騥 ॠ«¨§ æ¨¨:
- `atoi/atol/atof, strtol/strtoul, rand/srand, qsort/bsearch, abs/labs, div/ldiv`
- ®«­ë© `<string.h>` (memchr/cmp/set/cpy, strcat/cmp/cpy/len/chr/spn/etc.)
- `<ctype.h>` (toupper/tolower)
- `<math.h>` (sinf/cosf/sqrtf/etc.)
‹¨­ª¥à  ¢â®¬ â¨ç¥áª¨ âﭥ⠨§ z80.lib ª®£¤  ­ã¦­®. **… ¯¥à¥¯¨á뢠âì**.
 è¨ Sprinter-specific ®¡ï§ â¥«ì­ë¥ ¬®¤ã«¨ ®áâ îâáï: atexit, env, errno, setjmp, putchar/puts/getchar, conio, fsdir, time, mouse, open/read/lseek/close.
## Build-system: libsprinter.lib + sprinter-cc ? ? ƒŽ’Ž‚Ž
- [x] `lib/Makefile` ? ᮡ¨à ¥â ª ¦¤ë© libc/*.c ¢ `.rel`,  à娢¨àã¥â ç¥à¥§ sdar ¢ `lib/sprinter.lib`
- [x] ‚ª«îç ¥â runtime/bank.s ¨ runtime/heap.s (auto-pulled ¯à¨ __banked/malloc)
- [x] `bin/sprinter-cc` ? bash-wrapper: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨© `--crt0=default|minimal|banked`, `--bank N=FILE.c`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
- [x] `examples/hello_sccc/` ? ¤¥¬®: `hello.c` ᮡ¨à ¥âáï §  ®¤¨­ shell-¢ë§®¢, à §¬¥à ᮢ¯ ¤ ¥â á àãç­ë¬ Makefile (925 ¡ ©â)
- [x] Split `putchar.c` ? `putchar.c` + `puts.c` ¤«ï per-function granularity (puts override SDCC's z80.lib version)
- [x] ‚ª«îçñ­ ¢ `make all` (§ ¢¨á¨¬®áâì `lib` ¯¥à¥¤ `examples`)
‚®§¬®¦­ë¥ ã«ãç襭¨ï (®¯æ¨®­ «ì­®):
- [ ] Œ¨£à¨à®¢ âì ®áâ «ì­ë¥ examples ­  sprinter-cc ¢¬¥áâ® àãç­ëå Makefile (ª®á¬¥â¨ª )
- [ ] „ «ì­¥©è ï ¤¥ª®¬¯®§¨æ¨ï libc/*.c per-function (­® ⥪ãé ï granularity 㦥 ¤ ñâ ­ã¦­ë© à §¬¥à ? «¨­ª¥à ¯ ª¥âã¥â .rel 楫¨ª®¬, ¨ ¤«ï ¡®«ì設á⢠ ä ©«®¢ íâ® ®¤­  äã­ªæ¨ï)
## â ¯ 9 ? memory modes ¤«ï sprinter-cc
DSS ¢ë¤¥«ï¥â áâà ­¨æë ¯ ¬ï⨠¯® à §¬¥à㠯ਫ®¦¥­¨ï: < 16 KB ? ®¤­  áâà ­¨æ , ¢ ®áâ «ì­ë¥ ®ª­  ¯®¤ª«îç ¥âáï ?áâà ­¨æ  #FF? (read=0xFF, write ¨£­®à¨âáï). ˆ§-§  í⮣® CODE-¢-W1 + DATA-¢-W2 ¤«ï ¬ «¥­ìª®© ¯à®£à ¬¬ë ¬®«ç  «®¬ ¥âáï. ‘¬. [memory/sprinter_memory_modes.md](../../.claude/projects/-Volumes-SAM8-Projects-DIY-Z80-Sprinter-C-Compiler/memory/sprinter_memory_modes.md).
- [x] **`tiny`**: ¢áñ (CODE+DATA+á⥪) ¢ W2. Default. Verified hello/argv/conio/malloc/file/etc.
- [x] **`--memory MODE` ä« £ ¢ sprinter-cc**: parser + per-mode ¤¥ä®«âë CODE_LOC/DATA_LOC, override ç¥à¥§ ï¢­ë¥ `--code-loc`/`--data-loc`. tiny à ¡®â ¥â; small/big/huge ª®¬¯¨«¨àãîâáï á warning'®¬ (runtime ­¥ £®â®¢). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--memory-manual SPEC`**: ¯ àá¨â `CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`small` runtime**: `runtime/crt0_small.s` ¨á¯®«ì§ã¥â ESTEX `$3D GETMEM` + `$3A SETWIN2` çâ®¡ë ¢ë¤¥«¨âì ¨ § ¬ ¯¨âì W2-áâà ­¨æã „Ž gsinit. **…** BIOS `$C4` ? á⥪ ­  í⮬ íâ ¯¥ ¢ W1 (boot_stack ¢ HOME),   BIOS âॡã¥â á⥪ ¢ W2. ®á«¥ ¬ ¯¯¨­£  SP ¯¥à¥ª«îç ¥âáï ­  0xBFFE, ¤ «ìè¥ áâ ­¤ àâ­ë© flow. ¥ «¨§®¢ ­® 2026-05-30, verified hello.exe.
- [x] **`small` auto-detect ¤«ï >16 KB ¯à®£à ¬¬**: `crt0_small.s` ç¨â ¥â ¯®àâ `0xC2` (⥪ãé ï áâà ­¨æ  ¢ W2 ? ­¥ `0xA2`! íâ® W1). …᫨ 0xFF ? ¢ë¤¥«ï¥â page; ¨­ ç¥ DSS 㦥 ᤥ« «  íâ® (¯à®£à ¬¬  á ¬  ¢ë«¥§«  ¢ W2). ޤ¨­ crt0 ¯®ªà뢠¥â 0..30 KB. mkexe â ª¦¥ à §à¥è ¥â HOME span W1+W2 (0x4000..0xBFFF). Verified hello: small (5 KB ä ©«, SETWIN2 path) + 32 KB ä ©« (auto-skip). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`big` runtime** (tiny + banked code ¢ W1): ¯ à ¬¥âਧ®¢ «¨ `crt0_banked.s` + `bank.s` ç¥à¥§ `.ifdef BANK_W1` ? ¤à㣮© banking port (0xA2 vs 0xE2), ¤à㣮© load-addr (0x4000 vs 0xC000). sprinter-cc prepend'¨â `BANK_W1 = 1` ¯à¨ `--memory big`, ¯¥à¥¤ ñâ `mkexe -B 0x4000`. ਬ¥à `examples/banked_big/`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`huge` runtime** (small + banked code ¢ W3): merge W2-detect «®£¨ª¨ ¨§ `crt0_small.s` ¢ `crt0_banked.s`. ‘ãé¥áâ¢ãî騩 ¯à¨¬¥à `examples/banked/` ⥯¥àì ¨á¯®«ì§ã¥â MEMORY=huge. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--debug` ä« £**: prepend `DEBUG_RT = 1` ¢ crt0 + `-DDEBUG_RT` ¢ sdcc. Žâªà뢠¥â symbol `_w2_self_allocated` (uint8_t) ? runtime diagnostic ªâ®  ««®æ¨à®¢ « W2. ¥ «¨§®¢ ­® 2026-05-30.
### „¨§ ©­-à¥è¥­¨ï ¯® libc ¨ crt0
**ޤ­  `sprinter.lib`** à ¡®â ¥â ¤«ï ¢á¥å memory mode ? `.rel`-ç«¥­ë relocatable, SDLD ¤¥« ¥â dead-code elimination per-member (¡¥§ £à ä¨ª¨ ­¥ ¯®¤â¢ ¥â `gfx_core.rel` ¨ â.¤.). Verified hello vs malloc_test ç¥à¥§ map-ä ©«ë.
**`gfx.lib` ®â¤¥«ì­® ? … ­ã¦¥­**: dead-code elimination 㦥 à ¡®â ¥â.
**`libc_banked` (libc ¢ bank ¢¬¥áâ® HOME)** ? ¨¤¥ï ­  ¯®â®¬, ª®£¤  HOME (16 KB) § ¡¨â user-ª®¤®¬ + libc ¢ `huge` mode. ¥ «¨§ã¥âáï ç¥à¥§ `--codeseg BANK0` ¯à¨ ª®¬¯¨«ï樨 libc; trade-off: trampoline ~30 横«®¢ ­  ª ¦¤ë© libc-¢ë§®¢. ’ਣ£¥à: ॠ«ì­ ï ¯à®£à ¬¬  ã¯àñâáï ¢ HOME budget.
**HW-§ ¢¨á¨¬ë¥ ¬®¤ã«¨ ? `sprinter_home.lib` ®â¤¥«ì­®.** — áâì libc 䨧¨ç¥áª¨ ­¥ ¬®¦¥â ¡ëâì § ¡ ­ª®¢ ­  ¢ W3, ¯®â®¬ã çâ® ®­  Ž’€…’ á W3:
- `gfx_*` ? ¯¨è¥â ¢ ¢¨¤¥®¯ ¬ïâì `0xC000+` ¯®á«¥ swap W3 ­  video page
- `bank_io` (mem_alloc_pages/bank_read/bank_write) ? swap'¨â W3 ç¥à¥§ `OUT (0xE2)`
- ã¤ã騥 ISR ? ¯à¥à뢠­¨¥ ¬®¦¥â ¯à¨©â¨ ª®£¤  W3 ­  çñ¬ 㣮¤­®
‚ huge mode í⨠¬®¤ã«¨ „Ž‹†› ®áâ âìáï ¢ HOME (W1). Š®£¤  ¡ã¤¥¬ ¤¥« âì `libc_banked`, **®¤­®¢à¥¬¥­­®** ¢ë¤¥«ï¥¬ `sprinter_home.lib` (HOME-only) ¨§ `sprinter.lib` (bankable). ”¨­ «ì­ ï á奬 :
```
sprinter_home.lib HOME-only: gfx, bank_io, ISR shims
sprinter.lib bankable: printf, malloc, string, conio, stdio, env, ...
sprinter_banked.lib â®â ¦¥ sprinter.lib ­® --codeseg BANK0 (¤«ï huge)
```
’ਣ£¥à: ॠ«¨§ æ¨ï `--memory huge` runtime.
**crt0 ? ¯® ®¤­®¬ã ­  mode:**
- `crt0.s` ? ⥪ã騩, ¤«ï **tiny/big**: SP=0xBFFE, ¯ àá¨â argv (W2-à¥áãàá 㦥 ¢ë¤¥«¥­ DSS).
- `crt0_minimal.s` ? ⥪ã騩, ¤«ï tiny ¡¥§ argv.
- `crt0_small.s` ? **­®¢ë©, step 3**: ¤«ï **small/huge**,  ««®æ¨àã¥â W2 ç¥à¥§ `mem_alloc_pages` „Ž gsinit, ¬ ¯¯¨â ¢ ¯®àâ `0xA2`, ¯®â®¬ áâ ­¤ àâ­ë© flow.
- `crt0_banked.s` ? ⥪ã騩, ¤«ï **big**: trampoline-â ¡«¨æ  ¤«ï W3 ¡ ­ª®¢, CODE ¢ W2.
- `crt0_banked_small.s` ? **­®¢ë©**: huge = small (W2-alloc) + banked (W3 trampolines).
sprinter-cc ¯®¤¡¨à ¥â crt0 ¯® `--memory` mode (ᥩç á `--crt0=` íâ® override).
- [x] ** áâà ¨¢ ¥¬ë© à §¬¥à á⥪ **: ä« £ `sprinter-cc --stack-size BYTES`. Wrapper £¥­¥à¨àã¥â `heap_top.s` á `___sdcc_heap_end = stack_top + 1 - stack_size`, ®â¤¥«ì­ë© .rel «¨­ªã¥âáï per-program. Default ?1278 ¡ ©â (heap_top=0xBB00) ¨§ `runtime/heap_top.s`. ¥ «¨§®¢ ­® 2026-05-30.
ˆ­â¥à䥩á: `sprinter-cc --memory [tiny|small|big|huge|manual] [--memory-manual SPEC] [--stack-size N] foo.c`. `--memory-manual` ¨¬¥¥â á¬ë᫠⮫쪮 á `--memory manual`.
## Known issues / quirks
- **ESTEX $46 ENV API**: ? à ¡®â ¥â. „®ª-æ¨ï ¢ `DiskSyscalls.txt v1.6` ®è¨¡®ç­® ®¯¨á뢠¥â return-status ? A=0 íâ® NOT FOUND, ­¥ FOUND. ‡ ä¨ªá¨à®¢ ­® ¢ `memory/sprinter_platform.md`.
## ŽŸ‡€’…‹œ›… ‡€„€—ˆ „‹Ÿ V2 (¯®á«¥ ५¨§  v1)
### Turbo-C-style graphics API (BGI-like) ? **MUST ¤«ï v2**
 áè¨à¨âì ­ è `gfx_*` API ¤® ã஢­ï **Turbo-C `<graphics.h>`** (BGI) ¤«ï MS-DOS.
ணࠬ¬¨áâë ¯à¨¢ëªè¨¥ ª Turbo-C ¤®«¦­ë ¯¥à¥­®á¨âì £à ä¨ç¥áª¨© ª®¤ 1-¢-1.
**—â® ¤®«¦­® ¡ëâì** (­  ®á­®¢¥ Borland BGI):
Setup/teardown:
- `initgraph()` / `closegraph()` ? ã ­ á ᥩç á `gfx_init`/`gfx_done`, ¤®¡ ¢¨âì alias
- `getmaxx()` / `getmaxy()` ? ¬ ªà®á ­  GFX_WIDTH-1 / GFX_HEIGHT-1
- `cleardevice()` ? alias to gfx_clear
- `getgraphmode()` / `setgraphmode()` ? ã ­ á get_videomode/set_videomode
Color/palette:
- `setcolor(c)`, `getcolor()` ? current draw color
- `setbkcolor(c)`, `getbkcolor()` ? background color
- `setpalette(idx, c)` ? ¯ «¨âà  entry
- `getpalette(&info)` ? read all palette
Primitives (¬ë 㦥 ¨¬¥¥¬ íª¢¨¢ «¥­âë ? ¤®¡ ¢¨âì BGI-¨¬¥­  ª ª aliases):
- `putpixel(x, y, c)` ? ¥áâì ª ª gfx_putpixel
- `getpixel(x, y)` ? ­ã¦­® ॠ«¨§®¢ âì (RMW ®¡à â­®¥ ? IN)
- `moveto(x, y)`, `lineto(x, y)`, `linerel(dx, dy)` ? current point + line drawing
- `line(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_line
- `rectangle(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_rect (­® ¤à㣮© API: x1,y1,x2,y2 vs x,y,w,h!)
- `bar(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_fill_rect
- `bar3d(x1, y1, x2, y2, depth, topflag)` ? ­®¢®¥: rect + 3d edges
- `circle(x, y, r)`, `arc(...)`, `ellipse(...)`, `pieslice(...)` ? ­®¢ë¥ primitives
- `fillpoly()`, `drawpoly()` ? ¯®«¨£®­ë
- `floodfill(x, y, border_color)` ? § «¨¢ª 
Text on graphics screen:
- `outtext(s)` / `outtextxy(x, y, s)` ? ¥áâì ª ª gfx_text (alias)
- `settextstyle(font, dir, size)` ? multiple bitmap fonts
- `gettextsettings(&info)`
- `textwidth(s)` / `textheight(s)` ? measure
Image manipulation:
- `imagesize(x1, y1, x2, y2)` ? bytes needed for getimage
- `getimage(x1, y1, x2, y2, buf)` ? save rect to buffer
- `putimage(x, y, buf, op)` ? paste back with COPY_PUT/XOR_PUT/AND_PUT/OR_PUT/NOT_PUT
Clipping/viewport:
- `setviewport(x1, y1, x2, y2, clip)` ? drawing clip rect
- `getviewsettings(&info)`
- `clearviewport()`
- `setactivepage(p)` / `setvisualpage(p)` ? ¤¢®©­ ï ¡ãä¥à¨§ æ¨ï (Sprinter ¨¬¥¥â 2 screen)
Line style:
- `setlinestyle(style, pattern, thickness)` ? SOLID_LINE / DOTTED_LINE / etc.
- `getlinesettings(&info)`
**Acceptance:** ¯¥à¥­®á ⨯¨ç­®© Turbo-C BGI ¯à®£à ¬¬ë (à¨áãî饩 á ¨á¯®«ì§®¢ ­¨¥¬
moveto/lineto/circle/bar/setcolor) ¤®«¦¥­ à ¡®â âì ¡¥§ áãé¥á⢥­­ëå ¯à ¢®ª.
**Notes:**
- BGI fonts (TRIPLEX/SANS_SERIF/GOTHIC) ? ã ­ á ®¤¨­ BIOS font, ®áâ «ì­ë¥ ­ã¦­®
¤®¡ ¢¨âì (ª ª bitmap data ¢ lib)
- imagesize/getimage/putimage ? á ¬ë¥ ¢®áâॡ®¢ ­­ë¥ ¤«ï game/animation
- Active/visual page (¤¢®©­ ï ¡ãä¥à¨§ æ¨ï) ? Sprinter ¯®¤¤¥à¦¨¢ ¥â 2 graphics pages,
­ã¦¥­ API switching
‘¬. â ª¦¥ `examples/` Turbo C 2.x BGIDEMO ª ª reference çâ® ­ã¦­®.
### IM2 Interrupt Handlers ? **MUST ¤«ï v2**
User-§ ¤ ¢ ¥¬ë¥ ISR ç¥à¥§ Z80 IM 2 mode. ã¦­ë ¤«ï:
- Timer ticks (50 Hz frame counter, ¯« ¢­ ï  ­¨¬ æ¨ï)
- Music playback (AY, COVOX)
- Real-time games (input + game logic + render ¢ interrupt-driven)
- Async keyboard / mouse handling
**Status:** Ž’‹Ž†…Ž ¤® v2. ®«­ë© research + design ¢ `docs/im2_isr_design.md`.
**¥è¥­¨¥ ¯®  àå¨â¥ªâãà¥:** ॠ«¨§®¢ âì ª ª ®â¤¥«ì­ë© memory mode `--memory im2`
(¢¬¥á⮠⮣® çâ®¡ë «¥§âì ¢® ¢á¥ áãé¥áâ¢ãî騥 crt0). Detail'¨ ¢ design-doc.
**¥§î¬¥ research' ** (¯®«­ë© ⥪áâ ¢ `docs/im2_isr_design.md`):
- Vector 0xFF ? frame + keyboard + CBL. Disambiguation ¯® ¯®àâ ¬ 0x19 / 0xFE
- Mouse hardware-IRQ ­¥ ¯à¨å®¤¨â (­  ⥪ã饩 ¯« â¥)
- Vector table / ISR / stack ŽŸ‡€ ¡ëâì ¢ W2 (0x8000..0xBFFF)
- DSS ¨¬¥¥â ᢮© IM 2 handler ? ­ã¦­® chain'¨âìáï (¨­ ç¥ ª« ¢¨ âãà  / SYSTIME «®¬ îâáï)
### à®ç¨¥ ªàã¯­ë¥ ¯ã­ªâë ¤«ï v2
- [ ] **FILE API rewrite ? buffered streams** ? ⥪ãé ï ॠ«¨§ æ¨ï ¢
`libc/stdio/file.c` íâ® provisional unbuffered shim (ª ¦¤ë© fputc/fgetc
= ®¤¨­ read/write syscall). 㦭  ¯®«­®æ¥­­ ï buffered ᥬ ­â¨ª 
ª ª ¢ Solid-C:
```c
typedef struct {
uint flags; // +0..1 file status flags
int level; // +2..3 empty/fill level of buffer
char *curp; // +4..5 current active pointer
int fd; // +6..7 underlying low-level fd
char *buffer; // +8..9 data transfer buffer
char hold; // +10 ungetc byte if no buffer
short token; // +11..12 reserved
char dummy; // +13 reserved
} FILE;
```
stdin/stdout/stderr ? fd-¬ àª¥àë `0 / -1 / -2`. Žâà¨æ â¥«ì­ë¥ ¤«ï
stdout/stderr ¢ë¡à ­ë ­ ¬¥à¥­­®: ESTEX OPEN ¬®¦¥â ¢¥à­ãâì positive
small fd (1, 2, ?) ¤«ï ®¡ëç­®£® ä ©«  ? ¥á«¨ ¡ë stdout=1, ॠ«ì­ë©
fd=1 áâ «ª¨¢ «áï ¡ë á ¨¤¥­â¨ä¨ª â®à®¬. fd=0 ¤«ï stdin ¡¥§®¯ á­®
(ESTEX 0 ­¥ ¢®§¢à é ¥â). ‘ ¬¨ fd ­¥ ¯¥à¥¤ îâáï ¢ syscall'ë ?
¤¨á¯¥âç¥à¨§ æ¨ï ¯® ä« £ ¬ `_F_CONIN/_F_CONOUT`.
ਭâ¥à-¯®â®ª¨ (stdaux/stdprn) … ॠ«¨§ã¥¬ ? Sprinter ¯à¨­â¥à­®©
API ­¥ ¨¬¥¥â.
€«ìâ¥à­ â¨¢  ? ¢§ïâì ॠ«¨§ æ¨î ¨§ third_party/solid-c (sources ¢
`SRC/CLIB/`); â ¬ ¥áâì £®â®¢ë© buffered FILE + fopen/fread/fwrite/
fseek/setvbuf ¨ â.¤. €¤ ¯â¨à®¢ âì ª ­ è¨¬ open/read/write/lseek.
ਠrewrite § ®¤­® à¥è¨âì deferred issues stdio-review:
- `fwrite` short-write ¤®«¦¥­ áâ ¢¨âì `_F_ERROR`
- `fgets(buf, 1, fp)` ? áâ ­¤ àâ £®¢®à¨â "empty string", ¬ë ¢¥à­ã«¨ NULL
- `mode_to_flags` ? break-out ­  '+' (cosmetic)
- [ ] **Audio API** ? AY-3-8910 + COVOX ç¥à¥§ ¯à¥à뢠­¨ï (âॡã¥â IM2)
- [ ] **ISA-8 slot support** ? ZX-Bus ª àâë (sound, network, etc.) ? âॡã¥â IM2 + ç⥭¨ï port®¢
## à®ç¨¥ § ¤ ç¨ (v1 backlog, ­¥ ¡«®ª¨àãî騥)
- [x] **#9: text I/O split (Turbo-C style)** ? stdio (puts/printf/putchar) ⥯¥àì fast no-attr ç¥à¥§ PCHARS/PUTCHAR. conio (cputs/cprintf/putch) ¯à¨¬¥­ï¥â attr ç¥à¥§ textcolor/textbackground/textattr. KEEP_EXIST_ATTR ? conio fallback ­  fast path. Verified ¢ hello.exe. ‘¬. `memory/text_output_api_split.md`. ¥ «¨§®¢ ­® 2026-05-31.
- [x] **Mouse API ¯®«­ë©** (१¨¤¥­â­ë© driver, RST 30h) ? ¢á¥ 14 ä㭪権 ®¡ñà­ãâë (init/show/hide/refresh/read/goto/bounds/text_cursor/load_cursor/get_cursor/get/set_sensitivity/video_mode_changed). ‘¬. `memory/mouse_api.md`. Verified ¢ MAME 2026-05-31. Sensitivity = divider (¬¥­ìè¥ = ¡ëáâ॥).
- [ ] Interrupt handlers ? IM 2 vector table ¢ HOME ¤«ï user ISR'®¢
- [ ] ®¤¤¥à¦ª  `restore SP on EXIT` (¯ ââ¥à­ ¨§ z88dk +pps) ? ¯à®¢¥à¨âì ­ã¦­® «¨
- [ ] CI:  ¢â®¬ â¨ç¥áª¨ § ¯ã᪠âì MAME á `-aviwrite` ¤«ï screenshot-áà ¢­¥­¨ï, ç⮡ë â¥áâë ¯à¨¬¥à®¢ ¯à®å®¤¨«¨ ¡¥§ 祫®¢¥ª 
## ˆ¤¥¨ ­  ¯®â®¬
- ®¤¤¥à¦ª  `<setjmp.h>` (¥áâì ¢ SDCC stdlib ? ­ã¦­® ¯à®â¥áâ¨à®¢ âì çâ® ­ è crt0 ᮢ¬¥á⨬)
- `<time.h>` ç¥à¥§ ESTEX SYSTIME (`$21`) ¨ CMOS BIOS-ä㭪樨
- ZX Spectrum-ᮢ¬¥áâ¨¬ë© à¥¦¨¬ ª ª ®â¤¥«ì­ë© target (¤«ï ¯®àâ¨à®¢ ­¨ï ᯥªâà㬮¢áª¨å ¯à®£à ¬¬)
- ®¤¤¥à¦ª  ZX-Bus ª àâ (sound, network, etc.) ? ­ã¦­ë ¤à ©¢¥àë
- Profile-guided optimization tools (hot/cold detection) ¤«ï ªà㯭ëå ¯à®£à ¬¬
## Linker duplicate-symbol warnings (¡« £®¯à¨ïâ­ë¥, ®â䨫ìâ஢ ­ë)
Š®£¤  ¬ë á®§­ â¥«ì­® overrides'¨¬ SDCC z80.lib ä㭪樨 ᮡá⢥­­®© ¢¥àᨥ© ¢ `sprinter.lib`, `sdldz80` ¯¨è¥â `?ASlink-Warning-Definition of public symbol '...' found more than once`. ‹¨­ª¥à ¡¥àñâ ¯¥à¢®¥ ­ ©¤¥­­®¥ ®¯à¥¤¥«¥­¨¥ (­ è¥), ¯®í⮬㠯®¢¥¤¥­¨¥ ª®à४⭮¥ ? warning ⮫쪮 noise.
’¥ªã騥 overrides:
- `_puts` ? ­ è  ¢¥àá¨ï ç¥à¥§ PCHARS+\r\n vs SDCC posix puts
- `___sdcc_heap` ? ­ è heap ¢ W2 vs SDCC's áâ ­¤ àâ­ë©
- `_asctime`, `_localtime` (¨ ¢®§¬®¦­® ¤à㣨¥ ¨§ time) ? ­ è `posix_time.c` ç¥à¥§ ESTEX SYSTIME vs SDCC's `time.rel` ª®â®àë© § ¢¨á¨â ®â `_RtcRead`
**’¥ªã饥 à¥è¥­¨¥:** `bin/sprinter-cc` ®â䨫ìâ஢뢠¥â warning-¡«®ª (warning + 2 follow-up `Library:` áâப¨) ¨§ ¢ë¢®¤  `sdcc`. —¥à¥§ `-v` (verbose) ¢áñ ¯®ª §ë¢ ¥âáï. ¥ «¨§®¢ ­® ç¥à¥§ awk-pipe.
**‚®§¬®¦­ë¥ ã«ãç襭¨ï:**
- ¥à¥©â¨ ­  explicit `--nostdlib` + àãç­®© ᯨ᮪ ­ã¦­ëå ¬®¤ã«¥© ¨§ z80.lib (string, math, stdlib ¡¥§ override'­ãâëå) ? ã¡à âì ˆ‘’Ž—ˆŠ warning'®¢, ­¥ ¬ áª¨à®¢ âì
- ˆ«¨: ¯¥à¥¨¬¥­®¢ âì ­ è¨ `_puts` ? `_puts_sprinter` + alias ç¥à¥§ linker flag (­¥ 㢥७ çâ® SDCC ¯®¤¤¥à¦¨¢ ¥â)
- ˆ«¨: ®áâ ¢¨âì ª ª ᥩç á (à ¡®ç¥¥ ¨ benign) ? ¯à¨®à¨â¥â ­¨§ª¨©
## TODO: ¯à®¢¥à¨âì ­  ॠ«ì­®¬ ¦¥«¥§¥
- [ ] **Port_Y banking trick** (`docs/part2/SprinterGraphics programming.txt`):
¤®ªã ã⢥ত ¥â çâ® ¯®á«¥ `OUT (0x89), Y`  ¤à¥á  0xC000+0x400*N ¢ ®ª­¥ W3
¬ ¯¯ïâáï ­  áâப¨ Y..Y+15 (®¤­® ¯à®£à ¬¬¨à®¢ ­¨¥ ? 16 áâப).
Empirical 2026-06-01 ¢ MAME 0.283 íâ®â trick **­¥ à ¡®â ¥â** ? ¯¨ªá¥«¨
¯®  ¤à¥á ¬ ¢ëè¥ 0xC000+row_width ã室ïâ ¢ ­¥¢¨¤¨¬ãî ®¡« áâì. Š ­®­¨ç¥áª¨©
`docs/samples/plasma2.asm` ⮦¥ ­¥ ¨á¯®«ì§ã¥â banking, ¯¥à¥ãáâ ­ ¢«¨¢ ¥â
Port_Y per row.
« ­:
1. ®«ãç¨âì ¤®áâ㯠ª ॠ«ì­®¬ã Sprinter
2. ‡ ¯ãáâ¨âì â¥áâ dual-write (`_gfx_putpixel_raw` + ¢â®à®© write ¢ `0xD000+x`)
3. …᫨ ­  ¦¥«¥§¥ ¢¨¤­ë ¤¢®©­ë¥ «¨­¨¨ ? ¡ £  MAME, ®âªàëâì issue á
¬¨­¨¬ «ì­ë¬ ९à®
4. …᫨ ­  ¦¥«¥§¥ ⮦¥ ®¤­  «¨­¨ï ? ¤®ªã¬¥­â ­¥¢¥à­ë©, 㤠«¨âì 㯮¬¨­ ­¨¥
¨§ ¤®ª¨ ¨ ¯à®áâ® ®áâ ¢¨âì ⥪ãéãî ॠ«¨§ æ¨î (Port_Y per pixel)
5. …᫨ banking à ¡®â ¥â ­  ¦¥«¥§¥ ? ¢­¥¤à¨âì ªíè¨à®¢ ­¨¥ Port_Y ¢
`_gfx_putpixel_raw` (sentinel out-of-range, á¬. memory/gfx_port_y_banking.md)
‘¢ï§ ­­ë© ¢ë¨£àëè ¤«ï Bresenham (60-pixel ¤¨ £®­ «ì) ? ®ª®«® 8? ¬¥­ìè¥
OUT (0x89) ®¯¥à æ¨©, ¤«ï `gfx_fill_rect 320x256` ? 16? ¬¥­ìè¥. ¥ ¡«®ª¨àã¥â
release v1.
## GFX: à áè¨à¥­¨ï ¯® `docs/part2/accelerator_doc.txt`
®á«¥ ¯à®ç⥭¨ï ¤¥â «ì­®£® accelerator doc ¢ë¥­ë ­¥§ ªàëâë¥ ­ ¯à ¢«¥­¨ï.
‘¥©ç á ¢ ª®¤¥ ¨á¯®«ì§ã¥âáï ⮫쪮 £®à¨§®­â «ì­ë©/¢¥à⨪ «ì­ë© Fill mode.
### Quick wins ¤«ï ⥪ãé¨å primitives
- [ ] **‡ ¬¥­¨âì SMC ­  `LD A, (var)` ¤«ï block-size**. „®ªã¬¥­â ®
à §à¥è ¥â `LD A, (HL)`, `LD A, (BC)`, `LD A, (DE)` (­® ­¥ `LD A, r`).
â® ã¡¥àñâ SMC complexity ¢ `gfx_lines.c:hfill_chunk/vfill_chunk` ¨
`gfx_16.c:g16_hfill_chunk`. ‡ ¯à¥é¥­® ⮫쪮 register-to-register.
- [ ] **Šíè¨à®¢ ­¨¥ block-size**. „®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel § ¯®¬¨­ ¥â
block size ¬¥¦¤ã bursts (á¬. `Horizontal_Line_Fill`: ãáâ ­ ¢«¨¢ îâ
size + `LD B,B` ®âª«î祭¨¥, ¯®â®¬ ¢ª«îç îâ Fill mode ¨ ¨á¯®«ì§ãîâ
á®åà ­ñ­­ë© size). „«ï `gfx_fill_rect` á 100 ®¤¨­ ª®¢ë¬¨
áâப ¬¨ ? ãáâ ­®¢¨âì size 1 à §,   ­¥ 100.
### Bank-prefix modes (port 0xE2 bits)
„®ªã¬¥­â ¯®ª §ë¢ ¥â âਠ¢ à¨ ­â  ¡ ­ª  ¢¨¤¥®áâà ­¨æë ¯®¬¨¬® áâ ­¤ àâ­®£® 0x50:
| Bank byte | Effect |
|---|---|
| 0x50 | Normal write ? ¯¨è¥âáï ¢ shadow + ¢¨¤¨¬ë© |
| 0x54 | "no copy in main shadow RAM" |
| 0x58 | **"FF is transparent"** ? ¡ ©â 0xFF ¯à¨ write ®áâ ¢«ï¥â background |
| 0x5C | both |
Bank 0x58 ®¡êïá­ï¥â ¯®ç¥¬ã mouse cursor à¨áã¥âáï á 0xFF-¯à®§à ç­®áâìî.
â® ¯ãâì ª **sprite-blending ç¥à¥§ accel block copy**:
- [ ] **`gfx_set_bank_transparent(on)`** ¨«¨ ä« £ ¢ `gfx_set_bank` ¤«ï
¢ë¡®à  0x50/0x58 ¯à¨ ®âà¨á®¢ª¥ sprite'®¢
- [ ] ˆá¯®«ì§®¢ âì ¢ ­®¢®¬ `gfx_blit()` çâ®¡ë ¯® ä ªâã ¯®«ãç âì
transparent sprites ç¥à¥§ accel-ª®¯¨î
### Block copy mode (sprite blit'ë)
`LD L,L` (horizontal) ¨ `LD A,A` (vertical) ? ०¨¬ ª®¯¨à®¢ ­¨ï ¡«®ª  ç¥à¥§
256-¡ ©â­ãî accel memory. â® ¡ §¨á ¤«ï blit'®¢.
- [ ] **`gfx_blit(src_data, x, y, w, h)`** ? ª®¯¨à®¢ ­¨¥ sprite' 
(¯à®¨§¢®«ì­ë© à §¬¥à, ç¥à¥§ accel)
- [ ] **`gfx_blit_transparent(src, x, y, w, h)`** ? á ¨á¯®«ì§®¢ ­¨¥¬ bank 0x58
‘¬. `Draw_Restangle_Data` ¢ accelerator_doc.txt ª ª à¥ä¥à¥­á.
### AND / OR / XOR operations ç¥à¥§ accel
„®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel ¯®¤¤¥à¦¨¢ ¥â «®£¨ç¥áª¨¥ ®¯¥à æ¨¨ á ¡«®ª ¬¨
¤ ­­ëå. ਬ¥­¥­¨ï:
- XOR ? ¨­¢¥àá¨ï ®¡« á⨠(¢ë¤¥«¥­¨¥ selection ¢ UI)
- OR / AND ? masking, alpha-style blending
- ‘¬. ¯à¨¬¥à ¢ accelerator_doc.txt: "256 bytes block coding via XOR"
- [ ] **`gfx_xor_rect`** / **`gfx_or_rect`** / **`gfx_and_rect`** ?
¯à¨¬¨â¨¢ë «®£¨ç¥áª¨å ®¯¥à æ¨© ­ ¤ ¯àאַ㣮«ì­¨ª®¬
- [ ] **`gfx_invert_rect(x, y, w, h)`** ? alias ­  xor á 0xFF
### Bitmap fonts à §­ëå à §¬¥à®¢
‘¥©ç á `gfx_text` / `gfx_putchar` å à¤ª®¦¥­­® à ¡®â îâ á 8?8 èà¨ä⮬
(BIOS WIN_GET_ZG ¢®§¢à é ¥â 256?8 ¡ ©â). „«ï ¡ã¤ãé¨å UI / â¨âã«ì­¨ª®¢
­ã¦­ë:
- [ ] **`gfx_set_font_size(w, h)`** ? ¯¥à¥ª«îç¨âì è¨à¨­ã/¢ëá®âã glyph' 
- [ ] **`gfx_set_font_data(ptr, w, h, advance)`** ? § ¬¥­¨âì 㪠§ â¥«ì
­  ¯®«ì§®¢ â¥«ì᪨© èà¨äâ + à §¬¥àë
- [ ] ®¤¤¥à¦ª  **proportional** (advance != w) èà¨ä⮢ ? ¤®¡ ¢¨âì
array advance[256] ­  è¨à¨­ã ª ¦¤®£® glyph' 
- [ ] **Big-font ०¨¬ë**: 8?16, 16?16, 16?8 (¤«ï â¨âã«ì­¨ª®¢)
- [ ] ‚®§¬®¦­® ®â¤¥«ì­ë© API `gfx_text_ex(x, y, str, font_id)` £¤¥
font_id ¢ë¡¨à ¥â ®¤¨­ ¨§ § £à㦥­­ëå èà¨ä⮢
- [ ] **Anti-alias 2-bit èà¨äâë** (¡¨â ä®­ / ¡¨â £à ­¨æ  / 2-¡¨â alpha?)
? far future, ¤«ï smooth UI
## ”¨­ «ì­ë© íâ ¯ ®¯â¨¬¨§ æ¨© (­¥ ᥩç á)
- **`gfx_line` ç¥à¥§ accel ¤«ï ¯®«®£¨å ¤¨ £®­ «¥©** ? Bresenham ¤«ï «¨­¨¨ á |dy| << |dx| (¨«¨ ­ ®¡®à®â) ¢ë¤ ñâ ¤«¨­­ë¥ runs ®¤¨­ ª®¢®£® Y (¨«¨ X): ¯¨ªá¥«ì, ¯¨ªá¥«ì, ¯¨ªá¥«ì, è £ Y, ¯¨ªá¥«ì, ¯¨ªá¥«ì... Š ¦¤ë© â ª®© run ? íâ® £®â®¢ë©  à£ã¬¥­â ¤«ï `gfx_hline` (¨«¨ `vline`).
« ­ ¨áá«¥¤®¢ ­¨ï: ¯®áç¨â âì ¤«¨­ã runs ª ª äã­ªæ¨î ®â ­ ª«®­ ; à¥è¨âì ¬¨­¨¬ «ì­ë© run length, ¯à¨ ª®â®à®¬ ¢ë£®¤­¥¥ accel hline 祬 N?putpixel (overhead accel ~20?s, putpixel ~5?s ? accel ¢ë£®¤­¥¥ ¯à¨ run ? 4-5 px); ¤«ï ªàãâëå ¤¨ £®­ «¥© (dx ? dy) ®áâ ¢¨âì Bresenham, ¤«ï ¯®«®£¨å ? run-length-based fill.
‘¥©ç á `gfx_line` orthogonal cases 㦥 ç¥à¥§ accel ? ®¯â¨¬¨§¨à®¢ âì ⮫쪮 ª®áë¥.
- **`gfx_fill_rect` á ®¤­¨¬ W3-swap ­  ¢áî ®¯¥à æ¨î** ? ᥩç á ª ¦¤ë© ¢­ãâ७­¨© `gfx_hline`/`gfx_vline` ¤¥« ¥â ᢮© DI/save-W3/restore-W3/EI. Œ®¦­® ᤥ« âì internal `_fill_rect_inner` ª®â®àë© ¤¥à¦¨â W3 § ¬ ¯«¥­­ë¬ ¨ DI ¢¥áì æ¨ª«; ~20?s ? ª®«¨ç¥á⢮ áâப/á⮫¡æ®¢ íª®­®¬¨¨. ਬ¥­¨¬® ª® ¢á¥¬ ª®¬¯®§¨â­ë¬ ¯à¨¬¨â¨¢ ¬.
# MDView ? à®á¬®âà騪 Markdown ¤«ï Sprinter
**MDView** ? ¯à®£à ¬¬  ¤«ï ¯à®á¬®âà  ¤®ªã¬¥­â®¢ ¢ ä®à¬ â¥ *Markdown* ­  ª®¬¯ìîâ¥à¥
Sprinter (¯à®æ¥áá®à Z80). „®ªã¬¥­â åà ­¨âáï ¢ ®â¤¥«ì­®¬ W3 ®ª­¥ ¨ ­¥ § ­¨¬ ¥â
®á­®¢­ãî RAM ¯à®£à ¬¬ë.
## ‚®§¬®¦­®áâ¨
- „®ªã¬¥­âë ¤® **128 Š** (8 áâà ­¨æ EMM ¯® 16 Š ª ¦¤ ï)
- „® **16 384** íªà ­­ëå áâப ¢ ¨­¤¥ªá¥
- €¢â®¬ â¨ç¥áª¨© ¯¥à¥­®á á«®¢ ¯® è¨à¨­¥ íªà ­  (80 á⮫¡æ®¢)
- ƒ®à¨§®­â «ì­ë© ᤢ¨£ ¤«ï è¨à®ª¨å áâப (¡«®ª¨ ª®¤ , â ¡«¨æë)
- ‘â âãá-¡ à: ¨¬ï ä ©« , ¤¨ ¯ §®­ áâப, ¯à®æ¥­â ¯à®ªàã⪨
- ‘¯¨­­¥à ¢ áâப¥ á®áâ®ï­¨ï ¢® ¢à¥¬ï § £à㧪¨ ¨ ¨­¤¥ªá æ¨¨
- ®¤¤¥à¦ª  ?¬ï£ª®£®? ᪫¥¨¢ ­¨ï áâப ¢  ¡§ æ å ¨ æ¨â â å
## ‡ ¯ãáª
```
mdview [¨¬ï_ä ©« .md]
```
…᫨ ¨¬ï ä ©«  ­¥ § ¤ ­®, § £à㦠¥âáï `README.MD`.
## “¯à ¢«¥­¨¥
```
Š« ¢¨è  „¥©á⢨¥
ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Up Down பàã⪠ ­  ®¤­ã áâப㠢¢¥àå / ¢­¨§
PgUp PgDn பàã⪠ ­  áâà ­¨æã (30 áâப)
Home  ç «® ¤®ªã¬¥­â 
End Š®­¥æ ¤®ªã¬¥­â 
Left Right ƒ®à¨§®­â «ì­ë© ᤢ¨£ (⮫쪮 nowrap-áâப¨)
F1 Žª­® á¯à ¢ª¨
F8 Š®¤¨à®¢ª : CP866 ? CP1251 ? KOI8-R ? UTF-8 ? ...
F10 / Esc ‚ë室 ¨§ ¯à®£à ¬¬ë
```
Š®¤¨à®¢ª  ®¯à¥¤¥«ï¥âáï  ¢â®¬ â¨ç¥áª¨ ¯à¨ ®âªàë⨨ (BOM + í¢à¨á⨪  ¯®
¯¥à¢ë¬ 4 Š); `F8` ¯¥à¥ª«î砥⠥ñ ¢àãç­ãî, ¥á«¨ ¤¥â¥ªæ¨ï ®è¨¡« áì.
8-¡¨â­ë¥ ª®¤¨à®¢ª¨ (CP866/CP1251/KOI8-R) ¯¥à¥ª«îç îâáï ¬£­®¢¥­­® (६ ¯ ­ 
®âà¨á®¢ª¥). ‚â®à®© ­ ¡®à ¨­¤¥ªá/ªíè  (­ ¯à¨¬¥à UTF-8) áâநâáï «¥­¨¢® ? ¯à¨
¯¥à¢®¬ ¯¥à¥ª«î祭¨¨ ¢ ­¥£® (ª®à®âª ï ¯ ã§  ᮠᯨ­­¥à®¬), ¤ «ìè¥ ¬£­®¢¥­­®.
## ‘¨­â ªá¨á Markdown
### ‡ £®«®¢ª¨
®¤¤¥à¦¨¢ îâáï ã஢­¨ H1?H4. “஢­¨ H5 ¨ H6 ®â®¡à ¦ îâáï ª ª H4.
# ‡ £®«®¢®ª ¯¥à¢®£® ã஢­ï
## ‡ £®«®¢®ª ¢â®à®£® ã஢­ï
### ‡ £®«®¢®ª âà¥â쥣® ã஢­ï
#### ‡ £®«®¢®ª ç¥â¢ñà⮣® ã஢­ï
### ’¥ªá⮢®¥ ä®à¬ â¨à®¢ ­¨¥
**†¨à­ë© ⥪áâ** ¢ë¤¥«ï¥âáï ¤¢®©­ë¬¨ §¢ñ§¤®çª ¬¨: `**⥪áâ**`
*Šãàᨢ* ¢ë¤¥«ï¥âáï ®¤¨­®ç­ë¬¨ §¢ñ§¤®çª ¬¨ `*⥪áâ*` ¨«¨ §­ ª®¬ ¯®¤çñન¢ ­¨ï `_⥪áâ_`
`‚áâ஥­­ë© ª®¤` ®¡®§­ ç ¥âáï ®¡à â­ë¬¨ ª ¢ë窠¬¨
~~‡ çñભãâë© â¥ªáâ~~ ? ¤¢®©­ë¥ ⨫ì¤ë: `~~⥪áâ~~`
### ¥­ã¬¥à®¢ ­­ë© ᯨ᮪
Œ àª¥àë `-`, `*` ¨«¨ `+`:
- ¥à¢ë© ¯ã­ªâ ᯨ᪠
- ‚â®à®© ¯ã­ªâ ᯨ᪠
- ’à¥â¨© ¯ã­ªâ á ¤®áâ â®ç­® ¤«¨­­ë¬ ⥪á⮬, ª®â®àë© ¯à¨ ­¥®¡å®¤¨¬®áâ¨
¡ã¤¥â ¯¥à¥­¥áñ­ ­  á«¥¤ãîéãî áâபã á á®åà ­¥­¨¥¬ ®âáâ㯠
### 㬥஢ ­­ë© ᯨ᮪
1. ¥à¢ë© í«¥¬¥­â
2. ‚â®à®© í«¥¬¥­â
3. ’à¥â¨© í«¥¬¥­â
### –¨â â 
> «®ª æ¨â âë ­ ç¨­ ¥âáï á ᨬ¢®«  `>`. ¥áª®«ìª® ¯®á«¥¤®¢ â¥«ì­ëå
> áâப ®¤­®© æ¨â âë ᪫¥¨¢ îâáï ¢ ¥¤¨­ë©  ¡§ æ á  ¢â®¬ â¨ç¥áª¨¬
> ¯¥à¥­®á®¬ á«®¢.
### «®ª ª®¤  (verbatim)
«®ª ª®¤  § ª«îç ¥âáï ¢ âன­ë¥ ®¡à â­ë¥ ª ¢ë窨. ‚­ãâਠ¡«®ª 
⥪á⠮⮡ࠦ ¥âáï ?ª ª ¥áâì? ¡¥§ à §¡®à  Markdown:
```
#include <stdio.h>
#include <sprinter.h>
int main(void) {
puts("Hello, Sprinter!");
return 0;
}
```
### ƒ®à¨§®­â «ì­ ï «¨­¨ï
’ਠ¨«¨ ¡®«¥¥ ᨬ¢®«®¢ `---`, `***` ¨«¨ `___` ­  ®â¤¥«ì­®© áâப¥:
---
## ’¥å­¨ç¥áª¨¥ å à ªâ¥à¨á⨪¨
- **« âä®à¬ :** Sprinter, ¯à®æ¥áá®à Z80 @ 21 Œƒæ
- **Š®¤¨à®¢ª¨:** CP866 / CP1251 / KOI8-R / UTF-8 ( ¢â®®¯à¥¤¥«¥­¨¥, `F8`)
- **Œ ªá¨¬ «ì­ë© à §¬¥à ä ©« :** 128 Š
- **Œ ªá¨¬ «ì­®¥ ç¨á«® áâப ¢ ¨­¤¥ªá¥:** 16 384
- **Œ ªá¨¬ «ì­ ï ¤«¨­  áâப¨ ¢ ७¤¥à-ªíè¥:** 255 ï祥ª (á¬. ®£à ­¨ç¥­¨¥ ­¨¦¥)
- **¥¦¨¬ ¯ ¬ïâ¨:** small
- Š®¤ ¯à®£à ¬¬ë, c⥪, ¤ ­­ë¥, ªãç  ? ®ª­a W1-W2 (32 Š,  ¤à¥á  0x4000?0xBFFF).
- ãä¥à ä ©«  ? áâà ­¨æë EMM, ®â®¡à ¦ ¥¬ë¥ ¢ W3 (0xC000?0xFFFF)
## ˆ§¢¥áâ­ë¥ ®£à ­¨ç¥­¨ï
### „«¨­  áâப¨ ¢ MD-०¨¬¥ ? 255 ï祥ª
¥­¤¥à-ªíè åà ­¨â ª ¦¤ãî «®£¨ç¥áªãî áâப㠪 ª **­¥ ¡®«¥¥ 255 ¯ à (ᨬ¢®«,  âਡãâ)**
? ª®­áâ ­â  `MAX_CACHE_LINE_LEN`. ‹¨¬¨â § ¤ ­ ⨯ ¬¨: `g_ncells` ¨
`cache_rec_t.len` ? `uint8_t`. Š á ¥âáï ¢á¥å áâப, ­® § ¬¥â­¥¥ ¢á¥£® ­ 
**£®à¨§®­â «ì­® áªà®««¨à㥬ëå** áâப å (¡«®ª¨ ª®¤  ¨ áâப¨ â ¡«¨æ, ä« £
`IF_HSCROLL`), ª®â®àë¥ ¢ MD-०¨¬¥ ¬®¦­® «¨áâ âì ¢¯à ¢®.
**—â® ¯à®¨á室¨â á ¡®«¥¥ ¤«¨­­®© áâப®©:** ¯à¨ ¨­¤¥ªá æ¨¨ `gc_put()` ¬®«ç 
®â¡à á뢠¥â ª ¦¤ãî ï祩ªã ¯®á«¥ 255-© (`if (g_ncells < MAX_CACHE_LINE_LEN)`).
‚ ªíè ¯®¯ ¤ îâ ⮫쪮 ¯¥à¢ë¥ 255 ï祥ª, ®áâ â®ª **â¥àï¥âáï** ? ¤® ­¥£® ­¥«ì§ï
¤®áªà®««¨âì ¨ **­¥â ¬ àª¥à  ®¡à¥§ª¨** ­  255-© ¯®§¨æ¨¨ (¬ àª¥à `>` ®§­ ç ¥â «¨èì
?¥áâì ¥éñ ¢ ¯à¥¤¥« å ªíè ?). ¥à¥¯®«­¥­¨ï ¡ãä¥à  ­¥â ? `gc_put` ¯à®¢¥àï¥â £à ­¨æã.
‚ ¦­®: ?255 ï祥ª? ? íâ® **®â७¤¥à¥­­ ï è¨à¨­ **, ­¥ ¡ ©âë ¨á室­¨ª . ’ ¡ë ¢
ª®¤¥ à §¢®à ç¨¢ îâáï ¢ ¯à®¡¥«ë (¤® `TAB_STOP`),   ï祩ª¨ â ¡«¨æë ¤®¡¨¢ îâáï
¯à®¡¥« ¬¨ ¤® è¨à¨­ë ª®«®­ª¨ + à ¬ª¨ `³` ? ¯®í⮬㠪 ¯ ¤®á⨣ ¥âáï à ­ìè¥, 祬
255 ?¯®«¥§­ëå? ᨬ¢®«®¢.
> **RAW-०¨¬ (`F2`) í⮣® «¨¬¨â  ­¥ ¨¬¥¥â** ? ®­ à¨áã¥â ¯àאַ ¨§ ä ©« 
> ¯®¡ ©â®¢®, ¤«¨­­ë¥ áâப¨ ¢¨¤­ë 楫¨ª®¬ (ç¥à¥§ wrap `F3` ¨«¨ £®à¨§. áªà®««).
**ˆ¤¥ï á­ïâ¨ï «¨¬¨â ** (®æ¥­ª , ­¥ ॠ«¨§®¢ ­®) ? à áè¨à¨âì ¤«¨­ã ¤® `uint16_t`:
- `cache_rec_t.len` `uint8_t?uint16_t` ? áâàãªâãà  ®áâ ñâáï **஢­® 8 ¡ ©â**
(len áꥤ ¥â ®¤¨­ pad-¡ ©â),  ¤à¥á æ¨ï `idx<<3` ­¥ ¬¥­ï¥âáï. ¥á¯« â­®.
- `g_ncells` / `g_ncells_at_space` ? `uint16_t` ? £« ¢­ ï 業  ¯® **ª®¤ã/᪮à®áâ¨**:
16-¡¨â­ ï  à¨ä¬¥â¨ª  ­  Z80 ¢ £®àï祬 `gc_put` (¢ë§®¢ ­  ª ¦¤ãî ï祩ªã) ¨ ¢
scan-横« å. Žà¨¥­â¨à: **+0.2?0.4 Š ª®¤ ** + § ¬¥¤«¥­¨¥ ¨­¤¥ªá æ¨¨.
- ãä¥à `g_cells[MAX_CACHE_LINE_LEN*2]` ¢ near-RAM (W2) ? £« ¢­ ï 業  ¯®
**¯ ¬ïâ¨**: `2 ? ª ¯` ¡ ©â. ‘¥©ç á 510 ; ª ¯ 512 ? +0.5 Š, 1024 ? +1.5 Š.
EMM-ªíè ª®­â¥­â  (1 Œ) ¤«¨­­ë¥ áâப¨ âﭥ⠫¥£ª® ? 㧪®¥ ¬¥áâ® ¨¬¥­­® near.
- `viewport_x` (¨ ª®¯¨ï ¢ `docset_t`) + ¯®â®«®ª `max_vx` (ᥩç á 248) ? `uint16_t`,
¨­ ç¥ åà ­¨âì >255 ¬®¦­®,   ¤®áªà®««¨âì ­¥«ì§ï. «îá `widths[]`/`ccx` ¢ â ¡«¨æ å/ª®¤¥.
¥ «¨áâ¨ç­ë© ª®¬¯à®¬¨áá ? ª ¯ 512?1023: 墠â¨â ¯®ç⨠¢á¥¬ «¨á⨭£ ¬/â ¡«¨æ ¬,
業  ~+0.3 Š ª®¤  ¨ +0.5?1.5 Š near-RAM. **„¥èñ¢ ï ¯®«ã¬¥à  ¡¥§ `uint16_t`** ?
áâ ¢¨âì ç¥áâ­ë© ¬ àª¥à ®¡à¥§ª¨ ­  255-© ¯®§¨æ¨¨, çâ®¡ë ¯®â¥àï ¡ë«  ¢¨¤­ .
## TODO
1. **“¢¥«¨ç¥­¨¥ à §¬¥à  ¤®ªã¬¥­â®¢.** ‘­ïâì «¨¬¨â 128 Š: „®áâ â®ç­®
à §à¥è¨âì à ¡®â âì á ¡®«ì訬 ª®«-¢®¬ áâà ­¨æ ¯ ¬ïâ¨, ¯®ª  ®ââ¥áâ¨à®¢ ­­®
­  à ¡®â¥ á 8-¬î áâà ­¨æ ¬¨ ¯® 16Š¡.
‘¤¥« ­®: ä®à¬ â¨à®¢ ­­ë¥ â ¡«¨æë á à ¬ª®©; ¯®¤¤¥à¦ª  ª®¤¨à®¢®ª
CP866 / CP1251 / KOI8-R / UTF-8 á  ¢â®®¯à¥¤¥«¥­¨¥¬ ¨ ¯¥à¥ª«î祭¨¥¬ ¯® `F8`
(¢â®à®© ­ ¡®à áâநâáï «¥­¨¢®, ¯® ¯¥à¢®¬ã ¯¥à¥ª«î祭¨î).
4. **“᪮७¨¥ ७¤¥à¨­£ .** Šíè áâப íªà ­ . Ž¯â¨¬¨§ æ¨ï 横«  ¢ë¢®¤ 
ᨬ¢®«®¢ ç¥à¥§ BIOS WRCHAR (¯ ª¥â­ë© ¢ë¢®¤, DMA).
---
*MDView v0.2 ú (c) 2026 ¥â஢ €.ƒ.*
---
# Sprinter C Compiler ? v1.0
C toolchain for **Sprinter** ? the Z80-based home computer by Peters Plus, running
ESTEX DSS. Host: macOS / Linux. Target: `.EXE` files in SprintEXE format.
Built on top of **SDCC 4.5** (vendored in `third_party/sdcc/`). This repository adds
everything Sprinter-specific: crt0, linker integration, libc wrappers over ESTEX,
banked-call trampolines, graphics & accelerator API, mouse driver wrappers, and the
`mkexe` utility for producing SprintEXE images.
## What you get
* **`bin/sprinter-cc`** ? one-line driver: `sprinter-cc -o foo.exe foo.c`
* **Memory modes**: `tiny`, `small`, `big`, `huge`, `manual` ? see below.
* **stdio + conio**: printf, puts, putchar, getchar, fopen/fread/..., cprintf, cputs, putch, textcolor/textbackground/textattr, gotoxy, kbhit/getch.
* **Graphics**: 320?256?256 and 640?256?16 modes, accelerator-backed primitives (hline / vline / rect / fill_rect / line via Bresenham, plus clear), bitmap-font text in both modes via BIOS character generator.
* **File I/O**: POSIX (`open`/`read`/`write`/`close`/`lseek`/`unlink`/`creat`), FILE\* streams (`fopen`/`fgets`/`fwrite`/...), directory listing (`ffirst`/`fnext`), `chdir`/`getcwd`/`mkdir`/`rmdir`, `stat`/`fstat`.
* **Memory**: 32 KB heap (W2-resident), banking-aware page allocator (`mem_alloc_pages`/`bank_read`/`bank_write`), explicit memory modes for sub-16 KB programs.
* **Mouse**: full Sprinter driver wrapper (14 functions including custom cursor bitmaps).
* **Environment**: `getenv`/`putenv`/`sysenv` over ESTEX `$46`.
* **Time**: `getdatetime`/`setdatetime` + POSIX `time`/`localtime`/`mktime`/`asctime`/`ctime`.
* **Misc**: `errno`/`strerror`/`perror`, `atexit`, `setjmp`/`longjmp`, `sleep`, full argv parsing in crt0.
## Quick start
```sh
git clone <this repo> sprinter-c
cd sprinter-c
make sdcc # one-time: fetch SDCC 4.5 binary (~25 MB)
make all # build mkexe + libsprinter.lib + 27 examples
make floppy # pack everything into mame/v306/IMG/mc.img
cd mame/v306 && ./run_mame.sh # boot Sprinter in MAME
```
Compile a single program:
```sh
cat > hello.c <<EOF
#include <stdio.h>
int main(void) { puts("Hello, Sprinter!"); return 0; }
EOF
bin/sprinter-cc -o hello.exe hello.c
```
That's it ? `hello.exe` is now a valid SprintEXE you can `RUN HELLO` from the ESTEX shell.
## Memory modes
Sprinter's address space is four 16 KB windows (W0 / W1 / W2 / W3). DSS allocates
pages by program size ? small programs get only one page. Pick a memory mode based
on what your program needs:
| Mode | Code lives in | Banking | Use when | Note |
|---|---|---|---|---|
| `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB | |
| `small` | W1-W2 (0x4100+) | no | code+data < 30 KB | |
| `big` | W2 + W1 banking | yes (W1) | tiny + extra code modules | |
| `huge` | W1-W2 + W3 banking | yes (W3) | small + extra code modules | |
| `manual` | user-specified | optional | special layouts | Not implemented |
```sh
sprinter-cc --memory small -o big.exe bigprog.c
sprinter-cc --memory huge -o app.exe main.c --bank 1=engine.c --bank 2=ai.c
```
Banked functions are declared with `__banked`:
```c
void engine_tick(int dt) __banked; // lives in BANK1, automatically swapped
```
## Examples (27 total)
| Example | What it demonstrates |
|---|---|
| `hello` | Hello world with stdio + conio Turbo-C-style colors |
| `argv` | argv parsing in crt0 |
| `cat` | File I/O ? read & print TEST.TXT |
| `seek` | 32-bit lseek over a 100 KB file |
| `ls` | Directory listing via ffirst/fnext |
| `filetest` | FILE\* streams (fopen/fread/...) |
| `stattest` | `stat`/`fstat` on files and directories |
| `errno` | errno / strerror / perror |
| `mem_test` | Page allocator + bank\_read/bank\_write |
| `malloc` | Heap stress test (200+ allocations) |
| `banked` | Banked code in W3 (huge mode) |
| `bankedbg` | Banked code in W1 (big mode) |
| `banklocl` | Bank-local static data and BSS |
| `mouse` | Mouse driver in text mode |
| `gfx_mous` | Mouse with custom bitmap cursor in graphics mode |
| `gfx_demo` | 320?256?256 lines / rects / accelerator |
| `gfx_d16` | 640?256?16 same primitives |
| `gfx_text` | Bitmap-font text on graphics screen |
| `timedir` | Date/time + directory listing |
| `ptime` | POSIX time API |
| `openenv` | open() flags + environment vars |
| `conio` | conio API smoke test |
| `attrprob` | Probe Sprinter text attribute byte layout |
| `strtest` | string.h test (from SDCC's z80.lib) |
| `stdlib` | stdlib.h test (qsort / rand / strtol / etc.) |
| `assrtest` | assert() |
| `rt_test` | Runtime helpers (sleep, setjmp, atexit) |
## Headers
Standard:
* `<stdio.h>` ? puts / printf / FILE\* + Sprinter-specific dec/hex helpers
* `<stdlib.h>` ? atoi / atof / malloc / qsort / ... (from SDCC z80.lib)
* `<string.h>` / `<ctype.h>` / `<math.h>` ? from SDCC z80.lib
* `<unistd.h>` ? read / write / close / lseek / unlink
* `<fcntl.h>` ? open / creat + O\_RDONLY / O\_CREAT / ...
* `<errno.h>` ? errno + error names + strerror
* `<sys/stat.h>` ? stat / fstat
* `<setjmp.h>` / `<assert.h>` ? from SDCC
Sprinter-specific:
* `<conio.h>` ? putch / cputs / cprintf, textcolor / textbackground / textattr, kbhit / getch, clrscr, gotoxy, wherex/y
* `<gfx.h>` ? gfx_init/done, palette, putpixel, hline/vline/rect/fill_rect/line, text ? for both 320 and 640 modes (gfx_\*16 variants)
* `<mouse.h>` ? full 14-function driver wrapper + mouse_cursor_t with bitmap support
* `<dir.h>` ? chdir / getcwd / mkdir / rmdir / ffirst / fnext / ffblk
* `<time.h>` ? getdatetime / setdatetime + POSIX time / localtime / etc.
* `<sprinter.h>` ? raw ports, ESTEX/BIOS function numbers, env API
* `<sprinter_exit.h>` ? exit / \_exit / atexit
* `<sprinter_mem.h>` ? mem\_alloc\_pages / mem\_free\_block / bank\_read / bank\_write
* `<sprinter_compat.h>` ? Solid-C compatibility layer (aliases + BOOL/WORD/uint types)
## Toolchain commands
```sh
make all # build mkexe + lib + every example
make floppy # repack mame/v306/IMG/mc.img with all .exe files
make check # 17 mkexe unit-tests
make clean # remove all build artefacts
make sdcc # one-time: fetch SDCC 4.5 binary
```
### sprinter-cc options
```
sprinter-cc -o foo.exe foo.c [more.c ...] [options]
--memory MODE tiny | small | big | huge | manual (default: tiny)
--memory-manual SPEC explicit placement (CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3)
--stack-size N bytes reserved for the stack (default ~1278)
--crt0=TYPE default | minimal | banked | small
--bank N=FILE.c compile FILE.c into bank N (repeatable, max 15)
--debug enable runtime diagnostics (defines DEBUG_RT)
-I PATH extra include path
-L 0xADDR / -E / -S override load / entry / stack addresses
-Wl FLAG pass FLAG to sdldz80
--mkexe FLAG pass FLAG to mkexe (e.g. --mkexe -p --mkexe 0 for bank padding)
-v verbose
```
## Status
What works in v1.0:
* Compile / link / pack to SprintEXE ? verified on all 27 examples
* Four memory modes (tiny / small / big / huge)
* Graphics (both modes) with accelerator
* Mouse (text + graphics cursor)
* File I/O, directories, environment, time
* All headers listed above
Deferred to v2.0 (see `docs/TODO.md`):
* **Turbo-C-style BGI graphics API** ? `initgraph` / `setcolor` / `circle` /
`getimage` / `putimage` / etc. on top of our `gfx_*` primitives
* Remaining Solid-C compatibility gaps (Phase 2/3) ? see `docs/solid_c_compatibility.md`
* Manual memory mode
* Rewrite FILE\* stream API (current implementation is very primitive and doesn't use buffers)
Deferred to v3.0:
* **IM2 interrupt handlers** ? research complete (`docs/im2_isr_design.md`),
implementation scheduled for v3
* **Audio API** (AY-3-8910 + COVOX) ? requires IM2
* **ISA-8 slot drivers** ? requires IM2 (???)
## Documentation
* `docs/TODO.md` ? roadmap and open work items
* `docs/solid_c_compatibility.md` ? gap analysis vs Solid-C 2004
* `docs/im2_isr_design.md` ? interrupt handler design (v2)
* `docs/converted/` ? source documentation (ESTEX, BIOS, architecture)
converted to plain text for `grep`
* `docs/reference/`, `docs/samples/`, `docs/memory management/` ? original
Russian docs and code samples from Peters Plus
## Repository layout
```
bin/sprinter-cc one-line compiler driver (bash)
toolchain/mkexe/ host-side tool: .ihx -> .exe SprintEXE
toolchain/check_banks.py post-link bank size enforcer
runtime/ crt0 variants (default, minimal, small, banked)
bank trampolines, heap, heap_top
libc/include/ headers
libc/io|stdio|mem|gfx/ C and asm sources for libsprinter.lib
lib/ Makefile that archives libsprinter.lib via sdar
examples/ 27 example programs
mame/v306/ MAME binary + Sprinter ROM/HDD images + floppy script
third_party/sdcc/ vendored SDCC 4.5 (fetched via `make sdcc`)
third_party/solid-c/ reference: original Sprinter native C (for compat target)
docs/ documentation
```
## License
This repository contains:
* Original code in `bin/`, `toolchain/`, `runtime/`, `libc/`, `lib/`, `examples/` ?
MIT-licensed.
* `third_party/sdcc/` ? SDCC 4.5 under GPLv2 with linking exception
(see `third_party/sdcc/COPYING.txt`)
* `third_party/solid-c/` ? original Sprinter Solid C, used only as a reference
## Credits
* **Sprinter / Peters Plus** ? ˆ¢ ­ Œ ª, „¬¨â਩  à¨­®¢ and the original team
* **SDCC** ? for the underlying Z80 compiler
* **MAME** ? for the Sprinter Sp2000 emulation
---
For questions / patches: see CONTRIBUTING.md (TBD) or open an issue.
---
# TODO / Roadmap
Žâªàëâë¥ § ¤ ç¨ ¢ ¯®à浪¥ ã¡ë¢ ­¨ï ¯à¨®à¨â¥â . ® ¬¥à¥ ¯®ï¢«¥­¨ï ॠ«ì­ëå ¯à®£à ¬¬ ? ¯à¨®à¨â¥âë ¡ã¤ãâ ᬥé âìáï.
## â ¯ 5 ? malloc / free + banking-aware page allocator ? ƒŽ’Ž‚Ž
- [x] SDCC's `malloc`/`free` + ­ è `runtime/heap.s` (¯®«­®áâìî § ¬¥­ï¥â library heap.rel, 14000-¡ ©â­ë© heap ¢ ®ª­¥ 2)
- [x] `libc/mem/mem_alloc.c` ? page allocator: `mem_alloc_pages`/`mem_free_block`/`mem_get_page`/`mem_info` ç¥à¥§ ESTEX `$3C/$3D/$3E` + BIOS `$C4`
- [x] `libc/mem/bank_io.c` ? HOME-१¨¤¥­â­ë¥ `bank_read`/`bank_write`/`bank_load_byte`/`bank_store_byte` ᮠ᢮¯®¬ W3 ¢­ãâà¨
- [x] `examples/malloc_test/` ? ¯à®¢¥àª  SDCC's malloc (~210 64-¡ ©â­ëå allocations ç¥à¥§ ¢áî heap)
- [x] `examples/mem_test/` ? ¯à®¢¥àª  page allocator: 3 áâà ­¨æë, à §­ë¥ ¯ ââ¥à­ë ç¥à¥§ bank_write, ¢¥à¨ä¨ª æ¨ï ç¥à¥§ bank_read
## â ¯ 6 ? argv parsing + sprinter-cc wrapper ? ƒŽ’Ž‚Ž
- [x] crt0 ¯ àá¨â ESTEX command-line ¨§ IX-prefix (inline asm ¢ `runtime/crt0.s`)
- [x] Strip leading CP/M-style space (DSS quirk)
- [x] ¥à¥¤ ç  `argc`/`argv` ¢ main() ç¥à¥§ HL/DE (SDCC __sdcccall(1) ABI)
- [x] argv[0] = basename .EXE ç¥à¥§ ESTEX APPINFO ($47 subfn 2)
- [x] `runtime/crt0_minimal.s` ? opt-out ¤«ï ®ç¥­ì ¬ «¥­ìª¨å ¯à®£à ¬¬
- [x] `runtime/crt0_banked.s` ? ⥯¥àì ⮦¥ ¯ àá¨â argv (parse_argv + get_progname ᪮¯¨à®¢ ­ë ¨§ crt0.s; ¡ã¤¥â factored ¢ argv.s ª®£¤  ¢®§ì¬ñ¬áï §  libsprinter.lib)
- [x] Bash-®¡ñà⪠ `bin/sprinter-cc`: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨©: `--memory`, `--memory-manual`, `--stack-size`, `--crt0=`, `--bank N=FILE.c`, `--debug`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
## â ¯ 8 ? £à ä¨ª  (320?256?256 + 640?256?16 + accel + bitmap font) ? ƒŽ’Ž‚Ž
- [x] **8a** Graphics core: `gfx_init`/`gfx_done`/`gfx_clear`/`gfx_putpixel`/`gfx_pal_load`/`gfx_pal_set` (libc/gfx/gfx_core.c).  «¨âà  ç¥à¥§ BIOS PIC_SET_PAL ($A4). Verified 320?256?256.
- [x] **8b** ‹¨­¨¨/¯àאַ㣮«ì­¨ª¨/fill ç¥à¥§ accelerator (libc/gfx/gfx_lines.c): `gfx_hline`/`gfx_vline` ç¥à¥§ accel Fill (LD C,C / LD E,E + SMC block-size), `gfx_rect`/`gfx_fill_rect` á heuristic ¢ë¡®à®¬ ®à¨¥­â æ¨¨ (h/v bursts count), `gfx_line` á Bresenham ¤«ï ¤¨ £®­ «¥©. `gfx_clear` ⮦¥ ¯¥à¥¯¨á ­ ­  column-major accel (~4? ¡ëáâ॥).
- [x] **8c** 640?256?16 mode (libc/gfx/gfx_16.c): `gfx_*16` API, HIGH nibble = LEFT pixel (¤®ªã¬¥­â æ¨ï misleading), per-row RMW ¤«ï vline (®¤¨­ ¡ ©â = 2 £®à¨§®­â «ì­ëå ¯¨ªá¥«ï).
- [x] **8d** Bitmap font + gfx_text (libc/gfx/gfx_text.c): èà¨äâ ç¥à¥§ BIOS WIN_GET_ZG ($B8), interleaved layout `font[row*256+char]`, `gfx_text`/`gfx_putchar` ¤«ï 320 mode, `gfx_text16`/`gfx_putchar16` ¤«ï 640 mode á pair-table lookup.
‘¬. memory/sprinter_graphics.md, sprinter_accelerator.md, sprinter_graphics_16.md, sprinter_font_format.md.
Žâªàëâë¥ ¬¥«®ç¨ (­¥ ¡«®ª¨àãîâ):
- [ ] ˜à¨äâ-quad ¤«ï 640: per-cell ¯ «¨âà  (mode 0x82 à §à¥è ¥â 1 ¨§ 4 ¯ «¨âà per 16?8 cell) ? ç¥à¥§ ¯àאַ© ¤®áâ㯠ª area-®¯¨á ­¨ï íªà ­  0x0300..0x039F
## Auto-banking (á¬. `memory/banking_roadmap.md` ¤«ï ¤¥â «¥©)
Phase 1 ? file-level bin-packing ? ॠ«¨§®¢ë¢ âì ª®£¤  ¯à®¥ªâ ¯¥à¥à áâñâ ~30 KB ª®¤ .
- [ ] `toolchain/auto_bank.py`:
-  àá¨â à §¬¥àë ¨§ `.rel`-ä ©«®¢ (¨«¨ ¨§ .map ¯®á«¥ dry-run link' )
- First-fit-decreasing bin-packing
- “¢ ¦ ¥â `#pragma codeseg BANKn` ª ª manual override
- ¥à¥«¨­ª®¢ë¢ ¥â á ­®¢ë¬¨ `-Wl-b_BANKn=...` ¯ à ¬¥âà ¬¨
- ¥ç â ¥â ¯« ­ à á¯à¥¤¥«¥­¨ï
Phase 2-5: incremental rebalance, declarative `banks.toml`, function-level, call-graph-aware. ’®«ìª® ¥á«¨/ª®£¤  ¯®­ ¤®¡¨âáï.
## Bank-local static data (mutable data ¢ ⮬ ¦¥ ¡ ­ª¥ çâ® ¨ ª®¤) ? ? ƒŽ’Ž‚Ž
- [x] ਬ¥à `examples/bank_local_data/` ? äã­ªæ¨ï ¢ BANK1 ᮠ᢮¨¬ writable BSS array + const table + malloc-â¥áâ
- [x] `mkexe -p 0` ¤«ï ­ã«¥¢®£® padding ¡ ­ª®¢ (BSS-storage ®¡­ã«ï¥âáï ¯à¨ § £à㧪¥)
- [x] Š ­®­¨ç¥áª¨© à¥æ¥¯â: `--codeseg BANK1 --constseg BANK1 --dataseg BANK1` ¤«ï bank1.c + `-Wl-b_BANK1=0x1C000` ¤«ï «¨­ª®¢ª¨. **`--dataseg BANK1` Ž’€…’** ? à ­ìè¥ ª § «®áì ®¡à â­®¥ ¨§-§  trampoline bug ª®â®àë© ¬ áª¨à®¢ « १ã«ìâ â.
- [x] **Šà¨â¨ç­ë© 䨪á trampoline'a ¢ runtime/bank.s** ? áâ àë© `pop af; out (n), a` ª«®¡¡¥à¨« A ? ¢á¥ banked-ä㭪樨 ¢®§¢à é î騥 uint8_t â¨å® ¢®§¢à é «¨ ¬ãá®à. ®¢ë© `pop bc; out (c), b` á®åà ­ï¥â A.
- [x] **malloc ¨§ banked-ä㭪樨 à ¡®â ¥â ¯à®§à ç­®** ? heap ¦¨¢ñâ ¢ W2 (HOME), W2 ­¨ª®£¤  ­¥ ᢠ¯ ¥âáï trampoline'®¬, pointer ¢ «¨¤¥­ ¨§ «î¡®£® ª®­â¥ªáâ . ‘¬. memory/bank_local_data_pattern.md.
- [x] „®ªã¬¥­â æ¨ï ¢ memory: `memory/bank_local_data_pattern.md` (¯®«­ë© à¥æ¥¯â + malloc + nuances), `memory/sdcc_banking.md` (trampoline fix)
- [ ] Ž¯æ¨®­ «ì­® ? à áè¨à¨âì `check_banks.py` çâ®¡ë ¯®ª §ë¢ âì à §¡¨¢ªã size = code + const + bss per bank (cosmetic)
‡ ç¥¬: ¤«ï ¬®¤ã«¥© á ¡®«ì訬 private state (level loader, audio engine, scene data). ª®­®¬¨â W2 heap ¤«ï ¤¨­ ¬¨ª¨,   áâ â¨ª  ®áâ ñâáï ¢ ¡íª¥.
## ®¤áª §ª¨ ¨§ solid-c (­ â¨¢­ë© Sprinter C ? `third_party/solid-c/`)
®á«¥  ­ «¨§  solid-c'®¢áª®© libc (á¬. `memory/solid_c_findings.md`) ¢ë¥­ë £®â®¢ë¥ ¯ ââ¥à­ë ¤«ï á«¥¤ãîé¨å ­¥¤®áâ îé¨å ä㭪権. ਮà¨â¥â ®â **¢ë᮪®£®** ª ­¨§ª®¬ã:
### High-priority gaps («¥£ª® ¯®àâ¨à®¢ âì, ¡®«ìè ï ¯®«ì§ )
- [x] **`errno` + `strerror`/`perror`** ? â ¡«¨çª  32 ®è¨¡®ª (libc/io/errno.c)
- [x] ** áè¨à¥­­ë© `open()`** ¤«ï O_CREAT/O_TRUNC/O_APPEND/O_EXCL state machine
- [x] **`atexit`** ? 8-callback LIFO + `exit()` + `_exit()` (libc/io/atexit.c)
- [x] **`setjmp`/`longjmp`** ? 6-¡ ©â jmp_buf={sp,ix,pc} (libc/io/setjmp.c)
- [x] **`sleep(seconds)`** ? 50Hz halt-loop (libc/io/sleep.c)
- [x] **ESTEX ENV API** ($46, getenv/putenv) ? libc/io/env.c. “竨 doc-bug: ॠ«ì­® A=0 íâ® NOT FOUND
### Medium-priority (­ã¦­® ¤«ï shell-like ã⨫¨â)
- [ ] **Mouse driver** ? `rst $30h`, 17 ä㭪権. **‘­ ç «  â¥áâ çâ® à ¡®â ¥â ¢ MAME**.
- [x] **`ffirst`/`fnext` + ffblk_t struct** ¤«ï directory listing ? ॠ«¨§®¢ ­®, demo: ls.exe
- [x] **`getdatetime`/`setdatetime`** ç¥à¥§ ESTEX $21/$22 ? libc/io/time.c, demo: time_dir_test
- [x] **`chdir`/`getcwd`/`mkdir`/`rmdir`** ? wrappers ¤«ï ESTEX $1B-$1E ? libc/io/fsdir.c
- [x] **conio: `kbhit`/`getch`/`getche`/`cputs`/`clrscr`/`gotoxy`** ? ॠ«¨§®¢ ­®
- [x] **conio extras**: `wherex`/`wherey` ($53), `wrchar`/`rdchar` ($58/$57), `textmode_get/set` ($50/$51), `clrscr_attr` ($56) + COLOR macros
### Low-priority ? ? FILE* stack ƒŽ’Ž‚Ž
- [x] **Œ¨­¨¬ «ì­ë© unbuffered FILE\*** ? `libc/stdio/file.c` + `libc/include/stdio.h`. fopen/fclose/fputs/fgets/fread/fwrite/fseek/ftell/rewind/feof/ferror/clearerr/fflush + stdin/stdout/stderr ª ª pseudo-streams. ‘¬. `memory/file_star_design.md` ¨ `examples/filetest`.
- [ ] fprintf / fscanf ? ­ã¦­  printf-ç¥à¥§-callback machinery. ®ª  ¯®«ì§®¢ â¥«ì ¬®¦¥â `sprintf(buf, ...) + fputs(buf, fp)`.
- [ ] Ž¯æ¨®­ «ì­ë© buffered mode (setvbuf, line/block buffering) ? ¥á«¨ ª®£¤ -â® ¯®­ ¤®¡¨âáï.
### POSIX time API ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/posix_time.c` ? time/localtime/gmtime/mktime/asctime/ctime ¯®¢¥àå getdatetime. SDCC's time.rel ¨§¡¥£ ¥¬ (­¥«ì§ï override _RtcRead). ‘¬. `examples/ptime`.
### sys/stat ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/stat.c` ? POSIX stat/fstat. ƒ¨¡à¨¤ open+fstat ¤«ï ä ©«®¢, ffirst+iter ¤«ï ¯ ¯®ª (¢ª«îç ï "."/".."). ‘¬. `examples/stattest` ¨ `memory/estex_ffirst_dotdot.md`.
### assert ? ? ƒŽ’Ž‚Ž (¨á¯®«ì§ã¥¬ SDCC's __assert ç¥à¥§ fallback include path)
## libc/stdlib ? ? ­¥ ­ã¦­® ¤¥« âì (á¬. memory/sdcc_stdlib_works.md)
஢¥à¥­® ç¥à¥§ `examples/stdlib_test/`: SDCC z80.lib ᮤ¥à¦¨â à ¡®â î騥 ॠ«¨§ æ¨¨:
- `atoi/atol/atof, strtol/strtoul, rand/srand, qsort/bsearch, abs/labs, div/ldiv`
- ®«­ë© `<string.h>` (memchr/cmp/set/cpy, strcat/cmp/cpy/len/chr/spn/etc.)
- `<ctype.h>` (toupper/tolower)
- `<math.h>` (sinf/cosf/sqrtf/etc.)
‹¨­ª¥à  ¢â®¬ â¨ç¥áª¨ âﭥ⠨§ z80.lib ª®£¤  ­ã¦­®. **… ¯¥à¥¯¨á뢠âì**.
 è¨ Sprinter-specific ®¡ï§ â¥«ì­ë¥ ¬®¤ã«¨ ®áâ îâáï: atexit, env, errno, setjmp, putchar/puts/getchar, conio, fsdir, time, mouse, open/read/lseek/close.
## Build-system: libsprinter.lib + sprinter-cc ? ? ƒŽ’Ž‚Ž
- [x] `lib/Makefile` ? ᮡ¨à ¥â ª ¦¤ë© libc/*.c ¢ `.rel`,  à娢¨àã¥â ç¥à¥§ sdar ¢ `lib/sprinter.lib`
- [x] ‚ª«îç ¥â runtime/bank.s ¨ runtime/heap.s (auto-pulled ¯à¨ __banked/malloc)
- [x] `bin/sprinter-cc` ? bash-wrapper: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨© `--crt0=default|minimal|banked`, `--bank N=FILE.c`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
- [x] `examples/hello_sccc/` ? ¤¥¬®: `hello.c` ᮡ¨à ¥âáï §  ®¤¨­ shell-¢ë§®¢, à §¬¥à ᮢ¯ ¤ ¥â á àãç­ë¬ Makefile (925 ¡ ©â)
- [x] Split `putchar.c` ? `putchar.c` + `puts.c` ¤«ï per-function granularity (puts override SDCC's z80.lib version)
- [x] ‚ª«îçñ­ ¢ `make all` (§ ¢¨á¨¬®áâì `lib` ¯¥à¥¤ `examples`)
‚®§¬®¦­ë¥ ã«ãç襭¨ï (®¯æ¨®­ «ì­®):
- [ ] Œ¨£à¨à®¢ âì ®áâ «ì­ë¥ examples ­  sprinter-cc ¢¬¥áâ® àãç­ëå Makefile (ª®á¬¥â¨ª )
- [ ] „ «ì­¥©è ï ¤¥ª®¬¯®§¨æ¨ï libc/*.c per-function (­® ⥪ãé ï granularity 㦥 ¤ ñâ ­ã¦­ë© à §¬¥à ? «¨­ª¥à ¯ ª¥âã¥â .rel 楫¨ª®¬, ¨ ¤«ï ¡®«ì設á⢠ ä ©«®¢ íâ® ®¤­  äã­ªæ¨ï)
## â ¯ 9 ? memory modes ¤«ï sprinter-cc
DSS ¢ë¤¥«ï¥â áâà ­¨æë ¯ ¬ï⨠¯® à §¬¥à㠯ਫ®¦¥­¨ï: < 16 KB ? ®¤­  áâà ­¨æ , ¢ ®áâ «ì­ë¥ ®ª­  ¯®¤ª«îç ¥âáï ?áâà ­¨æ  #FF? (read=0xFF, write ¨£­®à¨âáï). ˆ§-§  í⮣® CODE-¢-W1 + DATA-¢-W2 ¤«ï ¬ «¥­ìª®© ¯à®£à ¬¬ë ¬®«ç  «®¬ ¥âáï. ‘¬. [memory/sprinter_memory_modes.md](../../.claude/projects/-Volumes-SAM8-Projects-DIY-Z80-Sprinter-C-Compiler/memory/sprinter_memory_modes.md).
- [x] **`tiny`**: ¢áñ (CODE+DATA+á⥪) ¢ W2. Default. Verified hello/argv/conio/malloc/file/etc.
- [x] **`--memory MODE` ä« £ ¢ sprinter-cc**: parser + per-mode ¤¥ä®«âë CODE_LOC/DATA_LOC, override ç¥à¥§ ï¢­ë¥ `--code-loc`/`--data-loc`. tiny à ¡®â ¥â; small/big/huge ª®¬¯¨«¨àãîâáï á warning'®¬ (runtime ­¥ £®â®¢). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--memory-manual SPEC`**: ¯ àá¨â `CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`small` runtime**: `runtime/crt0_small.s` ¨á¯®«ì§ã¥â ESTEX `$3D GETMEM` + `$3A SETWIN2` çâ®¡ë ¢ë¤¥«¨âì ¨ § ¬ ¯¨âì W2-áâà ­¨æã „Ž gsinit. **…** BIOS `$C4` ? á⥪ ­  í⮬ íâ ¯¥ ¢ W1 (boot_stack ¢ HOME),   BIOS âॡã¥â á⥪ ¢ W2. ®á«¥ ¬ ¯¯¨­£  SP ¯¥à¥ª«îç ¥âáï ­  0xBFFE, ¤ «ìè¥ áâ ­¤ àâ­ë© flow. ¥ «¨§®¢ ­® 2026-05-30, verified hello.exe.
- [x] **`small` auto-detect ¤«ï >16 KB ¯à®£à ¬¬**: `crt0_small.s` ç¨â ¥â ¯®àâ `0xC2` (⥪ãé ï áâà ­¨æ  ¢ W2 ? ­¥ `0xA2`! íâ® W1). …᫨ 0xFF ? ¢ë¤¥«ï¥â page; ¨­ ç¥ DSS 㦥 ᤥ« «  íâ® (¯à®£à ¬¬  á ¬  ¢ë«¥§«  ¢ W2). ޤ¨­ crt0 ¯®ªà뢠¥â 0..30 KB. mkexe â ª¦¥ à §à¥è ¥â HOME span W1+W2 (0x4000..0xBFFF). Verified hello: small (5 KB ä ©«, SETWIN2 path) + 32 KB ä ©« (auto-skip). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`big` runtime** (tiny + banked code ¢ W1): ¯ à ¬¥âਧ®¢ «¨ `crt0_banked.s` + `bank.s` ç¥à¥§ `.ifdef BANK_W1` ? ¤à㣮© banking port (0xA2 vs 0xE2), ¤à㣮© load-addr (0x4000 vs 0xC000). sprinter-cc prepend'¨â `BANK_W1 = 1` ¯à¨ `--memory big`, ¯¥à¥¤ ñâ `mkexe -B 0x4000`. ਬ¥à `examples/banked_big/`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`huge` runtime** (small + banked code ¢ W3): merge W2-detect «®£¨ª¨ ¨§ `crt0_small.s` ¢ `crt0_banked.s`. ‘ãé¥áâ¢ãî騩 ¯à¨¬¥à `examples/banked/` ⥯¥àì ¨á¯®«ì§ã¥â MEMORY=huge. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--debug` ä« £**: prepend `DEBUG_RT = 1` ¢ crt0 + `-DDEBUG_RT` ¢ sdcc. Žâªà뢠¥â symbol `_w2_self_allocated` (uint8_t) ? runtime diagnostic ªâ®  ««®æ¨à®¢ « W2. ¥ «¨§®¢ ­® 2026-05-30.
### „¨§ ©­-à¥è¥­¨ï ¯® libc ¨ crt0
**ޤ­  `sprinter.lib`** à ¡®â ¥â ¤«ï ¢á¥å memory mode ? `.rel`-ç«¥­ë relocatable, SDLD ¤¥« ¥â dead-code elimination per-member (¡¥§ £à ä¨ª¨ ­¥ ¯®¤â¢ ¥â `gfx_core.rel` ¨ â.¤.). Verified hello vs malloc_test ç¥à¥§ map-ä ©«ë.
**`gfx.lib` ®â¤¥«ì­® ? … ­ã¦¥­**: dead-code elimination 㦥 à ¡®â ¥â.
**`libc_banked` (libc ¢ bank ¢¬¥áâ® HOME)** ? ¨¤¥ï ­  ¯®â®¬, ª®£¤  HOME (16 KB) § ¡¨â user-ª®¤®¬ + libc ¢ `huge` mode. ¥ «¨§ã¥âáï ç¥à¥§ `--codeseg BANK0` ¯à¨ ª®¬¯¨«ï樨 libc; trade-off: trampoline ~30 横«®¢ ­  ª ¦¤ë© libc-¢ë§®¢. ’ਣ£¥à: ॠ«ì­ ï ¯à®£à ¬¬  ã¯àñâáï ¢ HOME budget.
**HW-§ ¢¨á¨¬ë¥ ¬®¤ã«¨ ? `sprinter_home.lib` ®â¤¥«ì­®.** — áâì libc 䨧¨ç¥áª¨ ­¥ ¬®¦¥â ¡ëâì § ¡ ­ª®¢ ­  ¢ W3, ¯®â®¬ã çâ® ®­  Ž’€…’ á W3:
- `gfx_*` ? ¯¨è¥â ¢ ¢¨¤¥®¯ ¬ïâì `0xC000+` ¯®á«¥ swap W3 ­  video page
- `bank_io` (mem_alloc_pages/bank_read/bank_write) ? swap'¨â W3 ç¥à¥§ `OUT (0xE2)`
- ã¤ã騥 ISR ? ¯à¥à뢠­¨¥ ¬®¦¥â ¯à¨©â¨ ª®£¤  W3 ­  çñ¬ 㣮¤­®
‚ huge mode í⨠¬®¤ã«¨ „Ž‹†› ®áâ âìáï ¢ HOME (W1). Š®£¤  ¡ã¤¥¬ ¤¥« âì `libc_banked`, **®¤­®¢à¥¬¥­­®** ¢ë¤¥«ï¥¬ `sprinter_home.lib` (HOME-only) ¨§ `sprinter.lib` (bankable). ”¨­ «ì­ ï á奬 :
```
sprinter_home.lib HOME-only: gfx, bank_io, ISR shims
sprinter.lib bankable: printf, malloc, string, conio, stdio, env, ...
sprinter_banked.lib â®â ¦¥ sprinter.lib ­® --codeseg BANK0 (¤«ï huge)
```
’ਣ£¥à: ॠ«¨§ æ¨ï `--memory huge` runtime.
**crt0 ? ¯® ®¤­®¬ã ­  mode:**
- `crt0.s` ? ⥪ã騩, ¤«ï **tiny/big**: SP=0xBFFE, ¯ àá¨â argv (W2-à¥áãàá 㦥 ¢ë¤¥«¥­ DSS).
- `crt0_minimal.s` ? ⥪ã騩, ¤«ï tiny ¡¥§ argv.
- `crt0_small.s` ? **­®¢ë©, step 3**: ¤«ï **small/huge**,  ««®æ¨àã¥â W2 ç¥à¥§ `mem_alloc_pages` „Ž gsinit, ¬ ¯¯¨â ¢ ¯®àâ `0xA2`, ¯®â®¬ áâ ­¤ àâ­ë© flow.
- `crt0_banked.s` ? ⥪ã騩, ¤«ï **big**: trampoline-â ¡«¨æ  ¤«ï W3 ¡ ­ª®¢, CODE ¢ W2.
- `crt0_banked_small.s` ? **­®¢ë©**: huge = small (W2-alloc) + banked (W3 trampolines).
sprinter-cc ¯®¤¡¨à ¥â crt0 ¯® `--memory` mode (ᥩç á `--crt0=` íâ® override).
- [x] ** áâà ¨¢ ¥¬ë© à §¬¥à á⥪ **: ä« £ `sprinter-cc --stack-size BYTES`. Wrapper £¥­¥à¨àã¥â `heap_top.s` á `___sdcc_heap_end = stack_top + 1 - stack_size`, ®â¤¥«ì­ë© .rel «¨­ªã¥âáï per-program. Default ?1278 ¡ ©â (heap_top=0xBB00) ¨§ `runtime/heap_top.s`. ¥ «¨§®¢ ­® 2026-05-30.
ˆ­â¥à䥩á: `sprinter-cc --memory [tiny|small|big|huge|manual] [--memory-manual SPEC] [--stack-size N] foo.c`. `--memory-manual` ¨¬¥¥â á¬ë᫠⮫쪮 á `--memory manual`.
## Known issues / quirks
- **ESTEX $46 ENV API**: ? à ¡®â ¥â. „®ª-æ¨ï ¢ `DiskSyscalls.txt v1.6` ®è¨¡®ç­® ®¯¨á뢠¥â return-status ? A=0 íâ® NOT FOUND, ­¥ FOUND. ‡ ä¨ªá¨à®¢ ­® ¢ `memory/sprinter_platform.md`.
## ŽŸ‡€’…‹œ›… ‡€„€—ˆ „‹Ÿ V2 (¯®á«¥ ५¨§  v1)
### Turbo-C-style graphics API (BGI-like) ? **MUST ¤«ï v2**
 áè¨à¨âì ­ è `gfx_*` API ¤® ã஢­ï **Turbo-C `<graphics.h>`** (BGI) ¤«ï MS-DOS.
ணࠬ¬¨áâë ¯à¨¢ëªè¨¥ ª Turbo-C ¤®«¦­ë ¯¥à¥­®á¨âì £à ä¨ç¥áª¨© ª®¤ 1-¢-1.
**—â® ¤®«¦­® ¡ëâì** (­  ®á­®¢¥ Borland BGI):
Setup/teardown:
- `initgraph()` / `closegraph()` ? ã ­ á ᥩç á `gfx_init`/`gfx_done`, ¤®¡ ¢¨âì alias
- `getmaxx()` / `getmaxy()` ? ¬ ªà®á ­  GFX_WIDTH-1 / GFX_HEIGHT-1
- `cleardevice()` ? alias to gfx_clear
- `getgraphmode()` / `setgraphmode()` ? ã ­ á get_videomode/set_videomode
Color/palette:
- `setcolor(c)`, `getcolor()` ? current draw color
- `setbkcolor(c)`, `getbkcolor()` ? background color
- `setpalette(idx, c)` ? ¯ «¨âà  entry
- `getpalette(&info)` ? read all palette
Primitives (¬ë 㦥 ¨¬¥¥¬ íª¢¨¢ «¥­âë ? ¤®¡ ¢¨âì BGI-¨¬¥­  ª ª aliases):
- `putpixel(x, y, c)` ? ¥áâì ª ª gfx_putpixel
- `getpixel(x, y)` ? ­ã¦­® ॠ«¨§®¢ âì (RMW ®¡à â­®¥ ? IN)
- `moveto(x, y)`, `lineto(x, y)`, `linerel(dx, dy)` ? current point + line drawing
- `line(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_line
- `rectangle(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_rect (­® ¤à㣮© API: x1,y1,x2,y2 vs x,y,w,h!)
- `bar(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_fill_rect
- `bar3d(x1, y1, x2, y2, depth, topflag)` ? ­®¢®¥: rect + 3d edges
- `circle(x, y, r)`, `arc(...)`, `ellipse(...)`, `pieslice(...)` ? ­®¢ë¥ primitives
- `fillpoly()`, `drawpoly()` ? ¯®«¨£®­ë
- `floodfill(x, y, border_color)` ? § «¨¢ª 
Text on graphics screen:
- `outtext(s)` / `outtextxy(x, y, s)` ? ¥áâì ª ª gfx_text (alias)
- `settextstyle(font, dir, size)` ? multiple bitmap fonts
- `gettextsettings(&info)`
- `textwidth(s)` / `textheight(s)` ? measure
Image manipulation:
- `imagesize(x1, y1, x2, y2)` ? bytes needed for getimage
- `getimage(x1, y1, x2, y2, buf)` ? save rect to buffer
- `putimage(x, y, buf, op)` ? paste back with COPY_PUT/XOR_PUT/AND_PUT/OR_PUT/NOT_PUT
Clipping/viewport:
- `setviewport(x1, y1, x2, y2, clip)` ? drawing clip rect
- `getviewsettings(&info)`
- `clearviewport()`
- `setactivepage(p)` / `setvisualpage(p)` ? ¤¢®©­ ï ¡ãä¥à¨§ æ¨ï (Sprinter ¨¬¥¥â 2 screen)
Line style:
- `setlinestyle(style, pattern, thickness)` ? SOLID_LINE / DOTTED_LINE / etc.
- `getlinesettings(&info)`
**Acceptance:** ¯¥à¥­®á ⨯¨ç­®© Turbo-C BGI ¯à®£à ¬¬ë (à¨áãî饩 á ¨á¯®«ì§®¢ ­¨¥¬
moveto/lineto/circle/bar/setcolor) ¤®«¦¥­ à ¡®â âì ¡¥§ áãé¥á⢥­­ëå ¯à ¢®ª.
**Notes:**
- BGI fonts (TRIPLEX/SANS_SERIF/GOTHIC) ? ã ­ á ®¤¨­ BIOS font, ®áâ «ì­ë¥ ­ã¦­®
¤®¡ ¢¨âì (ª ª bitmap data ¢ lib)
- imagesize/getimage/putimage ? á ¬ë¥ ¢®áâॡ®¢ ­­ë¥ ¤«ï game/animation
- Active/visual page (¤¢®©­ ï ¡ãä¥à¨§ æ¨ï) ? Sprinter ¯®¤¤¥à¦¨¢ ¥â 2 graphics pages,
­ã¦¥­ API switching
‘¬. â ª¦¥ `examples/` Turbo C 2.x BGIDEMO ª ª reference çâ® ­ã¦­®.
### IM2 Interrupt Handlers ? **MUST ¤«ï v2**
User-§ ¤ ¢ ¥¬ë¥ ISR ç¥à¥§ Z80 IM 2 mode. ã¦­ë ¤«ï:
- Timer ticks (50 Hz frame counter, ¯« ¢­ ï  ­¨¬ æ¨ï)
- Music playback (AY, COVOX)
- Real-time games (input + game logic + render ¢ interrupt-driven)
- Async keyboard / mouse handling
**Status:** Ž’‹Ž†…Ž ¤® v2. ®«­ë© research + design ¢ `docs/im2_isr_design.md`.
**¥è¥­¨¥ ¯®  àå¨â¥ªâãà¥:** ॠ«¨§®¢ âì ª ª ®â¤¥«ì­ë© memory mode `--memory im2`
(¢¬¥á⮠⮣® çâ®¡ë «¥§âì ¢® ¢á¥ áãé¥áâ¢ãî騥 crt0). Detail'¨ ¢ design-doc.
**¥§î¬¥ research' ** (¯®«­ë© ⥪áâ ¢ `docs/im2_isr_design.md`):
- Vector 0xFF ? frame + keyboard + CBL. Disambiguation ¯® ¯®àâ ¬ 0x19 / 0xFE
- Mouse hardware-IRQ ­¥ ¯à¨å®¤¨â (­  ⥪ã饩 ¯« â¥)
- Vector table / ISR / stack ŽŸ‡€ ¡ëâì ¢ W2 (0x8000..0xBFFF)
- DSS ¨¬¥¥â ᢮© IM 2 handler ? ­ã¦­® chain'¨âìáï (¨­ ç¥ ª« ¢¨ âãà  / SYSTIME «®¬ îâáï)
### à®ç¨¥ ªàã¯­ë¥ ¯ã­ªâë ¤«ï v2
- [ ] **FILE API rewrite ? buffered streams** ? ⥪ãé ï ॠ«¨§ æ¨ï ¢
`libc/stdio/file.c` íâ® provisional unbuffered shim (ª ¦¤ë© fputc/fgetc
= ®¤¨­ read/write syscall). 㦭  ¯®«­®æ¥­­ ï buffered ᥬ ­â¨ª 
ª ª ¢ Solid-C:
```c
typedef struct {
uint flags; // +0..1 file status flags
int level; // +2..3 empty/fill level of buffer
char *curp; // +4..5 current active pointer
int fd; // +6..7 underlying low-level fd
char *buffer; // +8..9 data transfer buffer
char hold; // +10 ungetc byte if no buffer
short token; // +11..12 reserved
char dummy; // +13 reserved
} FILE;
```
stdin/stdout/stderr ? fd-¬ àª¥àë `0 / -1 / -2`. Žâà¨æ â¥«ì­ë¥ ¤«ï
stdout/stderr ¢ë¡à ­ë ­ ¬¥à¥­­®: ESTEX OPEN ¬®¦¥â ¢¥à­ãâì positive
small fd (1, 2, ?) ¤«ï ®¡ëç­®£® ä ©«  ? ¥á«¨ ¡ë stdout=1, ॠ«ì­ë©
fd=1 áâ «ª¨¢ «áï ¡ë á ¨¤¥­â¨ä¨ª â®à®¬. fd=0 ¤«ï stdin ¡¥§®¯ á­®
(ESTEX 0 ­¥ ¢®§¢à é ¥â). ‘ ¬¨ fd ­¥ ¯¥à¥¤ îâáï ¢ syscall'ë ?
¤¨á¯¥âç¥à¨§ æ¨ï ¯® ä« £ ¬ `_F_CONIN/_F_CONOUT`.
ਭâ¥à-¯®â®ª¨ (stdaux/stdprn) … ॠ«¨§ã¥¬ ? Sprinter ¯à¨­â¥à­®©
API ­¥ ¨¬¥¥â.
€«ìâ¥à­ â¨¢  ? ¢§ïâì ॠ«¨§ æ¨î ¨§ third_party/solid-c (sources ¢
`SRC/CLIB/`); â ¬ ¥áâì £®â®¢ë© buffered FILE + fopen/fread/fwrite/
fseek/setvbuf ¨ â.¤. €¤ ¯â¨à®¢ âì ª ­ è¨¬ open/read/write/lseek.
ਠrewrite § ®¤­® à¥è¨âì deferred issues stdio-review:
- `fwrite` short-write ¤®«¦¥­ áâ ¢¨âì `_F_ERROR`
- `fgets(buf, 1, fp)` ? áâ ­¤ àâ £®¢®à¨â "empty string", ¬ë ¢¥à­ã«¨ NULL
- `mode_to_flags` ? break-out ­  '+' (cosmetic)
- [ ] **Audio API** ? AY-3-8910 + COVOX ç¥à¥§ ¯à¥à뢠­¨ï (âॡã¥â IM2)
- [ ] **ISA-8 slot support** ? ZX-Bus ª àâë (sound, network, etc.) ? âॡã¥â IM2 + ç⥭¨ï port®¢
## à®ç¨¥ § ¤ ç¨ (v1 backlog, ­¥ ¡«®ª¨àãî騥)
- [x] **#9: text I/O split (Turbo-C style)** ? stdio (puts/printf/putchar) ⥯¥àì fast no-attr ç¥à¥§ PCHARS/PUTCHAR. conio (cputs/cprintf/putch) ¯à¨¬¥­ï¥â attr ç¥à¥§ textcolor/textbackground/textattr. KEEP_EXIST_ATTR ? conio fallback ­  fast path. Verified ¢ hello.exe. ‘¬. `memory/text_output_api_split.md`. ¥ «¨§®¢ ­® 2026-05-31.
- [x] **Mouse API ¯®«­ë©** (१¨¤¥­â­ë© driver, RST 30h) ? ¢á¥ 14 ä㭪権 ®¡ñà­ãâë (init/show/hide/refresh/read/goto/bounds/text_cursor/load_cursor/get_cursor/get/set_sensitivity/video_mode_changed). ‘¬. `memory/mouse_api.md`. Verified ¢ MAME 2026-05-31. Sensitivity = divider (¬¥­ìè¥ = ¡ëáâ॥).
- [ ] Interrupt handlers ? IM 2 vector table ¢ HOME ¤«ï user ISR'®¢
- [ ] ®¤¤¥à¦ª  `restore SP on EXIT` (¯ ââ¥à­ ¨§ z88dk +pps) ? ¯à®¢¥à¨âì ­ã¦­® «¨
- [ ] CI:  ¢â®¬ â¨ç¥áª¨ § ¯ã᪠âì MAME á `-aviwrite` ¤«ï screenshot-áà ¢­¥­¨ï, ç⮡ë â¥áâë ¯à¨¬¥à®¢ ¯à®å®¤¨«¨ ¡¥§ 祫®¢¥ª 
## ˆ¤¥¨ ­  ¯®â®¬
- ®¤¤¥à¦ª  `<setjmp.h>` (¥áâì ¢ SDCC stdlib ? ­ã¦­® ¯à®â¥áâ¨à®¢ âì çâ® ­ è crt0 ᮢ¬¥á⨬)
- `<time.h>` ç¥à¥§ ESTEX SYSTIME (`$21`) ¨ CMOS BIOS-ä㭪樨
- ZX Spectrum-ᮢ¬¥áâ¨¬ë© à¥¦¨¬ ª ª ®â¤¥«ì­ë© target (¤«ï ¯®àâ¨à®¢ ­¨ï ᯥªâà㬮¢áª¨å ¯à®£à ¬¬)
- ®¤¤¥à¦ª  ZX-Bus ª àâ (sound, network, etc.) ? ­ã¦­ë ¤à ©¢¥àë
- Profile-guided optimization tools (hot/cold detection) ¤«ï ªà㯭ëå ¯à®£à ¬¬
## Linker duplicate-symbol warnings (¡« £®¯à¨ïâ­ë¥, ®â䨫ìâ஢ ­ë)
Š®£¤  ¬ë á®§­ â¥«ì­® overrides'¨¬ SDCC z80.lib ä㭪樨 ᮡá⢥­­®© ¢¥àᨥ© ¢ `sprinter.lib`, `sdldz80` ¯¨è¥â `?ASlink-Warning-Definition of public symbol '...' found more than once`. ‹¨­ª¥à ¡¥àñâ ¯¥à¢®¥ ­ ©¤¥­­®¥ ®¯à¥¤¥«¥­¨¥ (­ è¥), ¯®í⮬㠯®¢¥¤¥­¨¥ ª®à४⭮¥ ? warning ⮫쪮 noise.
’¥ªã騥 overrides:
- `_puts` ? ­ è  ¢¥àá¨ï ç¥à¥§ PCHARS+\r\n vs SDCC posix puts
- `___sdcc_heap` ? ­ è heap ¢ W2 vs SDCC's áâ ­¤ àâ­ë©
- `_asctime`, `_localtime` (¨ ¢®§¬®¦­® ¤à㣨¥ ¨§ time) ? ­ è `posix_time.c` ç¥à¥§ ESTEX SYSTIME vs SDCC's `time.rel` ª®â®àë© § ¢¨á¨â ®â `_RtcRead`
**’¥ªã饥 à¥è¥­¨¥:** `bin/sprinter-cc` ®â䨫ìâ஢뢠¥â warning-¡«®ª (warning + 2 follow-up `Library:` áâப¨) ¨§ ¢ë¢®¤  `sdcc`. —¥à¥§ `-v` (verbose) ¢áñ ¯®ª §ë¢ ¥âáï. ¥ «¨§®¢ ­® ç¥à¥§ awk-pipe.
**‚®§¬®¦­ë¥ ã«ãç襭¨ï:**
- ¥à¥©â¨ ­  explicit `--nostdlib` + àãç­®© ᯨ᮪ ­ã¦­ëå ¬®¤ã«¥© ¨§ z80.lib (string, math, stdlib ¡¥§ override'­ãâëå) ? ã¡à âì ˆ‘’Ž—ˆŠ warning'®¢, ­¥ ¬ áª¨à®¢ âì
- ˆ«¨: ¯¥à¥¨¬¥­®¢ âì ­ è¨ `_puts` ? `_puts_sprinter` + alias ç¥à¥§ linker flag (­¥ 㢥७ çâ® SDCC ¯®¤¤¥à¦¨¢ ¥â)
- ˆ«¨: ®áâ ¢¨âì ª ª ᥩç á (à ¡®ç¥¥ ¨ benign) ? ¯à¨®à¨â¥â ­¨§ª¨©
## TODO: ¯à®¢¥à¨âì ­  ॠ«ì­®¬ ¦¥«¥§¥
- [ ] **Port_Y banking trick** (`docs/part2/SprinterGraphics programming.txt`):
¤®ªã ã⢥ত ¥â çâ® ¯®á«¥ `OUT (0x89), Y`  ¤à¥á  0xC000+0x400*N ¢ ®ª­¥ W3
¬ ¯¯ïâáï ­  áâப¨ Y..Y+15 (®¤­® ¯à®£à ¬¬¨à®¢ ­¨¥ ? 16 áâப).
Empirical 2026-06-01 ¢ MAME 0.283 íâ®â trick **­¥ à ¡®â ¥â** ? ¯¨ªá¥«¨
¯®  ¤à¥á ¬ ¢ëè¥ 0xC000+row_width ã室ïâ ¢ ­¥¢¨¤¨¬ãî ®¡« áâì. Š ­®­¨ç¥áª¨©
`docs/samples/plasma2.asm` ⮦¥ ­¥ ¨á¯®«ì§ã¥â banking, ¯¥à¥ãáâ ­ ¢«¨¢ ¥â
Port_Y per row.
« ­:
1. ®«ãç¨âì ¤®áâ㯠ª ॠ«ì­®¬ã Sprinter
2. ‡ ¯ãáâ¨âì â¥áâ dual-write (`_gfx_putpixel_raw` + ¢â®à®© write ¢ `0xD000+x`)
3. …᫨ ­  ¦¥«¥§¥ ¢¨¤­ë ¤¢®©­ë¥ «¨­¨¨ ? ¡ £  MAME, ®âªàëâì issue á
¬¨­¨¬ «ì­ë¬ ९à®
4. …᫨ ­  ¦¥«¥§¥ ⮦¥ ®¤­  «¨­¨ï ? ¤®ªã¬¥­â ­¥¢¥à­ë©, 㤠«¨âì 㯮¬¨­ ­¨¥
¨§ ¤®ª¨ ¨ ¯à®áâ® ®áâ ¢¨âì ⥪ãéãî ॠ«¨§ æ¨î (Port_Y per pixel)
5. …᫨ banking à ¡®â ¥â ­  ¦¥«¥§¥ ? ¢­¥¤à¨âì ªíè¨à®¢ ­¨¥ Port_Y ¢
`_gfx_putpixel_raw` (sentinel out-of-range, á¬. memory/gfx_port_y_banking.md)
‘¢ï§ ­­ë© ¢ë¨£àëè ¤«ï Bresenham (60-pixel ¤¨ £®­ «ì) ? ®ª®«® 8? ¬¥­ìè¥
OUT (0x89) ®¯¥à æ¨©, ¤«ï `gfx_fill_rect 320x256` ? 16? ¬¥­ìè¥. ¥ ¡«®ª¨àã¥â
release v1.
## GFX: à áè¨à¥­¨ï ¯® `docs/part2/accelerator_doc.txt`
®á«¥ ¯à®ç⥭¨ï ¤¥â «ì­®£® accelerator doc ¢ë¥­ë ­¥§ ªàëâë¥ ­ ¯à ¢«¥­¨ï.
‘¥©ç á ¢ ª®¤¥ ¨á¯®«ì§ã¥âáï ⮫쪮 £®à¨§®­â «ì­ë©/¢¥à⨪ «ì­ë© Fill mode.
### Quick wins ¤«ï ⥪ãé¨å primitives
- [ ] **‡ ¬¥­¨âì SMC ­  `LD A, (var)` ¤«ï block-size**. „®ªã¬¥­â ®
à §à¥è ¥â `LD A, (HL)`, `LD A, (BC)`, `LD A, (DE)` (­® ­¥ `LD A, r`).
â® ã¡¥àñâ SMC complexity ¢ `gfx_lines.c:hfill_chunk/vfill_chunk` ¨
`gfx_16.c:g16_hfill_chunk`. ‡ ¯à¥é¥­® ⮫쪮 register-to-register.
- [ ] **Šíè¨à®¢ ­¨¥ block-size**. „®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel § ¯®¬¨­ ¥â
block size ¬¥¦¤ã bursts (á¬. `Horizontal_Line_Fill`: ãáâ ­ ¢«¨¢ îâ
size + `LD B,B` ®âª«î祭¨¥, ¯®â®¬ ¢ª«îç îâ Fill mode ¨ ¨á¯®«ì§ãîâ
á®åà ­ñ­­ë© size). „«ï `gfx_fill_rect` á 100 ®¤¨­ ª®¢ë¬¨
áâப ¬¨ ? ãáâ ­®¢¨âì size 1 à §,   ­¥ 100.
### Bank-prefix modes (port 0xE2 bits)
„®ªã¬¥­â ¯®ª §ë¢ ¥â âਠ¢ à¨ ­â  ¡ ­ª  ¢¨¤¥®áâà ­¨æë ¯®¬¨¬® áâ ­¤ àâ­®£® 0x50:
| Bank byte | Effect |
|---|---|
| 0x50 | Normal write ? ¯¨è¥âáï ¢ shadow + ¢¨¤¨¬ë© |
| 0x54 | "no copy in main shadow RAM" |
| 0x58 | **"FF is transparent"** ? ¡ ©â 0xFF ¯à¨ write ®áâ ¢«ï¥â background |
| 0x5C | both |
Bank 0x58 ®¡êïá­ï¥â ¯®ç¥¬ã mouse cursor à¨áã¥âáï á 0xFF-¯à®§à ç­®áâìî.
â® ¯ãâì ª **sprite-blending ç¥à¥§ accel block copy**:
- [ ] **`gfx_set_bank_transparent(on)`** ¨«¨ ä« £ ¢ `gfx_set_bank` ¤«ï
¢ë¡®à  0x50/0x58 ¯à¨ ®âà¨á®¢ª¥ sprite'®¢
- [ ] ˆá¯®«ì§®¢ âì ¢ ­®¢®¬ `gfx_blit()` çâ®¡ë ¯® ä ªâã ¯®«ãç âì
transparent sprites ç¥à¥§ accel-ª®¯¨î
### Block copy mode (sprite blit'ë)
`LD L,L` (horizontal) ¨ `LD A,A` (vertical) ? ०¨¬ ª®¯¨à®¢ ­¨ï ¡«®ª  ç¥à¥§
256-¡ ©â­ãî accel memory. â® ¡ §¨á ¤«ï blit'®¢.
- [ ] **`gfx_blit(src_data, x, y, w, h)`** ? ª®¯¨à®¢ ­¨¥ sprite' 
(¯à®¨§¢®«ì­ë© à §¬¥à, ç¥à¥§ accel)
- [ ] **`gfx_blit_transparent(src, x, y, w, h)`** ? á ¨á¯®«ì§®¢ ­¨¥¬ bank 0x58
‘¬. `Draw_Restangle_Data` ¢ accelerator_doc.txt ª ª à¥ä¥à¥­á.
### AND / OR / XOR operations ç¥à¥§ accel
„®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel ¯®¤¤¥à¦¨¢ ¥â «®£¨ç¥áª¨¥ ®¯¥à æ¨¨ á ¡«®ª ¬¨
¤ ­­ëå. ਬ¥­¥­¨ï:
- XOR ? ¨­¢¥àá¨ï ®¡« á⨠(¢ë¤¥«¥­¨¥ selection ¢ UI)
- OR / AND ? masking, alpha-style blending
- ‘¬. ¯à¨¬¥à ¢ accelerator_doc.txt: "256 bytes block coding via XOR"
- [ ] **`gfx_xor_rect`** / **`gfx_or_rect`** / **`gfx_and_rect`** ?
¯à¨¬¨â¨¢ë «®£¨ç¥áª¨å ®¯¥à æ¨© ­ ¤ ¯àאַ㣮«ì­¨ª®¬
- [ ] **`gfx_invert_rect(x, y, w, h)`** ? alias ­  xor á 0xFF
### Bitmap fonts à §­ëå à §¬¥à®¢
‘¥©ç á `gfx_text` / `gfx_putchar` å à¤ª®¦¥­­® à ¡®â îâ á 8?8 èà¨ä⮬
(BIOS WIN_GET_ZG ¢®§¢à é ¥â 256?8 ¡ ©â). „«ï ¡ã¤ãé¨å UI / â¨âã«ì­¨ª®¢
­ã¦­ë:
- [ ] **`gfx_set_font_size(w, h)`** ? ¯¥à¥ª«îç¨âì è¨à¨­ã/¢ëá®âã glyph' 
- [ ] **`gfx_set_font_data(ptr, w, h, advance)`** ? § ¬¥­¨âì 㪠§ â¥«ì
­  ¯®«ì§®¢ â¥«ì᪨© èà¨äâ + à §¬¥àë
- [ ] ®¤¤¥à¦ª  **proportional** (advance != w) èà¨ä⮢ ? ¤®¡ ¢¨âì
array advance[256] ­  è¨à¨­ã ª ¦¤®£® glyph' 
- [ ] **Big-font ०¨¬ë**: 8?16, 16?16, 16?8 (¤«ï â¨âã«ì­¨ª®¢)
- [ ] ‚®§¬®¦­® ®â¤¥«ì­ë© API `gfx_text_ex(x, y, str, font_id)` £¤¥
font_id ¢ë¡¨à ¥â ®¤¨­ ¨§ § £à㦥­­ëå èà¨ä⮢
- [ ] **Anti-alias 2-bit èà¨äâë** (¡¨â ä®­ / ¡¨â £à ­¨æ  / 2-¡¨â alpha?)
? far future, ¤«ï smooth UI
## ”¨­ «ì­ë© íâ ¯ ®¯â¨¬¨§ æ¨© (­¥ ᥩç á)
- **`gfx_line` ç¥à¥§ accel ¤«ï ¯®«®£¨å ¤¨ £®­ «¥©** ? Bresenham ¤«ï «¨­¨¨ á |dy| << |dx| (¨«¨ ­ ®¡®à®â) ¢ë¤ ñâ ¤«¨­­ë¥ runs ®¤¨­ ª®¢®£® Y (¨«¨ X): ¯¨ªá¥«ì, ¯¨ªá¥«ì, ¯¨ªá¥«ì, è £ Y, ¯¨ªá¥«ì, ¯¨ªá¥«ì... Š ¦¤ë© â ª®© run ? íâ® £®â®¢ë©  à£ã¬¥­â ¤«ï `gfx_hline` (¨«¨ `vline`).
« ­ ¨áá«¥¤®¢ ­¨ï: ¯®áç¨â âì ¤«¨­ã runs ª ª äã­ªæ¨î ®â ­ ª«®­ ; à¥è¨âì ¬¨­¨¬ «ì­ë© run length, ¯à¨ ª®â®à®¬ ¢ë£®¤­¥¥ accel hline 祬 N?putpixel (overhead accel ~20?s, putpixel ~5?s ? accel ¢ë£®¤­¥¥ ¯à¨ run ? 4-5 px); ¤«ï ªàãâëå ¤¨ £®­ «¥© (dx ? dy) ®áâ ¢¨âì Bresenham, ¤«ï ¯®«®£¨å ? run-length-based fill.
‘¥©ç á `gfx_line` orthogonal cases 㦥 ç¥à¥§ accel ? ®¯â¨¬¨§¨à®¢ âì ⮫쪮 ª®áë¥.
- **`gfx_fill_rect` á ®¤­¨¬ W3-swap ­  ¢áî ®¯¥à æ¨î** ? ᥩç á ª ¦¤ë© ¢­ãâ७­¨© `gfx_hline`/`gfx_vline` ¤¥« ¥â ᢮© DI/save-W3/restore-W3/EI. Œ®¦­® ᤥ« âì internal `_fill_rect_inner` ª®â®àë© ¤¥à¦¨â W3 § ¬ ¯«¥­­ë¬ ¨ DI ¢¥áì æ¨ª«; ~20?s ? ª®«¨ç¥á⢮ áâப/á⮫¡æ®¢ íª®­®¬¨¨. ਬ¥­¨¬® ª® ¢á¥¬ ª®¬¯®§¨â­ë¬ ¯à¨¬¨â¨¢ ¬.
# MDView ? à®á¬®âà騪 Markdown ¤«ï Sprinter
**MDView** ? ¯à®£à ¬¬  ¤«ï ¯à®á¬®âà  ¤®ªã¬¥­â®¢ ¢ ä®à¬ â¥ *Markdown* ­  ª®¬¯ìîâ¥à¥
Sprinter (¯à®æ¥áá®à Z80). „®ªã¬¥­â åà ­¨âáï ¢ ®â¤¥«ì­®¬ W3 ®ª­¥ ¨ ­¥ § ­¨¬ ¥â
®á­®¢­ãî RAM ¯à®£à ¬¬ë.
## ‚®§¬®¦­®áâ¨
- „®ªã¬¥­âë ¤® **128 Š** (8 áâà ­¨æ EMM ¯® 16 Š ª ¦¤ ï)
- „® **16 384** íªà ­­ëå áâப ¢ ¨­¤¥ªá¥
- €¢â®¬ â¨ç¥áª¨© ¯¥à¥­®á á«®¢ ¯® è¨à¨­¥ íªà ­  (80 á⮫¡æ®¢)
- ƒ®à¨§®­â «ì­ë© ᤢ¨£ ¤«ï è¨à®ª¨å áâப (¡«®ª¨ ª®¤ , â ¡«¨æë)
- ‘â âãá-¡ à: ¨¬ï ä ©« , ¤¨ ¯ §®­ áâப, ¯à®æ¥­â ¯à®ªàã⪨
- ‘¯¨­­¥à ¢ áâப¥ á®áâ®ï­¨ï ¢® ¢à¥¬ï § £à㧪¨ ¨ ¨­¤¥ªá æ¨¨
- ®¤¤¥à¦ª  ?¬ï£ª®£®? ᪫¥¨¢ ­¨ï áâப ¢  ¡§ æ å ¨ æ¨â â å
## ‡ ¯ãáª
```
mdview [¨¬ï_ä ©« .md]
```
…᫨ ¨¬ï ä ©«  ­¥ § ¤ ­®, § £à㦠¥âáï `README.MD`.
## “¯à ¢«¥­¨¥
```
Š« ¢¨è  „¥©á⢨¥
ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Up Down பàã⪠ ­  ®¤­ã áâப㠢¢¥àå / ¢­¨§
PgUp PgDn பàã⪠ ­  áâà ­¨æã (30 áâப)
Home  ç «® ¤®ªã¬¥­â 
End Š®­¥æ ¤®ªã¬¥­â 
Left Right ƒ®à¨§®­â «ì­ë© ᤢ¨£ (⮫쪮 nowrap-áâப¨)
F1 Žª­® á¯à ¢ª¨
F8 Š®¤¨à®¢ª : CP866 ? CP1251 ? KOI8-R ? UTF-8 ? ...
F10 / Esc ‚ë室 ¨§ ¯à®£à ¬¬ë
```
Š®¤¨à®¢ª  ®¯à¥¤¥«ï¥âáï  ¢â®¬ â¨ç¥áª¨ ¯à¨ ®âªàë⨨ (BOM + í¢à¨á⨪  ¯®
¯¥à¢ë¬ 4 Š); `F8` ¯¥à¥ª«î砥⠥ñ ¢àãç­ãî, ¥á«¨ ¤¥â¥ªæ¨ï ®è¨¡« áì.
8-¡¨â­ë¥ ª®¤¨à®¢ª¨ (CP866/CP1251/KOI8-R) ¯¥à¥ª«îç îâáï ¬£­®¢¥­­® (६ ¯ ­ 
®âà¨á®¢ª¥). ‚â®à®© ­ ¡®à ¨­¤¥ªá/ªíè  (­ ¯à¨¬¥à UTF-8) áâநâáï «¥­¨¢® ? ¯à¨
¯¥à¢®¬ ¯¥à¥ª«î祭¨¨ ¢ ­¥£® (ª®à®âª ï ¯ ã§  ᮠᯨ­­¥à®¬), ¤ «ìè¥ ¬£­®¢¥­­®.
## ‘¨­â ªá¨á Markdown
### ‡ £®«®¢ª¨
®¤¤¥à¦¨¢ îâáï ã஢­¨ H1?H4. “஢­¨ H5 ¨ H6 ®â®¡à ¦ îâáï ª ª H4.
# ‡ £®«®¢®ª ¯¥à¢®£® ã஢­ï
## ‡ £®«®¢®ª ¢â®à®£® ã஢­ï
### ‡ £®«®¢®ª âà¥â쥣® ã஢­ï
#### ‡ £®«®¢®ª ç¥â¢ñà⮣® ã஢­ï
### ’¥ªá⮢®¥ ä®à¬ â¨à®¢ ­¨¥
**†¨à­ë© ⥪áâ** ¢ë¤¥«ï¥âáï ¤¢®©­ë¬¨ §¢ñ§¤®çª ¬¨: `**⥪áâ**`
*Šãàᨢ* ¢ë¤¥«ï¥âáï ®¤¨­®ç­ë¬¨ §¢ñ§¤®çª ¬¨ `*⥪áâ*` ¨«¨ §­ ª®¬ ¯®¤çñન¢ ­¨ï `_⥪áâ_`
`‚áâ஥­­ë© ª®¤` ®¡®§­ ç ¥âáï ®¡à â­ë¬¨ ª ¢ë窠¬¨
~~‡ çñભãâë© â¥ªáâ~~ ? ¤¢®©­ë¥ ⨫ì¤ë: `~~⥪áâ~~`
### ¥­ã¬¥à®¢ ­­ë© ᯨ᮪
Œ àª¥àë `-`, `*` ¨«¨ `+`:
- ¥à¢ë© ¯ã­ªâ ᯨ᪠
- ‚â®à®© ¯ã­ªâ ᯨ᪠
- ’à¥â¨© ¯ã­ªâ á ¤®áâ â®ç­® ¤«¨­­ë¬ ⥪á⮬, ª®â®àë© ¯à¨ ­¥®¡å®¤¨¬®áâ¨
¡ã¤¥â ¯¥à¥­¥áñ­ ­  á«¥¤ãîéãî áâபã á á®åà ­¥­¨¥¬ ®âáâ㯠
### 㬥஢ ­­ë© ᯨ᮪
1. ¥à¢ë© í«¥¬¥­â
2. ‚â®à®© í«¥¬¥­â
3. ’à¥â¨© í«¥¬¥­â
### –¨â â 
> «®ª æ¨â âë ­ ç¨­ ¥âáï á ᨬ¢®«  `>`. ¥áª®«ìª® ¯®á«¥¤®¢ â¥«ì­ëå
> áâப ®¤­®© æ¨â âë ᪫¥¨¢ îâáï ¢ ¥¤¨­ë©  ¡§ æ á  ¢â®¬ â¨ç¥áª¨¬
> ¯¥à¥­®á®¬ á«®¢.
### «®ª ª®¤  (verbatim)
«®ª ª®¤  § ª«îç ¥âáï ¢ âன­ë¥ ®¡à â­ë¥ ª ¢ë窨. ‚­ãâਠ¡«®ª 
⥪á⠮⮡ࠦ ¥âáï ?ª ª ¥áâì? ¡¥§ à §¡®à  Markdown:
```
#include <stdio.h>
#include <sprinter.h>
int main(void) {
puts("Hello, Sprinter!");
return 0;
}
```
### ƒ®à¨§®­â «ì­ ï «¨­¨ï
’ਠ¨«¨ ¡®«¥¥ ᨬ¢®«®¢ `---`, `***` ¨«¨ `___` ­  ®â¤¥«ì­®© áâப¥:
---
## ’¥å­¨ç¥áª¨¥ å à ªâ¥à¨á⨪¨
- **« âä®à¬ :** Sprinter, ¯à®æ¥áá®à Z80 @ 21 Œƒæ
- **Š®¤¨à®¢ª¨:** CP866 / CP1251 / KOI8-R / UTF-8 ( ¢â®®¯à¥¤¥«¥­¨¥, `F8`)
- **Œ ªá¨¬ «ì­ë© à §¬¥à ä ©« :** 128 Š
- **Œ ªá¨¬ «ì­®¥ ç¨á«® áâப ¢ ¨­¤¥ªá¥:** 16 384
- **¥¦¨¬ ¯ ¬ïâ¨:** small
- Š®¤ ¯à®£à ¬¬ë, c⥪, ¤ ­­ë¥, ªãç  ? ®ª­a W1-W2 (32 Š,  ¤à¥á  0x4000?0xBFFF).
- ãä¥à ä ©«  ? áâà ­¨æë EMM, ®â®¡à ¦ ¥¬ë¥ ¢ W3 (0xC000?0xFFFF)
## TODO
1. **“¢¥«¨ç¥­¨¥ à §¬¥à  ¤®ªã¬¥­â®¢.** ‘­ïâì «¨¬¨â 128 Š: „®áâ â®ç­®
à §à¥è¨âì à ¡®â âì á ¡®«ì訬 ª®«-¢®¬ áâà ­¨æ ¯ ¬ïâ¨, ¯®ª  ®ââ¥áâ¨à®¢ ­­®
­  à ¡®â¥ á 8-¬î áâà ­¨æ ¬¨ ¯® 16Š¡.
‘¤¥« ­®: ä®à¬ â¨à®¢ ­­ë¥ â ¡«¨æë á à ¬ª®©; ¯®¤¤¥à¦ª  ª®¤¨à®¢®ª
CP866 / CP1251 / KOI8-R / UTF-8 á  ¢â®®¯à¥¤¥«¥­¨¥¬ ¨ ¯¥à¥ª«î祭¨¥¬ ¯® `F8`
(¢â®à®© ­ ¡®à áâநâáï «¥­¨¢®, ¯® ¯¥à¢®¬ã ¯¥à¥ª«î祭¨î).
4. **“᪮७¨¥ ७¤¥à¨­£ .** Šíè áâப íªà ­ . Ž¯â¨¬¨§ æ¨ï 横«  ¢ë¢®¤ 
ᨬ¢®«®¢ ç¥à¥§ BIOS WRCHAR (¯ ª¥â­ë© ¢ë¢®¤, DMA).
---
*MDView v0.2 ú (c) 2026 ¥â஢ €.ƒ.*
---
# Sprinter C Compiler ? v1.0
C toolchain for **Sprinter** ? the Z80-based home computer by Peters Plus, running
ESTEX DSS. Host: macOS / Linux. Target: `.EXE` files in SprintEXE format.
Built on top of **SDCC 4.5** (vendored in `third_party/sdcc/`). This repository adds
everything Sprinter-specific: crt0, linker integration, libc wrappers over ESTEX,
banked-call trampolines, graphics & accelerator API, mouse driver wrappers, and the
`mkexe` utility for producing SprintEXE images.
## What you get
* **`bin/sprinter-cc`** ? one-line driver: `sprinter-cc -o foo.exe foo.c`
* **Memory modes**: `tiny`, `small`, `big`, `huge`, `manual` ? see below.
* **stdio + conio**: printf, puts, putchar, getchar, fopen/fread/..., cprintf, cputs, putch, textcolor/textbackground/textattr, gotoxy, kbhit/getch.
* **Graphics**: 320?256?256 and 640?256?16 modes, accelerator-backed primitives (hline / vline / rect / fill_rect / line via Bresenham, plus clear), bitmap-font text in both modes via BIOS character generator.
* **File I/O**: POSIX (`open`/`read`/`write`/`close`/`lseek`/`unlink`/`creat`), FILE\* streams (`fopen`/`fgets`/`fwrite`/...), directory listing (`ffirst`/`fnext`), `chdir`/`getcwd`/`mkdir`/`rmdir`, `stat`/`fstat`.
* **Memory**: 32 KB heap (W2-resident), banking-aware page allocator (`mem_alloc_pages`/`bank_read`/`bank_write`), explicit memory modes for sub-16 KB programs.
* **Mouse**: full Sprinter driver wrapper (14 functions including custom cursor bitmaps).
* **Environment**: `getenv`/`putenv`/`sysenv` over ESTEX `$46`.
* **Time**: `getdatetime`/`setdatetime` + POSIX `time`/`localtime`/`mktime`/`asctime`/`ctime`.
* **Misc**: `errno`/`strerror`/`perror`, `atexit`, `setjmp`/`longjmp`, `sleep`, full argv parsing in crt0.
## Quick start
```sh
git clone <this repo> sprinter-c
cd sprinter-c
make sdcc # one-time: fetch SDCC 4.5 binary (~25 MB)
make all # build mkexe + libsprinter.lib + 27 examples
make floppy # pack everything into mame/v306/IMG/mc.img
cd mame/v306 && ./run_mame.sh # boot Sprinter in MAME
```
Compile a single program:
```sh
cat > hello.c <<EOF
#include <stdio.h>
int main(void) { puts("Hello, Sprinter!"); return 0; }
EOF
bin/sprinter-cc -o hello.exe hello.c
```
That's it ? `hello.exe` is now a valid SprintEXE you can `RUN HELLO` from the ESTEX shell.
## Memory modes
Sprinter's address space is four 16 KB windows (W0 / W1 / W2 / W3). DSS allocates
pages by program size ? small programs get only one page. Pick a memory mode based
on what your program needs:
| Mode | Code lives in | Banking | Use when | Note |
|---|---|---|---|---|
| `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB | |
| `small` | W1-W2 (0x4100+) | no | code+data < 30 KB | |
| `big` | W2 + W1 banking | yes (W1) | tiny + extra code modules | |
| `huge` | W1-W2 + W3 banking | yes (W3) | small + extra code modules | |
| `manual` | user-specified | optional | special layouts | Not implemented |
```sh
sprinter-cc --memory small -o big.exe bigprog.c
sprinter-cc --memory huge -o app.exe main.c --bank 1=engine.c --bank 2=ai.c
```
Banked functions are declared with `__banked`:
```c
void engine_tick(int dt) __banked; // lives in BANK1, automatically swapped
```
## Examples (27 total)
| Example | What it demonstrates |
|---|---|
| `hello` | Hello world with stdio + conio Turbo-C-style colors |
| `argv` | argv parsing in crt0 |
| `cat` | File I/O ? read & print TEST.TXT |
| `seek` | 32-bit lseek over a 100 KB file |
| `ls` | Directory listing via ffirst/fnext |
| `filetest` | FILE\* streams (fopen/fread/...) |
| `stattest` | `stat`/`fstat` on files and directories |
| `errno` | errno / strerror / perror |
| `mem_test` | Page allocator + bank\_read/bank\_write |
| `malloc` | Heap stress test (200+ allocations) |
| `banked` | Banked code in W3 (huge mode) |
| `bankedbg` | Banked code in W1 (big mode) |
| `banklocl` | Bank-local static data and BSS |
| `mouse` | Mouse driver in text mode |
| `gfx_mous` | Mouse with custom bitmap cursor in graphics mode |
| `gfx_demo` | 320?256?256 lines / rects / accelerator |
| `gfx_d16` | 640?256?16 same primitives |
| `gfx_text` | Bitmap-font text on graphics screen |
| `timedir` | Date/time + directory listing |
| `ptime` | POSIX time API |
| `openenv` | open() flags + environment vars |
| `conio` | conio API smoke test |
| `attrprob` | Probe Sprinter text attribute byte layout |
| `strtest` | string.h test (from SDCC's z80.lib) |
| `stdlib` | stdlib.h test (qsort / rand / strtol / etc.) |
| `assrtest` | assert() |
| `rt_test` | Runtime helpers (sleep, setjmp, atexit) |
## Headers
Standard:
* `<stdio.h>` ? puts / printf / FILE\* + Sprinter-specific dec/hex helpers
* `<stdlib.h>` ? atoi / atof / malloc / qsort / ... (from SDCC z80.lib)
* `<string.h>` / `<ctype.h>` / `<math.h>` ? from SDCC z80.lib
* `<unistd.h>` ? read / write / close / lseek / unlink
* `<fcntl.h>` ? open / creat + O\_RDONLY / O\_CREAT / ...
* `<errno.h>` ? errno + error names + strerror
* `<sys/stat.h>` ? stat / fstat
* `<setjmp.h>` / `<assert.h>` ? from SDCC
Sprinter-specific:
* `<conio.h>` ? putch / cputs / cprintf, textcolor / textbackground / textattr, kbhit / getch, clrscr, gotoxy, wherex/y
* `<gfx.h>` ? gfx_init/done, palette, putpixel, hline/vline/rect/fill_rect/line, text ? for both 320 and 640 modes (gfx_\*16 variants)
* `<mouse.h>` ? full 14-function driver wrapper + mouse_cursor_t with bitmap support
* `<dir.h>` ? chdir / getcwd / mkdir / rmdir / ffirst / fnext / ffblk
* `<time.h>` ? getdatetime / setdatetime + POSIX time / localtime / etc.
* `<sprinter.h>` ? raw ports, ESTEX/BIOS function numbers, env API
* `<sprinter_exit.h>` ? exit / \_exit / atexit
* `<sprinter_mem.h>` ? mem\_alloc\_pages / mem\_free\_block / bank\_read / bank\_write
* `<sprinter_compat.h>` ? Solid-C compatibility layer (aliases + BOOL/WORD/uint types)
## Toolchain commands
```sh
make all # build mkexe + lib + every example
make floppy # repack mame/v306/IMG/mc.img with all .exe files
make check # 17 mkexe unit-tests
make clean # remove all build artefacts
make sdcc # one-time: fetch SDCC 4.5 binary
```
### sprinter-cc options
```
sprinter-cc -o foo.exe foo.c [more.c ...] [options]
--memory MODE tiny | small | big | huge | manual (default: tiny)
--memory-manual SPEC explicit placement (CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3)
--stack-size N bytes reserved for the stack (default ~1278)
--crt0=TYPE default | minimal | banked | small
--bank N=FILE.c compile FILE.c into bank N (repeatable, max 15)
--debug enable runtime diagnostics (defines DEBUG_RT)
-I PATH extra include path
-L 0xADDR / -E / -S override load / entry / stack addresses
-Wl FLAG pass FLAG to sdldz80
--mkexe FLAG pass FLAG to mkexe (e.g. --mkexe -p --mkexe 0 for bank padding)
-v verbose
```
## Status
What works in v1.0:
* Compile / link / pack to SprintEXE ? verified on all 27 examples
* Four memory modes (tiny / small / big / huge)
* Graphics (both modes) with accelerator
* Mouse (text + graphics cursor)
* File I/O, directories, environment, time
* All headers listed above
Deferred to v2.0 (see `docs/TODO.md`):
* **Turbo-C-style BGI graphics API** ? `initgraph` / `setcolor` / `circle` /
`getimage` / `putimage` / etc. on top of our `gfx_*` primitives
* Remaining Solid-C compatibility gaps (Phase 2/3) ? see `docs/solid_c_compatibility.md`
* Manual memory mode
* Rewrite FILE\* stream API (current implementation is very primitive and doesn't use buffers)
Deferred to v3.0:
* **IM2 interrupt handlers** ? research complete (`docs/im2_isr_design.md`),
implementation scheduled for v3
* **Audio API** (AY-3-8910 + COVOX) ? requires IM2
* **ISA-8 slot drivers** ? requires IM2 (???)
## Documentation
* `docs/TODO.md` ? roadmap and open work items
* `docs/solid_c_compatibility.md` ? gap analysis vs Solid-C 2004
* `docs/im2_isr_design.md` ? interrupt handler design (v2)
* `docs/converted/` ? source documentation (ESTEX, BIOS, architecture)
converted to plain text for `grep`
* `docs/reference/`, `docs/samples/`, `docs/memory management/` ? original
Russian docs and code samples from Peters Plus
## Repository layout
```
bin/sprinter-cc one-line compiler driver (bash)
toolchain/mkexe/ host-side tool: .ihx -> .exe SprintEXE
toolchain/check_banks.py post-link bank size enforcer
runtime/ crt0 variants (default, minimal, small, banked)
bank trampolines, heap, heap_top
libc/include/ headers
libc/io|stdio|mem|gfx/ C and asm sources for libsprinter.lib
lib/ Makefile that archives libsprinter.lib via sdar
examples/ 27 example programs
mame/v306/ MAME binary + Sprinter ROM/HDD images + floppy script
third_party/sdcc/ vendored SDCC 4.5 (fetched via `make sdcc`)
third_party/solid-c/ reference: original Sprinter native C (for compat target)
docs/ documentation
```
## License
This repository contains:
* Original code in `bin/`, `toolchain/`, `runtime/`, `libc/`, `lib/`, `examples/` ?
MIT-licensed.
* `third_party/sdcc/` ? SDCC 4.5 under GPLv2 with linking exception
(see `third_party/sdcc/COPYING.txt`)
* `third_party/solid-c/` ? original Sprinter Solid C, used only as a reference
## Credits
* **Sprinter / Peters Plus** ? ˆ¢ ­ Œ ª, „¬¨â਩  à¨­®¢ and the original team
* **SDCC** ? for the underlying Z80 compiler
* **MAME** ? for the Sprinter Sp2000 emulation
---
For questions / patches: see CONTRIBUTING.md (TBD) or open an issue.
---
# TODO / Roadmap
Žâªàëâë¥ § ¤ ç¨ ¢ ¯®à浪¥ ã¡ë¢ ­¨ï ¯à¨®à¨â¥â . ® ¬¥à¥ ¯®ï¢«¥­¨ï ॠ«ì­ëå ¯à®£à ¬¬ ? ¯à¨®à¨â¥âë ¡ã¤ãâ ᬥé âìáï.
## â ¯ 5 ? malloc / free + banking-aware page allocator ? ƒŽ’Ž‚Ž
- [x] SDCC's `malloc`/`free` + ­ è `runtime/heap.s` (¯®«­®áâìî § ¬¥­ï¥â library heap.rel, 14000-¡ ©â­ë© heap ¢ ®ª­¥ 2)
- [x] `libc/mem/mem_alloc.c` ? page allocator: `mem_alloc_pages`/`mem_free_block`/`mem_get_page`/`mem_info` ç¥à¥§ ESTEX `$3C/$3D/$3E` + BIOS `$C4`
- [x] `libc/mem/bank_io.c` ? HOME-१¨¤¥­â­ë¥ `bank_read`/`bank_write`/`bank_load_byte`/`bank_store_byte` ᮠ᢮¯®¬ W3 ¢­ãâà¨
- [x] `examples/malloc_test/` ? ¯à®¢¥àª  SDCC's malloc (~210 64-¡ ©â­ëå allocations ç¥à¥§ ¢áî heap)
- [x] `examples/mem_test/` ? ¯à®¢¥àª  page allocator: 3 áâà ­¨æë, à §­ë¥ ¯ ââ¥à­ë ç¥à¥§ bank_write, ¢¥à¨ä¨ª æ¨ï ç¥à¥§ bank_read
## â ¯ 6 ? argv parsing + sprinter-cc wrapper ? ƒŽ’Ž‚Ž
- [x] crt0 ¯ àá¨â ESTEX command-line ¨§ IX-prefix (inline asm ¢ `runtime/crt0.s`)
- [x] Strip leading CP/M-style space (DSS quirk)
- [x] ¥à¥¤ ç  `argc`/`argv` ¢ main() ç¥à¥§ HL/DE (SDCC __sdcccall(1) ABI)
- [x] argv[0] = basename .EXE ç¥à¥§ ESTEX APPINFO ($47 subfn 2)
- [x] `runtime/crt0_minimal.s` ? opt-out ¤«ï ®ç¥­ì ¬ «¥­ìª¨å ¯à®£à ¬¬
- [x] `runtime/crt0_banked.s` ? ⥯¥àì ⮦¥ ¯ àá¨â argv (parse_argv + get_progname ᪮¯¨à®¢ ­ë ¨§ crt0.s; ¡ã¤¥â factored ¢ argv.s ª®£¤  ¢®§ì¬ñ¬áï §  libsprinter.lib)
- [x] Bash-®¡ñà⪠ `bin/sprinter-cc`: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨©: `--memory`, `--memory-manual`, `--stack-size`, `--crt0=`, `--bank N=FILE.c`, `--debug`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
## â ¯ 8 ? £à ä¨ª  (320?256?256 + 640?256?16 + accel + bitmap font) ? ƒŽ’Ž‚Ž
- [x] **8a** Graphics core: `gfx_init`/`gfx_done`/`gfx_clear`/`gfx_putpixel`/`gfx_pal_load`/`gfx_pal_set` (libc/gfx/gfx_core.c).  «¨âà  ç¥à¥§ BIOS PIC_SET_PAL ($A4). Verified 320?256?256.
- [x] **8b** ‹¨­¨¨/¯àאַ㣮«ì­¨ª¨/fill ç¥à¥§ accelerator (libc/gfx/gfx_lines.c): `gfx_hline`/`gfx_vline` ç¥à¥§ accel Fill (LD C,C / LD E,E + SMC block-size), `gfx_rect`/`gfx_fill_rect` á heuristic ¢ë¡®à®¬ ®à¨¥­â æ¨¨ (h/v bursts count), `gfx_line` á Bresenham ¤«ï ¤¨ £®­ «¥©. `gfx_clear` ⮦¥ ¯¥à¥¯¨á ­ ­  column-major accel (~4? ¡ëáâ॥).
- [x] **8c** 640?256?16 mode (libc/gfx/gfx_16.c): `gfx_*16` API, HIGH nibble = LEFT pixel (¤®ªã¬¥­â æ¨ï misleading), per-row RMW ¤«ï vline (®¤¨­ ¡ ©â = 2 £®à¨§®­â «ì­ëå ¯¨ªá¥«ï).
- [x] **8d** Bitmap font + gfx_text (libc/gfx/gfx_text.c): èà¨äâ ç¥à¥§ BIOS WIN_GET_ZG ($B8), interleaved layout `font[row*256+char]`, `gfx_text`/`gfx_putchar` ¤«ï 320 mode, `gfx_text16`/`gfx_putchar16` ¤«ï 640 mode á pair-table lookup.
‘¬. memory/sprinter_graphics.md, sprinter_accelerator.md, sprinter_graphics_16.md, sprinter_font_format.md.
Žâªàëâë¥ ¬¥«®ç¨ (­¥ ¡«®ª¨àãîâ):
- [ ] ˜à¨äâ-quad ¤«ï 640: per-cell ¯ «¨âà  (mode 0x82 à §à¥è ¥â 1 ¨§ 4 ¯ «¨âà per 16?8 cell) ? ç¥à¥§ ¯àאַ© ¤®áâ㯠ª area-®¯¨á ­¨ï íªà ­  0x0300..0x039F
## Auto-banking (á¬. `memory/banking_roadmap.md` ¤«ï ¤¥â «¥©)
Phase 1 ? file-level bin-packing ? ॠ«¨§®¢ë¢ âì ª®£¤  ¯à®¥ªâ ¯¥à¥à áâñâ ~30 KB ª®¤ .
- [ ] `toolchain/auto_bank.py`:
-  àá¨â à §¬¥àë ¨§ `.rel`-ä ©«®¢ (¨«¨ ¨§ .map ¯®á«¥ dry-run link' )
- First-fit-decreasing bin-packing
- “¢ ¦ ¥â `#pragma codeseg BANKn` ª ª manual override
- ¥à¥«¨­ª®¢ë¢ ¥â á ­®¢ë¬¨ `-Wl-b_BANKn=...` ¯ à ¬¥âà ¬¨
- ¥ç â ¥â ¯« ­ à á¯à¥¤¥«¥­¨ï
Phase 2-5: incremental rebalance, declarative `banks.toml`, function-level, call-graph-aware. ’®«ìª® ¥á«¨/ª®£¤  ¯®­ ¤®¡¨âáï.
## Bank-local static data (mutable data ¢ ⮬ ¦¥ ¡ ­ª¥ çâ® ¨ ª®¤) ? ? ƒŽ’Ž‚Ž
- [x] ਬ¥à `examples/bank_local_data/` ? äã­ªæ¨ï ¢ BANK1 ᮠ᢮¨¬ writable BSS array + const table + malloc-â¥áâ
- [x] `mkexe -p 0` ¤«ï ­ã«¥¢®£® padding ¡ ­ª®¢ (BSS-storage ®¡­ã«ï¥âáï ¯à¨ § £à㧪¥)
- [x] Š ­®­¨ç¥áª¨© à¥æ¥¯â: `--codeseg BANK1 --constseg BANK1 --dataseg BANK1` ¤«ï bank1.c + `-Wl-b_BANK1=0x1C000` ¤«ï «¨­ª®¢ª¨. **`--dataseg BANK1` Ž’€…’** ? à ­ìè¥ ª § «®áì ®¡à â­®¥ ¨§-§  trampoline bug ª®â®àë© ¬ áª¨à®¢ « १ã«ìâ â.
- [x] **Šà¨â¨ç­ë© 䨪á trampoline'a ¢ runtime/bank.s** ? áâ àë© `pop af; out (n), a` ª«®¡¡¥à¨« A ? ¢á¥ banked-ä㭪樨 ¢®§¢à é î騥 uint8_t â¨å® ¢®§¢à é «¨ ¬ãá®à. ®¢ë© `pop bc; out (c), b` á®åà ­ï¥â A.
- [x] **malloc ¨§ banked-ä㭪樨 à ¡®â ¥â ¯à®§à ç­®** ? heap ¦¨¢ñâ ¢ W2 (HOME), W2 ­¨ª®£¤  ­¥ ᢠ¯ ¥âáï trampoline'®¬, pointer ¢ «¨¤¥­ ¨§ «î¡®£® ª®­â¥ªáâ . ‘¬. memory/bank_local_data_pattern.md.
- [x] „®ªã¬¥­â æ¨ï ¢ memory: `memory/bank_local_data_pattern.md` (¯®«­ë© à¥æ¥¯â + malloc + nuances), `memory/sdcc_banking.md` (trampoline fix)
- [ ] Ž¯æ¨®­ «ì­® ? à áè¨à¨âì `check_banks.py` çâ®¡ë ¯®ª §ë¢ âì à §¡¨¢ªã size = code + const + bss per bank (cosmetic)
‡ ç¥¬: ¤«ï ¬®¤ã«¥© á ¡®«ì訬 private state (level loader, audio engine, scene data). ª®­®¬¨â W2 heap ¤«ï ¤¨­ ¬¨ª¨,   áâ â¨ª  ®áâ ñâáï ¢ ¡íª¥.
## ®¤áª §ª¨ ¨§ solid-c (­ â¨¢­ë© Sprinter C ? `third_party/solid-c/`)
®á«¥  ­ «¨§  solid-c'®¢áª®© libc (á¬. `memory/solid_c_findings.md`) ¢ë¥­ë £®â®¢ë¥ ¯ ââ¥à­ë ¤«ï á«¥¤ãîé¨å ­¥¤®áâ îé¨å ä㭪権. ਮà¨â¥â ®â **¢ë᮪®£®** ª ­¨§ª®¬ã:
### High-priority gaps («¥£ª® ¯®àâ¨à®¢ âì, ¡®«ìè ï ¯®«ì§ )
- [x] **`errno` + `strerror`/`perror`** ? â ¡«¨çª  32 ®è¨¡®ª (libc/io/errno.c)
- [x] ** áè¨à¥­­ë© `open()`** ¤«ï O_CREAT/O_TRUNC/O_APPEND/O_EXCL state machine
- [x] **`atexit`** ? 8-callback LIFO + `exit()` + `_exit()` (libc/io/atexit.c)
- [x] **`setjmp`/`longjmp`** ? 6-¡ ©â jmp_buf={sp,ix,pc} (libc/io/setjmp.c)
- [x] **`sleep(seconds)`** ? 50Hz halt-loop (libc/io/sleep.c)
- [x] **ESTEX ENV API** ($46, getenv/putenv) ? libc/io/env.c. “竨 doc-bug: ॠ«ì­® A=0 íâ® NOT FOUND
### Medium-priority (­ã¦­® ¤«ï shell-like ã⨫¨â)
- [ ] **Mouse driver** ? `rst $30h`, 17 ä㭪権. **‘­ ç «  â¥áâ çâ® à ¡®â ¥â ¢ MAME**.
- [x] **`ffirst`/`fnext` + ffblk_t struct** ¤«ï directory listing ? ॠ«¨§®¢ ­®, demo: ls.exe
- [x] **`getdatetime`/`setdatetime`** ç¥à¥§ ESTEX $21/$22 ? libc/io/time.c, demo: time_dir_test
- [x] **`chdir`/`getcwd`/`mkdir`/`rmdir`** ? wrappers ¤«ï ESTEX $1B-$1E ? libc/io/fsdir.c
- [x] **conio: `kbhit`/`getch`/`getche`/`cputs`/`clrscr`/`gotoxy`** ? ॠ«¨§®¢ ­®
- [x] **conio extras**: `wherex`/`wherey` ($53), `wrchar`/`rdchar` ($58/$57), `textmode_get/set` ($50/$51), `clrscr_attr` ($56) + COLOR macros
### Low-priority ? ? FILE* stack ƒŽ’Ž‚Ž
- [x] **Œ¨­¨¬ «ì­ë© unbuffered FILE\*** ? `libc/stdio/file.c` + `libc/include/stdio.h`. fopen/fclose/fputs/fgets/fread/fwrite/fseek/ftell/rewind/feof/ferror/clearerr/fflush + stdin/stdout/stderr ª ª pseudo-streams. ‘¬. `memory/file_star_design.md` ¨ `examples/filetest`.
- [ ] fprintf / fscanf ? ­ã¦­  printf-ç¥à¥§-callback machinery. ®ª  ¯®«ì§®¢ â¥«ì ¬®¦¥â `sprintf(buf, ...) + fputs(buf, fp)`.
- [ ] Ž¯æ¨®­ «ì­ë© buffered mode (setvbuf, line/block buffering) ? ¥á«¨ ª®£¤ -â® ¯®­ ¤®¡¨âáï.
### POSIX time API ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/posix_time.c` ? time/localtime/gmtime/mktime/asctime/ctime ¯®¢¥àå getdatetime. SDCC's time.rel ¨§¡¥£ ¥¬ (­¥«ì§ï override _RtcRead). ‘¬. `examples/ptime`.
### sys/stat ? ? ƒŽ’Ž‚Ž
- [x] `libc/io/stat.c` ? POSIX stat/fstat. ƒ¨¡à¨¤ open+fstat ¤«ï ä ©«®¢, ffirst+iter ¤«ï ¯ ¯®ª (¢ª«îç ï "."/".."). ‘¬. `examples/stattest` ¨ `memory/estex_ffirst_dotdot.md`.
### assert ? ? ƒŽ’Ž‚Ž (¨á¯®«ì§ã¥¬ SDCC's __assert ç¥à¥§ fallback include path)
## libc/stdlib ? ? ­¥ ­ã¦­® ¤¥« âì (á¬. memory/sdcc_stdlib_works.md)
஢¥à¥­® ç¥à¥§ `examples/stdlib_test/`: SDCC z80.lib ᮤ¥à¦¨â à ¡®â î騥 ॠ«¨§ æ¨¨:
- `atoi/atol/atof, strtol/strtoul, rand/srand, qsort/bsearch, abs/labs, div/ldiv`
- ®«­ë© `<string.h>` (memchr/cmp/set/cpy, strcat/cmp/cpy/len/chr/spn/etc.)
- `<ctype.h>` (toupper/tolower)
- `<math.h>` (sinf/cosf/sqrtf/etc.)
‹¨­ª¥à  ¢â®¬ â¨ç¥áª¨ âﭥ⠨§ z80.lib ª®£¤  ­ã¦­®. **… ¯¥à¥¯¨á뢠âì**.
 è¨ Sprinter-specific ®¡ï§ â¥«ì­ë¥ ¬®¤ã«¨ ®áâ îâáï: atexit, env, errno, setjmp, putchar/puts/getchar, conio, fsdir, time, mouse, open/read/lseek/close.
## Build-system: libsprinter.lib + sprinter-cc ? ? ƒŽ’Ž‚Ž
- [x] `lib/Makefile` ? ᮡ¨à ¥â ª ¦¤ë© libc/*.c ¢ `.rel`,  à娢¨àã¥â ç¥à¥§ sdar ¢ `lib/sprinter.lib`
- [x] ‚ª«îç ¥â runtime/bank.s ¨ runtime/heap.s (auto-pulled ¯à¨ __banked/malloc)
- [x] `bin/sprinter-cc` ? bash-wrapper: `sprinter-cc -o foo.exe foo.c` ®¤­®© áâப®©
- [x] ®¤¤¥à¦ª  ®¯æ¨© `--crt0=default|minimal|banked`, `--bank N=FILE.c`, `-I`, `-L`/`-E`/`-S`, `-Wl`, `--mkexe`
- [x] `examples/hello_sccc/` ? ¤¥¬®: `hello.c` ᮡ¨à ¥âáï §  ®¤¨­ shell-¢ë§®¢, à §¬¥à ᮢ¯ ¤ ¥â á àãç­ë¬ Makefile (925 ¡ ©â)
- [x] Split `putchar.c` ? `putchar.c` + `puts.c` ¤«ï per-function granularity (puts override SDCC's z80.lib version)
- [x] ‚ª«îçñ­ ¢ `make all` (§ ¢¨á¨¬®áâì `lib` ¯¥à¥¤ `examples`)
‚®§¬®¦­ë¥ ã«ãç襭¨ï (®¯æ¨®­ «ì­®):
- [ ] Œ¨£à¨à®¢ âì ®áâ «ì­ë¥ examples ­  sprinter-cc ¢¬¥áâ® àãç­ëå Makefile (ª®á¬¥â¨ª )
- [ ] „ «ì­¥©è ï ¤¥ª®¬¯®§¨æ¨ï libc/*.c per-function (­® ⥪ãé ï granularity 㦥 ¤ ñâ ­ã¦­ë© à §¬¥à ? «¨­ª¥à ¯ ª¥âã¥â .rel 楫¨ª®¬, ¨ ¤«ï ¡®«ì設á⢠ ä ©«®¢ íâ® ®¤­  äã­ªæ¨ï)
## â ¯ 9 ? memory modes ¤«ï sprinter-cc
DSS ¢ë¤¥«ï¥â áâà ­¨æë ¯ ¬ï⨠¯® à §¬¥à㠯ਫ®¦¥­¨ï: < 16 KB ? ®¤­  áâà ­¨æ , ¢ ®áâ «ì­ë¥ ®ª­  ¯®¤ª«îç ¥âáï ?áâà ­¨æ  #FF? (read=0xFF, write ¨£­®à¨âáï). ˆ§-§  í⮣® CODE-¢-W1 + DATA-¢-W2 ¤«ï ¬ «¥­ìª®© ¯à®£à ¬¬ë ¬®«ç  «®¬ ¥âáï. ‘¬. [memory/sprinter_memory_modes.md](../../.claude/projects/-Volumes-SAM8-Projects-DIY-Z80-Sprinter-C-Compiler/memory/sprinter_memory_modes.md).
- [x] **`tiny`**: ¢áñ (CODE+DATA+á⥪) ¢ W2. Default. Verified hello/argv/conio/malloc/file/etc.
- [x] **`--memory MODE` ä« £ ¢ sprinter-cc**: parser + per-mode ¤¥ä®«âë CODE_LOC/DATA_LOC, override ç¥à¥§ ï¢­ë¥ `--code-loc`/`--data-loc`. tiny à ¡®â ¥â; small/big/huge ª®¬¯¨«¨àãîâáï á warning'®¬ (runtime ­¥ £®â®¢). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--memory-manual SPEC`**: ¯ àá¨â `CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`small` runtime**: `runtime/crt0_small.s` ¨á¯®«ì§ã¥â ESTEX `$3D GETMEM` + `$3A SETWIN2` çâ®¡ë ¢ë¤¥«¨âì ¨ § ¬ ¯¨âì W2-áâà ­¨æã „Ž gsinit. **…** BIOS `$C4` ? á⥪ ­  í⮬ íâ ¯¥ ¢ W1 (boot_stack ¢ HOME),   BIOS âॡã¥â á⥪ ¢ W2. ®á«¥ ¬ ¯¯¨­£  SP ¯¥à¥ª«îç ¥âáï ­  0xBFFE, ¤ «ìè¥ áâ ­¤ àâ­ë© flow. ¥ «¨§®¢ ­® 2026-05-30, verified hello.exe.
- [x] **`small` auto-detect ¤«ï >16 KB ¯à®£à ¬¬**: `crt0_small.s` ç¨â ¥â ¯®àâ `0xC2` (⥪ãé ï áâà ­¨æ  ¢ W2 ? ­¥ `0xA2`! íâ® W1). …᫨ 0xFF ? ¢ë¤¥«ï¥â page; ¨­ ç¥ DSS 㦥 ᤥ« «  íâ® (¯à®£à ¬¬  á ¬  ¢ë«¥§«  ¢ W2). ޤ¨­ crt0 ¯®ªà뢠¥â 0..30 KB. mkexe â ª¦¥ à §à¥è ¥â HOME span W1+W2 (0x4000..0xBFFF). Verified hello: small (5 KB ä ©«, SETWIN2 path) + 32 KB ä ©« (auto-skip). ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`big` runtime** (tiny + banked code ¢ W1): ¯ à ¬¥âਧ®¢ «¨ `crt0_banked.s` + `bank.s` ç¥à¥§ `.ifdef BANK_W1` ? ¤à㣮© banking port (0xA2 vs 0xE2), ¤à㣮© load-addr (0x4000 vs 0xC000). sprinter-cc prepend'¨â `BANK_W1 = 1` ¯à¨ `--memory big`, ¯¥à¥¤ ñâ `mkexe -B 0x4000`. ਬ¥à `examples/banked_big/`. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`huge` runtime** (small + banked code ¢ W3): merge W2-detect «®£¨ª¨ ¨§ `crt0_small.s` ¢ `crt0_banked.s`. ‘ãé¥áâ¢ãî騩 ¯à¨¬¥à `examples/banked/` ⥯¥àì ¨á¯®«ì§ã¥â MEMORY=huge. ¥ «¨§®¢ ­® 2026-05-30.
- [x] **`--debug` ä« £**: prepend `DEBUG_RT = 1` ¢ crt0 + `-DDEBUG_RT` ¢ sdcc. Žâªà뢠¥â symbol `_w2_self_allocated` (uint8_t) ? runtime diagnostic ªâ®  ««®æ¨à®¢ « W2. ¥ «¨§®¢ ­® 2026-05-30.
### „¨§ ©­-à¥è¥­¨ï ¯® libc ¨ crt0
**ޤ­  `sprinter.lib`** à ¡®â ¥â ¤«ï ¢á¥å memory mode ? `.rel`-ç«¥­ë relocatable, SDLD ¤¥« ¥â dead-code elimination per-member (¡¥§ £à ä¨ª¨ ­¥ ¯®¤â¢ ¥â `gfx_core.rel` ¨ â.¤.). Verified hello vs malloc_test ç¥à¥§ map-ä ©«ë.
**`gfx.lib` ®â¤¥«ì­® ? … ­ã¦¥­**: dead-code elimination 㦥 à ¡®â ¥â.
**`libc_banked` (libc ¢ bank ¢¬¥áâ® HOME)** ? ¨¤¥ï ­  ¯®â®¬, ª®£¤  HOME (16 KB) § ¡¨â user-ª®¤®¬ + libc ¢ `huge` mode. ¥ «¨§ã¥âáï ç¥à¥§ `--codeseg BANK0` ¯à¨ ª®¬¯¨«ï樨 libc; trade-off: trampoline ~30 横«®¢ ­  ª ¦¤ë© libc-¢ë§®¢. ’ਣ£¥à: ॠ«ì­ ï ¯à®£à ¬¬  ã¯àñâáï ¢ HOME budget.
**HW-§ ¢¨á¨¬ë¥ ¬®¤ã«¨ ? `sprinter_home.lib` ®â¤¥«ì­®.** — áâì libc 䨧¨ç¥áª¨ ­¥ ¬®¦¥â ¡ëâì § ¡ ­ª®¢ ­  ¢ W3, ¯®â®¬ã çâ® ®­  Ž’€…’ á W3:
- `gfx_*` ? ¯¨è¥â ¢ ¢¨¤¥®¯ ¬ïâì `0xC000+` ¯®á«¥ swap W3 ­  video page
- `bank_io` (mem_alloc_pages/bank_read/bank_write) ? swap'¨â W3 ç¥à¥§ `OUT (0xE2)`
- ã¤ã騥 ISR ? ¯à¥à뢠­¨¥ ¬®¦¥â ¯à¨©â¨ ª®£¤  W3 ­  çñ¬ 㣮¤­®
‚ huge mode í⨠¬®¤ã«¨ „Ž‹†› ®áâ âìáï ¢ HOME (W1). Š®£¤  ¡ã¤¥¬ ¤¥« âì `libc_banked`, **®¤­®¢à¥¬¥­­®** ¢ë¤¥«ï¥¬ `sprinter_home.lib` (HOME-only) ¨§ `sprinter.lib` (bankable). ”¨­ «ì­ ï á奬 :
```
sprinter_home.lib HOME-only: gfx, bank_io, ISR shims
sprinter.lib bankable: printf, malloc, string, conio, stdio, env, ...
sprinter_banked.lib â®â ¦¥ sprinter.lib ­® --codeseg BANK0 (¤«ï huge)
```
’ਣ£¥à: ॠ«¨§ æ¨ï `--memory huge` runtime.
**crt0 ? ¯® ®¤­®¬ã ­  mode:**
- `crt0.s` ? ⥪ã騩, ¤«ï **tiny/big**: SP=0xBFFE, ¯ àá¨â argv (W2-à¥áãàá 㦥 ¢ë¤¥«¥­ DSS).
- `crt0_minimal.s` ? ⥪ã騩, ¤«ï tiny ¡¥§ argv.
- `crt0_small.s` ? **­®¢ë©, step 3**: ¤«ï **small/huge**,  ««®æ¨àã¥â W2 ç¥à¥§ `mem_alloc_pages` „Ž gsinit, ¬ ¯¯¨â ¢ ¯®àâ `0xA2`, ¯®â®¬ áâ ­¤ àâ­ë© flow.
- `crt0_banked.s` ? ⥪ã騩, ¤«ï **big**: trampoline-â ¡«¨æ  ¤«ï W3 ¡ ­ª®¢, CODE ¢ W2.
- `crt0_banked_small.s` ? **­®¢ë©**: huge = small (W2-alloc) + banked (W3 trampolines).
sprinter-cc ¯®¤¡¨à ¥â crt0 ¯® `--memory` mode (ᥩç á `--crt0=` íâ® override).
- [x] ** áâà ¨¢ ¥¬ë© à §¬¥à á⥪ **: ä« £ `sprinter-cc --stack-size BYTES`. Wrapper £¥­¥à¨àã¥â `heap_top.s` á `___sdcc_heap_end = stack_top + 1 - stack_size`, ®â¤¥«ì­ë© .rel «¨­ªã¥âáï per-program. Default ?1278 ¡ ©â (heap_top=0xBB00) ¨§ `runtime/heap_top.s`. ¥ «¨§®¢ ­® 2026-05-30.
ˆ­â¥à䥩á: `sprinter-cc --memory [tiny|small|big|huge|manual] [--memory-manual SPEC] [--stack-size N] foo.c`. `--memory-manual` ¨¬¥¥â á¬ë᫠⮫쪮 á `--memory manual`.
## Known issues / quirks
- **ESTEX $46 ENV API**: ? à ¡®â ¥â. „®ª-æ¨ï ¢ `DiskSyscalls.txt v1.6` ®è¨¡®ç­® ®¯¨á뢠¥â return-status ? A=0 íâ® NOT FOUND, ­¥ FOUND. ‡ ä¨ªá¨à®¢ ­® ¢ `memory/sprinter_platform.md`.
## ŽŸ‡€’…‹œ›… ‡€„€—ˆ „‹Ÿ V2 (¯®á«¥ ५¨§  v1)
### Turbo-C-style graphics API (BGI-like) ? **MUST ¤«ï v2**
 áè¨à¨âì ­ è `gfx_*` API ¤® ã஢­ï **Turbo-C `<graphics.h>`** (BGI) ¤«ï MS-DOS.
ணࠬ¬¨áâë ¯à¨¢ëªè¨¥ ª Turbo-C ¤®«¦­ë ¯¥à¥­®á¨âì £à ä¨ç¥áª¨© ª®¤ 1-¢-1.
**—â® ¤®«¦­® ¡ëâì** (­  ®á­®¢¥ Borland BGI):
Setup/teardown:
- `initgraph()` / `closegraph()` ? ã ­ á ᥩç á `gfx_init`/`gfx_done`, ¤®¡ ¢¨âì alias
- `getmaxx()` / `getmaxy()` ? ¬ ªà®á ­  GFX_WIDTH-1 / GFX_HEIGHT-1
- `cleardevice()` ? alias to gfx_clear
- `getgraphmode()` / `setgraphmode()` ? ã ­ á get_videomode/set_videomode
Color/palette:
- `setcolor(c)`, `getcolor()` ? current draw color
- `setbkcolor(c)`, `getbkcolor()` ? background color
- `setpalette(idx, c)` ? ¯ «¨âà  entry
- `getpalette(&info)` ? read all palette
Primitives (¬ë 㦥 ¨¬¥¥¬ íª¢¨¢ «¥­âë ? ¤®¡ ¢¨âì BGI-¨¬¥­  ª ª aliases):
- `putpixel(x, y, c)` ? ¥áâì ª ª gfx_putpixel
- `getpixel(x, y)` ? ­ã¦­® ॠ«¨§®¢ âì (RMW ®¡à â­®¥ ? IN)
- `moveto(x, y)`, `lineto(x, y)`, `linerel(dx, dy)` ? current point + line drawing
- `line(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_line
- `rectangle(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_rect (­® ¤à㣮© API: x1,y1,x2,y2 vs x,y,w,h!)
- `bar(x1, y1, x2, y2)` ? ¥áâì ª ª gfx_fill_rect
- `bar3d(x1, y1, x2, y2, depth, topflag)` ? ­®¢®¥: rect + 3d edges
- `circle(x, y, r)`, `arc(...)`, `ellipse(...)`, `pieslice(...)` ? ­®¢ë¥ primitives
- `fillpoly()`, `drawpoly()` ? ¯®«¨£®­ë
- `floodfill(x, y, border_color)` ? § «¨¢ª 
Text on graphics screen:
- `outtext(s)` / `outtextxy(x, y, s)` ? ¥áâì ª ª gfx_text (alias)
- `settextstyle(font, dir, size)` ? multiple bitmap fonts
- `gettextsettings(&info)`
- `textwidth(s)` / `textheight(s)` ? measure
Image manipulation:
- `imagesize(x1, y1, x2, y2)` ? bytes needed for getimage
- `getimage(x1, y1, x2, y2, buf)` ? save rect to buffer
- `putimage(x, y, buf, op)` ? paste back with COPY_PUT/XOR_PUT/AND_PUT/OR_PUT/NOT_PUT
Clipping/viewport:
- `setviewport(x1, y1, x2, y2, clip)` ? drawing clip rect
- `getviewsettings(&info)`
- `clearviewport()`
- `setactivepage(p)` / `setvisualpage(p)` ? ¤¢®©­ ï ¡ãä¥à¨§ æ¨ï (Sprinter ¨¬¥¥â 2 screen)
Line style:
- `setlinestyle(style, pattern, thickness)` ? SOLID_LINE / DOTTED_LINE / etc.
- `getlinesettings(&info)`
**Acceptance:** ¯¥à¥­®á ⨯¨ç­®© Turbo-C BGI ¯à®£à ¬¬ë (à¨áãî饩 á ¨á¯®«ì§®¢ ­¨¥¬
moveto/lineto/circle/bar/setcolor) ¤®«¦¥­ à ¡®â âì ¡¥§ áãé¥á⢥­­ëå ¯à ¢®ª.
**Notes:**
- BGI fonts (TRIPLEX/SANS_SERIF/GOTHIC) ? ã ­ á ®¤¨­ BIOS font, ®áâ «ì­ë¥ ­ã¦­®
¤®¡ ¢¨âì (ª ª bitmap data ¢ lib)
- imagesize/getimage/putimage ? á ¬ë¥ ¢®áâॡ®¢ ­­ë¥ ¤«ï game/animation
- Active/visual page (¤¢®©­ ï ¡ãä¥à¨§ æ¨ï) ? Sprinter ¯®¤¤¥à¦¨¢ ¥â 2 graphics pages,
­ã¦¥­ API switching
‘¬. â ª¦¥ `examples/` Turbo C 2.x BGIDEMO ª ª reference çâ® ­ã¦­®.
### IM2 Interrupt Handlers ? **MUST ¤«ï v2**
User-§ ¤ ¢ ¥¬ë¥ ISR ç¥à¥§ Z80 IM 2 mode. ã¦­ë ¤«ï:
- Timer ticks (50 Hz frame counter, ¯« ¢­ ï  ­¨¬ æ¨ï)
- Music playback (AY, COVOX)
- Real-time games (input + game logic + render ¢ interrupt-driven)
- Async keyboard / mouse handling
**Status:** Ž’‹Ž†…Ž ¤® v2. ®«­ë© research + design ¢ `docs/im2_isr_design.md`.
**¥è¥­¨¥ ¯®  àå¨â¥ªâãà¥:** ॠ«¨§®¢ âì ª ª ®â¤¥«ì­ë© memory mode `--memory im2`
(¢¬¥á⮠⮣® çâ®¡ë «¥§âì ¢® ¢á¥ áãé¥áâ¢ãî騥 crt0). Detail'¨ ¢ design-doc.
**¥§î¬¥ research' ** (¯®«­ë© ⥪áâ ¢ `docs/im2_isr_design.md`):
- Vector 0xFF ? frame + keyboard + CBL. Disambiguation ¯® ¯®àâ ¬ 0x19 / 0xFE
- Mouse hardware-IRQ ­¥ ¯à¨å®¤¨â (­  ⥪ã饩 ¯« â¥)
- Vector table / ISR / stack ŽŸ‡€ ¡ëâì ¢ W2 (0x8000..0xBFFF)
- DSS ¨¬¥¥â ᢮© IM 2 handler ? ­ã¦­® chain'¨âìáï (¨­ ç¥ ª« ¢¨ âãà  / SYSTIME «®¬ îâáï)
### à®ç¨¥ ªàã¯­ë¥ ¯ã­ªâë ¤«ï v2
- [ ] **FILE API rewrite ? buffered streams** ? ⥪ãé ï ॠ«¨§ æ¨ï ¢
`libc/stdio/file.c` íâ® provisional unbuffered shim (ª ¦¤ë© fputc/fgetc
= ®¤¨­ read/write syscall). 㦭  ¯®«­®æ¥­­ ï buffered ᥬ ­â¨ª 
ª ª ¢ Solid-C:
```c
typedef struct {
uint flags; // +0..1 file status flags
int level; // +2..3 empty/fill level of buffer
char *curp; // +4..5 current active pointer
int fd; // +6..7 underlying low-level fd
char *buffer; // +8..9 data transfer buffer
char hold; // +10 ungetc byte if no buffer
short token; // +11..12 reserved
char dummy; // +13 reserved
} FILE;
```
stdin/stdout/stderr ? fd-¬ àª¥àë `0 / -1 / -2`. Žâà¨æ â¥«ì­ë¥ ¤«ï
stdout/stderr ¢ë¡à ­ë ­ ¬¥à¥­­®: ESTEX OPEN ¬®¦¥â ¢¥à­ãâì positive
small fd (1, 2, ?) ¤«ï ®¡ëç­®£® ä ©«  ? ¥á«¨ ¡ë stdout=1, ॠ«ì­ë©
fd=1 áâ «ª¨¢ «áï ¡ë á ¨¤¥­â¨ä¨ª â®à®¬. fd=0 ¤«ï stdin ¡¥§®¯ á­®
(ESTEX 0 ­¥ ¢®§¢à é ¥â). ‘ ¬¨ fd ­¥ ¯¥à¥¤ îâáï ¢ syscall'ë ?
¤¨á¯¥âç¥à¨§ æ¨ï ¯® ä« £ ¬ `_F_CONIN/_F_CONOUT`.
ਭâ¥à-¯®â®ª¨ (stdaux/stdprn) … ॠ«¨§ã¥¬ ? Sprinter ¯à¨­â¥à­®©
API ­¥ ¨¬¥¥â.
€«ìâ¥à­ â¨¢  ? ¢§ïâì ॠ«¨§ æ¨î ¨§ third_party/solid-c (sources ¢
`SRC/CLIB/`); â ¬ ¥áâì £®â®¢ë© buffered FILE + fopen/fread/fwrite/
fseek/setvbuf ¨ â.¤. €¤ ¯â¨à®¢ âì ª ­ è¨¬ open/read/write/lseek.
ਠrewrite § ®¤­® à¥è¨âì deferred issues stdio-review:
- `fwrite` short-write ¤®«¦¥­ áâ ¢¨âì `_F_ERROR`
- `fgets(buf, 1, fp)` ? áâ ­¤ àâ £®¢®à¨â "empty string", ¬ë ¢¥à­ã«¨ NULL
- `mode_to_flags` ? break-out ­  '+' (cosmetic)
- [ ] **Audio API** ? AY-3-8910 + COVOX ç¥à¥§ ¯à¥à뢠­¨ï (âॡã¥â IM2)
- [ ] **ISA-8 slot support** ? ZX-Bus ª àâë (sound, network, etc.) ? âॡã¥â IM2 + ç⥭¨ï port®¢
## à®ç¨¥ § ¤ ç¨ (v1 backlog, ­¥ ¡«®ª¨àãî騥)
- [x] **#9: text I/O split (Turbo-C style)** ? stdio (puts/printf/putchar) ⥯¥àì fast no-attr ç¥à¥§ PCHARS/PUTCHAR. conio (cputs/cprintf/putch) ¯à¨¬¥­ï¥â attr ç¥à¥§ textcolor/textbackground/textattr. KEEP_EXIST_ATTR ? conio fallback ­  fast path. Verified ¢ hello.exe. ‘¬. `memory/text_output_api_split.md`. ¥ «¨§®¢ ­® 2026-05-31.
- [x] **Mouse API ¯®«­ë©** (१¨¤¥­â­ë© driver, RST 30h) ? ¢á¥ 14 ä㭪権 ®¡ñà­ãâë (init/show/hide/refresh/read/goto/bounds/text_cursor/load_cursor/get_cursor/get/set_sensitivity/video_mode_changed). ‘¬. `memory/mouse_api.md`. Verified ¢ MAME 2026-05-31. Sensitivity = divider (¬¥­ìè¥ = ¡ëáâ॥).
- [ ] Interrupt handlers ? IM 2 vector table ¢ HOME ¤«ï user ISR'®¢
- [ ] ®¤¤¥à¦ª  `restore SP on EXIT` (¯ ââ¥à­ ¨§ z88dk +pps) ? ¯à®¢¥à¨âì ­ã¦­® «¨
- [ ] CI:  ¢â®¬ â¨ç¥áª¨ § ¯ã᪠âì MAME á `-aviwrite` ¤«ï screenshot-áà ¢­¥­¨ï, ç⮡ë â¥áâë ¯à¨¬¥à®¢ ¯à®å®¤¨«¨ ¡¥§ 祫®¢¥ª 
## ˆ¤¥¨ ­  ¯®â®¬
- ®¤¤¥à¦ª  `<setjmp.h>` (¥áâì ¢ SDCC stdlib ? ­ã¦­® ¯à®â¥áâ¨à®¢ âì çâ® ­ è crt0 ᮢ¬¥á⨬)
- `<time.h>` ç¥à¥§ ESTEX SYSTIME (`$21`) ¨ CMOS BIOS-ä㭪樨
- ZX Spectrum-ᮢ¬¥áâ¨¬ë© à¥¦¨¬ ª ª ®â¤¥«ì­ë© target (¤«ï ¯®àâ¨à®¢ ­¨ï ᯥªâà㬮¢áª¨å ¯à®£à ¬¬)
- ®¤¤¥à¦ª  ZX-Bus ª àâ (sound, network, etc.) ? ­ã¦­ë ¤à ©¢¥àë
- Profile-guided optimization tools (hot/cold detection) ¤«ï ªà㯭ëå ¯à®£à ¬¬
## Linker duplicate-symbol warnings (¡« £®¯à¨ïâ­ë¥, ®â䨫ìâ஢ ­ë)
Š®£¤  ¬ë á®§­ â¥«ì­® overrides'¨¬ SDCC z80.lib ä㭪樨 ᮡá⢥­­®© ¢¥àᨥ© ¢ `sprinter.lib`, `sdldz80` ¯¨è¥â `?ASlink-Warning-Definition of public symbol '...' found more than once`. ‹¨­ª¥à ¡¥àñâ ¯¥à¢®¥ ­ ©¤¥­­®¥ ®¯à¥¤¥«¥­¨¥ (­ è¥), ¯®í⮬㠯®¢¥¤¥­¨¥ ª®à४⭮¥ ? warning ⮫쪮 noise.
’¥ªã騥 overrides:
- `_puts` ? ­ è  ¢¥àá¨ï ç¥à¥§ PCHARS+\r\n vs SDCC posix puts
- `___sdcc_heap` ? ­ è heap ¢ W2 vs SDCC's áâ ­¤ àâ­ë©
- `_asctime`, `_localtime` (¨ ¢®§¬®¦­® ¤à㣨¥ ¨§ time) ? ­ è `posix_time.c` ç¥à¥§ ESTEX SYSTIME vs SDCC's `time.rel` ª®â®àë© § ¢¨á¨â ®â `_RtcRead`
**’¥ªã饥 à¥è¥­¨¥:** `bin/sprinter-cc` ®â䨫ìâ஢뢠¥â warning-¡«®ª (warning + 2 follow-up `Library:` áâப¨) ¨§ ¢ë¢®¤  `sdcc`. —¥à¥§ `-v` (verbose) ¢áñ ¯®ª §ë¢ ¥âáï. ¥ «¨§®¢ ­® ç¥à¥§ awk-pipe.
**‚®§¬®¦­ë¥ ã«ãç襭¨ï:**
- ¥à¥©â¨ ­  explicit `--nostdlib` + àãç­®© ᯨ᮪ ­ã¦­ëå ¬®¤ã«¥© ¨§ z80.lib (string, math, stdlib ¡¥§ override'­ãâëå) ? ã¡à âì ˆ‘’Ž—ˆŠ warning'®¢, ­¥ ¬ áª¨à®¢ âì
- ˆ«¨: ¯¥à¥¨¬¥­®¢ âì ­ è¨ `_puts` ? `_puts_sprinter` + alias ç¥à¥§ linker flag (­¥ 㢥७ çâ® SDCC ¯®¤¤¥à¦¨¢ ¥â)
- ˆ«¨: ®áâ ¢¨âì ª ª ᥩç á (à ¡®ç¥¥ ¨ benign) ? ¯à¨®à¨â¥â ­¨§ª¨©
## TODO: ¯à®¢¥à¨âì ­  ॠ«ì­®¬ ¦¥«¥§¥
- [ ] **Port_Y banking trick** (`docs/part2/SprinterGraphics programming.txt`):
¤®ªã ã⢥ত ¥â çâ® ¯®á«¥ `OUT (0x89), Y`  ¤à¥á  0xC000+0x400*N ¢ ®ª­¥ W3
¬ ¯¯ïâáï ­  áâப¨ Y..Y+15 (®¤­® ¯à®£à ¬¬¨à®¢ ­¨¥ ? 16 áâப).
Empirical 2026-06-01 ¢ MAME 0.283 íâ®â trick **­¥ à ¡®â ¥â** ? ¯¨ªá¥«¨
¯®  ¤à¥á ¬ ¢ëè¥ 0xC000+row_width ã室ïâ ¢ ­¥¢¨¤¨¬ãî ®¡« áâì. Š ­®­¨ç¥áª¨©
`docs/samples/plasma2.asm` ⮦¥ ­¥ ¨á¯®«ì§ã¥â banking, ¯¥à¥ãáâ ­ ¢«¨¢ ¥â
Port_Y per row.
« ­:
1. ®«ãç¨âì ¤®áâ㯠ª ॠ«ì­®¬ã Sprinter
2. ‡ ¯ãáâ¨âì â¥áâ dual-write (`_gfx_putpixel_raw` + ¢â®à®© write ¢ `0xD000+x`)
3. …᫨ ­  ¦¥«¥§¥ ¢¨¤­ë ¤¢®©­ë¥ «¨­¨¨ ? ¡ £  MAME, ®âªàëâì issue á
¬¨­¨¬ «ì­ë¬ ९à®
4. …᫨ ­  ¦¥«¥§¥ ⮦¥ ®¤­  «¨­¨ï ? ¤®ªã¬¥­â ­¥¢¥à­ë©, 㤠«¨âì 㯮¬¨­ ­¨¥
¨§ ¤®ª¨ ¨ ¯à®áâ® ®áâ ¢¨âì ⥪ãéãî ॠ«¨§ æ¨î (Port_Y per pixel)
5. …᫨ banking à ¡®â ¥â ­  ¦¥«¥§¥ ? ¢­¥¤à¨âì ªíè¨à®¢ ­¨¥ Port_Y ¢
`_gfx_putpixel_raw` (sentinel out-of-range, á¬. memory/gfx_port_y_banking.md)
‘¢ï§ ­­ë© ¢ë¨£àëè ¤«ï Bresenham (60-pixel ¤¨ £®­ «ì) ? ®ª®«® 8? ¬¥­ìè¥
OUT (0x89) ®¯¥à æ¨©, ¤«ï `gfx_fill_rect 320x256` ? 16? ¬¥­ìè¥. ¥ ¡«®ª¨àã¥â
release v1.
## GFX: à áè¨à¥­¨ï ¯® `docs/part2/accelerator_doc.txt`
®á«¥ ¯à®ç⥭¨ï ¤¥â «ì­®£® accelerator doc ¢ë¥­ë ­¥§ ªàëâë¥ ­ ¯à ¢«¥­¨ï.
‘¥©ç á ¢ ª®¤¥ ¨á¯®«ì§ã¥âáï ⮫쪮 £®à¨§®­â «ì­ë©/¢¥à⨪ «ì­ë© Fill mode.
### Quick wins ¤«ï ⥪ãé¨å primitives
- [ ] **‡ ¬¥­¨âì SMC ­  `LD A, (var)` ¤«ï block-size**. „®ªã¬¥­â ®
à §à¥è ¥â `LD A, (HL)`, `LD A, (BC)`, `LD A, (DE)` (­® ­¥ `LD A, r`).
â® ã¡¥àñâ SMC complexity ¢ `gfx_lines.c:hfill_chunk/vfill_chunk` ¨
`gfx_16.c:g16_hfill_chunk`. ‡ ¯à¥é¥­® ⮫쪮 register-to-register.
- [ ] **Šíè¨à®¢ ­¨¥ block-size**. „®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel § ¯®¬¨­ ¥â
block size ¬¥¦¤ã bursts (á¬. `Horizontal_Line_Fill`: ãáâ ­ ¢«¨¢ îâ
size + `LD B,B` ®âª«î祭¨¥, ¯®â®¬ ¢ª«îç îâ Fill mode ¨ ¨á¯®«ì§ãîâ
á®åà ­ñ­­ë© size). „«ï `gfx_fill_rect` á 100 ®¤¨­ ª®¢ë¬¨
áâப ¬¨ ? ãáâ ­®¢¨âì size 1 à §,   ­¥ 100.
### Bank-prefix modes (port 0xE2 bits)
„®ªã¬¥­â ¯®ª §ë¢ ¥â âਠ¢ à¨ ­â  ¡ ­ª  ¢¨¤¥®áâà ­¨æë ¯®¬¨¬® áâ ­¤ àâ­®£® 0x50:
| Bank byte | Effect |
|---|---|
| 0x50 | Normal write ? ¯¨è¥âáï ¢ shadow + ¢¨¤¨¬ë© |
| 0x54 | "no copy in main shadow RAM" |
| 0x58 | **"FF is transparent"** ? ¡ ©â 0xFF ¯à¨ write ®áâ ¢«ï¥â background |
| 0x5C | both |
Bank 0x58 ®¡êïá­ï¥â ¯®ç¥¬ã mouse cursor à¨áã¥âáï á 0xFF-¯à®§à ç­®áâìî.
â® ¯ãâì ª **sprite-blending ç¥à¥§ accel block copy**:
- [ ] **`gfx_set_bank_transparent(on)`** ¨«¨ ä« £ ¢ `gfx_set_bank` ¤«ï
¢ë¡®à  0x50/0x58 ¯à¨ ®âà¨á®¢ª¥ sprite'®¢
- [ ] ˆá¯®«ì§®¢ âì ¢ ­®¢®¬ `gfx_blit()` çâ®¡ë ¯® ä ªâã ¯®«ãç âì
transparent sprites ç¥à¥§ accel-ª®¯¨î
### Block copy mode (sprite blit'ë)
`LD L,L` (horizontal) ¨ `LD A,A` (vertical) ? ०¨¬ ª®¯¨à®¢ ­¨ï ¡«®ª  ç¥à¥§
256-¡ ©â­ãî accel memory. â® ¡ §¨á ¤«ï blit'®¢.
- [ ] **`gfx_blit(src_data, x, y, w, h)`** ? ª®¯¨à®¢ ­¨¥ sprite' 
(¯à®¨§¢®«ì­ë© à §¬¥à, ç¥à¥§ accel)
- [ ] **`gfx_blit_transparent(src, x, y, w, h)`** ? á ¨á¯®«ì§®¢ ­¨¥¬ bank 0x58
‘¬. `Draw_Restangle_Data` ¢ accelerator_doc.txt ª ª à¥ä¥à¥­á.
### AND / OR / XOR operations ç¥à¥§ accel
„®ªã¬¥­â ¯®ª §ë¢ ¥â çâ® accel ¯®¤¤¥à¦¨¢ ¥â «®£¨ç¥áª¨¥ ®¯¥à æ¨¨ á ¡«®ª ¬¨
¤ ­­ëå. ਬ¥­¥­¨ï:
- XOR ? ¨­¢¥àá¨ï ®¡« á⨠(¢ë¤¥«¥­¨¥ selection ¢ UI)
- OR / AND ? masking, alpha-style blending
- ‘¬. ¯à¨¬¥à ¢ accelerator_doc.txt: "256 bytes block coding via XOR"
- [ ] **`gfx_xor_rect`** / **`gfx_or_rect`** / **`gfx_and_rect`** ?
¯à¨¬¨â¨¢ë «®£¨ç¥áª¨å ®¯¥à æ¨© ­ ¤ ¯àאַ㣮«ì­¨ª®¬
- [ ] **`gfx_invert_rect(x, y, w, h)`** ? alias ­  xor á 0xFF
### Bitmap fonts à §­ëå à §¬¥à®¢
‘¥©ç á `gfx_text` / `gfx_putchar` å à¤ª®¦¥­­® à ¡®â îâ á 8?8 èà¨ä⮬
(BIOS WIN_GET_ZG ¢®§¢à é ¥â 256?8 ¡ ©â). „«ï ¡ã¤ãé¨å UI / â¨âã«ì­¨ª®¢
­ã¦­ë:
- [ ] **`gfx_set_font_size(w, h)`** ? ¯¥à¥ª«îç¨âì è¨à¨­ã/¢ëá®âã glyph' 
- [ ] **`gfx_set_font_data(ptr, w, h, advance)`** ? § ¬¥­¨âì 㪠§ â¥«ì
­  ¯®«ì§®¢ â¥«ì᪨© èà¨äâ + à §¬¥àë
- [ ] ®¤¤¥à¦ª  **proportional** (advance != w) èà¨ä⮢ ? ¤®¡ ¢¨âì
array advance[256] ­  è¨à¨­ã ª ¦¤®£® glyph' 
- [ ] **Big-font ०¨¬ë**: 8?16, 16?16, 16?8 (¤«ï â¨âã«ì­¨ª®¢)
- [ ] ‚®§¬®¦­® ®â¤¥«ì­ë© API `gfx_text_ex(x, y, str, font_id)` £¤¥
font_id ¢ë¡¨à ¥â ®¤¨­ ¨§ § £à㦥­­ëå èà¨ä⮢
- [ ] **Anti-alias 2-bit èà¨äâë** (¡¨â ä®­ / ¡¨â £à ­¨æ  / 2-¡¨â alpha?)
? far future, ¤«ï smooth UI
## ”¨­ «ì­ë© íâ ¯ ®¯â¨¬¨§ æ¨© (­¥ ᥩç á)
- **`gfx_line` ç¥à¥§ accel ¤«ï ¯®«®£¨å ¤¨ £®­ «¥©** ? Bresenham ¤«ï «¨­¨¨ á |dy| << |dx| (¨«¨ ­ ®¡®à®â) ¢ë¤ ñâ ¤«¨­­ë¥ runs ®¤¨­ ª®¢®£® Y (¨«¨ X): ¯¨ªá¥«ì, ¯¨ªá¥«ì, ¯¨ªá¥«ì, è £ Y, ¯¨ªá¥«ì, ¯¨ªá¥«ì... Š ¦¤ë© â ª®© run ? íâ® £®â®¢ë©  à£ã¬¥­â ¤«ï `gfx_hline` (¨«¨ `vline`).
« ­ ¨áá«¥¤®¢ ­¨ï: ¯®áç¨â âì ¤«¨­ã runs ª ª äã­ªæ¨î ®â ­ ª«®­ ; à¥è¨âì ¬¨­¨¬ «ì­ë© run length, ¯à¨ ª®â®à®¬ ¢ë£®¤­¥¥ accel hline 祬 N?putpixel (overhead accel ~20?s, putpixel ~5?s ? accel ¢ë£®¤­¥¥ ¯à¨ run ? 4-5 px); ¤«ï ªàãâëå ¤¨ £®­ «¥© (dx ? dy) ®áâ ¢¨âì Bresenham, ¤«ï ¯®«®£¨å ? run-length-based fill.
‘¥©ç á `gfx_line` orthogonal cases 㦥 ç¥à¥§ accel ? ®¯â¨¬¨§¨à®¢ âì ⮫쪮 ª®áë¥.
- **`gfx_fill_rect` á ®¤­¨¬ W3-swap ­  ¢áî ®¯¥à æ¨î** ? ᥩç á ª ¦¤ë© ¢­ãâ७­¨© `gfx_hline`/`gfx_vline` ¤¥« ¥â ᢮© DI/save-W3/restore-W3/EI. Œ®¦­® ᤥ« âì internal `_fill_rect_inner` ª®â®àë© ¤¥à¦¨â W3 § ¬ ¯«¥­­ë¬ ¨ DI ¢¥áì æ¨ª«; ~20?s ? ª®«¨ç¥á⢮ áâப/á⮫¡æ®¢ íª®­®¬¨¨. ਬ¥­¨¬® ª® ¢á¥¬ ª®¬¯®§¨â­ë¬ ¯à¨¬¨â¨¢ ¬.