Skip to content

Game Loop (HALT)

Frame-synchronised game loop using the HALT instruction. Locks to 50Hz for consistent timing across all Spectrums.

Taught in Game 1, Unit 1 game-looptiminghaltinterrupt

Overview

The simplest way to achieve consistent timing on the ZX Spectrum. The HALT instruction pauses execution until the next interrupt fires (50 times per second on PAL systems). This gives you exactly one frame to process input, update game state, and render.

Code

; =============================================================================
; GAME LOOP - HALT SYNCHRONISED
; 50Hz frame-locked game loop for ZX Spectrum
; Taught: Game 1 (Ink War), Unit 1
; CPU: Variable | Memory: ~20 bytes
; =============================================================================

; Main game loop structure
main_loop:
    halt                        ; Wait for next interrupt (50Hz)

    call    read_input          ; Check keyboard/joystick
    call    update_game         ; Update game state
    call    draw_screen         ; Render graphics

    jp      main_loop           ; Repeat forever

; Placeholder routines (replace with your game code)
read_input:
    ret

update_game:
    ret

draw_screen:
    ret

Minimal working example:

            org     32768

start:
            call    init_game

main_loop:
            halt                ; Sync to 50Hz
            call    read_keyboard
            call    move_player
            jp      main_loop

init_game:
            ; Your initialisation here
            ret

read_keyboard:
            ; Your input code here
            ret

move_player:
            ; Your movement code here
            ret

            end     start

Trade-offs

AspectCost
CPUFree (waits for interrupt)
Memory1 byte (halt = $76)
LimitationTied to 50Hz - can’t run faster or slower

When to use: Most games. Simple, reliable, works on all Spectrums.

When to avoid: When you need sub-frame timing (scrollers, raster effects) or variable frame rates.

How It Works

  1. The Z80’s HALT instruction suspends the CPU
  2. The ULA generates an interrupt 50 times per second (PAL) or 60 times (NTSC)
  3. When the interrupt fires, HALT releases and execution continues
  4. Your game code runs, then hits HALT again to wait for the next frame

This guarantees your game runs at a consistent speed regardless of how fast your code executes (as long as it completes within one frame).

Frame Budget

At 50Hz, you have 20ms per frame. On a 3.5MHz Z80, that’s approximately:

  • 70,000 T-states per frame
  • Enough for most games
  • If you exceed the budget, the game slows down

Patterns: Keyboard Reading

Vault: ZX Spectrum