Puregrain.Machine.ZxSpectrum
- Package
- purescript-puregrain
- Repository
- roman-mkh/puregrain
The ZX Spectrum's screen: 8 × 8 cells, each with two colors, an ink
and a paper, from the machine's 8 colors, plus one BRIGHT bit for both.
With Puregrain.Cells, that gives images the Spectrum could show:
import Puregrain.Cells (ditherCells, nearestInCell, orderedInCell)
import Puregrain.Machine.ZxSpectrum as Zx
-- ordered dithering inside the cells, with a threshold map m
{ cells, image } = ditherCells noDiffusion (orderedInCell m) Zx.screen picture
-- error diffusion inside the cells
{ cells, image } = ditherCells atkinson nearestInCell Zx.screen picture
Ordered dithering, with the 8 × 8 Bayer map, looks most like the Spectrum's own art and keeps every tone; with error diffusion, Atkinson looks best.
cells holds each cell's Attribute: its ink, paper and BRIGHT, as a
screen file needs them; toScr turns the whole result into one. The
colors are those of Puregrain.Palette.Presets.zxSpectrum. The
colors, the attributes and the file layouts in full:
docs/machine-screens/zx-spectrum.md.
#attributes Source
attributes :: NonEmptyArray AttributeEvery attribute that looks different: per brightness, 8 cells of a single color and 28 pairs, 72 in all, minus one, because all black looks the same with and without BRIGHT (it's listed once, without). Ink is the darker color, the lower code, and paper the lighter, as in the Spectrum's default of black ink on white paper; a single-color cell has ink = paper.
They're listed in the order Puregrain.Cells tries them, where the
earlier wins a tie: the single colors first, then the pairs by the
distance between their two colors, nearest first (at equal distances,
normal before bright, then by ink, then by paper). A cell that several
palettes fit equally well thus gets the narrowest, the calmest.
#attributePalette Source
attributePalette :: Attribute -> CellPaletteThe attribute's colors, for Puregrain.Cells: the ink, then the
paper, or the one color of a single-color cell. With orderedInCell,
the order means that a cell is ink with paper dots added as a pixel
nears the paper.
#toScr Source
toScr :: { cells :: Array (Array Attribute), image :: Array (Array RGB) } -> Either String (Array Int)A dithered screen as a .scr file: the 6912 bytes of the Spectrum's
screen memory, as SAVE "name" SCREEN$ saves them, and as many
emulators and tools open them.
{ cells, image }: whatPuregrain.Cells.ditherCellsreturns with this module'sscreen, for a 256 × 192 picture.
bytes = toScr (ditherCells noDiffusion (orderedInCell m) screen picture)
The first 6144 bytes are the bitmap, one bit per pixel (1 for the ink, 0 for the paper, the leftmost pixel in the highest bit), its rows in the Spectrum's interleaved order. Then come 768 attribute bytes, one per cell, row by row: BRIGHT × 64 + paper × 8 + ink, with FLASH off. A single-color cell has all its bits 0.
Left, with a message, for an image that isn't 256 × 192, for cells
that don't form the matching 32 × 24 grid, or for a pixel that isn't
one of its cell's colors: then the cells weren't chosen for this image.
#toTap Source
toTap :: String -> { cells :: Array (Array Attribute), image :: Array (Array RGB) } -> Either String (Array Int)A dithered screen as a .tap tape image: a short BASIC program that
starts by itself and loads the screen, then the screen as a CODE file.
Open it in an emulator, or type LOAD "" on a Spectrum: the picture
appears and stays until a key is pressed.
String: the name on the tape, up to 10 printable ASCII characters.{ cells, image }: as fortoScr.
bytes = toTap "sphere" (ditherCells noDiffusion (orderedInCell m) screen picture)
Left, with a message, for a name that's too long or holds other
characters, and as toScr for the screen. The tape format:
https://worldofspectrum.net/zx-modules/fileformats/tapformat.html
- Modules
- Puregrain
- Puregrain.
Cells - Puregrain.
Dither - Puregrain.
Internal. Fifo - Puregrain.
Internal. Image - Puregrain.
Internal. Kernel - Puregrain.
Internal. Row - Puregrain.
Internal. State - Puregrain.
Internal. Step - Puregrain.
Internal. Util - Puregrain.
Kernel - Puregrain.
Machine. ZxSpectrum - Puregrain.
Ordered - Puregrain.
Palette - Puregrain.
Palette. Presets - Puregrain.
Pixel - Puregrain.
Quantize