The Need for Attribute Memory
On many Z80 retro systems (such as the ZX Spectrum), the screen display is split into two distinct areas of memory:
- Pixel Data: Where the bits defining the shape of the image (the ‘black’ or ‘white’ dots) are stored.
- Attribute Data: Where the bits defining the appearance (color, brightness, flash) of the image are stored.
This separation is necessary to save memory, as one attribute byte typically controls the appearance of an entire $8\times 8$ block of pixels.
The Attribute Byte Structure
A single attribute byte (8 bits) is loaded into a specific area of RAM (e.g., 5800H
on the Spectrum) and controls everything about the appearance of a character cell or block of pixels.
Generic Attribute Byte Breakdown:
| Bits | 7 | 6-3 | 2-0 | | :— | :— | :— | | Function | Flash | Background Color (Paper) | Foreground Color (Ink) |
Example: Setting Colors If the foreground (Ink) color is blue (binary 001) and the background (Paper) is red (binary 100), the byte would be composed and then stored in the attribute RAM.
Calculating the Attribute Address
The attribute memory typically starts immediately after the pixel memory and is laid out linearly. Calculating the attribute address for a given pixel coordinate (X, Y) is much simpler than calculating the pixel address:
The Simple Calculation: The attribute memory address is usually the base address plus the row number and column number.
ATTRIBUTE_BASE EQU 5800H ; Example base address
; Assuming H holds the Y-coordinate (row 0-23) and L holds the X-coordinate (column 0-31)
GET_ATTRIBUTE_ADDR:
LD DE, ATTRIBUTE_BASE ; Start address of attribute memory
LD A, H ; Load Y (row) into A
AND 0FH ; Mask for 0-15 (if needed)
; Multiply Y by 32 (the number of columns) - using shifts is faster!
LD B, A ; Copy Y value
LD A, 0 ; A = 0
RR A ; Shift A right (prepares for addition)
; ... (Complex multiplication/addition routine using DE and HL)
LD HL, DE ; HL holds the final attribute address
RET
``&rave;
## Changing the Attribute
Once the address `HL` is calculated, you simply load the desired attribute byte and store it at that location.
```asm
CALL GET_ATTRIBUTE_ADDR ; Get the target address in HL
LD A, 047H ; Attribute byte: Flash OFF (0), Paper Blue (4), Ink White (7)
LD (HL), A ; Write the new attribute byte to memory
Bitwise Attribute Modification: If you only want to change the flash state without touching the colors, you can use the BIT
, SET
, and RES
instructions on the byte at (HL)
instead of overwriting the whole byte.