Smooth Sprite Movement on the ZX Spectrum (1 of 2)


This Devlog is part 1 of a 2-part log explaining some of the methods ZX Spectrum game writers can use to create smooth sprite movement. Part 1 focuses on the video hardware and timing, part 2 will focus on how the sprites are written to video memory.

What is a Sprite?

A sprite is a 2D bitmap image typically moving over some type of background image. Imagine Miner Willy from the Jet Set Willy game, he is a sprite. Some home computers from the Spectrum era had dedicated hardware to handle the display and movement of sprites, the ZX Spectrum, however, did not. Game designers for the Spectrum had to write code to display, remove, update animation frames, and redisplay sprites at their new position.

Video Timing

An important part of successfully managing sprites is timing. If a sprite is updated while the TV's electron beam is drawing it, it will flicker or tear which is undesirable. This flicker can be seen in many Spectrum games when there is a lot of movement on the screen.

Halt Timing

A PAL TV refreshes the screen 50 times per second and each time the electron beam begins a new video frame the Uncommitted Logic Array (ULA) in the Spectrum sends an interrupt to the Spectrum's CPU (the Spectrum only has one interrupt and this is it). The Z80 CPU has a handy instruction, 'halt', which causes the CPU to do nothing (execute 'nop' instructions) until an interrupt is detected. Using this instruction it is possible to synchronize the CPU with the video output.

Although a PAL TV refreshes the screen 50 timers per second (every 20ms) a game designer doesn't have 20ms to update the sprites. This is because for the majority of this time, the electron bean is drawing the active (non-border) portion of the screen which is exactly what we want to avoid.

So, when you consider the CPU gets the refresh interrupt from the ULA when the electron beam is on its way back to the top left-hand corner of the screen, and you only want to update sprites when the electron beam is drawing the non-active (border) portions of the screen, you only have the time it takes the electron beam to draw the top border to update the sprites. The top border is 64 pixel rows, 16 are off screen and the other 48 are visible. It takes 64uS to draw 1 pixel row, therefore it tales 64 x 64uS to draw the top border or ~4ms.

Floating Bus Timing

The floating bus refers to a 'feature' of the Spectrum hardware. There are two main chips inside the Spectrum, the Central Processing Unit (CPU) and the Uncommitted Logic Array (ULA). While the CPU runs the application, game, etc. the ULA handles I/O port accesses and generates the video output. Because both the ULA and the CPU need to access the video memory, the 8-bit data bus from both devices are connected together via 470-Ohm resistors. This allows each to access the video memory when the other isn't, with the ULA taking priority since the electron beam on the TV cannot be paused.

The ULA monitors the address and control signals from the CPU and if it detects the CPU trying to access video memory at the same time, it simply pauses the CPU clock until the ULA finishes its video memory access. This means the CPU is slower at accessing this memory than other memory in the system. This type of memory is known as contended memory, bank-5 (addresses $4000-$7fff) on the Spectrum is contended memory. Timing critical routines should not be placed in this memory bank.

A side effect of the ULA and CPU data-busses being connected via 480-Ohm resistors is, if the CPU reads from unused I/O ports it can read the value currently on the ULA's data bus. The value read will be the value the ULA is reading from video memory to draw the screen. This information can be used to accurately time the CPU's video memory accesses.

In Castle Escape, the bottom 3 character rows of the screen are used to display the score, status message, lives, etc. The border around the status information is red ink and black paper, this translates to an attribute value of $02. This is the only place in the entire game these colors are used together and so the value $02 can be used to detect when the ULA is drawing this part of the screen. If the sprite updating starts at this point, there will effectively be the time it takes the electron beam to draw the last 24 pixel rows of the active portion of the screen in addition to the bottom and top borders. There are 56 pixel rows in the bottom border plus 24 pixel rows of active screen which takes 80 x 64uS to draw (~5ms), plus the 4ms from the top border which gives ~9ms. Over double the amount of time for sprite updates compared to the 'Halt Timing' method.

More to come...

In part 2 of this log, I'll outline the methods used in Castle Escape to update the sprites, stay tuned.

IH.

Get Castle Escape (ZX Spectrum 48K-128K)

Buy Now$1.99 USD or more

Leave a comment

Log in with itch.io to leave a comment.