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:

  1. Pixel Data: Where the bits defining the shape of the image (the ‘black’ or ‘white’ dots) are stored.
  2. 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.