The Challenge of the Spectrum Screen
The ZX Spectrum screen memory is not linear. To save on hardware costs, the memory map was designed to simplify the display hardware’s access but complicate the CPU’s access.
The Layout: The screen is divided into three major vertical bands, and within each band, the lines are interleaved. This means to find the address of the pixel at (X, Y), you must perform a complex, multi-step calculation.
The Full Screen Address Calculation
To calculate the 16-bit memory address (`HL′) for a pixel at coordinates (X, Y), you must use the following structure:
Address = `4000H′ (Base) + Field + Row + ByteOffset
Step 1: Calculating the Field (4000H′ to
4FFFH′)
The highest three bits of the Y-coordinate (`Y7, Y6, Y5′) determine which of the three vertical thirds of the screen the pixel belongs to. This calculation uses addition and shifting:
Formula: ((Y & 11100000B) >> 3)
; Assume Y-coordinate is in A
LD C, A ; C ← Y-coordinate
AND 0E0H ; Mask Y to keep only bits Y5, Y6, Y7
RRCA ; Rotate 3 times right (moves Y7, Y6, Y5 to Y4, Y3, Y2)
RRCA
RRCA
OR 040H ; Set high bit for the 4000H block
LD H, A ; H ← High byte of the address
Step 2: Calculating the Row (C0H′ to
3FFH′ Address Span)
The next three bits of the Y-coordinate (`Y4, Y3, Y2′) determine the address offset within the current third.
Formula: `((Y & 00011100B) » 3)′
LD A, C ; Restore Y-coordinate in A
AND 01CH ; Mask Y to keep only bits Y2, Y3, Y4
RRCA
RRCA
RRCA ; Y4, Y3, Y2 → bits 4, 3, 2 of the result
LD L, A ; L ← Low byte of the address offset
Step 3: Calculating the Line (The Interleaving)
The lowest three bits of the Y-coordinate (`Y1, Y0′) determine the line within the 8-pixel block.
Formula: `(Y & 00000111B) × 32′
This requires a fast multiplication routine (or a series of additions/shifts) to multiply the three bits by 32, which is the number of bytes per horizontal screen line. The result is added to the previous calculation.
Step 4: Final Column Offset
Finally, the X-coordinate is simply divided by 8 to get the final column offset. The full sum of all these parts yields the final 16-bit address for the pixel byte: `HL′.