Screen
The Spectrum’s screen memory layout
Table of Contents
Screen Layout
The screen has a fixed resolution of 256x192 pixels or 32x24 characters.
Colour is restricted to 8x8 pixel squares equivalent to each character.
It is located in memory at address 0x4000…0x5AFF and is split into two parts:
Address |
Name |
Content |
4000 |
DISPLAYFILE |
Screen Memory |
57FF |
|
5800 |
DISPLAYATTR |
Screen Colour data |
5AFF |
|
128K Spectrum's
The 128K Spectrum's have a second screen in RAM Bank #7 which can be used as an alternate to the default one
which is in RAM Bank #5. The memory layout is the same except for where it appears in the
memory map.
This section will refer to the default memory location as used by all Spectrum's.
If you want to use the alternate screen then you need to change the base address to that of the correct bank.
These are shown in the memory map's:
1 - Display File
The display pixel format
Address | Len | Name | Description |
4000 | 6144 | DISPLAYFILE | The start of the standard Spectrum's standard screen |
The display file contains the pixel data for the screen.
Arranged in a map of 192 rows, each 32 bytes long. Each byte contains 8 pixels.
Be aware, the rows are not stored linearly, but in a way that has been optimised for the ULA.
The first 256 bytes in memory represents the first byte of each character in the first 8 rows,
then the second byte of each character, and so on.
Once the first 8 rows have been done it repeats twice more for the next 8 rows then the last 8.
Although the memory map for the spectrum screen seems weird with its layout,
it's actually pretty logical. You can tell this weirdness is down to how the ULA works internally.
Calculating the characters address
If you have:
R
with the screen row (0…23)
C
with the column (0…31)
N
for the byte offset within the character (0…7)
then you can calculate the address using the following table:
Screen Address |
MSB |
LSB |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
0 |
1 |
0 |
R4 |
R3 |
N2 |
N1 |
N0 |
R2 |
R1 |
R0 |
C4 |
C3 |
C2 |
C1 |
C0 |
The formula is simple:
$$ Address = \left( \overbrace{ ( 0x40 | ( R \And 0x18 ) | N ) }^{MSB} \ll 8 \right) | \left( \overbrace{ ( ( R \And 0x07) \ll 5 ) | C }^{LSB} \right) $$
Pseudo code:
1lsb := ((R << 5) AND 0xC0) OR C
2msb := 0x40 OR (R AND 0x18) OR N
Machine Code:
An example routine in Z80 Machine Code for this calculation is
available to download.
Addresses of bytes within the same character
If you calculate the address of the top row of the character (i.e. N
=0) then, when rendering the
character to the screen you just need to increment the upper byte of the address.
This works as the lower 3 bits of the upper byte represent the row for the character.
The adjacent table shows the addresses for each row of the first 5 characters on row 0 of the screen.
Char Row |
Address |
Char 0 |
Char 1 |
Char 2 |
Char 3 |
Char 4 |
0 |
4000 |
4001 |
4002 |
4003 |
4004 |
1 |
4100 |
4101 |
4102 |
4103 |
4104 |
2 |
4200 |
4201 |
4202 |
4203 |
4204 |
3 |
4300 |
4301 |
4302 |
4303 |
4304 |
4 |
4400 |
4401 |
4402 |
4403 |
4404 |
5 |
4500 |
4501 |
4502 |
4503 |
4504 |
6 |
4600 |
4601 |
4602 |
4603 |
4604 |
7 |
4700 |
4701 |
4702 |
4703 |
4704 |
Get address of the next character
You can get the address of the next character simply by adding one to the lower byte of the address.
Be careful however when wrapping around the end of the line as, after the first 8 lines the address will fail.
Ideally you should calculate the address again at the start of each line.
This might explain why the original spectrum editor was 8 lines long, as you only needed to set the high byte to an
appropriate 8-line block in memory and set the low byte to the offset in the line being edited to get that
characters screen address.
A simple 256 character editor
As mentioned above, you could use one third of the screen as a simple editor which is capable of displaying 256
characters.
Address |
MSB |
Rows |
Screen position |
4000 |
0x40 |
0 |
7 |
Top third |
4800 |
0x48 |
8 |
15 |
Middle third |
5000 |
0x50 |
16 |
23 |
Bottom third |
As long as you restrict yourself to one third of the screen you can simply calculate the address within this simple
editor by selecting the high byte for the required section of the screen and use the characters position in the line
as the low byte.
2 - Display Attributes
The display attributes specifying colour information
Address | Len | Name | Description |
5800 | 768 | DISPLAYATTR | The display attributes holding colour information |
The display attribute section contains the colour information and occupies addresses 0x5800…0x5AFF.
It's a direct map of the characters on the screen, arranged in 24 rows, each 32 characters long.
Each byte consists of the Foreground (INK) and Background (PAPER) colour for all pixels contained
within the equivalent position in the Display File.