Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.
What's in here:
bin/sprinter-cc — driver script invoking SDCC + linker + mkexe
libc/ — Sprinter-specific libc layer over ESTEX/BIOS
(conio, gfx, io, mem, stdio + headers)
runtime/ — crt0 variants (default/small/banked/minimal)
+ heap + bank trampolines
toolchain/ — mkexe (SprintEXE packer, C + tests)
examples/ — 30 demo programs (gfx, file I/O, env, time, …)
lib/Makefile — builds the libc archive (sprinter.lib)
docs/ — converted Sprinter manuals + asm reference samples
third_party/ — solid-c reference compiler dump + sdcc setup script
release_docs/ — packaging / release notes
gitignore overhaul:
• Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
on macOS APFS). Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
• Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
INPUT fixtures, not build outputs.
• Collapse the duplicated SDCC/C/Sdcc sections into one section per
concern (build outputs / vendored / OS-junk).
• Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* gfx.h — Sprinter graphics primitives.
|
||||
*
|
||||
* Two main modes:
|
||||
* GFX_MODE_320x256x256 (0x81) — one byte per pixel, palette of 256
|
||||
* entries. API functions suffixed _256.
|
||||
* GFX_MODE_640x256x16 (0x82) — 4 bits per pixel, palette of 16.
|
||||
* API functions suffixed _16.
|
||||
*
|
||||
* Common API (no suffix) covers things that are mode-agnostic:
|
||||
* gfx_init / gfx_done
|
||||
* gfx_set_visible_page / gfx_set_draw_page / gfx_set_bank
|
||||
* gfx_wait_vsync
|
||||
* gfx_pal_load / gfx_pal_set
|
||||
* gfx_load_default_font / gfx_set_font
|
||||
*
|
||||
* Addressing reminder:
|
||||
* pixel (x, y) lives at CPU 0xC000 + (x or x/2) with Port_Y (0x89) = y;
|
||||
* the gfx code maps a 16 KB VRAM page into W3 around every write.
|
||||
* For double-buffering, page 1 starts 320 bytes later (0xC140).
|
||||
*
|
||||
* Palette: BIOS $A4 (RST 8); 4 bytes per entry — B, G, R, pad.
|
||||
*/
|
||||
|
||||
#ifndef GFX_H
|
||||
#define GFX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* ESTEX SETVMOD codes — same values as the SETVMOD `A` register. */
|
||||
#define GFX_MODE_TEXT_40x32 0x02
|
||||
#define GFX_MODE_TEXT_80x32 0x03
|
||||
#define GFX_MODE_320x256x256 0x81
|
||||
#define GFX_MODE_640x256x16 0x82
|
||||
|
||||
/* Pixel dimensions of mode 0x81 (320×256, 256 colours). */
|
||||
#define GFX_WIDTH 320
|
||||
#define GFX_HEIGHT 256
|
||||
|
||||
/* Pixel dimensions of mode 0x82 (640×256, 16 colours). Each byte at
|
||||
* 0xC000+x_byte holds two pixels: high nibble = LEFT (even-x), low
|
||||
* nibble = RIGHT (odd-x) — see memory/sprinter_graphics.md. */
|
||||
#define GFX_WIDTH_16 640
|
||||
#define GFX_HEIGHT_16 256
|
||||
#define GFX_COLORS_16 16
|
||||
|
||||
/* ---- Setup / teardown -------------------------------------------- *
|
||||
*
|
||||
* Switch to `mode`, returning the previous mode for restore. `page`
|
||||
* (0 or 1) selects the initial graphics screen — both the visible and
|
||||
* the draw page are set to it, and the W3 bank is reset to 0x50 (the
|
||||
* canonical visible video page). Programs that don't double-buffer
|
||||
* just pass 0. */
|
||||
uint8_t gfx_init(uint8_t mode, uint8_t page);
|
||||
|
||||
/* Restore a previously-saved video mode. */
|
||||
void gfx_done(uint8_t mode);
|
||||
|
||||
/* ---- Page selection (double-buffering) and bank control ---------- *
|
||||
*
|
||||
* The Sprinter hardware holds two graphics screens. The VISIBLE page
|
||||
* is what's shown on screen; the DRAW page is where the gfx_* writes
|
||||
* land. Render the next frame into the hidden page and flip when ready.
|
||||
*
|
||||
* "Bank" is the W3 page byte (0x50..0x5F) — bits 2,3 select
|
||||
* normal/temp/transparent display modes. All gfx_* primitives map
|
||||
* THIS bank into W3 before touching 0xC000+. Default is 0x50. */
|
||||
|
||||
void gfx_set_visible_page(uint8_t page); /* 0 or 1 */
|
||||
uint8_t gfx_get_visible_page(void);
|
||||
|
||||
void gfx_set_draw_page(uint8_t page); /* 0 or 1 */
|
||||
uint8_t gfx_get_draw_page(void);
|
||||
|
||||
void gfx_set_bank(uint8_t bank); /* 0x50..0x5F */
|
||||
uint8_t gfx_get_bank(void);
|
||||
|
||||
/* Block until the next frame interrupt (50 Hz on Sprinter). Uses
|
||||
* `EI; HALT` — the Z80 sleeps until the next IM2 tick that DSS programs
|
||||
* for keyboard / cursor handling. Typical use:
|
||||
*
|
||||
* gfx_set_draw_page(hidden);
|
||||
* draw_frame(...);
|
||||
* gfx_wait_vsync(); // wait for vretrace
|
||||
* gfx_set_visible_page(hidden); // tear-free flip
|
||||
*/
|
||||
void gfx_wait_vsync(void);
|
||||
|
||||
/* ---- 320×256×256 (mode 0x81) drawing API -------------------------- *
|
||||
* Colour args are palette indices 0..255. */
|
||||
|
||||
void gfx_clear256 (uint8_t color);
|
||||
void gfx_putpixel256 (int x, int y, uint8_t color);
|
||||
void gfx_hline256 (int x, int y, int len, uint8_t color);
|
||||
void gfx_vline256 (int x, int y, int len, uint8_t color);
|
||||
void gfx_line256 (int x0, int y0, int x1, int y1, uint8_t color);
|
||||
void gfx_rect256 (int x, int y, int w, int h, uint8_t color);
|
||||
void gfx_fill_rect256(int x, int y, int w, int h, uint8_t color);
|
||||
|
||||
/* ---- 640×256×16 (mode 0x82) drawing API --------------------------- *
|
||||
* Colour args are palette indices 0..15. The accelerator works
|
||||
* byte-wise so vline16 falls back to per-row RMW (a byte spans two
|
||||
* horizontal pixels). */
|
||||
|
||||
void gfx_clear16 (uint8_t color);
|
||||
void gfx_putpixel16 (int x, int y, uint8_t color);
|
||||
void gfx_hline16 (int x, int y, int len, uint8_t color);
|
||||
void gfx_vline16 (int x, int y, int len, uint8_t color);
|
||||
void gfx_line16 (int x0, int y0, int x1, int y1, uint8_t color);
|
||||
void gfx_rect16 (int x, int y, int w, int h, uint8_t color);
|
||||
void gfx_fill_rect16(int x, int y, int w, int h, uint8_t color);
|
||||
|
||||
/* ---- Bitmap-font text -------------------------------------------- *
|
||||
* Font is 256 glyphs × 8 rows × 1 byte (ZX-Spectrum format), 2 KB.
|
||||
* On first use the default system font is fetched via BIOS WIN_GET_ZG
|
||||
* (fn 0xB8). gfx_set_font() lets you swap in a custom font (the
|
||||
* pointer is held — keep the storage alive). */
|
||||
|
||||
void gfx_load_default_font(void);
|
||||
void gfx_set_font(const uint8_t *font);
|
||||
|
||||
/* 320×256×256 text: one byte per pixel; advances x by 8 per char. */
|
||||
void gfx_putchar256(int x, int y, char c, uint8_t fg, uint8_t bg);
|
||||
void gfx_text256 (int x, int y, const char *s, uint8_t fg, uint8_t bg);
|
||||
|
||||
/* 640×256×16 text: 4 bits per pixel; x must be EVEN (byte-aligned). */
|
||||
void gfx_putchar16 (int x, int y, char c, uint8_t fg, uint8_t bg);
|
||||
void gfx_text16 (int x, int y, const char *s, uint8_t fg, uint8_t bg);
|
||||
|
||||
/* ---- Palette ----------------------------------------------------- *
|
||||
* Each graphics page has its own palette page (page 0 → palette 0,
|
||||
* page 1 → palette 1). For seamless double-buffering, load the same
|
||||
* palette into both. */
|
||||
|
||||
/* Load a contiguous block of palette entries.
|
||||
* pal_num: 0..3 (graphics palettes)
|
||||
* start: first colour slot (0..255)
|
||||
* count: number of slots (0 → 256)
|
||||
* data: pointer to count entries, each formatted (B, G, R, 0). */
|
||||
void gfx_pal_load(uint8_t pal_num, uint8_t start, uint8_t count,
|
||||
const uint8_t *data);
|
||||
|
||||
/* Convenience: set one palette entry from RGB. Internally builds the
|
||||
* BGR+pad triple and calls gfx_pal_load(pal_num, idx, 1, ...). */
|
||||
void gfx_pal_set (uint8_t pal_num, uint8_t idx,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user