In the last lesson, you built a full Name Table map that displayed a bordered pattern across the screen using tiles.
Now we’ll bring that image to life by introducing the Colour Table — the VRAM section that defines the foreground (ink) and background (paper) colours for each tile row.
By the end of this lesson, you’ll understand exactly how the Colour Table works, why we must write it to all three screen sections, and how to colourise specific tile patterns like borders and spot fills.
The Colour Table is a 6 KB section of VRAM that gives the VDP its colour information for each pixel row of every pattern.
Each byte in the Colour Table controls one row of an 8×8 pattern:
High nibble = foreground colour (pixels set to 1)
Low nibble = background colour (pixels set to 0)
So for every 8×8 tile pattern (8 bytes of shape data), there are 8 matching bytes in the Colour Table.
For example:
01000000b = dark blue ink on black background
01110000b = cyan ink on black background
11000000b = dark green ink on black background
10000000b = red ink on black background
In Graphics Mode II, the Colour Table is divided into three sections — one for each third of the screen.
Each section provides the colour bytes for the pattern data in its corresponding Pattern Generator Table region.
Screen SectionStart AddressVRAM High Byte (decimal)DescriptionTop third8192 (0x2000)96Rows 0–7Middle third9216 (0x2400)104Rows 8–15Bottom third10240 (0x2800)112Rows 16–23
Just like with the Pattern Table, this means we must write our colour data three times — once per bank — to ensure every part of the screen displays consistently.
The setup at the start of the code is the same as before:
LD A,2 : OUT (9),A
LD A,128 : OUT (9),A
LD A,224 : OUT (9),A
LD A,129 : OUT (9),A
This enables Graphics Mode II, unlocking three pattern and colour banks.
LD A,240 : OUT (9),A ; 11110000 = white on black
LD A,135 : OUT (9),A
These are the overall screen defaults — individual tile colours come from the Colour Table we’re about to write.
The tile patterns (corners, horizontals, verticals, and spots) are written as before, across all three VRAM sections.
Each tile pattern defines shape, but not colour.
Now comes the new part of the program.
This section defines the colour bytes for each tile type across all three screen sections.
Each byte has two nibbles:
High nibble = foreground (ink)
Low nibble = background (paper)
The Einstein’s VDP uses these nibble values for colours:
Colour
Value: 0
Binary: 0000
Transparent
Colour
Value: 1
Binary: 0001
Black
Colour
Value: 2
Binary: 0010
Medium Green
Colour
Value: 3
Binary: 0011
Light Green
Colour
Value: 4
Binary: 0100
Dark Blue
Colour
Value: 5
Binary: 0101
Light Blue (Cyan)
Colour
Value: 6
Binary: 0110
Dark Red
Colour
Value: 7
Binary: 0111
Cyan
Colour
Value: 8
Binary: 1000
Medium Red
Colour
Value: 9
Binary: 1001
Light Red
Colour
Value: A
Binary: 1010
Dark Yellow
Colour
Value: B
Binary: 1011
Light Yellow
Colour
Value: C
Binary: 1100
Dark Green
Colour
Value: D
Binary: 1101
Magenta
Colour
Value: E
Binary: 1110
Grey
Colour
Value: F
Binary: 1111
White
TileColour Byte
Foreground: Dark Blue (4)
Background: Black (0)
Description: Blue border corners
Corner
01000000
TileColour Byte
Foreground: Cyan (7)
Background: Black (0)
Description: Cyan horizontal bars
Horizontal
01110000
TileColour Byte
Foreground: Dark Green (C)
Background: Black (0)
Description: Green vertical edges
Vertical
11000000
TileColour Byte
Foreground: Medium Red (8)
Background: Black (0)
Description: Red spots inside
Spot
10000000
Each pattern row uses the same colour combination, so each byte is repeated eight times.
The Colour Table must be filled for all three display regions:
Screen SectionStart AddressHigh Byte (decimal)Top third0x200096Middle third0x2400104Bottom third0x2800112
For each tile pattern, the program:
OUT (8),A ×8).Example (corner tile, top third):
LD A,8 : OUT (9),A
LD A,96 : OUT (9),A
LD A,%01000000 : OUT (8),A
OUT (8),A
OUT (8),A
OUT (8),A
OUT (8),A
OUT (8),A
OUT (8),A
OUT (8),A
This defines a blue-on-black colour scheme for the corner pattern in the top section of the screen.
The same is then repeated for the other patterns and VRAM banks (high bytes 104 and 112).
After all colour data is written, the program clears the Name Table and loads the same TileMap data from the previous lesson — meaning the same border and spot pattern layout now displays in colour.
Finally:
JP $
keeps the program running indefinitely.
When run, the display now shows:
Each pattern is independently coloured using the Colour Table entries defined for its tile number.
ORG 256
; -----------------------
; Enable Graphics Mode II
; ----------------------
; Set Register 0 values
LD A,2
OUT (9),A
LD A,128
OUT (9),A
; Set Register 1 values
LD A,224
OUT (9),A
LD A,129
OUT (9),A
; ---------------------------
; Set Foreground / Background
; ---------------------------
LD A, 240 ; 11110000 (white foreground, black background)
OUT (9), A ; Send to Port 9
LD A, 135 ; 128 (bit 7 set) + 7 (register 7)
OUT (9), A ; Send to Port 9
; -----------------
; Write Blank Tiles
; -----------------
; Top Third Blank Tile
LD A, 0 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 64 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A, 0 ; Load 170 into A
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
; Middle Third Blank Tile
LD A, 0 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 72 ; Load 72 into A register
OUT (9), A ; Send to Port 9
LD A, 0 ; Load 170 into A
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
; Bottom Third Blank Tile
LD A, 0 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 80 ; Load 80 into A register
OUT (9), A ; Send to Port 9
LD A, 0 ; Load 170 into A
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
OUT (8), A ; Send to Port 8
; -------------------
; Write Pattern Tiles
; -------------------
; Top Third Pattern Tiles
; Corner Tile
LD A, 8 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 64 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%11111111 : OUT (8),A
LD A,%10000001 : OUT (8),A
LD A,%10111101 : OUT (8),A
LD A,%10100101 : OUT (8),A
LD A,%10100101 : OUT (8),A
LD A,%10111101 : OUT (8),A
LD A,%10000001 : OUT (8),A
LD A,%11111111 : OUT (8),A
; Horizontal Tile
LD A, 16 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 64 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%00000000 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%00000000 : OUT (8),A
; Vertical Tile
LD A, 24 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 64 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
; Spot Tile
LD A, 32 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 64 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%00000000 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%00000000 : OUT (8),A
; Middle Third Pattern Tiles
; Vertical Tile
LD A, 24 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 72 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
; Spot Tile
LD A, 32 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 72 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%00000000 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%00000000 : OUT (8),A
; Bottom Third Pattern Tiles
; Corner Tile
LD A, 8 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 80 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%11111111 : OUT (8),A
LD A,%10000001 : OUT (8),A
LD A,%10111101 : OUT (8),A
LD A,%10100101 : OUT (8),A
LD A,%10100101 : OUT (8),A
LD A,%10111101 : OUT (8),A
LD A,%10000001 : OUT (8),A
LD A,%11111111 : OUT (8),A
; Horizontal Tile
LD A, 16 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 80 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%00000000 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%11111111 : OUT (8),A
LD A,%00000000 : OUT (8),A
; Vertical Tile
LD A, 24 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 80 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
LD A,%01011010 : OUT (8),A
; Spot Tile
LD A, 32 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 80 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%00000000 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00111100 : OUT (8),A
LD A,%00000000 : OUT (8),A
LD A,%00000000 : OUT (8),A
; ------------------
; Write Colour Table
; ------------------
; Top Third Pattern Tiles Colours
; Corner Tile
LD A, 8 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 96 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
; Horizontal Tile
LD A, 16 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 96 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A, 24 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 96 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
; Spot Tile
LD A, 32 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 96 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
; Middle Third Pattern Tiles Colours
; Vertical Tile
LD A, 24 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 104 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
; Spot Tile
LD A, 32 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 104 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
; Bottom Third Pattern Tiles Colours
; Corner Tile
LD A, 8 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 112 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
LD A,%01000000 : OUT (8),A
; Horizontal Tile
LD A, 16 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 112 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A,%01110000 : OUT (8),A
LD A, 24 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 112 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
LD A,%11000000 : OUT (8),A
; Spot Tile
LD A, 32 ; Load zero into A register
OUT (9), A ; Send to Port 9
LD A, 112 ; Load 64 into A register
OUT (9), A ; Send to Port 9
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
LD A,%10000000 : OUT (8),A
; --------------------------------
; Clear Name Table with Blank Tile
; --------------------------------
LD A, 0 ; Low Byte
OUT (9), A ; Send to Port 9
LD A, 120 ; High Byte
OUT (9), A ; Send to Port 9
LD BC, 768 ; Set Counter for table address space
ClearLoop:
LD A, 0 ; Load zero into A register
OUT (8), A ; Send to Port 8
DEC BC ; Decrement BC Counter
LD A, B ; Load B into A register
OR C ; Bitwise OR to compare
JR NZ, ClearLoop ; Jump to start unless BC is zero
; -------------------------------------
; Write Tiles to Name Table / Tile Map
; -------------------------------------
; Point to start of name table
LD A, 0 ; Low Byte
OUT (9), A ; Send to Port 9
LD A, 120 ; High Byte
OUT (9), A ; Send to Port 9
LD HL, TileMap
LD BC, 768
Loop:
LD A, (HL)
OUT (8), A
INC HL
DEC BC
LD A, B ; Load B into A register
OR C ; Bitwise OR to compare
JR NZ, Loop ; Jump to start unless BC is zero
JP $ ; JP Idefinitely
TileMap:
DB 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3
DB 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1
You’ve now extended your tile engine to support per-tile colours using the Colour Table.
This foundation sets you up for the next stage: using dynamic colour effects, palette changes, and multi-coloured tiles for more advanced visuals.