"""Amstrad CPC (Gate Array) colour palette. The CPC has a fixed palette of 27 colours (3 levels -- 0x00, 0x60, 0xFF -- of R, G and B). The Gate Array selects them by a 5-bit "hardware ink" number 0-31; those 32 numbers map onto the 27 colours (a few duplicates). RGB values and the hardware-ink ordering are taken verbatim from MAME's ``amstrad_palette[32]`` so the encoder matches exactly what the emulator renders. A pen (the value stored per pixel: 0-15 in mode 0, 0-3 in mode 1, 0-1 in mode 2) is assigned an ink via the Gate Array palette; the .sna stores those 17 ink numbers (16 pens + border). We therefore index colours by HARDWARE INK NUMBER, so ``HW_INK[k]`` is both this palette's RGB and the byte written to the snapshot. """ from __future__ import annotations import numpy as np from ..palette import srgb_to_lab # amstrad_palette[32] from MAME (src/mame/amstrad/amstrad_m.cpp), indexed by the # Gate Array hardware ink number. HW_INK = np.array([ (96, 96, 96), (96, 96, 96), (0, 255, 96), (255, 255, 96), (0, 0, 96), (255, 0, 96), (0, 96, 96), (255, 96, 96), (255, 0, 96), (255, 255, 96), (255, 255, 0), (255, 255, 255), (255, 0, 0), (255, 0, 255), (255, 96, 0), (255, 96, 255), (0, 0, 96), (0, 255, 96), (0, 255, 0), (0, 255, 255), (0, 0, 0), (0, 0, 255), (0, 96, 0), (0, 96, 255), (96, 0, 96), (96, 255, 96), (96, 255, 0), (96, 255, 255), (96, 0, 0), (96, 0, 255), (96, 96, 0), (96, 96, 255), ], dtype=np.float64) # The 27 unique colours, each as the FIRST hardware ink number that produces it # (so encoders work with a clean 27-entry palette, and INK[i] gives the snapshot # byte for unique colour i). INK = [] _seen = {} for _k, _rgb in enumerate(map(tuple, HW_INK.astype(int))): if _rgb not in _seen: _seen[_rgb] = _k INK.append(_k) INK = np.array(INK, dtype=np.int64) # 27 hardware ink numbers PALETTE = HW_INK[INK] # 27 unique RGB colours # Neutral grey ramp (for the monochrome mode): black, grey, bright white. GREYS = [i for i, (r, g, b) in enumerate(map(tuple, PALETTE.astype(int))) if r == g == b] # indices into PALETTE def get_palette() -> np.ndarray: return PALETTE def palette_lab() -> np.ndarray: return srgb_to_lab(PALETTE) def ink_byte(unique_index: int) -> int: """Hardware ink number (snapshot byte) for a unique-palette colour index.""" return int(INK[unique_index])