Files
snark13 858e5755ad ChangeLog:
- big commit.
2026-06-10 10:35:48 +03:00

160 lines
6.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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);
/* Read a contiguous block of entries back from a graphics palette. */
void gfx_pal_get (uint8_t pal_num, uint8_t start, uint8_t count,
uint8_t *data);
/* Read one entry into R, G, B pointers (any may be NULL). */
void gfx_pal_get_color(uint8_t pal_num, uint8_t idx,
uint8_t *r, uint8_t *g, uint8_t *b);
/* Restore the system default graphics palette (BIOS $A6, type=1). */
void gfx_pal_reset(void);
#endif