INTRODUCTION

The ZX80 was not designed to produce a steady display whilst running a BASIC program, but only when the computer was waiting for user input. In this state, a carefully timed routine within the ROM loops continuously to generate the TV display at precisely the right time. On each iteration it checks the state of the keyboard and if no keys are being pressed then it outputs the visible lines forming one scan of the TV picture, known as a TV frame. The keyboard scanning routine is tuned such that it occupies the remaining time within the TV frame, and hence an iteration of the loop always takes the time period of a full TV frame. In the UK PAL television system there are 50 TV frames per second and so a single frame spans 20ms. In the USA NTSC PAL television system there are 60 frames per second and so a single frame spans 16.67ms.

It is not possible for a standard BASIC program to run and produce a steady TV picture (also known as a flicker-free display), but companies soon produced machine code programs that were structured to divide their time between running the program functionality and generating the TV display. The first (source: Personal Computer World magazine, Vol. 4 No. 7, September 1981, page 113) was from the partnership of Ken Macdonald and Ron Bissell (later to be known as Macronics) who released their Amazing Active Display, which was a machine code pause routine. At a similar time, Dr. Ian Logan created an alternate method. Both were reported in Interface magazine, Vol. 1 Issue 4, December 1980, page 3.

The Amazing Active Display technique was attributed to Ken Macdonald in Sinclair User magazine No. 1 (April 1982, 'Software Overview', page 51), but in an interview with Ken Macdonald in Home Computing Weekly magazine (6th December 1983, page 72) he reveals that it was his Macronics partner Ron Bissell that developed the technique. This is also revealed in an interview with Ron Bissell that appeared in Your Computer magazine (Vol. 2 No. 6, June 1982, page 36). A description of the Amazing Active Display was included in an advert published in Sync magazine (Vol. 1 No. 1, January/February 1981, page 19), and is reproduced below:


A review of the Amazing Active Display appeared in Sync magazine (Vol. 1 No. 2, March/April 1981, page 44) and states that "in the program, a machine language program, stored as hexadecimal code, is converted into decimal numbers and POKEd into the computer's memory". From this description, it would appear that the program was structured in a similar manner to Macronics' 3K Space Intruders game. The review states the cost of the Amazing Active Display as £10.

In the interview with Ron Bissel, he refers to the alternate flicker-free method devised by Dr. Ian Logan and states that it occupied more RAM since it worked by replicating whole sections of the ROM's display routine. Ian Logan's method was published in Sync magazine (Vol. 1 No. 3, May/June 1981, page 12) under the title of Auto-Display-Changing. The article mentions that the mechanism was described in more detail in the book The ZX80 Companion published by Linsac, which Ian Logan co-authored with Bob Maunder and Terry Trotter.

The Macronics team can be seen in the photo below:


To produce a continuous display, a program must be divided into one or more blocks of functionality where each block takes the same length of time to run and exactly occupies the remaining time within a TV frame. The program loops through these blocks of functionality executing one block per TV frame, and so it is only after several TV frames that a complete cycle of the program has been completed. For real-time animation applications, it is the number of TV frames spanned by each program cycle that determines the smoothness and responsiveness of the animation. For reasonable animation, at least 5 program cycles per second are required.

Several software companies would exploit this technique to produce flicker-free games for the ZX80. Hover over the buttons below to see a selection of adverts (source: Your Computer magazine, Vol. 1 No. 1, June/July 1981):


The advert from JRS Software is interesting since it describes a package to allow users to create their own flicker-free programs using a sequence of numeric codes.


TV PICTURE STRUCTURE

In a 50Hz TV broadcast signal, there are 25 TV frames per second. In a 60Hz TV broadcast signal, there are 30 TV frames per second. Each frame is composed of two fields. The first field contains the information for all the even lines making up the picture, and is followed by the another field that contains the information for all the odd lines. The fields are displayed so rapidly that the human eye only sees whole TV frames. This mechanism generates an interlaced TV picture.

In a broadcast TV picture, each frame consists of 625 scan lines (50Hz picture) / 575 scan lines (60Hz picture). This is divided into odd and even fields of 312.5 scan lines (50Hz picture) / 262.5 scan lines (60Hz picture). The half scan line allows an interlaced picture to be easily produced. Of these only 287.5 (50Hz) / 241.5 (60Hz) are visible and hence the equivalent of 25 scan lines do not contain picture information. The first 7.5 scan lines is used for the vertical synchronisation (including equalisation pulses), which instructs the TV set to commence the display of a new TV field. Some of the remaining 17.5 scan lines are used to provide data services such as teletext. For a 50Hz picture, each scan line spans 64µs. Whereas for a 60Hz picture, each scan line spans 63.55µs.

In the ZX80, things are a lot simpler as only even fields are produced. This results in a non-interlaced TV picture, with each frame consisting of half the number of scan lines as a broadcast TV picture. This means that the ZX80 produces a full TV picture after only 20ms (50Hz picture) / 33.33ms (60Hz picture).

The ZX80 deviates slightly from the ideal TV signal timings. For a 50Hz picture, it only outputs 310 scan lines instead of the ideal of 312.5 scan lines. For a 60Hz picture, it output 262 scan lines which is close to the ideal of 262.5 scan lines. Each scan line has a duration of 63.69µs, which is shorter than the ideal for a 50Hz picture, but longer than the ideal for a 60Hz picture. The scan lines are divided into different areas as follows:


TV Scan Line Display Areas

The 310 scan lines of a 50Hz picture is divided into 6 for the vertical synchronisation pulse, 56 for the top border, 192 for the main display area, and 56 for the bottom border. For a 60Hz picture, the top and bottom borders are each simply reduced to 32 scan lines. Out of the 112 (50Hz) / 64 (60Hz) border lines, 17 will not be visible on screen.

To support flicker-free programs, a time slot must be created per TV field where the ZX80 can run a section of the program. A natural time slot exists in the form of the vertical sync duration. However, this is only about 400µs long and so limits the complexity of program functionality that can be performed. An alternate solution is to make the ZX80 generate only the minimum number of top and bottom border scan lines needed to achieve a full visible TV picture. The 17 non-visible border lines, along with the 6 used for the VSync pulse, are then available for the ZX80 to run a block of the program. This equates to a duration of 1.592ms. The instructions executed within each block of program functionality must be crafted such that each always takes exactly the same number of T-states to execute.

Macronics' Breakout simply uses the existing vertical sync duration for its game functionality, whereas their 3K Space Intruders also employs the duration of the non-visible border lines for running the game functionality.

The ZX80 circuitry is driven by a ceramic resonator rated at 6.5MHz. This frequency is halved down to 3.25MHz and used to drive the Z80 CPU. Each iteration of display loop within the ROM takes 64167 T-states (50Hz picture) and 54231 T-states (60Hz picture), and this corresponds to a frame duration of 19.74ms (50Hz picture) and 16.67ms (60Hz picture). This is close enough to the 20ms (50Hz) / 16.68ms (60Hz) for TVs to accept and display the picture.


FLICKER-FREE DISPLAY ROUTINE

A block of program functionality will almost certainly contain a variety of conditional branches and it is essential to ensure that no matter which path is taken through this logic the number of T-states executed always totals 4761 T-states (i.e. the duration of 23 scan lines). Within this time, it is also necessary to start and stop the vertical sync pulse.

To ensure that each path of execution takes the same length of time, it is necessary to pad branches with instructions that do not alter the intended behaviour of the subroutine but instead simply introduce fixed delays. This is depicted in the following diagram:


Conditional Branch Balancing

Creating such blocks of program functionality involves a fair degree of trial and error, continually tweaking until the timing of all branches of execution balance. The best way to achieve this is by careful division of a block of program functionality into subroutines. Each subroutine is crafted to take a fixed length of time to execute, and is likely itself to be structured to use other such fixed duration subroutines. It becomes easy to create small subroutines that execute in a fixed duration, and then to use these as building blocks to create the next level of subroutines, which in turn are used in the level above them, etc. The process of layering subroutines means that each level contains a manageable number of conditional branches to balance. It also allows common subroutines to be re-used between layers, and even between blocks of program functionality.

A flicker-free program should contain a main loop, which is structured as follows:

MAIN_LOOP:
        {determine which block of program functionality to run in this TV frame cycle}

        {execute the selected block of program functionality}

        CALL GEN_TV_FRAME               ; 17+n      Output the visible TV frame scan lines.

        JP   MAIN_LOOP                  ; 10

The start of the loop assumes that the vertical sync generator circuitry within the ZX80 is turned on. Whilst the vertical sync pulse is being generated, a block of program functionality can be executed for approximately 1.5ms. A call to the GEN_TV_FRAME subroutine is then made. This subroutine turns off the vertical sync generator, outputs the visible scan lines and then switches the vertical sync generator back on. The GEN_TV_FRAME routine can be implemented as follows:

GEN_TV_FRAME:
        OUT  ($FF),A                    ; 11        Turn off the vertical sync generator.

; Generate the top border and main display area.


        LD   A,$EB                      ; 7         Timing counter for the duration of the first
                                        ;           scan line of the top border. Thereafter set
                                        ;           to $DD by the ROM.
        LD   BC,$1900                   ; 10        There are 25 HALTs within the display file,
                                        ;           i.e. 24 rows and 1 top border. C is set only
                                        ;           to achieve perfect timing.
        LD   HL,DFILE+$8000             ; 10        Point to the start of the display file, i.e.
                                        ;           the initial HALT representing the top border,
                                        ;           but with bit 15 of the address set.
        LD   C,$30			; 7         There are 48 scan lines (50Hz) above the ZX80
                                        ;           main display area (use 24 for 60Hz models).
        CALL $01B0                      ; 17+n      Produce the top border and main area.

; Generate the bottom border.

        LD   A,$EC                      ; 7         Timing counter for the duration of the first
                                        ;           scan line of the bottom border. Thereafter
                                        ;           set to $DD by the ROM.
        INC  B                          ; 4         Increment the row count, i.e. B holds $01.
        DEC  HL                         ; 6         Decrement the screen address, i.e. point to
                                        ;           the last HALT.
        LD   C,$2F			; 7         There are 47 scan lines (50Hz) above the ZX80
                                        ;           main display area (use 23 for 60Hz models).
        CALL $01B0                      ; 17+n      Produce the bottom border.

; Start the vertical sync pulse.

        IN   A,($FE)                    ; 11        Turn on the vertical sync generator. It be
                                        ;           will be turned off approximately 23 scan
        RET                             ; 10        lines from now.

Using a subroutine in this way adds an overhead of the RET and IN instruction, and the CALL to run the subroutine. This reduces the 4761 T-states available for program functionality per TV field down to 4723 T-states. Taking the JP instruction in the main loop into account reduces the time further to 4713 T-states. Note that the subroutine could be restructured with the IY register pair set such that IY+$23 points to a location holding the number of border scan lines and then the ROM called at $01AD.

An OUT instruction is used to switch the vertical sync generator off. Typically port $FF is used, but the actual port number is not decoded on the ZX80 and so an OUT to any port number will switch off the vertical sync generator. The display routine within the ROM uses the C register to specify the number of border scan lines to produce. It should be set based on the model of ZX80 detected, i.e. 50Hz or 60Hz. This only needs to be done once at the start of a program and can be done as follows:

        IN   A,($FE)                    ; 11        Read the input port.
        RLA                             ; 4
        RLA                             ; 4         Test bit 6 (the region indicator).
        SBC  A,A                        ; 4         $FF (50Hz) or $00 (60Hz).
        AND  $18                        ; 7         $18 (50Hz) or $00 (60Hz).
        ADD  A,$17                      ; 7         $2F (50Hz) or $17 (60Hz), i.e. 47 (50Hz) or 23 (60Hz).
        LD   (IY+$23),A                 ; 19        Store the bottom border count.

Note that the above will determine the minimum number of border scan lines required to produce a full visible picture.

The vertical sync generator is switched on by an IN instruction from a port with address line A0 low. Typically port $FE is used since this port also reads the keyboard. A program can therefore make use of this fact to perform two tasks in one action, and this is exactly what the ROM display routine does.

A program can incorporate multiple display loop routines and switch between them as and when required. For example, a game could have a display loop it uses during game play and another display loop it uses during the title screen. Ideally, accurate TV field timing would be maintained when switching between different display loops but if not then a momentary flicker would be seen as the transition occurs. Deliberately omitting generation of TV fields could be exploited within programs to rapidly achieve a pure black screen.


8K BASIC ROM SUPPORT

The release of the 8K BASIC ROM upgrade gave the ZX80 the same functionality as the ZX81 but with the exception of its SLOW display mode. Companies realised that the approach used to create flicker-free programs on 4K ROM ZX80 could also be applied to machines fitted with the new 8K ROM. Further, they found that only minimal changes were required to the video generation routine and so the rest of the program's machine code could be identical. A program could be written for one ROM and then quickly ported to the other. In addition, a program written to run on the ZX80 with the 8K ROM would also run without modification on the ZX81. The ZX81 would actually be run in FAST mode, by-passing the new steady display mechanism.

In order not to invoke the ZX81's horizontal sync generator, the OUT instruction used to switch off the vertical sync pulse cannot be $FE.

The video routine changes required to support the 8K ROM amounted to replacing the call to $01B0 with a call to $02B5. The call to $02B5 in the 8K ROM assumes the C register to be loaded with the number of scan lines, and it's equivalent in the 4K ROM is a call to $01B0.

LD   C,nn      ; The lines in the border.
CALL $01B0     ; Produce the bottom border.
LD   C,nn      ; The lines in the border.
CALL $02B5     ; Produce the bottom border.
4K ROM Version 8K ROM Version

In the adverts above, it can be seen that many of the flicker-free games were released for both 4K ROM and 8K ROM machines.