We can now combine the ship loop with the clock we have examined separately. Held-key movement should depend on update opportunities, not an arbitrary delay count.
Start from the pixel-motion version. Replace the counted delay loop at the start of main_loop with HALT, the frame-byte load and the alternate-frame gate. Add the private IM2 setup and handler from the clock experiment before entering restart. The complete editor contains those changes together.
The rest of the movement sequence stays erase old image → read input and move → draw new image. The interrupt handler only increments frames; it does not modify ship position or call the drawing code.
Source · view and edit
Companion file: assets.inc
The include line reads this editable data when you assemble. Keep it beside your source for a local build.
Edit the source, then assemble.
Edits are saved in this browser. Keep a downloaded copy of work you want to keep.
Focus the Spectrum screen to use the keyboard, or hold these buttons. Assemble again for a fresh machine.
Run the program to inspect it. Editing source does not change the running machine.
ship_x- —
updates- —
frames- —
Predict speed from two quantities
The ship moves two pixels on an update while one direction is held. At 25 updates per second, that is 50 pixels per second until a boundary prevents further movement.
From x=116 to the right bound at 224 is 108 pixels, or 54 updates. That takes about 2.16 seconds after movement begins. Measuring your reaction time or a browser key press will not give an exact instruction count; the numbers explain the program’s rate, not how quickly you can press a button.
Change ld e,2 in steer to ld e,1, assemble and compare. Keep the frame gate unchanged. You have halved distance per update without changing the update frequency.
If updates continues increasing while the ship rests at x=224, has movement escaped the boundary?
Show the explanation
No. The counter measures update opportunities. The proposed rightward position is clamped back to 224, so many updates can produce the same position. Read the position and counter as different pieces of state.
Keep a useful failure experiment
Try removing call ship before call steer again. The clock still advances correctly, but the trail returns. Timing and erasure solve different problems. Fixing one does not repair the other.
R restarts the experiment and clears its small state. Reassembling restarts the whole machine, including the frame byte. A restart within an already running game need not reset the underlying frame clock; later we will store a fresh frame baseline when a run begins.
If the ship does not move, first check whether frames changes. A frozen frame byte suggests an interrupt setup problem. A changing frame byte with a fixed updates byte points towards the gate or main-loop flow. If both advance, inspect the O/P input and proposed position. This is a shorter investigation than changing the interrupt code whenever anything looks stationary.
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)