Screen device

This is the specification for the screen device of the Bedrock computer system.

This document is aimed at people who are implementing the Bedrock system from scratch. For people who are learning about or writing program for the Bedrock system, the screen device manual will generally be more useful.

Concepts

Screen palette

The screen has a 16 colour palette, with each colour in the palette indexed as colour zero through fifteen. Each colour in the palette is selected from a 12-bit RGB colour space. Every pixel on the screen is rendered using a palette index. Changing a colour in the palette will change the colour of all pixels that use that index.

The initial colour palette is determined by the implementation.

Screen layer

The screen contains two overlapping layers, called the foreground layer and the background layer. Each pixel on a layer is coloured using a palette index. When rendering the screen contents, each pixel of the screen is rendered as the foreground colour of that pixel if it is not colour zero, otherwise it is rendered as the background colour.

The initial colour of each pixel on the foregroud and background layer is colour zero.

Screen cursor

The screen cursor is a pair of signed 16 bit coordinates representing the position of a pixel on the screen. The horizontal coordinate increases rightwards, and the vertical coordinate increases downwards. The intial value of each coordinate is zero. The origin is the top-left pixel of the screen.

Sprite buffer

The sprite buffer is a 16 byte block of writeable memory with an associated pointer. The initial value of each byte is zero. The initial value of the pointer is zero.

Pushing a byte into the sprite buffer will write that byte to the address referenced by the pointer, and then will increment the pointer by 1, wrapping to zero after 15.

The sprite buffer is treated as a circular buffer that is split into two 8 byte planes by the pointer. The high plane is made up of the eight bytes starting from the address referenced by the pointer, and the low plane is made up of the remaining eight bytes.

Sprite data

A sprite is an 8x8 pixel square image. A 1-bit sprite is stored as eight bytes, and a 2-bit sprite is stored as sixteen bytes.

Sprites are read from the sprite buffer. Each plane of the sprite buffer contains 1 bit of data per sprite pixel. Each byte of a plane maps to a row of the sprite, ordered top to bottom, and each bit of a byte maps to a pixel in the row, ordered left to right, from highest bit to lowest.

A 1-bit sprite is drawn using the low plane of the sprite buffer, with each pixel corresponding with a 1-bit colour value.

A 2-bit sprite is drawn using both planes of the sprite buffer, with each pixel corresponding with a 2-bit colour value. The high plane determines the high bit of each colour value and the low plane defines the low bit.

Each pixel of a sprite is drawn using the selected colour that corresponds with the colour value of that pixel:

High Low Description
0 0 Drawn as selected colour 0
0 1 Drawn as selected colour 1
1 0 Drawn as selected colour 2
1 1 Drawn as selected colour 3

Selected colours

The selected colours are a set of four palette colours that are used to draw sprites to the screen. Each selected colour is a palette index. The initial value of each selected colour is zero.

Ports

Port Name Description Read Write
0x50 Horizontal coordinate Horizontal cursor coordinate.
0x51 grouped grouped
0x52 Vertical coordinate Vertical cursor coordinate.
0x53 grouped grouped
0x54 Screen width Horizontal screen dimension.
0x55 grouped grouped
0x56 Screen height Vertical screen dimension.
0x57 grouped grouped
0x58 Palette Change the colour palette.
0x59 grouped grouped
0x5A Selection Select the sprite colours.
0x5B grouped grouped
0x5C Sprite Write to the sprite buffer.
0x5D aliased aliased
0x5E Draw Draw to the screen.
0x5F Move Move the screen cursor.

Horizontal coordinate

Reading from this port group will return the horizontal coordinate of the screen cursor. Writing to this port group will set the coordinate to the value written.

Vertical coordinate

Reading from this port group will return the vertical coordinate of the screen cursor. Writing to this port group will set the coordinate to the value written.

Screen width

Reading from this port group will perform an atomic read, returning the width of the screen in pixels. Reading while no screen is available will return zero.

Writing to this port group will perform an atomic write, requesting on commit that the width of the screen be locked and changed to the value written.

Screen height

Reading from this port group will perform an atomic read, returning the height of the screen in pixels. Reading while no screen is available will return zero.

Writing to this port group will perform an atomic write, requesting on commit that the height of the screen be locked and changed to the value written.

Palette

Writing to this port group will perform an atomic write, changing a colour in the screen palette on commit.

The upper four bits of the value written represent the palette index that will be overwritten, and the remaining 4-bit groups represent the red, green, and blue values of the colour.

Bits Description
0xF000 Palette index
0x0F00 Red channel
0x00F0 Green channel
0x000F Blue channel

Selection

Reading from this port will return a 16 bit value containing the four selected colours. Writing to this port will set the selected colours to the value written. Each group of four bits in the value read or written represents one of the selected colours:

Bits Description
0xF000 Selected colour 0
0x0F00 Selected colour 1
0x00F0 Selected colour 2
0x000F Selected colour 3

Sprite

Writing to this port will push the byte written to the sprite buffer.

Draw

Writing to this port will perform a draw operation according to the byte written. The upper four bits determine the operation to be performed, as follows:

Value Operation
0x0_ Set the colour of a pixel in the background layer.
0x1_ Draw a 1-bit sprite to the background layer.
0x2_ Fill the background layer with a solid colour.
0x3_ Draw a 2-bit sprite to the background layer.
0x4_ Draw a solid line to the background layer.
0x5_ Draw a 1-bit textured line to the background layer.
0x6_ Draw a solid rectangle to the background layer.
0x7_ Draw a 1-bit textured rectangle to the background layer.
0x8_ Set the colour of a pixel in the foreground layer.
0x9_ Draw a 1-bit sprite to the foreground layer.
0xA_ Fill the foreground layer with a solid colour.
0xB_ Draw a 2-bit sprite to the foreground layer.
0xC_ Draw a solid line to the foreground layer.
0xD_ Draw a 1-bit textured line to the foreground layer.
0xE_ Draw a solid rectangle to the foreground layer.
0xF_ Draw a 1-bit textured rectangle to the foreground layer.

If bit 0x10 of the byte written is unset, the lower four bits of the byte will represent the palette colour to use. Otherwise, the lower four bits will represent the transformations to apply to the sprite used by the operation, in the following order:

Bit Name Description
0x_1 Flip X Flip sprite across vertical center-line.
0x_2 Flip Y Flip sprite across horizontal center-line.
0x_4 Flip diagonal Flip sprite across top-left bottom-right diagonal.
0x_8 Transparent Don’t draw sprite pixels that use sprite colour 0.

The current cursor position is the current position of the screen cursor. The previous cursor position is the position of the screen cursor during the previous draw operation, or the origin if no draw operation has been performed.

When setting the colour of a pixel on a layer, the pixel on that layer at the current cursor position is changed to the given colour.

When filling a layer with a solid colour, each pixel on that layer is changed to the given colour.

When drawing a sprite to a layer, the sprite is read from the sprite buffer, then the given transformations are applied, and then each pixel of the sprite is drawn to that layer, with the top-left pixel of the sprite placed at the current cursor position.

When drawing a line to a layer, each pixel on the layer belonging to the shortest line that connects the previous and current cursor positions will be affected. Line pixels can connect diagonally or orthogonally. The algorithm chosen must be stable.

When drawing a rectangle to a layer, each pixel on the layer belonging to the smallest axis-aligned rectangle that contains both the previous and current cursor positions will be affected.

When drawing a solid line or rectangle, each pixel belonging to the line or rectangle will be changed to the given colour.

When drawing a textured line or rectangle, a 1-bit sprite is read from the sprite buffer, then the given transformations are applied, and then each pixel belonging to the line or rectangle will be drawn as the corresponding sprite pixel, as if the sprite were tiled outwards from the top-left corner of the screen.

Move

Writing to this port will move the screen cursor a number of pixels in a given direction according to the byte written. The upper two bits determine the direction to move, and the lower six bits determine the distance:

Bit Name
0x80 Negative
0x40 Vertical
0x3F Distance

If bit 0x40 is set, the vertical coordinate of the screen cursor will be modified, else the horizontal coordinate will be modified. If bit 0x80 is set, the distance will be subtracted from the coordinate, else the distance will be added.

Implementation notes

Double buffering

Double-buffering should be used to reduce flickering. Buffers should be flipped every time the system enters sleep mode. Palette changes should also be double-buffered in order to prevent the screen colours from updating separately from the image.

Fixed palette screens

For a two-colour screen with a fixed palette, every second palette index maps to the on colour and every other index maps to the off colour. For a three-colour screen, every fourth index maps instead to the grey colour. For a four-colour screen, the third and fourth index of every four map instead to the dim grey and bright grey colours.

Index 2 colour 3 colour 4 colour
0,4,8,C Off Off Off
1,5,9,D On On On
2,6,A,E Off Off Dim
3,7,B,F On Grey Bright

Wake behaviour

This device will send a wake request to the system device when the width or height of the screen changes.