Module

Puregrain.Machine.C64

Package
purescript-puregrain
Repository
roman-mkh/puregrain

The Commodore 64's hires bitmap screen: 320 × 200 pixels in cells of 8 × 8, each cell with two of the machine's 16 colors, a foreground and a background, chosen freely. With Puregrain.Cells, that gives pictures the C64 could show:

import Puregrain.Cells (ditherCells, nearestInCell, orderedInCell)
import Puregrain.Machine.C64 as C64

-- ordered dithering inside the cells, with a threshold map m
{ cells, image } = ditherCells noDiffusion (orderedInCell m) C64.hiresScreen picture

-- error diffusion inside the cells
{ cells, image } = ditherCells atkinson nearestInCell C64.hiresScreen picture

cells holds each cell's HiresCell: its foreground and background, as the machine's screen memory needs them; toHiresPrg turns the whole result into a C64 program that shows it, and toArtStudio into an Art Studio picture file. The colors are those of Puregrain.Palette.Presets.c64. The C64's multicolor mode isn't supported yet.

#HiresCell Source

newtype HiresCell

One hires cell's colors: the foreground, the color of the cell's 1 bits, and the background, the color of its 0 bits, as C64 color codes (0 black, 1 white, 2 red, 3 cyan, 4 purple, 5 green, 6 blue, 7 yellow, 8 orange, 9 brown, 10 light red, 11 dark grey, 12 grey, 13 light green, 14 light blue, 15 light grey). Only the 136 values in hiresCells exist.

Instances

#foreground Source

foreground :: HiresCell -> Int

The foreground's color code, 0 to 15: the color of the cell's 1 bits.

#background Source

background :: HiresCell -> Int

The background's color code, 0 to 15: the color of the cell's 0 bits.

#hiresCells Source

hiresCells :: NonEmptyArray HiresCell

Every hires cell that looks different: the 16 single colors and the 120 pairs, 136 in all. In a pair, the foreground is the darker color and the background the lighter, as with the ZX Spectrum's black ink on white paper. Darker means a lower luma, 0.299 R + 0.587 G + 0.114 B, since the C64's color codes aren't in order of brightness. A single-color cell has foreground = background.

They're listed in the order Puregrain.Cells tries them, where the earlier wins a tie: the single colors first, by code, then the pairs by the distance between their two colors, nearest first (at equal distances, by foreground, then by background). A cell that several palettes fit equally well thus gets the narrowest, the calmest.

#hiresPalette Source

hiresPalette :: HiresCell -> CellPalette

The cell's colors, for Puregrain.Cells: the foreground, then the background, or the one color of a single-color cell. With orderedInCell, the order means that a cell is foreground, with background dots added as a pixel nears the background.

#hiresScreen Source

hiresScreen :: CellMode HiresCell

The C64's hires screen mode, for Puregrain.Cells: cells of 8 × 8 pixels, each using one of the hiresCells, tried in their order, with hiresPalette's colors.

#toHiresPrg Source

toHiresPrg :: { cells :: Array (Array HiresCell), image :: Array (Array RGB) } -> Either String (Array Int)

A dithered hires screen as a .prg file: a C64 program that shows the picture by itself. Open it in an emulator, which starts it, or load and run it on a C64 (LOAD "name",8 and RUN). The picture stays until a key is pressed; then the screen is as it was.

  • { cells, image }: what Puregrain.Cells.ditherCells returns with this module's hiresScreen, for a 320 × 200 picture.
bytes = toHiresPrg (ditherCells noDiffusion (orderedInCell m) hiresScreen picture)

The file is 14,145 bytes: the address it loads at, 2049 ($0801), where BASIC programs start, and from there a short BASIC program, the viewer; the cells' colors at 3072 ($0C00), one byte per cell, row by row: foreground × 16 + background; and the bitmap at 8192 ($2000), one bit per pixel (1 for the foreground, 0 for the background, the leftmost pixel in the highest bit), each cell's 8 bytes in a row, the cells row by row. Zeros fill the gaps. A single-color cell has all its bits 0. The viewer points the video chip at the colors and the bitmap where they are, with a black border, and puts everything back after a key.

Left, with a message, for an image that isn't 320 × 200, for cells that don't form the matching 40 × 25 grid, or for a pixel that isn't one of its cell's colors: then the cells weren't chosen for this image.

#toArtStudio Source

toArtStudio :: { cells :: Array (Array HiresCell), image :: Array (Array RGB) } -> Either String (Array Int)

A dithered hires screen as an Art Studio file, .art: the format of the C64's best-known hires paint program, which many viewers and converters open.

  • { cells, image }: what Puregrain.Cells.ditherCells returns with this module's hiresScreen, for a 320 × 200 picture.
bytes = toArtStudio (ditherCells noDiffusion (orderedInCell m) hiresScreen picture)

The file is 9009 bytes: the address it loads at, 8192 ($2000); the bitmap, 8000 bytes; the cells' colors, 1000 bytes, both as in toHiresPrg; and 7 filler bytes, zeros, as long as Art Studio's own files.

Left, with a message, as for toHiresPrg.