Files
snark13 49a87b4d02 libc: add Sprinter palette API (graphics + text planes)
palette.h/video/palette.c wrap BIOS $A4 PIC_SET_PAL/PIC_GET_PAL and $A6
SET_PAL_INIT for the 8 palette pages (0-3 graphics, 4-7 text planes).
gfx_palette.c and conio/text_palette.c are thin per-domain wrappers;
text_palette.c maps the text "plane" 0..3 (paper/ink/blink-paper/
blink-ink) onto BIOS pages 4..7. Covered by tests/text_palette.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 17:07:55 +03:00

90 lines
3.9 KiB
C

/*
* palette.h — Sprinter palette (low-level).
*
* The Sprinter has eight 256-colour palette pages, shared by graphics and
* text modes:
*
* pal_num 0..3 — graphics palettes. Each character cell selects which
* of the four it uses through bits 7..6 of its mode byte.
* Used by graphics modes 0x81 / 0x82.
* pal_num 4..7 — text-mode planes — together they form the colour table
* of the text-mode attribute byte:
* 4 = paper (background, non-blink phase)
* 5 = ink (foreground, non-blink phase)
* 6 = paper-blink (background during blink half-cycle)
* 7 = ink-blink (foreground during blink half-cycle)
* Each plane holds 256 BGR colours indexed directly by
* the 8-bit attribute byte of the cell.
*
* Entry format — 4 bytes per colour, in Blue-Green-Red-pad order; the pad
* byte is reserved and must be 0.
*
* Notes on the underlying BIOS ($A4):
* - `count = 0` means 256 entries (full plane).
* - On write, data is AND-masked against `pal_mask` before reaching
* VRAM. pal_load/pal_set_color hard-code mask = 0xFF (no masking).
*
* Blink semantics (text planes):
* The hardware constantly alternates between planes 4↔6 (paper) and
* 5↔7 (ink). To DISABLE blink everywhere in IBM-CGA style, copy plane
* 4 → 6 and 5 → 7 (so both phases show the same colour). To ENABLE
* ZX-Spectrum style flash, swap entries 6 ↔ 7 for the desired attrs.
* The system default (PAL_CGA) leaves flash visible only for attribute
* bytes with bit 7 set.
*
* Backed by BIOS PIC_SET_PAL/PIC_GET_PAL ($A4) and SET_PAL_INIT ($A6).
* Higher-level wrappers live in <conio.h> (text_pal_*) and <gfx.h>
* (gfx_pal_*); use those directly unless you need raw plane control.
*/
#ifndef PALETTE_H
#define PALETTE_H
#include <stdint.h>
/* Default-palette types for pal_reset(). Values match BIOS $A6 B-register. */
#define PAL_GRAPH 1 /* graphics palette (planes 0..3) */
#define PAL_SINCLAIR 2 /* Spectrum palette (text planes 4..7, ZX colours) */
#define PAL_CGA 3 /* CGA text palette (text planes 4..7, IBM CGA) */
/* Load a contiguous block of palette entries.
* pal_num: 0..7 (0..3 graphics, 4..7 text)
* start: first slot (0..255)
* count: number of slots (0 means 256)
* bgr0: pointer to count entries of 4 bytes each: Blue, Green, Red, 0 */
void pal_load(uint8_t pal_num, uint8_t start, uint8_t count,
const uint8_t *bgr0);
/* Read a contiguous block of palette entries back into RAM.
* Same parameter shape as pal_load — bgr0 here is a write buffer of
* count*4 bytes that receives B,G,R,0 quadruples. */
void pal_get (uint8_t pal_num, uint8_t start, uint8_t count,
uint8_t *bgr0);
/* Convenience: set one entry from an RGB triple. */
void pal_set_color(uint8_t pal_num, uint8_t slot,
uint8_t r, uint8_t g, uint8_t b);
/* Convenience: read one entry into R,G,B pointers (any may be NULL). */
void pal_get_color(uint8_t pal_num, uint8_t slot,
uint8_t *r, uint8_t *g, uint8_t *b);
/* Restore a built-in default palette (BIOS $A6 SET_PAL_INIT).
* type: PAL_GRAPH / PAL_SINCLAIR / PAL_CGA.
* Internally:
* PAL_GRAPH → A=0, E=0, B=1 (resets graphics palette 0)
* PAL_SINCLAIR → A=0, E=0, B=2
* PAL_CGA → A=0, E=0, B=3 (resets all text planes 4..7)
*
* Use pal_reset_at() if you need a non-zero page or a non-zero graphics
* palette index. */
void pal_reset(uint8_t type);
/* Full-control variant of pal_reset.
* pal_page: BIOS A register — "palette page" hardware index.
* graph_pal: BIOS E register — for PAL_GRAPH, target palette 0..3.
* type: BIOS B register — PAL_GRAPH / PAL_SINCLAIR / PAL_CGA. */
void pal_reset_at(uint8_t type, uint8_t pal_page, uint8_t graph_pal);
#endif