When drawing pixels directly on the Tatung Einstein, all our graphical data lives in VRAM (Video RAM). The VDP (Video Display Processor) reads from VRAM continuously to generate the on-screen image.
Two key tables control how the background is built:
(These are different from the Sprite Generator Table, which handles movable sprites.)
Think of the PGT as a collection of tiny 8×8 pixel blueprints, stored in VRAM.
Each tile (or pattern) is made up of 8 bytes — one byte per row of 8 pixels.
Each bit in the byte represents one pixel:
So a pattern is an 8×8 grid of on/off pixels described entirely by eight bytes.
For example, the letter “A” might look like this in binary:
00111100
01000010
01000010
01111110
01000010
01000010
00000000
00000000
Each of those rows is stored as one byte in VRAM.
In Graphics Mode II, the screen’s pattern table is divided into three separate sections in VRAM:
Screen RegionPGT Start AddressVRAM OffsetScreen AreaTop third0×0000Bank 0Rows 0–7Middle third0×0800 (2048)Bank 1Rows 8–15Bottom third0×1000 (4096)Bank 2Rows 16–23
Each section contains its own 256 pattern definitions — even if they are visually identical.
The reason is historical: Graphics Mode II gives the VDP more flexibility but at the cost of splitting the pattern space.
This means if you want a tile (for example, a blank tile) to appear correctly anywhere on the screen, you must define it in each third’s section of the PGT.
If you only define it in the top section (0x0000–0x07FF), the middle and bottom of the screen will read garbage data, because their parts of VRAM don’t contain a matching definition.
That’s why this program writes the same blank and striped tile patterns three times — once for each section of the PGT.
The Name Table is like a grid-based map — it tells the VDP which pattern number to draw in each of the 32×24 tile positions.
Each byte in the Name Table corresponds to one 8×8 cell on the screen, containing the pattern number to display there.
Example:
By filling the Name Table with pattern numbers, you can build an entire image using reusable tiles.
When the screen refreshes, the VDP:
Your program never draws pixels directly — it just defines and arranges tiles.
Once the tables are set up in VRAM, the VDP automatically renders the display each frame.
This example demonstrates how to enable Graphics Mode II, define blank and striped tiles in all three VRAM sections, clear the screen, and place a visible pattern in the top-left corner.
LD A,2
OUT (9),A
LD A,128
OUT (9),A
LD A,224
OUT (9),A
LD A,129
OUT (9),A
These register values switch the VDP into Graphics Mode II, unlocking full tile access across three pattern banks.
LD A,240 ; 11110000 (white ink, black background)
OUT (9),A
LD A,135 ; Register 7
OUT (9),A
Foreground = White (15)
Background = Black (0)
We now define a completely empty 8×8 pattern (all bits 0).
But since Graphics Mode II splits the pattern table, we must repeat this three times:
; --- Top Third Blank Tile ---
LD A,0
OUT (9),A
LD A,64
OUT (9),A
LD A,0
REPT 8
OUT (8),A
ENDR
; --- Middle Third Blank Tile ---
LD A,0
OUT (9),A
LD A,72
OUT (9),A
LD A,0
REPT 8
OUT (8),A
ENDR
; --- Bottom Third Blank Tile ---
LD A,0
OUT (9),A
LD A,80
OUT (9),A
LD A,0
REPT 8
OUT (8),A
ENDR
If we only wrote the blank tile in the first section, only the top third of the screen would show correctly. The middle and bottom areas would try to reference uninitialized pattern memory — potentially displaying random noise or artifacts.
By writing the same blank tile into each of the three PGT sections, we guarantee that when the Name Table requests pattern 0, every region of the screen uses the same definition.
This is essential for consistent backgrounds and proper screen clearing.
Just like with the blank tile, we define our visible tile three times — one for each third of the display.
; --- Top Third Pattern Tile ---
LD A,8
OUT (9),A
LD A,64
OUT (9),A
LD A,170 ; 10101010 pattern
REPT 8
OUT (8),A
ENDR
; --- Middle Third Pattern Tile ---
LD A,8
OUT (9),A
LD A,72
OUT (9),A
LD A,170
REPT 8
OUT (8),A
ENDR
; --- Bottom Third Pattern Tile ---
LD A,8
OUT (9),A
LD A,80
OUT (9),A
LD A,170
REPT 8
OUT (8),A
ENDR
Now Pattern 1 exists across all three PGT regions, so the striped tile will display correctly no matter where it’s placed on screen.
LD A,0
OUT (9),A
LD A,120
OUT (9),A
LD BC,768
ClearLoop:
LD A,0
OUT (8),A
DEC BC
LD A,B
OR C
JR NZ,ClearLoop
This fills all 768 Name Table entries with pattern 0 (the blank tile), effectively clearing the entire screen.
LD A,0
OUT (9),A
LD A,120
OUT (9),A
LD A,1
OUT (8),A
Pattern 1 (the striped tile) now appears in the top-left position of the screen.
JP $
This stops execution and leaves the display running indefinitely.
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 Tile
; ------------------
; Top Third Pattern 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, 170 ; 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 Pattern Tile
LD A, 8 ; 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, 170 ; 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 Pattern 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, 170 ; 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
; --------------------------------
; 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 Tile 1 to Name Table
; --------------------------
; 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
; Put tile 0 at top-left
LD A, 1 ; Load zero into A register
OUT (8), A ; Send to Port 8
JP $ ; JP Indefinitely
You’ve now learned not only how to write patterns into VRAM, but also why you must duplicate them across all three PGT sections in Graphics Mode II.
This method gives you total control over every pixel — and forms the foundation for scrolling backgrounds, tile-based games, and custom character sets.