The display’s frame clock and the game’s update rate need not be the same. We will keep the interrupt handler unchanged and let main code work on alternate frames.
Replace the previous program with this checkpoint, or add the following gate immediately after ld a,(frames) in main_loop:
and 1
jr nz,main_loopand 1 keeps the low bit. Even numbers end in binary 0; odd numbers end in 1. JR NZ goes back to wait when the result is nonzero. Main code therefore increments updates only on even frame-byte values.
Source · view and edit
Edit the source, then assemble.
Edits are saved in this browser. Keep a downloaded copy of work you want to keep.
Run the program to inspect it. Editing source does not change the running machine.
frames- —
updates- —
The border now changes half as often. frames still counts every interrupt, while updates counts accepted opportunities to do game work. Nothing has slowed the Spectrum’s clock.
Follow the wrap without guessing
Near the byte boundary the handler produces 254, 255, 0, 1, 2. Main code accepts 254, skips 255, accepts 0, skips 1 and accepts 2. Zero is an even value; wrapping does not insert a long pause.
After 600 PAL frames, this experiment advances updates by 300. The display reads snapshots of two live counters, so it is not an instruction-by-instruction trace. They may advance before you finish reading a pair.
main_loop:
halt
ld a,(frames)
and 1
jr nz,main_loop
ld hl,(updates)
inc hl
ld (updates),hl
; A display change every 32 updates: easy to see, separate from timing.
ld a,l
rrca
rrca
rrca
rrca
rrca
and 7
out ($FE),a
jp main_loopTry a slower rhythm
Replace and 1 with and 3. Now only frame values whose lowest two bits are both zero reach the update. That happens once every four frames, giving 12.5 updates per second on a 50-frame-per-second PAL machine.
Would and 2 mean one update every three frames?
Show the explanation
No. It tests only bit 1, accepting two frame values in a row and rejecting the next two. The pattern is uneven. AND is a bit operation, not a division operator with an arbitrary divisor. Masks 1 and 3 happen to identify multiples of two and four because of their binary shape.
This is still a small experiment, not a scheduler that can catch up after any amount of work. HALT waits for the next interrupt when execution reaches it. If an update takes too long, the program can miss its intended opportunity. We will measure that limit when the storm contains many moving objects.
Restore and 1. That gives the game twenty-five update opportunities per second and leaves two display frames in which to complete each update.
Sources
Zilog, Z80 CPU User Manual, UM008011-0816, “Interrupt Enable/Disable”, “Mode 2” and the DI, EI, HALT and RETI instruction entries. The frame-rate experiments here target the stock 48K PAL Spectrum.
Run it here
This unit's program, built for you.
- Program
- meteor-storm.tap
- Machine
- ZX Spectrum 48K (PAL)