
OK, people, you got me...:)
PLEASE< notice that this file is based on the old 1.6 FAQ and
therefore it has many errors. It is also incomplete, for example
I completely lost track of AtariST emulator and xzx. I also have no
info on Macintosh emulator. Anyway, send you comments to fms@wam.umd.edu

Marat Fayzullin



                                comp.sys.sinclair
                            Sinclair ZX Spectrum FAQ
                               v.2.0 (July 3 1994)

                       Maintained by Marat Fayzullin [FMS]
                            email:  fms@wam.umd.edu
                                  IRC: RST38h



  Updates: Minor corrections resulted from bugging me by netters.
           Also, info on emulator for Mac. This FAQ is done based on
           the ancient version 1.6 because I have lost the later
           version. PLEASE, check it out carefully and send me all
           corrections/additions.
           You can always get this FAQ and other my stuff from

               http://www.cs.umd.edu/users/fms/

           which also contains links to ZX Spectrum related sites around
           the Net. Hope you will like it. People, I would greatly
           appreciate if somebody created a decent ZX Spectrum WWW homepage.
           The current one wasn't updated for months. Volunteers can
           mail their art [html documents, texts, pictures] to
           fms@wam.umd.edu. Pack them, email them and I will try to put
           them onto WWW.

Some things currently needed:

1. Info on Macintosh emulator and the last version number are badly
   needed.
2. Info on v.2.0 of AtariST emulator is needed. I had it but it got lost
   with the last FAQ :( Please, desribe it again.

3. Table of Z80 command set [I had it somewhere in an ASCII-file but lost it]
   Please, do not send plain command lists, I need a table.
4. IBMPC-based emulator which allows loading files using home-brewn ADT/DAT
   connected to the parallel port.
5. Any information about v.2.0 of Atari-based ZXSPECTRUM emulator. This version
   is said to run on TTs and Falcons and load/save .SNA files. If you have
   it and it is not commercial, please, upload it to ftp.nvg.unit.no which
   currently has version 1.2.

  Send your additions and corections to fms@wam.umd.edu. Sorry, if I made any
errors.


********************************** CONTENTS ****************************

I.   EMULATORS           - comparison of existing ZX-Spectrum emulators
II.  NET ADDRESSES       - ZX-Spectrum-related Net addresses
III. VARIOUS QUESTIONS   - no comments :)
IV.  SNAPSHOT FORMATS    - descriptions of snapshot formats
     1. KGB format
     2. .SNA format
V.   GENERAL INFORMATION - info on ZX-Spectrum's hardware
     1. Z80 CPU          - undocumented opcodes and weird features
        a) CBh opcodes
        b) FDh and DDh opcodes
        c) EDh opcodes
        d) R register
        e) Undocumented flags
        f) IFF1 and IFF2
     2. ULA and I/O ports
     3. Interface I
        a) Port E7h
        b) Port EFh
VI.  PINOUTS
     1. ULA
     2. AY-3-8912
     3. Keyboard layout
VII. ACKNOWLEDGEMENTS

******************************* EMULATORS ******************************
  Strong points of emulators are labeled with asterisk [*].

1. Spectrum 1.7 [Amiga]   Author: Peter McGavin [peterm@kea.grace.cri.nz]

*  a) Multitasks.
   b) Loads/saves snapshots in Mirage Microdrive .SNA format compatible
      with JPP.
*  c) Loads/saves Spectrum files from/to tapes [through a sound-digitizer]
      or Amiga disks [in this case, each block is written into a separate
   d) Is reasonably fast on 68030/25MHz, but slow on 68000/7.14MHz machines.
      At least 68020/14MHz [A1200] and FAST RAM are recommended.
   e) Color palette is a bit strange.
   f) Some programs don't work.
   h) Emulates Cursor Joystick with cursor keys on keyboard and Kempston
      Joystick with joystick connected to Port 2 of Amiga.

2. KGB 1.3 [Amiga]

   a) Loads/saves snapshots in the format described below.
   b) Doesn't multitask.
   c) Loads/Saves Spectrum files from/to tapes [through a sound-digitizer].
   d) Isn't completely compatible with ZX-Spectrum
   e) Emulates Cursor Joystick with cursor keys, and Kempston Joystick
      with a joystick connected to Port 2 of Amiga.
*  f) Has a pitch-compensated mode, that transposes the sound two octaves
      up (handy on slow Amigas)
*  g) Operates in a monocrome mode as well as in color.

3. JPP [IBM PC]   Author: Arnt Gulbrandsen [agulbra@nvg.unit.no]

   a) Loads/saves snapshots in Mirage Microdrive .SNA format compatible
      with Spectrum 1.7.
   b) Loads/saves Spectrum files from/to tapes digitized into .VOC files.
   c) 386/25MHz or faster is needed for the best perfomance. 486/25MHz
      or 386/44MHz is needed for good sound emulation.
   d) Emulates Cursor Joystick with arrow keys and [Alt] key. Emulates
      Kempston Joystick with IBM PC joystick.
   e) Some games don't run.
   f) Screws up system screen mode on quit. Restore with MODE 80
      command.
*  g) Includes special program to convert snapshots between various
      formats such as .SNA,.PRG,.Z80,.SP and RAW.
   h) Needs ROM image file (included).
   i) Includes program reading and converting snapshots from MGT disks.

4. SPECEM [IBM PC] (a.k.a. irish emulator)

*  a) Works reasonably fast on 286 and a bit faster than necessary on
      386/486 systems. 386/40MHz or 486/25MHz is needed for good sound
      emulation.
   b) Allows to select between VGA and EGA modes.
   c) Loads/saves snapshots in .PRG format.
   d) Runs most games.
   e) Includes program loading snapshots from MGT/Datel Plus-D disks.
   f) Loads/saves Spectrum files to/from disk.
   g) Both Cursor and Kempston Joysticks are emulated by cursor keys.
      Kempston [FIRE] button is emulated with [ALT].

5. SP [IBM PC] (a.k.a. polish emulator)

   a) Doesn't load/save snapshots.
   b) Works in either CGA or EGA mode.
   c) Stores files in so-called .SPC or .ZX format. Each such file is an
      exact image of corresponding tape, with blocks written into the file
      one after another. Thus, .ZX file may contain several games. Program
      splitting .ZX files into separate blocks which can be later loaded
      into Spectrum 1.7 emulator and saved as .SNA files is available from
      fms@wam.umd.edu.
   d) Needs ROM image file called ROM.SPC (not included, use one from JPP
      package).

6. Z80 2.01 [IBM PC]   Author: Gerton Lunter [gerton@rcondw.rug.nl]

*  a) Emulates both Spectrum 48k and Spectrum 128k.
   b) Is fast on 286 and *very* fast on 386/486.
   c) Shareware. Some options are disabled in PD version.
   d) Has lots of options including monochrome option.
   e) Has small built-in debugger.

7. Speculator [Acorn Archimedes]    Author: Dave Lawrence

   a) Is not officially available at the moment - any copies circulating
      are pirate copies. As a result, documentation of the file format
      is not complete, and the conversion programs supplied with it do
      not work correctly.
   b) Is extremely fast on an ARM3 machine. To get normal Spectrum speed
      an ARM2 machine or an ARM3 machine with the cache turned off is
      required.
   c) Can save and load in its own file format.
   d) It is possible to return to the desktop from the emulator, and then
      re-enter the emulator at the point you left off.

8. Elwro 800-3 Jr v1.0 [IBM PC]   Authors: Piotr Schmidt & Piotr Wolter

   a) has not a 100% compatibility with ZX Spectrum (the real Elwro
      had problems with JetPac while other games were ok)
   b) capability of running CP/M system
   c) runs either in CGA,Hercules or EGA mode
   d) emulates 2 disk drives, accessed via * commands (e.g. SAVE * "file")
      with capacity of about 700kB. These are physically files.
   e) allows ROM changes (simply type a new file name)
   f) could change interrupt freq (45,50,65,70 Hz)
   g)on Joystick
   h) all system messages were in polish (good and bad at the same time)
   i) not the tape support
   j) had a utility to read the real Elwro Junior disks on PC
   k) released commercial only

9. ZX-SPECTRUM Emulator v1.2 [Atari]   Author: Christian Gandler

*  a) Works with ST (>=1MB), TT and Falcon030 in ST-low and ST-high.
   b) Doesn't load/save snapshots.
   c) Performance is ~70% of original Spectrum on plain STs.
   d) Emulates Kempston and Interface 2 Joysticks.
*  e) Emulates Interface 1 (Microdrives and RS232).
   f) Only keyboard ports read are those mentioned in the orange manual.

10. !Speccy [Acorn Archimedes]   Author: Karsten Witt

*  a) Runs at normal Spectrum speed on an ARM2 machine and very fast on an
      ARM3 machine. The speed is adjustable.
   b) Saves/loads Spectrum files to/from disk in its own file format.
   c) At the moment does not load/save in any snapshot formats. Apparently,
      the author is currently working on making it run in the desktop
      (multi-tasking) and allow loading of .SNA files.
   d) Comes with application and instructions for transferring files to/from
      tapes through the serial port.
   e) Doesn't fully implement the R register - however this doesn't affect most
      programs.
   f) Has an enhanced keyboard layout - there are keyboard short cuts to Caps
      Lock, Extended Mode, and also the cursor keys, the keypad, and other
      symbols (commas, colons etc.) can be entered easily.

11. xzx v0.5 [Unix+X]   Author: Des Herriott [dnh@mfltd.co.uk]

   a) Emulates a 48K Sinclair Spectrum.
*  b) Needs approx 486/33 to run at the correct speed (this is from
      general impressions, not exact timings). Sparc 10 or DEC Alpha
      will run it very fast.
   c) Makes heavy use of the MIT-SHM X11 extension, and works a good
      deal slower without it.
   d) No sound, tape or printer emulation, yet.
   e) Reads and writes .SNA format and reads .Z80 format snapshots.
   f) Emulates Kempston joystick with preset keys.

12. !MZX v1.0 [Acorn Archimedes]   Author: Graham Willmott

*  a) Multitasks. (can also single task if required)
   b) Loads/saves snapshots in .SNA format.
   c) Doesn't emulate R register correctly, or certain undocumented
      instructions.
   d) Runs at ~60% normal spectrum speed on an ARM2 machine, and
      considerably faster on other machines - currently there is
      no speed control available.

13. SPECTRUM v0.99c [IBM PC]   Author: Pedro Gimeno

*  a) Loads from tapes through a wire connected to the parallel port.
   b) Uses .SP format for snapshots.
   c) R register and I/O [other than tape] are not emulated.
   d) Matches real Spectrum speed at 386/25MHz.
   e) VGASPEC emulator is an *illegal* prerelease of this emulator.

14. MacSpeccy 1.0 [Macintosh]   Author: Danny Keogan [djkeogan@unix2.tcd.ie]

   *** No info on this emulator. PLEASE, send me the information
       about it!


*************************** NET ADDRESSES ******************************

FTP      ftp.inf.tu-dresden.de   /pub/incoming/zxspectrum
FTP      ftp.nvg.unit.no         /pub/spectrum
FTP      wuarchive.wustl.edu     /systems/sinclair
FTP      oak.oakland.edu         /pub/msdos/emulators
FTP      ftp.sun.ac.za           /pub/msdos/zx
FTP      ftp.ijs.si              /pub/zx
GOPHER   gopher.nvg.unit.no
WWW      www.nvg.unit.no         http://www.nvg.unit.no/Sinclair/Spectrum
WWW      www.cs.umd.edu          http://www.cs.umd.edu/users/fms/

**************************** VARIOUS QUESTIONS *************************

1. Is it legal to use ZX-Spectrum ROM images?
   Yes, it is. Amstrad, owning copyright for ZX-Spectrum ROM, recently
   announced that ROM image can be freely distributed with emulators,
   although it can not be changed.

2. Is it legal to use memory snapshots?
   Formally, using snapshotted game without legal owning a copy of it
   on a tape is a *copyright violation*. Nevertheless, ZX-Spectrum games
   are not being sold anymore and using snapshots doesn't harm copyright
   holders much, if you don't make profit from it and don't distribute
   snapshots on a large scale. It seems that some companies [Ultimate/
   USGold] have nothing against free distribution of their games, but
   there is no written permission yet.

3. Is there a ZX-Spectrum emulator for X-Windows?
   YES, THERE IS. xzx by Des Herriott alows to run 48k Spectrum programs
   on a Unix machine with X-Windows. MIT SHM extension is highly
   recommended. The current version of xzx is 0.5 and can be obtained
   from ftp.nvg.unit.no.

4. How to convert snapshots between various formats?
   Most snapshots can be converted into one another using SPCONV program
   by Henk de Groot [groot@idca.tds.philips.nl]. MSDOS version of this
   program is supplied with JPP emulator [source included]. More portable
   version is available from FTP archive at ftp.nvg.unit.no. SPCONV
   converts files between following formats: .SNA,.Z80,.PRG,.SP and RAW.
   Also, registered version of Z80 contains a converter.

5. How to convert .ZX [or .SPC] files used with "polish" emulator into
   snapshots?
   Program called Butcher is available at ftp.nvg.unit.no. This program
   splits .ZX file into series of .header/.bytes files which can be
   loaded by Spectrum 1.7 emulator on Amiga. Program is written by Marat
   Fayzullin [fms@wam.umd.edu] and includes a binary for AmigaOS and a
   source code in C which will allow you to write your converter.

6. Where to get Microdrive cartridges?
   Microdrive cartridges [as well as complete Microdrive kits] can be
   obtained from

   W.N. Richardson & Co.
   18-21 Chiltern House
   Chiltern Hill
   Chalfont St Peter,
   Bucks, SL9 9UE

   PHONE: 0753-888866   FAX: 0753-887149

7. Address of "Spectrum Profi Club" in Germany:

   SPC
   c/o Haller
   Ernastr. 33

   D-51069 K"oln
   Germany

8. Fixing worn out ZX-Spectrum keyboard:
   If the connectors on the PCB have scratched off the silver from the
   ribbon, buy some so-called "conductive paint" which is a suspension
   of fine silver particles. If you let it dry, it conducts. Use a fine
   brush to replace what is scratched off from the ribbons. This paint
   is available from most electronics hobbyist stores [for example, from
   RadioShack in US].

9. What is the difference between several ROM-files included with JPP
   emulator?
   SPECTRUM.ROM - Spectrum ROM, exactly the same as in the original
                  Spectrum.
   GROOT.ROM    - Same ROM, but with lots of bug fixes and extensions
                  by Henk de Groot [groot@idca.tds.philips.nl]. List of
                  changes follows:
                  o Bug fixes as mentioned in "The complete Spectrum Rom
                    Disassembly" by Dr Ian Logan and Dr Frank O'Hara.
                  o Support for EPSON printer via an Z80-PIO chip and
                    Centronics connection.
                  o Monitor support: start up with black screen and white
                    characters.
                  o Lightpen support: Lightpen routine for DK'Tronics
                    lightpen is built in.
   TK95.ROM     - ROM from a Brazilian Spectrum clone called Micro
                  Digital TK95.

10. I'm trying to convert .Z80 file into .SNA format using SPCONV and
    it doesn't work. Why?
    You are probably using SPCONV v1.05 which came with JPP distribution.
    It has problems converting .Z80 files created by Z80 v2.01. Get
    SPCONV v1.06 off ftp.nvg.unit.no. It works.

11. How to request a game which is not on ftp.ijs.si?
    o Suppose you want the game 'xyquz'.
    o Check that the game in not available already.
    o Create an EMPTY file with name 'xyquz'. For example,
      on Unix this would be done with 'touch xyquz'.
    o Connect to ftp.ijs.si (this is the tricky part :-)
    o Drop your file in /incoming/zx/WISH, like this:
      ftp> cd /incoming/zx/WISH
      ftp> put xyquz
      ftp> quit <---- give others a chance
    o Delete you empty file (unless you are a messy person).

**************************** SNAPSHOT FORMATS **************************

1. KGB v.1.2-1.3 [Contributed by Troels Norgaard]
   Notice, that in 680x0 the most significant byte goes first.

Offset   Size   Description
------------------------------------------------------------------------
0        49284  RAM dump 16252..65535
49284    132    unused, make 0
49416    10     dc.w  10,10,4,1,1 (different settings)
49426    1      dc.b  InterruptStatus (0=DI/1=EI)
49427    2      dc.b  0,3
49429    1      dc.b  ColorMode (0=BW/1=Color)
49430    4      dc.l  0
49434    16     dc.w  BC,BC',DE,DE',HL,HL',IX,IY
49450    2      dc.b  I,R
49452    2      dc.w  0
49454    8      dc.b  0,A',0,A,0,F',0,F
49462    8      dc.w  0,PC,0,SP
49470    2      dc.w  SoundMode (0=Simple/1=Pitch/2=RomOnly)
49472    2      dc.w  HaltMode  (0=NoHalt/1=Halt)
49474    2      dc.w  IntMode   (-1=IM0/0=IM1/1=IM2)
49476    10     unused, make 0
------------------------------------------------------------------------
Total: 49486 bytes

2. Mirage Microdrive .SNA format used by Spectrum 1.7 and JPP
   Notice, that in Intel CPUs the least significant byte goes first.
   When the registers have been loaded, a RETN command is required to
   start the program. IFF2 is short for interrupt flip-flop 2, and for
   all practical purposes is the interrupt-enabled flag. Set means
   enabled.

Offset   Size   Description
------------------------------------------------------------------------
0        1      db    I
1        8      dw    HL',DE',BC',AF'
9        10     dw    HL,DE,BC,IY,IX
19       1      db    Interrupt (bit 2 contains IFF2, 1=EI/0=DI)
20       1      db    R
21       4      dw    AF,SP
25       1      db    IntMode (0=IM0/1=IM1/2=IM2)
26       1      db    BorderColor (0..7, not used by Spectrum 1.7)
27       49152  RAM dump 16384..65535
------------------------------------------------------------------------
Total: 49179 bytes


****************** GENERAL INFORMATION ABOUT ZX-SPECTRUM ***************

This section is based on the text contributed by Gerton Lunter, author
of "Z80" Spectrum emulator. I allowed myself to make some changes which
don't change the content.

1. Z80 CPU:

   Most Z80 opcodes are one byte long, not counting a possible byte or
word operand.  The four opcodes CB, DD, ED and FD are shift opcodes: they
change the meaning of the opcode following them.

a) CB opcodes:
   There are 248 different CB opcodes. The block CB 30 to CB 37 is missing
from the official list. These instructions, usually denoted by the mnemonic
SLL, Shift Left Logical, shift left the operand and make bit 0 always one.
These instructions are quite commonly used. For example, Bounder and Enduro
Racer use them.

b) DD and FD opcodes:
   The DD and FD opcodes precede instructions using the IX and IY registers.
If you look at the instructions carefully, you see how they work:

        2A nn           LD HL,(nn)
        DD 2A nn        LD IX,(nn)
        7E              LD A,(HL)
        DD 7E d         LD A,(IX+d)

A DD opcode simply changes the meaning of HL in the next instruction. If a
memory byte is addressed indirectly via HL, as in the second example, a
displacement byte is added. Otherwise the instruction simply acts on IX
instead of HL (A notational awkwardness, that will only bother assembler
and disassembler writers: JP (HL) is not indirect; it should have been
denoted by JP HL). If a DD opcode precedes an instruction that doesn't use
the HL register pair at all, the instruction is executed as usual. However,
if the instruction uses the H or L register, it will now use the high or
low halves of the IX register! Example:

        44              LD B,H
        FD 44           LD B,IYh

These types of inofficial instructions are used in very many programs. By the
way, many DD or FD opcodes after each other will effectively be NOPs, doing
nothing except repeatedly setting the flag "treat HL as IX" (or IY) and taking
up 4 T states (But try to let MONS disassemble such a block.).

c) ED opcodes:
   There are a number of inofficial ED instructions, but none of them are very
useful. The ED opcodes in the range 00-3F and 80-FF (except for the block
instructions of course) do nothing at all but taking up 8 T states and
incrementing the R register by 2.  Most of the unlisted opcodes in the range
40-7F do have an effect, however. The complete list: (* = not official)

        ED40   IN B,(C)                 ED60   IN H,(C)
        ED41   OUT (C),B                ED61   OUT (C),H
        ED42   SBC HL,BC                ED62   SBC HL,HL
        ED43   LD (nn),BC               ED63 * LD (nn),HL
        ED44   NEG                      ED64 * NEG
        ED45   RETN                     ED65 * RET
        ED46   IM 0                     ED66 * IM 0
        ED47   LD I,A                   ED67   RRD
        ED48   IN C,(C)                 ED68   IN L,(C)
        ED49   OUT (C),C                ED69   OUT (C),L
        ED4A   ADC HL,BC                ED6A   ADC HL,HL
        ED4B   LD BC,(nn)               ED6B * LD HL,(nn)
        ED4C * NEG                      ED6C * NEG
        ED4D   RETI                     ED6D * RET
        ED4E * IM 0/1                   ED6E * IM 0/1
        ED4F   LD R,A                   ED6F   RLD
        ED50   IN D,(C)                 ED70 * IN (C)
        ED51   OUT (C),D                ED71 * OUT (C),0
        ED52   SBC HL,DE                ED72   SBC HL,SP
        ED53   LD (nn),DE               ED73   LD (nn),SP
        ED54 * NEG                      ED74 * NEG
        ED55 * RET                      ED75 * RET
        ED56   IM 1                     ED76 * IM 1
        ED57   LD A,I                   ED77 * NOP
        ED58   IN E,(C)                 ED78   IN A,(C)
        ED59   OUT (C),E                ED79   OUT (C),A
        ED5A   ADC HL,DE                ED7A   ADC HL,SP
        ED5B   LD DE,(nn)               ED7B   LD SP,(nn)
        ED5C * NEG                      ED7C * NEG
        ED5D * RET                      ED7D * RET
        ED5E   IM 2                     ED7E * IM 2
        ED5F   LD A,R                   ED7F * NOP

The ED70 instruction reads from port (C), just like the other instructions,
but throws away the result. It does change the flags in the same way as the
other IN instructions, however. The ED71 instruction OUTs a byte zero to port
(C), interestingly.  These instructions "should", by regularity of the
instruction set, use (HL) as operand, but since from the processor's point of
view accessing memory or accessing I/O devices is almost the same thing, and
since the Z80 cannot access memory twice in one instruction (disregarding
instruction fetch of course) it can't fetch or store the data byte (A hint in
this direction is that, even though the NOP-synonyms LD B,B, LD C,C etcetera
do exist, LD (HL),(HL) is absent and replaced by the HALT instruction.).

The IM 0/1 instruction puts the processor in either IM 0 or 1, I couldn't
figure out which on my own Spectrum.

d) About the R register:
   This is not really an undocumented feature, although I have never seen any
thorough description of it anywhere. The R register is a counter that is
updated every instruction, where DD, FD, ED and CB are to be regarded as
separate instructions. So shifted instruction will increase R by two. There's
an interesting exception: doubly-shifted opcodes, the DDCB and FDCB ones,
increase R by two too. LDI increases R by two, LDIR increases it by 2 times
BC, as does LDDR etcetera.  The sequence LD R,A/LD A,R increases A by two,
except for the highest bit: this bit of the R register is never changed. This
is because in the old days everyone used 16 Kbit chips. Inside the chip the
bits where grouped in a 128x128 matrix, needing a 7 bit refresh cycle.
Therefore ZiLOG decided to count only the lowest 7 bits. You can easily check
that the R register is really crucial to memory refresh. Assemble this program:

        ORG 32768
        DI
        LD B,0
    L1: XOR A
        LD R,A
        DEC HL
        LD A,H
        OR L
        JR NZ,L1
        DJNZ L1
        EI
        RET

It will take about three minutes to run.  Look at the upper 32K of memory,
for instance the UDG graphics.  It will have faded.  Only the first few bytes
of each 256 byte block will still contain zeros, because they were refreshed
during the execution of the loop. The ULA took care of the refreshing of the
lower 16K (This example won't work on the emulator, of course!).

e) Undocumented flags:
   This undocumented "feature" of Z80 has its effect on programs like Sabre
Wulf, Ghosts'n Goblins and Speedlock. Bits 3 and 5 of the F register are not
used. They can contain information, as you can readily figure out by PUSHing
AF onto the stack and then POPping some it into another pair of registers.
Furthermore, sometimes their values change. I found the following empirical
rule:

    The values of bits 7, 5 and 3 follow the values of the corresponding
    bits of the last 8 bit result of an instruction that changed the usual
    flags.

For instance, after an ADD A,B those bits will be identical to the bits of
the A register (Bit 7 of F is the sign flag, and fits the rule exactly). An
exception is the CP x instruction (x=register, (HL) or direct argument). In
this case the bits are copied from the argument.
If the instruction is one that operates on a 16 bit word, the 8 bits of the
rule are the highest 8 bits of the 16 bit result - that was to be expected
since the S flag is extracted from bit 15.
Ghosts'n Goblins use the undocumented flag due to a programming error. The
rhino in Sabre Wulf walks backward or keeps running in little circles in a
corner, if the (in this case undocumented) behaviour of the sign flag in the
BIT instruction isn't right. I quote:

        AD86    DD CB 06 7E        BIT 7,(IX+6)
        AD8A    F2 8F AD           JP P,#AD8F

An amazing piece of code!  Speedlock does so many weird things that all must
be exactly right for it to run. Finally, the '128 ROM uses the AF register to
hold the return address of a subroutine for a while.

f) Interrupt flip-flops IFF1 and IFF2:
   There seems to be a little confusion about these. These flip flops are
simultaneously set or reset by the EI and DI instructions. IFF1 determines
whether interrupts are allowed, but its value cannot be read. The value of
IFF2 is copied to the P/V flag by LD A,I and LD A,R. When an NMI occurs, IFF1
is reset, thereby disallowing further [maskable] interrupts, but IFF2 is left
unchanged. This enables the NMI service routine to check whether the
interrupted program had enabled or disabled maskable interrupts. So, Spectrum
snapshot software can only read IFF2, but most emulators will emulate both,
and then the one that matters most is IFF1.

2. ZX-Spectrum Hardware:
   At the hardware level, the Spectrum is a very simple machine. There's the
16K ROM which occupies the lowest part of the address space, and 48K of RAM
which fills up the rest. An ULA which reads the lowest 6912 bytes of RAM to
display the screen, and contains the logic for just one I/O port completes the
machine, from a software point of view at least.
Every even I/O address will address the ULA, but to avoid problems with other
I/O devices only port FE should be used. If this port is written to, bits have
the following meaning:

        Bit   7   6   5   4   3   2   1   0
            +-------------------------------+
            |   |   |   | E | M |   Border  |
            +-------------------------------+

The lowest three bits specify the border color; a zero in bit 3 activates the
MIC output, and a one in bit 4 activates the EAR output (which sounds the
internal speaker). The real Spectrum also activates he MIC when the ear is
written to. The upper three bits are unused.
If port FE is read from, the highest eight address lines are important too. A
zero on one of these lines selects a particular half-row of five keys:

      IN:    Reads keys (bit 0 to bit 4 inclusive)

      #FEFE  SHIFT, Z, X, C, V            #EFFE  0, 9, 8, 7, 6
      #FDFE  A, S, D, F, G                #DFFE  P, O, I, U, Y
      #FBFE  Q, W, E, R, T                #BFFE  ENTER, L, K, J, H
      #F7FE  1, 2, 3, 4, 5                #7FFE  SPACE, SYM SHFT, M, N,

A zero in one of the five lowest bits means that the corresponding key is
pressed. If more than one address line is made low, the result is the logical
AND of all single inputs, so a zero in a bit means that at least one of the
appropriate keys is pressed. For example, only if each of the five lowest bits
of the result from reading from port 00FE (for instance by XOR A/IN A,(FE)) is
one, no key is pressed. A final remark about the keyboard. It is connected in
a matrix-like fashion, with 8 rows of 5 columns, as is obvious from the above
remarks. Any two keys pressed simultaneously can be uniquely decoded by reading
from the IN ports. However, if more than two keys are pressed decoding may not
be uniquely possible.  For instance, if you press Caps shift, B and V, the
Spectrum will think also the Space key is pressed, and react by giving the
"Break into Program" report. Without this matrix behaviour Zynaps, for
instance, won't pause when you press 5,6,7,8 and 0 simultaneously.
Bit 5 (value 64) of IN-port FE is the ear input bit. When the line is silent,
its value is zero, except in the early Model 2 of the Spectrum, where it was
one. When there is a signal, this bit toggles. The Spectrum loading software is
not sensitive to the polarity of this bit (which it definitely should not be,
not only because of this model difference, but also because you cannot be sure
the tape recorder doesn't change the polarity of the signal recorded!). Some
old programs rely on the fact that bit 5 is always one (for instance Spinads).
Bits 6 and 7 are always one. The ULA with the lower 16K of RAM, and the
processor with the upper 32K RAM and 16K ROM are working independently of each
other. The data and address buses of the Z80 and the ULA are connected by
small resistors; normally, these do effectively decouple the buses. However, if
the Z80 wants to read of write the lower 16K, the ULA halts the processor if it
is busy reading, and after it's finished lets the processor access lower memory
through the resistors. A very fast, cheap and neat design indeed!
If you run a program in the lower 16K of RAM, or read or write in that memory,
the processor is halted sometimes. This part of memory is therefore somewhat
slower than the upper 32K block. This is also the reason that you cannot write
a sound- or save-routine in lower memory; the timing won't be exact, and the
music will sound harsh. Also, INning from port FE will halt the processor,
because the ULA has to supply the result. Therefore, INning from port FE is a
tiny bit slower on average than INning from other ports; whilst normally an
IN A,(nn) instruction would take 11 T states, it takes 12.15 T states on
average if nn=FE. See below for more exact information.
If the processor reads from a non-existing IN port, for instance FF, the ULA
won't stop, but nothing will put anything on the data bus. Therefore, you'll
read a mixture of FF's (idle bus), and screen and ATTR data bytes (the latter
being very scarce, by the way). This will only happen when the ULA is reading
the screen memory, about 60% of the 1/50th second time slice in which a frame
is generated. The other 40% the ULA is building the border or generating a
vertical retrace. This behaviour is actually used in some programs, for
instance, in Arkanoid.
Finally, there is an interesting bug in the ULA which also has to do with this
split bus. After each instruction fetch cycle of the processor, the processor
puts the I-R register "pair" (not the 8 bit internal Instruction Register, but
the Interrupt and R registers) on the address bus. The lowest 7 bits, the R
register, are used for memory refresh. However, the ULA gets confused if I is
in the range 64-127, because it thinks the processor wants to read from lower
16K ram very, very often. The ULA can't cope with this read-frequency, and
regularly misses a screen byte.  Instead of the actual byte, the byte
previously read is used to build up the video signal.  The screen seems to be
filled with 'snow'; however, the Spectrum won't crash, and program will
continue to run normally.  There's one program I know of that uses this
to generate a nice effect: Vectron (which has very nice music too, by the way).
The processor has three interrupt modes, selected by the instructions IM 0,
IM 1 and IM 2. In mode 1, the processor simply executes an RST #38 instruction
if an interrupt is requested. This is the mode the Spectrum is normally in.
The other mode that is commonly used is IM 2. If an interrupt is requested,
egister (as
the high byte) with whatever the interrupting device places on the data bus.
The subroutine at this address is then called. Rodnay Zaks in his book
"Programming the Z80" states that only even bytes are allowed as low index
byte, but that isn't true. The normal Spectrum contains no hardware to place
a byte on the bus, and the bus will therefore always read FF (because the ULA
also doesn't read the screen if it generates an interrupt), so the resulting
index address is 256*I+255. However, some not-so-neat hardware devices put
things on the data bus when they shouldn't, so later programs didn't assume
the low index byte was FF. These programs contain a 257 byte table of equal
bytes starting at 256*I, and the interrupt routine is placed at an address
that is a multiple of 257. A useful but not so much used trick is to make the
table contain FF's (or use the ROM for this) and put a byte 18 hex, the opcode
for JR, at FFFF. The first byte of the ROM is a DI, F3 hex, so the JR will jump
to FFF4, where a long JP to the actual interrupt routine is put.
In interrupt mode 0, the processor executes the instruction that the
interrupting device places on the data bus. On a standard Spectrum this will be
the byte FF, coincidentally (...) the opcode for RST #38. But for the same
reasons as above, this is not really reliable.
The 50 Hz interrupt is synchronized with the video signal generation by the
ULA; both the interrupt and the video signal are generated by it. Many programs
use the interrupt to synchronize with the frame cycle. Some use it to generate
fantastic effects, such as full-screen characters, full-screen horizon
(Aquaplane) or pixel colour (Uridium for instance). Very many modern programs
use the fact that the screen is "written" (or "fired") to the CRT in a finite
time to do as much time-consuming screen calculations as possible without
causing character flickering: although the ULA has started displaying the
screen for this frame already, the electron beam will for a moment not "pass"
this or that part of the screen so it's safe to change something there. So the
exact time in the 1/50 second time-slice at which the screen is updated is
very important. Each line takes exactly 224 T states. After an interrupt
occurs, 64 line times pass before the byte 16384 is displayed. At least the
last 48 of these are actual border-lines. I could not determine whether my
monitor didn't display the others or whether it was in vertical retrace, but
luckily that's not really important. Then the 192 screen+border lines are
displayed, followed by about 56 border lines again. 56.5 border lines would
make up exactly 70000 T states, 1/50th of 3500000. However, I noticed that the
frequency of the 50 Hz interrupt (measured in 1/T states!) changes very
slightly when my Spectrum gets hot (I think it has something to do with the
relative change of the frequencies of the two crystals in the Spectrum), so the
time between interrupts will probably not be exactly 70000 T states. Anyway,
whether the final border block is of fixed or variable length doesn't concern
us either, the timings of the start and end of the screen, which are the
timings of real interest, are fixed.
Now for the timings of each line itself. I define a screen line to start with
256 screen pixels, then border, then horizontal retrace, and then border again.
All this takes 224 T states. Every half T state a pixel is written to the CRT,
so if the ULA is reading bytes it does so each 4 T states (and then it reads
two: a screen and an ATTR byte). The border is 48 pixels wide at each side. A
video screen line is therefore timed as follows: 128 T states of screen, 24 T
states of right border, 48 T states of horizontal retrace and 24 T states of
left border.
When an interrupt occurs, the running instruction has to be completed first.
So the start of the interrupt is fixed relatively to the start of the frame
up to the length of the last instruction in T states. If the processor was
executing a HALT (which, according to the Z80 books I read, is effectively
many NOPs), the interrupt routine starts at most 3 T states away from the
start of the frame. Of course the processor also needs some T states to store
the program counter on the stack, read the interrupt vector and jump to the
routine, but since I cannot determine that by only using the Spectrum, it is
useless information by that very reason alone!
Now when to OUT to the border to change it at the place you want? First of
all, you cannot change the border within a "byte", an 8-pixel chunk. If we
forget about the screen for a moment, if you OUT to port FE after 14326 to
14329 T states (including the OUT) from the start of the IM 2 interrupt
routine, the border will change at exactly the position of byte 16384 of the
screen. The other positions can be computed by remembering that 8 pixels take
4 T states, and a line takes 224 T states. You would think that OUTing after
14322 to 14325 T states, the border would change at 8 pixels left of the upper
left corner of the screen. This is right for 14322, 14323 and 14324 T states,
but if you wait 14325 T states the ULA happens to be reading byte 16384 (or
22528, or both) and will halt the processor for a while, thereby making you
miss the 8 pixels. This exception happens again after 224 T states, and
again after 448, an so forth. These 192 exceptions left of the actual screen
rectangle are the only ones; similar things don't happen at the right edge
because the ULA don't need to read things there - it has just finished!
As noted above, reading or writing in low ram (or OUTing to the ULA) causes
the ULA to halt the processor. When and how much? The processor is halted each
time you want to access the ULA or low memory and the ULA is busy reading. Of
the 312.5 'lines' the ULA generates, only 192 contain actual screen pixels,
and the ULA will only read bytes during 128 of the 224 T states of each screen
line. But if it does, the processor is halted for exactly 4 T states.

3. Interface I:

   The Interface I is quite complicated. It uses three different I/O ports,
and contains logic to page and unpage an 8K ROM if new commands are used. The
ROM is paged if the processor executes the instruction at ROM address 0008 or
1708 hexadecimal, the error and close# routines. It is inactivated when the
Z80 executes the RET at address 0700.

a) Port E7:
   I/O port E7 is used to send or receive data to and from the microdrive.
Accessing this port will halt the Z80 until the Interface I has collected 8
bits from the microdrive head; therefore, it the microdrive motor isn't
running, or there is no formatted cartridge in the microdrive, the Spectrum
hangs. This is the famous 'IN 0 crash'.

b) Port EF:

       Bit    7   6    5    4    3    2    1     0
            +---------------------------------------+
        READ|   |   |    |busy| dtr |gap| sync|write|
            |   |   |    |    |     |   |     |prot.|
            |---+---+----+----+-----+---+-----+-----|
       WRITE|   |   |wait| cts|erase|r/w|comms|comms|
            |   |   |    |    |     |   | clk | data|
            +---------------------------------------+

Bits DTR and CTS are used by the RS232 interface.  The WAIT bit is used by the
Network to synchronise, GAP, SYNC, WR_PROT, ERASE, R/_W, COMMS CLK and COMMS
DATA are used by the microdrive system. If the microdrive is not being used,
the COMMS DATA output selects the function of bit 0 of out-port F7:


       Bit      7    6   5   4   3   2   1       0
            +------------------------------------------+
        READ|txdata|   |   |   |   |   |   |    net    |
            |      |   |   |   |   |   |   |   input   |
            |------+---+---+---+---+---+---+-----------|
       WRITE|      |   |   |   |   |   |   |net output/|
            |      |   |   |   |   |   |   |   rxdata  |
            +------------------------------------------+

TXDATA and RXDATA are the input and output of the RS232 port. COMMS DATA
determines whether bit 0 of F7 is output for the RS232 or the network.


********************************** PINOUTS ********************************

1. ULA pinout

he *multiplexed* address-lines.
/WR   2    39 Q          One of the +5V is decoupled through a RC-low-pass.
/RD   3    38 /MREQ      U,V are the color-difference signals.
/WE   4    37 A15        /Y is the inverted video including sync.
A0    5    36 A14        D are the data-lines, decoupled from the CPU by
A1    6    35 /RAS       resistors.
A2    7    34 /ROM CS    T are the data-lines to the keyboard (address-lines
A3    8    33 /IO-ULA    through diodes).
A4    9    32 CLOCK      SOUND is the analog-I/O-line for beep, save and load.
A5   10    31 D7         CLK is the clock-source to the CPU including the
A6   11    30 D6         inhibited T-states.
/INT 12    29 D5         IO-ULA is (A0(CPU) OR /IORQ) for the I/O-port FEh
+5V  13    28 SOUND      Q is the 14MHz-crystal, other side grounded through
+5V  14    27 D4         a capacitor
U    15    26 T4
V    16    25 D3
/Y   17    24 T3
D0   18    23 T2
T0   19    22 D2
T1   20    21 D1

2. AY-3-8912

SOUND C   1    28  D0       Vcc is +5V.
PORT      2    27  D1       SOUND A, B and C can be tied together.
Vcc       3    26  D2       CLOCK can be some MHz.
SOUND B   4    25  D3
SOUND A   5    24  D4
GND       6    23  D5
PORT      7    22  D6
PORT      8    21  D7
PORT      9    20  BC1
PORT     10    19  BC2
PORT     11    18  BDIR
PORT     12    17  A8
PORT     13    16  RESET
CLOCK    14    15  CLOCK

3. Keyboard layout

  OUTER SIDE   A 15 14 8  13 12 9  10 11  INNER SIDE
             D
             0   BR EN CS P  0  A  Q  1
             1   SS L  Z  O  9  S  W  2
             2   M  K  X  I  8  D  E  3
             3   N  J  C  U  7  F  R  4
             4   B  H  V  Y  6  G  T  5
  INNER SIDE

  [BR] BREAK   [EN] ENTER   [CS] CAPS SHIFT   [SS] SYMBOL SHIFT

  In real the matrix connections are in one row on the top side of
  the membrane.


***************************** ACKNOWLEDGEMENTS ****************************

Thanks to:

  Gerton Lunter     - for the excellent information about ZX-Spectrum internals
                      and Z80 emulator for IBM PC.
  Peter McGavin     - for some useful information and [of course =:)] his
                      excellent Spectrum emulator which actually *multitasks*
                      under AmigaDOS and is system-friendlier than many other
                      programs I have seen.
  Arnt Gulbrandsen  - for keeping Spectrum FTP archive and multiple
                      contributions to this file. Also, for his IBMPC-based
                      JPP emulator.
  Den Herriott      - for his xzx emulator, which is the first and the only
                      way to play LodeRunner on a Unix workstation! :)
  Emil Obermayr     - for pinouts of ULA, AY-3-8912 and keyboard layout.
  A.G.Jackson        - information about emulators for Acorn Archimedes.
  Troels Norgaard    - information about KGB.
  Krzysztof Czysciak - information about Elwro emulator.
  Thorsten Roskowetz - information about Atari-based emulator.

  Everybody else who contributed to FAQ, manages FTP archives, writes
  ZX-Spectrum emulators, generally, keeps ZX-Spectrum alive!




