Egghead.page Logo

How the ZX Spectrum+2 Handled Interrupt-Driven Routines

The Sinclair ZX Spectrum+2 utilized the Z80 microprocessor’s Interrupt Mode 2 to manage timing-critical tasks through hardware signals generated by the ULA. This system allowed developers to synchronize software operations with the television screen refresh rate, enabling smooth animation and sound playback without constant CPU polling. By leveraging this hardware-based timing mechanism, the computer could maintain consistent performance for games and applications while managing display generation in the background.

At the heart of this process was the Z80 CPU, which was configured to operate in Interrupt Mode 2 (IM 2). Unlike Interrupt Mode 0, which executes a specific instruction provided on the data bus, or Mode 1, which jumps to a fixed address, Mode 2 allowed for a flexible vector table. When an interrupt occurred, the processor combined the contents of the special I register with a byte supplied by the hardware to form a 16-bit address. This address pointed to a location in memory that contained the actual starting address of the interrupt service routine.

The interrupt signal itself was generated by the Uncommitted Logic Array (ULA), the custom chip responsible for generating the video signal and managing memory access. During the flyback period of the television raster scan, the ULA would pulse the INT line on the Z80 CPU. On PAL systems, which were standard for the ZX Spectrum in Europe and the UK, this occurred 50 times per second. This frequency provided a reliable heartbeat for the system, ensuring that software routines could execute in sync with the screen refresh to prevent visual tearing.

Memory management was crucial for this routine to function correctly. The ROM initialized the I register to point to a specific page in memory where the interrupt vector table resided. Typically, the data bus would return a value of 0xFF during the interrupt acknowledge cycle due to the state of the ULA. Consequently, the vector table was often located at addresses ending in 0xFF, such as 0x3DFF or similar ranges depending on the specific memory configuration and ROM version. The table contained pairs of bytes that formed the jump address to the actual interrupt handler code.

While the built-in ROM provided a default interrupt routine to handle basic system tasks, advanced programmers often replaced this with custom handlers. By redirecting the vector table to point to user-defined code in RAM, developers could create multiplexed music players, smooth scrolling engines, and precise timing loops. This flexibility was a defining feature of ZX Spectrum development, allowing the hardware to be pushed beyond its original specifications through clever manipulation of the interrupt-driven architecture.