Arcade Space Invaders hardware redesigned
Jottings and notes... A Z80 conversion by Grant Searle
Last update: 22nd December 2012
I wanted to recreate an accurate reproduction of the
arcade version of the Space Invaders game, but using newer parts that I mainly
had in my spares drawers.
The original game used an 8080 processor but as the Z80 is virtually compatible, I wanted to use that instead because it is easier to get and only requires a single supply rail.
Although it should be able to run the original ROM code, I didn't know this for definite until the majority of the design was done (!).
The display is to remain rotated as on the arcade monitor. This doesn't cause issues with small monitors as they can easily be turned on their side.
The schematics on this page are very rough quick sketches that I did during the design and construction. I may replace them with properly drawn ones as time permits.
Areas to remain unchanged
The two areas that would remain the same were...
The only way to maintain an accurate rebuild is to use the same circuitry because it is all analogue. The only change I made was to use different ICs for the random noise generator used for the shoot and explosions. The remainder of the circuit is as shown in the original Space Invaders schematics.
2. The shifter
Originally, this could would have been supplied either as a dedicated chip or as a complete sub-circuit using available logic ICs. This could be implemented using a PLD but I chose to use the discrete logic version with small changes.
The rest of the circuit
The remainder of the original circuit was ignored after an initial understanding and totally redesigned from scratch. I referred to the original 8080 schematic as little as possible as I didn't want the existing design to influence how I redesigned the remainder of the circuit.
This was assembled on several "plug block" breadboards
joined together (as you can see at the top of the page).
This can be broken down into several logical blocks, as shown below.
The values of the ICs shown in the pictures are as follows:
All 2 or 3 digit numbers are standard "74LS" series. ie. "245" = "74LS245".
The memory map only uses the bottom 16K - first 8K for the ROM and the next 8K for the RAM (including the screen). From this, it was clear that a 2764 EPROM and a 6264 RAM would be ideal as the starter.
Only A0 to A13 are needed for addressing. A14 and A15 are therefore not connected.
0000 - 1FFF - ROM (8K)
2000 - 3FFF - RAM (8K, screen occupies 2400 - 3FFF)
The remainder of the memory map is unused, and due to
partial addressing, shadow images of the ROM and RAM appear:
4000 - 5FFF - ROM shadow
6000 - 7FFF - RAM shadow
8000 - 9FFF - ROM shadow
A000 - BFFF - RAM shadow
C000 - DFFF - ROM shadow
E000 - FFFF - RAM shadow
Port 4 - Shifter load (two loads needed to fully populate it)
Port 2 - Shifter offset (D2 to D0)
Port 3 and 5 - Sound
Port 0 to 2 - Input ports (buttons, joystick and dip switches) - not all used for Space Invaders
Port 3 - Shifter read
The circuitry can be described as shown in the following diagram. Most of the circuit is connected to the CPU data and address buses. The RAM can be isolated from the buses and switched to the display circuitry whenever a character needs to be retrieved and passed to the display shift register. During this time the CPU can be placed in a wait state if necessary to ensure the correct RAM contents are presented to the CPU when needed. The sound, input ports and the bit shifter are accessed through input/output addresses whilst the ROM and RAM are accessed by memory addressing.
The RAM needs to be shared between the CPU and the display
So, when both require the RAM at the same time some arbitration is needed.
CPU and display contention
If the CPU had priority then the display would show "snow"
effects whenever it had to allow the CPU access. This is clearly unacceptable on
an arcade display. As a result, priority for the display is a must.
The processor therefore needs to be stopped when trying to access RAM at the moment the display needs it. The Z80 processor has a /WAIT signal that can be used for this purpose.
The tricky part is to ensure the /WAIT is only pulled low for the shortest period and only when really needed to ensure the Z80 runs at the highest speed. In practice, the circuit that I design has a very low impact and the Z80 therefore runs at virtually full speed.
The Z80 CPU samples the /WAIT before it does a read so if the circuit generates the wait just before (but sufficiently soon) before it needed access to the RAM then the processor would not access it at the same time. At other "T States" (processor cycles) the /WAIT can be taken low but as the Z80 does not need the bus, it does not stop so these processor cycles continue at full speed.
When the Z80 is accessing the ROM, no waits are needed because it is reading a different chip to the RAM. During ROM execution, no processor slowdown occurs.
The other area than needed to be considered was the write signal on the RAM. If the CPU was currently executing a write operation, this signal must be disabled FIRST before changing the address to the display address otherwise the display part of the RAM would be corrupted. Then, once complete and the address bus has been returned to the CPU address, this signal is reconnected to the CPU.
The timing required is shown in Fig 1.
The master clock is divided (using the start of the counter chain connected to a 74LS138 multiplexer) into several time frames (16 for every character displayed, for which the 138 will use the first 8). These can then be used to select the start and stop of the wait, ram control, write disable and data transfer signals. The 138 is disabled if not during an active part of the display so the CPU will run at full speed for non-display areas of the screen. The complete schematic for the wait circuitry is shown on the top right of Fig 2.
With what I have designed, even if contention occurred, the CPU would only be held for a maximum one cycle every 4. However, in normal operation, it is much less as not all display accesses will contend, and non display time or ROM access have no contention.
Nothing unusual - a well published circuit with a 12MHz crystal and can be seen on the top left of Fig 2. This is used for the CPU and the display.
The counter circuits are shown in Fig 2.
The horizontal counters are clocked from the main clock. The first 4 stages are not needed for the horizontal count but these are utilised by the contention circuitry (see below).
Once the horizontal counter reaches the max value it is reset and the same signal will increment the vertical counter.
Once the vertical counter reaches the max value it is reset.
Suitable logic is added to the outputs of the horizontal and vertical counters to produce the HSYNC and VSYNC pulses needed for the monitor. These are the XORed together to make the CSYNC for a normal monitor video input.
The outputs of the counters are used as part of the address lines when accessing the display RAM.
The address lines of the ROM are connected directly to the Z80 processor as it has full access to the ROM.
The address lines for the RAM pass through a multiplexer (bottom right of Fig 1) which connects them either to the CPU address bus or to the display address (from the counters).
There are 32 bytes used for each line on the display. The horizontal address is zero at the start of the visible area (NOT the start of the display trace) so that the address for each byte displayed is correctly mapped. The horizontal address therefore is used for the lower 5 bits of the display address. The memory address used from the counters is built up as follows:
15 14 13 12 11 10 9
8 7 6 5 4 3 2 1 0
NA NA 1 V7 V6 V5 V4 V3 V2 V1 V0 H4 H3 H2 H1 H0
Where Vn are the outputs from the vertical counters and Hn are outputs from the horizontal counters.
NA = not applicable because A14 and A15 are not used in the memory map.
Similar to the horizontal, the vertical counter is zero at the start of the display area, not the top of the screen as this is also used as part of the address.
Data bus isolation
Fig 2, above, on the right hand side, shows a 245 on the data bus between the RAM and the CPU. This is to isolate the RAM from the rest of the circuit. When the display is actively reading data from the RAM, the CPU and other devices on the data bus must be isolated in case the data bus is already active (writes from the CPU or reads from the input ports).
In some of the simpler designs (such as the low cost computers from the 80s - the ZX81 and Jupiter Ace) there was no isolation, and it relied on resistors in line with the data buses to restrict high currents if the display was using the bus at the same time. This is not really good design as the buses should be low impedance to ensure fast response. Instead, I properly isolated the bus when needed so that there was no contention. This is shown below.
These occur at the start AND end of the vertical blank period, so both edges of this signal needed to be captured separately (because edge triggered logic only handles one edge) to allow the interrupts to occur. The /INT signal is pulled low and will return to high state once an "Interrupt acknowledge " is received from the CPU. This acknowledge is identified by /M1 and /IORQ going low.
The interrupt circuitry is shown in Fig 4 below.
The interrupt acknowledge is to place an instruction on the bus during the acknowledge phase. This is either "RST 8" or "RST 10". This is achieved with the circuit (Fig 5) shown below.
I/O address selector
One 74LS138 is used for the input port selector and one 74LS138 is used for the output port selector, as shown in Fig 6. The relevant outputs are then used to enable the required I/O ports.
Memory read/write logic
Derived from the CPU signals ( /WR, /MREQ and /RD ). The RAM write enable also has the write override (from the contention circuitry described earlier) to prevent accidental writes. This is shown in Fig 7. The ROM enables are shown in Fig 8.
The sound circuit is IDENTICAL to the original as I wanted authentic analogue sounds. The only change is that the sound circuitry runs on the 5V supply (satisfactorily) and also the noise generator was modified to the circuit shown below (as I couldn't obtain a 4006 IC). The clocking for this generator is taken from the vertical counter chain, as shown.
Video - sync signals
These are obtained from the display address timing chain shown in Fig. 2. Horizontal and vertical syncs are generated, then merged to produce the composite sync.
Video - monitor output
A simple resistive mixer is used to combine the /CSYNC with the VIDEO signals. This can then be fed into a standard 75 ohm input on a monitor.
The bit shifter
This takes up quite a large area of the board (12 ICs) and
is very similar to the original.
This consists of a 2-byte queue, where each write to it (port 4) moves the previous byte along to the "N-1" latch and stores the new byte in the "N" latch.
A write to port 2 determines how far along the 16-bit concatenation of the latest and previous bytes will be read.
The resulting 8-bit window of this 16 bit value is read from port 3.
A functional schematic of this is shown below. Other pins used on the ICs need to be connected appropriately.
The bytes are stored in 74LS364 latches, where each write will move the currently stored value in the left hand latches to the ones to the right of it. The data on the bus is simultaneously stored in the left hand latch.
The 74LS175 latch holds the shift offset (0 to 7) and is set by writing to port 2.
The offset address is passed to the eight 74LS151's to determine which of the 16 bits stored (actually, previous D0 is never reachable and is not used, but shown dotted for completeness) is to be chosen.
This value is then placed on the data bus (via the 74LS245) when port 3 is read.
...MORE TO COME...