The Need for a Dynamic List

When creating a game, you don’t want to waste time checking 50 memory locations if only 5 sprites are currently active. A Linked List is the most efficient data structure in Z80 assembly for managing a variable number of objects.

The Linked List Principle: Each sprite’s data block (the node) contains a pointer to the next sprite in the sequence. When the CPU finishes processing the current sprite, it simply follows the pointer to the next one. The list ends when a pointer value is zero or another terminator.

The Sprite Descriptor Revisited

We rely on the last field of our Sprite Descriptor (from Part 31) to point to the next sprite:

Offset Size (Bytes) Purpose
+8 2 Pointer to Next Sprite (If 0000H, the list ends)

The Linked List Processing Routine

The list processing routine requires a main pointer (HL) that constantly follows the chain.

The Setup: We need a fixed address that holds the pointer to the very first sprite (the list head).

SPRITE_LIST_HEAD DW 0000H ; Start of the list (0000H if empty)

PROCESS_SPRITES:
    LD   HL, (SPRITE_LIST_HEAD) ; HL ← Address of the first sprite (the head)

LOOP_START:
    LD   A, H                  ; Check the high byte of the pointer
    OR   L                     ; Check the low byte of the pointer
    JP   Z, LIST_END           ; If HL is 0000H, the list is empty/finished.

    ; --- 1. Process Current Sprite (HL) ---
    CALL UPDATE_COORDINATES    ; Update position, check collision, etc.
    CALL DRAW_SPRITE           ; Render the sprite on screen

    ; --- 2. Advance to Next Sprite ---
    LD   DE, 8                  ; DE = Offset to the next sprite pointer (+8)
    ADD  HL, DE                 ; HL ← HL + 8 (points to the 'Next Sprite Pointer' field)

    ; Get the address of the next sprite from memory at HL (offset +8)
    LD   E, (HL)                ; Read low byte of next address
    INC  HL
    LD   D, (HL)                ; Read high byte of next address
    LD   H, D                   ; Set H from D
    LD   L, E                   ; Set L from E (HL now points to the next sprite's base address)

    JP   LOOP_START             ; Continue the loop
    
LIST_END:
    RET

Adding/Removing Sprites

Adding a new sprite requires updating the ‘Next Sprite Pointer’ field of the current last sprite in the list. Removing a sprite is trickier and involves changing the pointer of the sprite before the removed one to point to the sprite after the removed one. This prevents breaking the chain.