Ramsoft presents:
The floating bus explained!
technical report - rev 1.06 (apr 25 2002)


  1. The floating bus
  2. The snow effect

1. The floating bus on the 48K and 128K

Due to the resistors which decouple the two dedicated buses inside the Spectrum, when the Z80 reads from an unattached port (such as 0xFF) it actually reads the data currently present on the ULA bus, which may happen to be a byte being transferred by the ULA from video memory for the screen rendering. If the ULA is building the border, then its data bus is idle (0xFF), otherwise we are perfectly able to predict whether it is reading a bitmap byte, an attribute or again it's idle. This "nice" effect goes under the name of floating bus. Unfortunately some programs do rely on the exact behaviour of the floating bus, so we can't simply forget about it; notable examples are Arkanoid (first edition), Cobra, Sidewize, Duet and DigiSynth.

In the next table we show the locations which are read by the ULA with their respective times (T-STATES), both in the 128K and in the 48K. Remember that during a port read, the Z80 fetches the input byte from the bus in the last cycle of the I/O transaction (i.e. T4).

Value128K time48K time
First row of pixels
Second row of pixels

The ULA reads a whole row of pixels and attributes using 16 x 8T cycles, the first of which starts at 14368 on the 128K and 14347 on the 48K. The screen bytes are fetched during the first 4T of each cycle (order: bitmap, attribute, bitmap+1, attribute+1), while in the last 4T the bus is idle (0xFF). After that 128T, the ULA is busy drawing the border and it does not read the video memory, so it leaves the bus idle for the remaining 228-128 = 100T (or 224-128 = 96T on the 48K). Then, the second row of pixels is started to be read at 14368+228 = 14596T (or 14347+224 = 14571T on the 48K) with the same scheme, and so on until the 192th row is finished.

The floating bus test program.

We have prepared a small test program to study the floating bus, which is available for download (see the bottom of this paragraph). It works on 48K/128K/+2 Spectrums and the specific ULA model is autodetected. Emulators must implement contended memory correctly for the program to produce reliable information.

The routines are calibrated so that the bus is sampled exactly at the T-STATE shown on the screen, i.e. the IN A,(0xFF) instruction is started exactly 10T before the target time. The IM2 T_OFS parameter takes into account the initial offset of the IM2 interrupt routine and it is automatically adjusted by the program according to the ULA type detected, so you don't need to change it. The first 8 lines of pixels are filled with bytes 0 through 255, while the attributes have values 64 through 95.
Using the keys shown at the bottom of the screen you can alter the various parameters, i.e. the sampling T-STATE, T_OFS and the input port (full 16-bit addresses accepted). Note that the sampling T-STATE is computed ignoring I/O contention delays (take this into account when you select a contended port).

We have also added a useful function to test and debug emulators: the self test routine is an automatic diagnostic procedure which tests the floating bus behaviour for the first 8 rows of pixels with absolute precision - a total of 228x8 (or 224x8) T-STATES are scanned one by one. The results are compared against the measurements from the real Spectrum (see the paragraph above for details); whenever a mismatch is detected, the program prints a warning with the expected value. If the emulator implements the floating bus correctly, at the end of the 128 burst reads performed by the test you should see "Floating bus OK" - otherwise the total error count is printed.

Click here to download the latest version of the test program (TAP).

With simple modifications, this tool is suitable to study other effects too.

2. The snow effect

Although the ULA is usually hyper-efficient to halt the Z80 even when not needed, sometimes it forgets to apply contention when it really should. Try the following program:

				LD A, 0x40
				LD I, A
You will see random dots and patterns appearing on the screen, a nice visual effect called the snow effect which has been used as a "special fx" in the game Vectron.

Technically speaking, this happens because when the I register falls in the range 0x40-0x7F then the ULA gets confused by the memory refresh cycles of the Z80 (performed during each instruction fetch), and it doesn't apply contention to take precedence as usual. Under this circumstance, the IR address put on the bus by the CPU interferes with the video memory address generated by the ULA (who wants to read the videoram to draw the screen), with the result that the RAM chip which contains the display file perceives a mixture of the two addresses. Therefore the ULA reads the data from an unexpected memory location (which still belongs to videoram), and a wrong pattern is displayed on the screen.
In detail, the address which is actually read by the ULA is the following:

		A15-A8 = A15-A8 of the ULA address
		 A7-A0 = the R register of the Z80
Remember that the attribute and bitmap bytes for a given screen cell (e.g. addresses 0x4000 and 0x5800) are stored at the same row but a different column in videoram. Since the clash alters the row address only, the ULA always reads matching attribute/bitmap couples - it simply displays the pattern in the wrong cell. This rule applies both to the 48K and 128K Spectrum models.

At the moment it's not 100% clear to us what happens inside the ULA in terms of circuitry logic and which determines the snow effect.

© 2002 RAMSOFT ZX Spectrum demogroup - web: http://www.ramsoft.bbk.org - email: ramsoft@bbk.org
This document is part of "The ULA internals" technical report, which will be published as soon as it is finished.