I’ve been writing a smooth scroll routine for the ZX Spectrum over the last few days, based upon my recollection of conversations I’d had with Mike Follin at Software Creations whilst he was developing LED Storm and Ghouls ‘n Ghosts.
The code is written purely in Z80 assembler and demonstrates the following techniques:
- Using the stack as a quick way to read and write blocks of data
- Using the vertical blank interrupt to run a game loop
- Racing the beam to avoid flicker and tearing
- Self-modifying code
- Masked sprites
- Sorting sprites by Y coordinate
The code takes two frames to display and move everything, so runs at 25fps @ 50hz
Racing the beam
This is a bit of a mind-bender and relies upon the fact that CRT screens are refreshed a line at a time by a beam that scanned from top to bottom, and left to right, drawing the image on the phosphors of the CRT tube.
Although modern TVs and emulators do not work on exactly the same principles, they must emulate the process in order to remain backwards compatible with legacy video signals.
At the start of Frame 1 whilst the beam is still drawing the border, the code pre-process the map and dynamically creates some of the code for drawing the scroll bitmap.
The code also reads the keyboard at this point.
As the beam just exits the border area the code starts writing the scroll bitmap to the video memory. This is behind the beam, so is not visible yet.
The code finishes drawing the scrolling bitmap as the beam is in the bottom border. It always follows behind the beam, should never overtake it.
The code starts drawing the sprites now in the border area and the beam wraps into the second frame.
The sprite drawing should always be ahead of the beam, so the sprites are sorted by Y coordinate, and drawn from top to bottom.
As the beam starts drawing the bitmap on the second frame, it will now display the background drawn behind the beam in Frame 1, and the sprites drawn ahead of beam in this frame.
Any other code, mainly game logic, is executed after the sprites have been drawn.
Timing the drawing around the horizontal refresh of the monitor is crucial to this routine working.
I’ll be looking into specific parts of this code in more detail over the next few blog posts, but if you want to see what is going on under the hood, the source code is available here. If you want to see it running under emulation, you can run it on this website here (click on the Scroll Demo link on the TV tuner). Alternatively, if you want to load it on a Spectrum, or an emulator of your choice, you can download the TAP file here.
Please note that the code is currently only compatible with 48K Spectrums due to the lazy way I’ve set up the interrupt.
You can also see me load this code onto my Spectrum here: