| 
                                         This section is broken into several parts: Channels
                                                  &
                                                  Streams,
                                             Hardware, ZX
                                                  Interface
                                                  I and Tape Data
                                                  Structure.
                                             Each of these may have several sub-sections. Within each section,
                                             you
                                             may
                                             find links to additional information elsewhere in this FAQ, or to
                                             other
                                             reference documents. Commented ROM listings are available from Geoff
                                                  Wearmouth,
                                             author of the SEA
                                                  Change
                                                  ROM.
                                         
                                        Channels & Streams: 
                                             There are 5 subsections:
                                             Introduction,
                                             Opening and Closing,
                                             Device Independence,
                                             More Stream Commands and
                                             Memory Formats. 
                                        
                                             - Introduction
 
                                                  The Spectrum has a surprisingly modern system of input and
                                                  output
                                                  when
                                                  the age of the Spectrum is considered.
                                                  However, what is more surprising is the fact that the
                                                  Spectrum
                                                  manual
                                                  barely scratches the surface of what is
                                                  possible.
  
                                                  I/O on the Spectrum is based on channels and streams. Since
                                                  the
                                                  standard Spectrum has only a limited range of I/O devices
                                                  is makes sense that different commands are available for
                                                  each I/O
                                                  device. For example, PRINT is used to send output to the
                                                  screen, whereas LPRINT is used to send output to the
                                                  printer.
  
                                                  The extra devices catered for by the ZX
                                                       Interface I (microdrives, RS-232, and
                                                  networking) reduced the practicality of continuing to invent
                                                  new
                                                  commands, although this was provided for in the case of the
                                                  microdrives.
  
                                                  Streams and channels intuitively correspond to the software
                                                  and
                                                  hardware parts of I/O respectively. That is, a stream should
                                                  be
                                                  thought of merely as a collection of data going to or coming
                                                  from
                                                  a
                                                  piece of hardware, and a channel should be associated with a
                                                  particular piece of hardware such as a printer. On the
                                                  Spectrum
                                                  streams are numbered from 0 through 15, and their basic
                                                  operations
                                                  are reading and writing data.
  
                                                  The BASIC statement INPUT #s; [input-list] will read data
                                                  from
                                                  stream
                                                  number s, 0 <= s <= 15, into the variables specified
                                                  in the
                                                  input-list. Conversely, the BASIC statement PRINT #s;
                                                  [print-list]
                                                  will write data to stream s, 0 <= s <= 15. In general
                                                  both
                                                  INPUT # and PRINT # can be used in the same way as their
                                                  ordinary
                                                  counterparts INPUT and PRINT. In particular all the normal
                                                  complexity of a PRINT statement can be used equally well in
                                                  a
                                                  PRINT #
                                                  statement. In each case the data sent to the stream is
                                                  exactly
                                                  the same as the data which would be sent to the screen by
                                                  the
                                                  PRINT
                                                  statement. The INPUT # statement is slightly more
                                                  complicated
                                                  in that is can both read and write data, as in INPUT "What
                                                  is
                                                  your
                                                  name? "; A$. In fact each stream really has two components,
                                                  an
                                                  input
                                                  stream and an output stream. Data written to the stream by
                                                  either
                                                  PRINT # or INPUT # goes to the output stream while input
                                                  comes
                                                  from
                                                  the input stream.
  
                                                  It is even possible to change streams part way through a
                                                  PRINT
                                                  statement, as in PRINT #3; "hello"; #6; "there". This is
                                                  obviously
                                                  fairly
                                                  confusing though, so should probably be avoided unless their
                                                  is a
                                                  good
                                                  reason for using this construct.
 
  
                                             - Opening and Closing
 
                                                  How do you know which stream numbers are associated with
                                                  which
                                                  channel? Before a stream is used it must be OPENed. Opening
                                                  a
                                                  stream
                                                  serves two purposes. It associates the given stream with a
                                                  particular
                                                  piece of hardware (the channel), and actually signals the
                                                  relevant
                                                  device
                                                  that it is going to be used. Stream are opened in BASIC
                                                  using the
                                                  syntax OPEN #s, c where s is the stream number being opened
                                                  and c
                                                  is a
                                                  string specifying the channel to associate the stream with.
                                                  Following
                                                  this command, any data sent to stream s will go to the
                                                  specified
                                                  channel.
                                                  It is possible to open several streams to the same device,
                                                  but
                                                  each
                                                  stream can only be associated with a single
                                                  channel.
  
                                                  The statement CLOSE #s is used to end the association of
                                                  stream s
                                                  with
                                                  a channel. If you attempt to close a channel which is
                                                  already
                                                  closed
                                                  on an unexpanded Spectrum then the machine might crash due
                                                  to two
                                                  bugs
                                                  in the ROM.
  
                                                  The unexpanded Spectrum supports four channels: "K" the
                                                  keyboard
                                                  channel, "S" the screen channel, "P" the printer channel,
                                                  and "R"
                                                  an
                                                  internal channel used by the Spectrum to send data to the
                                                  edit
                                                  buffer.
                                                  In practice the only channel that has both input and output
                                                  of
                                                  these
                                                  is
                                                  the keyboard channel. When the Spectrum is first powered up
                                                  the
                                                  following streams are opened automatically: 0: "K", 1: "K",
                                                  2:
                                                  "S", 3:
                                                  "P".
                                                  Thus, the command LPRINT is really an alternative to writing
                                                  PRINT #3.
                                                  The "R" channel cannot be opened from BASIC. It is possible
                                                  to
                                                  redefine the standard channels, thus OPEN #2, "P" will cause
                                                  output
                                                  normally sent to the screen to be redirected to the
                                                  printer.
  
                                                  For example, OPEN #5, "K" associates stream 5 with the
                                                  keyboard,
                                                  and
                                                  thereafter INPUT #5; A$ would behave in an identical manner
                                                  to
                                                  INPUT A$.
 
  
                                             - Device
                                                            Independence
 
                                                  The most important advantage of using streams is in the
                                                  writing
                                                  of
                                                  device independent programs. Say that you wish to give the
                                                  user
                                                  the
                                                  option
                                                  of having all output go to either the screen or to the
                                                  printer.
                                                  Without using streams it is necessary then to have separate
                                                  output
                                                  statements for
                                                  each device, as in;
  
                                                  IF (output = printer) THEN LPRINT "Hello" ELSE PRINT
                                                  "Hello"
  
                                                  By using streams we can just open a particular stream (say
                                                  4) to
                                                  the
                                                  desired output device and thereafter use only one output
                                                  statement;
  
                                                  PRINT #4; "Hello"
  
                                                  Obviously this will result is a much shorter program,
                                                  particularly, if
                                                  there are many output statements in the program. Further, it
                                                  is
                                                  an
                                                  easy
                                                  matter to add even further output devices if they become an
                                                  option
                                                  later in the programs development.
  
                                                  You could also hack an existing program by adding somewhere
                                                  near
                                                  the
                                                  start;
  
                                                  IF [printer required] THEN OPEN #2,"P"
  
                                                  which will make all ordinary PRINT instructions go to the
                                                  printer.
 
  
                                             - More Stream
                                                            Commands
 
                                                  BASIC also allows LIST and INKEY$ to be used to streams.
                                                  LIST #s
                                                  will
                                                  send a copy of the program to stream s; e.g. normally LIST
                                                  #3 is
                                                  the
                                                  same thing as LLIST. However, on the standard Spectrum
                                                  INKEY$ can
                                                  only
                                                  be used with the keyboard channel.
  
                                                  Note that INKEY$ is not the same as INKEY$ #1 because the
                                                  former
                                                  does
                                                  a stand-alone key scan whereas the latter attempts to read a
                                                  key
                                                  from the "K" device (which might involve changing the cursor
                                                  mode
                                                  and
                                                  listing the editing area if you happen to press both shifts,
                                                  for
                                                  example).
 
  
                                             - Memory Formats
 
                                                  Knowing about the actual layout of the stream records in
                                                  memory
                                                  is
                                                  useful if you want to add your own hardware devices to the
                                                  Spectrum,
                                                  or if you which to make you own specialized streams. The
                                                  information
                                                  that defines each channel is stored in the channel
                                                  information
                                                  area
                                                  starting at CHANS and ending at PROG - 2. Each channel
                                                  record has
                                                  the
                                                  following format:
  
                                                  
                                                       - two-byte address of the output routine,
 
                                                       - two-byte address of the input routine,
 
                                                       - one-byte channel code letter.
 
  
                                                   
                                                  where the input and output routines are address of machine
                                                  code
                                                  sub-
                                                  routines. The output routine must accept Spectrum character
                                                  codes
                                                  passed to it in the A register. The input routine must
                                                  return
                                                  data in
                                                  the form of Spectrum character codes, and signal that data
                                                  is
                                                  available by
                                                  setting the carry flag. If no data is available then this is
                                                  indicated
                                                  be resetting both the carry and zero flags. Stubs should be
                                                  provided
                                                  if a
                                                  channel does not support either input or output (e.g. the
                                                  stub
                                                  may
                                                  simply call RST 8 with an error code)
  
                                                  With the ZX Interface I
                                                  attached, an
                                                  extended format is used;
                                                  offset len description
     0  2  0x0008 (address of Spectrum error routine)
     2  2  0x0008 (ditto)
     4  1  A character describing the channel
     5  2  Address of output routine in the shadow ROM
     7  2  Address of input routine in the shadow ROM
     9  2  Total length of channel information
    11  *  Any other data needed by the channel
                                                  The first two words being 8 denotes that the input and
                                                  output
                                                  routines
                                                  are to be found in the shadow ROM. Either of them could be
                                                  an
                                                  ordinary
                                                  number instead, in which case the shadow ROM will not be
                                                  paged in
                                                  and
                                                  the word at offset 5 or 7 (as appropriate) could contain any
                                                  data.
  
                                                  Data about which streams are associated with which channels
                                                  is in
                                                  a
                                                  38-byte area of memory starting at STRMS. The table is a
                                                  series
                                                  of
                                                  16-bit offsets to the channel record vectored from CHANS. A
                                                  value
                                                  of
                                                  one indicates the channel record starting at CHANS, and so
                                                  on.
                                                  This
                                                  accounts for 32 bytes of the 38 - the remaining 6 bytes are
                                                  for
                                                  three
                                                  hidden streams (253, 254, 255) used internally by BASIC. A
                                                  zero
                                                  entry
                                                  in the table indicates a stream not open.
  
                                                  It is possible to redirect existing channels to your own I/O
                                                  routines.
                                                  This can be used among other things to cause LPRINT to use
                                                  your
                                                  own
                                                  printer driver rather than the one provided in the ROM. It
                                                  allows
                                                  you
                                                  to perform I/O for your own hardware devices, or for you to
                                                  write
                                                  your
                                                  own handlers from PRINT and INPUT.
  
                                                  It is easiest to modify the existing "P" channel record. The
                                                  "K"
                                                  channel is not a good option for modification because its
                                                  values
                                                  are
                                                  constantly
                                                  being restored by BASIC.
  
                                                  It is not possible to create a new channel from BASIC.
                                                  Another
                                                  difficulty is that without Interface I, OPEN will only work
                                                  with
                                                  K, S,
                                                  and P and so
                                                  it is necessary to provide some other way of opening your
                                                  own
                                                  channels. This short assembler routine will create a new
                                                  channel
                                                  and
                                                  associate
                                                  a stream with it:
                                                       LD HL,(PROG)  ; A new channel starts below PROG
     DEC HL        ;
     LD BC,0x0005  ; Make space
     CALL 0x1655   ;
     INC HL        ; HL points to 1st byte of new channel data
     LD A,0xfd     ; LSB of output routine
     LD (HL),A     ;
     INC HL        ;
     PUSH HL       ; Save address of 2nd byte of new channel data
     LD A,0xfd     ; MSB of output routine
     LD (HL),A     ;
     INC HL        ;
     LD A,0xc4     ; LSB of input routine
     LD (HL),A     ;
     INC HL        ;
     LD A,0x15     ; MSB of input routine
     LD (HL),A     ;
     INC HL        ;
     LD A,0x55     ; Channel name 'U'
     LD (HL),A     ;
     POP HL        ; Get address of 2nd byte of output routine
     LD DE,(CHANS) ; Calculate the offset to the channel data
     AND A         ; and store it in DE
     SBC HL,DE     ;
     EX DE,HL      ;
     LD HL,'STRMS' ;
     LD A,0x04     ; Stream to open, in this case #4.
     ADD A,0x03    ; Calculate the offset and store it in HL
     ADD A,A       ;
     LD B,0x00     ;
     LD C,A        ;
     ADD HL,BC     ;
     LD (HL),E     ; LSB of 2nd byte of new channel data
     INC HL        ;
     LD (HL),D     ; MSB of 2nd byte of new channel data
     RET
                                                  This routine will create a channel "U" (any ASCII character
                                                  from
                                                  0 to
                                                  255 will be accepted by the standard ROM since it ignores
                                                  this
                                                  information).
                                                  This channel has an output routine at 65021 and an input
                                                  routine
                                                  at
                                                  5572 (generates error report 'J'). A new entry is created in
                                                  the
                                                  STRMS
                                                  table
                                                  which points to the address of the second byte of new
                                                  channel
                                                  data.
                                                  The stream number can be from -3 to 15, but it is best to
                                                  stick
                                                  to the
                                                  range
                                                  4 to 15 and not modify the system streams (-3 to -1) or the
                                                  standard
                                                  streams (0 to 3).
                                              
                                         
                                        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.
  
                                             There are 4 subsections available:
                                             Port 0xfe,
                                             48K Spectrum,
                                             Contended Memory and
                                             Contended Input/Output. Within each
                                             section,
                                             you may find links to additional information elsewhere in this
                                             FAQ, or
                                             to
                                             reference documents located elsewhere. 
                                        
                                             - Port 0xfe
 
                                                  Every even I/O address will address the ULA, but to avoid problems
                                                  with
                                                  other I/O devices only Port 0xfe should be used. If this
                                                  port is
                                                  written to, bits have the following meaning:
  
                                                  
                                                  The lowest three bits specify the border colour; a zero in
                                                  bit 3
                                                  activates the MIC output, whilst a one in bit 4 activates
                                                  the EAR
                                                  output
                                                  and the internal speaker. However, the EAR and MIC sockets
                                                  are
                                                  connected only by resistors, so activating one activates the
                                                  other;
                                                  the
                                                  EAR is generally used for output as it produces a louder
                                                  sound.
                                                  The
                                                  upper two bits are unused.
  
                                                  If Port 0xfe 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)
      0xfefe  SHIFT, Z, X, C, V            0xeffe  0, 9, 8, 7, 6
      0xfdfe  A, S, D, F, G                0xdffe  P, O, I, U, Y
      0xfbfe  Q, W, E, R, T                0xbffe  ENTER, L, K, J, H
      0xf7fe  1, 2, 3, 4, 5                0x7ffe  SPACE, SYM SHFT, M, N, B
                                                        
                                                   
                                                  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, 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 6 of IN-Port 0xfe is the EAR input bit. The value read
                                                  from
                                                  this
                                                  port is not trivial, as can be seen from the following
                                                  program:
  
                                                        10 OUT 254,BIN 11101111
      20 PRINT IN 254
      30 OUT 254,BIN 11111111
      40 PRINT IN 254
      50 GOTO 10
                                                  For a correct test do not press any key while running, and
                                                  have
                                                  no EAR
                                                  input.
  
                                                  
                                                       - If the output is 191,255,191,255 etc, you are on
                                                            real
                                                            Spectrum Issue 3.
 
                                                       - If output is always 191 or always 255, change the
                                                            value
                                                            in
                                                            line 10 to BIN 11100111.
 
                                                       - If output is then 191,255,191,255 etc, then you are
                                                            on
                                                            Spectrum Issue 2.
 
                                                       - If output is still always 191 or always 255 you are
                                                            on
                                                            Spectrum emulator.
 
  
                                                   
                                                  The ULA chip uses the same pin
                                                  (28)
                                                  for
                                                  all of the MIC socket, EAR socket and the
                                                  internal speaker, so bits 3 and 4 of an OUT to Port 0xfe
                                                  will
                                                  affect
                                                  bit 6 as read by an IN from Port 0xfe. The difference
                                                  between
                                                  Issue 2
                                                  and 3 machines is:
  
                                                  Value output to bit: 4  3  |  Iss 2  Iss 3   Iss 2 V    Iss 3 V
                     1  1  |    1      1       3.79       3.70
                     1  0  |    1      1       3.66       3.56
                     0  1  |    1      0       0.73       0.66
                     0  0  |    0      0       0.39       0.34
                                                  Iss 2 is value of bit 6 read by IN 254 after the appropriate
                                                  OUT
                                                  from
                                                  an Issue 2, and Iss 3 is same for an Issue 3. Iss 2 V and
                                                  Iss 3 V
                                                  are
                                                  voltage levels on pin 28 of the ULA
                                                  chip
                                                  after the OUT, with no input signal on
                                                  the EAR socket.
  
                                                  From the above, it is clear that the difference between
                                                  Issue 2
                                                  and 3
                                                  is:
  
                                                  
                                                       - On an Issue 3, an OUT 254 with bit 4 reset will
                                                            give a
                                                            reset
                                                            bit 6 from IN 254.
 
                                                       - On an Issue 2, both bits 3 and 4 must be reset for
                                                            the
                                                            same
                                                            effect to occur.
 
  
                                                   
                                                  Pera Putnik tested the level at pin 28 at which input bit 6
                                                  changes
                                                  from 0 to 1 or reverse. This is exactly 0.70 Volts on both
                                                  Issue
                                                  2 and
                                                  Issue 3, with no inverting or hysteresis; this means that
                                                  bit 6
                                                  is 1
                                                  if the voltage on pin 28 is over 0.70 V, and otherwise it is
                                                  0,
                                                  on
                                                  both
                                                  Issues. At the hardware level, the only apparent difference
                                                  between
                                                  Issue 2 and 3 is that there are slightly higher voltages
                                                  from
                                                  Issue 2
                                                  machines. As can be seen from the table, the input
                                                  combination '0
                                                  1'
                                                  gives output voltages that are very close to the crucial 0.7
                                                  V.
  
                                                  The BASIC program used above is relatively slow, and for
                                                  faster
                                                  programs the situation isn't so simple, as there is
                                                       some
                                                       delay
                                                       when output
                                                       bit 4 changes from 1 to 0. To illustrate this,
                                                  here
                                                  are
                                                  2 short assembler routines:
  
                                                         ORG 45000
       LD A,0x18
       OR 0xf8
       OUT (254),A
       LD A,0x08
       OR 0xe8
       OUT (254),A
TIMING LD B,7      ;crucial value
DL     LD IX,0
       DJNZ DL
       IN A,(254)  ;query state
                                                  In this case IN A,(254), or output of this value sometimes
                                                  gives
                                                  255
                                                  and sometimes 191. If you make the constant in the TIMING
                                                  line
                                                  smaller
                                                  then result will be always 255, if delay is longer then
                                                  result
                                                  will be
                                                  always 191. Of course, the effect occurs only for Issue 3
                                                  machines.
  
                                                  The situation is again slightly different for a longer
                                                  duration
                                                  of
                                                  high output level on port 254:
  
                                                         ORG 50000
       HALT        ;synchronize with interrupts
       LD A,0x18
       OUT (254),A
       HALT        ;wait 20ms
       LD A,0x08
       OUT (254),A
       LD B,107    ;crucial value
DL     LD IX,0
       DJNZ DL
       IN A,(254)
                                                  As you can see, after a longer high level duration, the
                                                  delay is
                                                  also
                                                  much longer. The delay varies from approximately 180 T
                                                  states (about 50 microsec) to 2800 T states (about 800
                                                  microsec),
                                                  depending from duration of high level on port 254. The
                                                  explanation for
                                                  this delay is that there are capacitors connected between
                                                  pin 28
                                                  of
                                                  the ULA and
                                                  the EAR and MIC connectors, but note that there is
                                                       no
                                                       delay
                                                       when bit 4 changes from 0 to 1.
  
                                                  The 'traditional' explanation of the difference between
                                                  Issue 2
                                                  and 3
                                                  Spectrum (from techinfo.doc) is that PRINT IN 254 gives bit
                                                  6
                                                  reset on
                                                  an
                                                  Issue 3 and set on an Issue 2 machine occurs because, as
                                                  PRINT IN
                                                  254
                                                  is typed at a BASIC prompt, the speaker is called for every
                                                  keystroke, and the ROM beep routine contains a OR 8 before
                                                  OUT
                                                  (0xfe),A, so bit 3 is always set, and therefore an Issue 2
                                                  machine
                                                  will always
                                                  return a set bit 6.
  
                                                  Bits 5 and 7 as read by INning from Port 0xfe 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 or 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 read from a port that activates both the keyboard and
                                                  a
                                                  joystick port (e.g. Kempston), the joystick takes
                                                  priority.
  
                                              
                                             - 48K ZX Spectrum
 
                                                  If you run a program in the lower 16K of RAM, or read or
                                                  write in
                                                  that
                                                  memory, the processor is halted sometimes, as the
                                                  ULA needs to access the video
                                                  memory to
                                                  keep the TV updated; the electron beam
                                                  can't be interrupted, so the ULA is
                                                  given a higher priority to access the
                                                  contended memory. 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 0xfe (or any
                                                  other
                                                  even
                                                  port) will halt the processor, because the
                                                  ULA has to supply the result.
                                                  Therefore,
                                                  INning from
                                                  Port 0xfe is slower on average than
                                                  INning
                                                  from
                                                  other ports; whilst normally an IN A,(nn) instruction
                                                  would take 11 T states, it takes slightly longer if nn=0xfe.
                                                  There is
                                                  also an effect if the high byte of the port address is
                                                  between
                                                  0x40
                                                  and 0x7f, and this looks similar to a contended
                                                       memory access to the ULA.
                                                  See
                                                  the Contended Input/Output
                                                  section
                                                  for
                                                  more information.
  
                                                  If the processor reads from a non-existing IN port, for
                                                  instance
                                                  FF,
                                                  the ULA won't
                                                  stop (unless the high byte of the port address is between
                                                  0x40
                                                  and
                                                  0x7f), but nothing will put anything on the data bus.
                                                  Therefore,
                                                  you'll read a mixture of 0xff (idle bus), and screen and
                                                  ATTR
                                                  data
                                                  bytes. 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. One program which
                                                  uses
                                                  this to
                                                  generate a nice effect is Vectron.
  
                                                  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 (14336 T states;
                                                  see
                                                  below
                                                  for exact timings) pass before the first byte of the screen
                                                  (16384) is
                                                  displayed. At least the last 48 of these are actual
                                                  border-lines; the others may be either border or vertical
                                                  retrace.
  
                                                  Then the 192 screen+border lines are displayed, followed by
                                                  56
                                                  border
                                                  lines again. Note that this means that a frame is
                                                  (64+192+56)*224=69888 T states long, which means that the
                                                  '50 Hz'
                                                  interrupt is actually a 3.5MHz/69888=50.08 Hz interrupt.
                                                  This
                                                  fact can
                                                  be seen by taking a clock program, and running it for an
                                                  hour,
                                                  after
                                                  which it will be the expected 6 seconds fast. However, on a
                                                  real
                                                  Spectrum,
                                                  the frequency of the interrupt varies slightly as the
                                                  Spectrum
                                                  gets
                                                  hot; the reason for this is unknown, but placing a cooler
                                                  onto
                                                  the
                                                  ULA has been observed to
                                                  remove
                                                  this
                                                  effect.
  
                                                  Now for the timings of each line itself: 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.
  
                                                  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 execute
                                                  an OUT
                                                  to
                                                  Port 0xfe such that the OUT ends when
                                                  14339,
                                                  14340, 14341 or 14342 T states
                                                  have passed since the ULA
                                                  pulled
                                                  /INT
                                                  low, 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. However, there
                                                  are
                                                  complications due to the fact that Port
                                                       0xfe is
                                                  contended (as the
                                                  ULA must supply the result);
                                                  see
                                                  the
                                                  Contended Input/Output section
                                                  for
                                                  details.
  
                                                  NB: Investigations in May 2004 have
                                                  revealed
                                                  that the
                                                  machine timings vary, even between machines with the same
                                                  model
                                                  of ULA. Some machines use the
                                                  timings
                                                  given in this FAQ, while others are one T state later for
                                                  all
                                                  timings.
                                                  The reason for this is not currently understood.
  
                                                  The Spectrum's 'FLASH' effect is also produced by the ULA:
                                                  Every 16 frames, the ink and paper of all flashing bytes is
                                                  swapped;
                                                  ie a normal to inverted to normal cycle takes 32 frames,
                                                  which is (good as) 0.64 seconds.
 
  
                                             - Contended
                                                            Memory
 
                                                  When the ULA is drawing the
                                                  screen,
                                                  it
                                                  needs to access video memory;
                                                  the RAM cannot be read by two devices (the ULA and the processor) at
                                                  once,
                                                  and the ULA is given higher
                                                  priority (as
                                                  the electron beam cannot be
                                                  interrupted), so programs which run in the contended memory
                                                  (from
                                                  0x4000 to 0x7fff) or try to read from
                                                  Port 0xfe (when the ULA must supply the
                                                  result) will be slowed if the ULA
                                                  is
                                                  reading the screen. Note this effect occurs
                                                  only when the actual screen is being drawn; when the border
                                                  is
                                                  being
                                                  drawn, the
                                                  ULA supplies the result and no
                                                  delays
                                                  occur. The precise details are as follows:
  
                                                  
                                                       - At cycle 14335 (just one cycle before the top left
                                                            corner is
                                                            reached) the delay is 6 cycles.
 
                                                       - At cycle 14336 the delay is 5 cycles, and so on
                                                            according to
                                                            the following table:
 
                                                   
                                                        Cycle #    Delay
      -------    -----
       14335       6 (until 14341)
       14336       5 (  "     "  )
       14337       4 (  "     "  )
       14338       3 (  "     "  )
       14339       2 (  "     "  )
       14340       1 (  "     "  )
       14341   No delay
       14342   No delay
       14343       6 (until 14349)
       14344       5 (  "     "  )
       14345       4 (  "     "  )
       14346       3 (  "     "  )
       14347       2 (  "     "  )
       14348       1 (  "     "  )
       14349   No delay
       14350   No delay
                                                  etc., until the cycle 14463 (always relative to the start of
                                                  the
                                                  interrupt), in which the electron beam reaches the border
                                                  again
                                                  for 96
                                                  more
                                                  cycles. At cycle 14559 the same situation repeats. This is
                                                  valid
                                                  for
                                                  all 192 lines of screen data. While the
                                                  ULA is updating the border the
                                                  delay
                                                  does not happen at any time.
  
                                                  When counting cycles several things must be taken into
                                                  account.
                                                  One is
                                                  the interrupt setup time; another one is the precise moment
                                                  within
                                                  an instruction in which the R/W or I/O operation is
                                                  performed
                                                  (see the
                                                  table below). And one more thing: the fact that an interrupt
                                                  can't
                                                  happen
                                                  in the middle of an instruction (and a HALT counts as many
                                                  NOPs),
                                                  so
                                                  some cycles may be lost while waiting for the current
                                                  instruction
                                                  to
                                                  end.
                                                  That's an additional difficulty e.g. for byte-precision
                                                  colour
                                                  changes.
  
                                                  Now all that remains is to know exactly in which point(s)
                                                  within
                                                  an
                                                  instruction is the R/W or I/O operation acting, to know
                                                  where to
                                                  apply
                                                  the
                                                  delay. That depends on each instruction. For those one-byte
                                                  ops
                                                  which
                                                  do not perform memory or I/O access, the only affected point
                                                  is
                                                  the
                                                  opcode fetch which happens at the first cycle of the
                                                  instruction,
                                                  and
                                                  the address to test for contention is the current value of
                                                  the
                                                  program
                                                  counter PC.
  
                                                  For example, for a NOP (4 cycles), only the first cycle will
                                                  be
                                                  affected and only if PC lies within the contended memory
                                                  range.
                                                  So if
                                                  it's executed
                                                  in contended memory at cycle 14334, no delay will happen and
                                                  the
                                                  next
                                                  instruction will (try to) be executed at cycle 14338, but if
                                                  the
                                                  NOP
                                                  is
                                                  executed at cycle 14335, it will be delayed for 6 cycles
                                                  thus
                                                  taking
                                                  6+4=10 cycles so the next instruction will (try to) be
                                                  executed
                                                  at
                                                  cycle
                                                  14345. This case will be annotated in the table below as
                                                  pc:4,
                                                  meaning
                                                  that if PC lies within contended memory then the first cycle
                                                  will
                                                  be
                                                  subject to delay and the remaining three will be free of
                                                  delays.
  
                                                  The "try to" in the above paragraph is because, unless the
                                                  NOP is
                                                  at
                                                  PC=32767, the next instruction will be subject to another
                                                  delay
                                                  when
                                                  its
                                                  opcode is fetched (the first cycle in an opcode fetch is
                                                  always
                                                  subject to delays) since the cycle number relative to the
                                                  start
                                                  of the
                                                  frame is also
                                                  delayed.
  
                                                  So an entry like 'hl+1:3' means that if HL+1 is in range
                                                  16384-32767
                                                  and the current cycle number is subject to delays, then the
                                                  delay
                                                  corresponding to the current cycle must be inserted before
                                                  the
                                                  number
                                                  of T-states that figure after the colon.
  
                                                  Things get a bit more difficult with more-than-one-byte-long
                                                  instructions. Here's the sample pseudocode to apply delays
                                                  to an
                                                  instruction
                                                  with an entry in the table which reads 'pc:4,hl:3' (e.g. LD
                                                  (HL),A):
  
                                                    If 16384<=PC<=32767 then
     (Insert the delay corresponding to the current cycle, relative to the start of the frame)
     (according to the above table)
  (end if)
  Delay for 4 cycles (time after 'pc:').
  If 16384<=HL<=32767 then
     (Insert the delay corresponding to the current cycle...)
  (end if)
  Store A into (HL)
  Delay for 3 cycles (time taken to store A)
                                                  Example 1: if PC = 25000 and HL =
                                                  26000
                                                  and
                                                  the instruction at address 25000 is LD (HL),A and we're in
                                                  cycle 14335:
  
                                                  
                                                       - Insert 6 cycles (count for cycle 14335) going to
                                                            14341.
                                                       
 
                                                       - Read the opcode.
 
                                                       - Insert 4 cycles (opcode fetch). We're at cycle
                                                            14345.
                                                       
 
                                                       - Insert 4 cycles (count for cycle 14345). We're at
                                                            14349.
                                                       
 
                                                       - Store the byte.
 
                                                       - Insert 3 cycles (write to (HL)).
 
                                                    
                                                  Next opcode will be read at cycle 14352 (and 5 cycles will
                                                  be
                                                  inserted
                                                  then for sure because PC=25001).
  
                                                  Example 2: same but PC=40000 (not
                                                  contended):
  
                                                  
                                                       - Read the opcode.
 
                                                       - Insert 4 cycles (opcode fetch). We're at cycle
                                                            14339.
                                                       
 
                                                       - Insert 2 cycles (count for cycle 14339). We're at
                                                            14341.
                                                       
 
                                                       - Store the byte.
 
                                                       - Insert 3 cycles (write to (HL)).
 
                                                    
                                                  Access to I/O ports is treated slightly differently to
                                                  access to
                                                  memory; full details are given in the Contended Input/Output
                                                  section. The
                                                  delays specified there should be applied when an I/O port is
                                                  accessed;
                                                  this is designated by "IO" in the table below.
  
                                                  The values for the registers listed in the table below are
                                                  relative to
                                                  the starting value of the register when the instruction is
                                                  about
                                                  to be
                                                  executed.
  
                                                  In the table below:
  
                                                  
                                                       - dd is any of the registers BC,DE,HL,SP
 
                                                       - qq is any of the registers BC,DE,HL,AF
 
                                                       - ss is any of the registers BC,DE,HL
 
                                                       - ii is either of the index registers IX or IY.
 
                                                       - cc is any (applicable) condition
                                                            NZ,Z,NC,C,PO,PE,P,M
                                                       
 
                                                       - nn is a 16-bit number
 
                                                       - n is an 8-bit number
 
                                                       - b is a number from 0 to 7 (BIT/SET/RES
                                                            instructions)
                                                       
 
                                                       - r and r' are any of the registers A,B,C,D,E,H,L
                                                       
 
                                                       - alo is an arithmetic or logical operation:
                                                            ADD/ADC/SUB/SBC/AND/XOR/OR and CP
 
                                                       - sro is a shift/rotate operation:
                                                            RLC/RRC/RL/RR/SLA/SRA/SRL
                                                            and SLL (undocumented)
 
                                                    
                                                  Further notes:
  
                                                  
                                                       - For conditional instructions, entries in [square
                                                            brackets]
                                                            are applied if the condition is met. If the
                                                            instruction
                                                            is
                                                            not conditional (e.g. CALL nn) the entries in []
                                                            always
                                                            apply.
 
                                                       - The replacement of HL by either IX or IY does not
                                                            affect
                                                            the
                                                            timings, except for the addition of an initial
                                                            pc:4 for
                                                            the
                                                            DD or FD prefix; similarly, a DD or FD prefix on
                                                            an
                                                            instruction which does not involve HL just adds an
                                                            initial
                                                            pc:4.
 
                                                       - The undocumented
                                                                 variants of the doubly shifted DDCB and
                                                            FDCB
                                                            opcodes have the same timings as the documented
                                                            versions.
                                                       
 
                                                       - In some read-modify-write operations (like INC
                                                            (HL)),
                                                            the
                                                            write operation is always the last one. That may
                                                            be
                                                            important to know the exact point in which video
                                                            is
                                                            updated,
                                                            for example. In such instructions that point is
                                                            annotated
                                                            for clarity as "(write)" after the address.
 
                                                    
                                                      Instruction    Breakdown
    -----------    ---------
    NOP            pc:4
    LD r,r'
    alo A,r
    INC/DEC r
    EXX
    EX AF,AF'
    EX DE,HL
    DAA
    CPL
    CCF
    SCF
    DI
    EI
    RLA
    RRA
    RLCA
    RRCA
    JP (HL)
    NOPD           pc:4,pc+1:4
    sro r
    BIT b,r
    SET b,r
    RES b,r
    NEG
    IM 0/1/2
    LD A,I         pc:4,pc+1:5
    LD A,R
    LD I,A
    LD R,A
    INC/DEC dd     pc:6
    LD SP,HL
    ADD HL,dd      pc:11
    ADC HL,dd      pc:4,pc+1:11
    SBC HL,dd
    LD r,n         pc:4,pc+1:3
    alo A,n
    LD r,(ss)      pc:4,ss:3
    LD (ss),r
    alo A,(HL)     pc:4,hl:3
    LD r,(ii+n)    pc:4,pc+1:4,pc+2:3,pc+2:1 x 5,ii+n:3
    LD (ii+n),r
    alo A,(ii+n)
    BIT b,(HL)     pc:4,pc+1:4,hl:3,hl:1
    BIT b,(ii+n)   pc+1:4,pc+2:3,pc+3:3,pc+3:1 x 2,ii+n:3,ii+n:1
    LD dd,nn       pc:4,pc+1:3,pc+2:3
    JP nn
    JP cc,nn
    LD (HL),n      pc:4,pc+1:3,hl:3
    LD (ii+n),n    pc:4,pc+1:4,pc+2:3,pc+3:3,pc+3:1 x 2,ii+n:3
    LD A,(nn)      pc:4,pc+1:3,pc+2:3,nn:3
    LD (nn),A
    The following entry applies to the unprefixed version of these
    opcodes (22 and 2A)
    LD HL,(nn)     pc:4,pc+1:3,pc+2:3,nn:3,nn+1:3
    LD (nn),HL
    The following entry applies to the prefixed version of these
    opcodes (ED43, ED4B, ED53, ED5B, ED63, ED6B, ED73 and ED7B)
    LD dd,(nn)     pc:4,pc+1:4,pc+2:3,pc+3:3,nn:3,nn+1:3
    LD (nn),dd
    INC/DEC (HL)   pc:4,hl:3,hl:1,hl(write):3
    SET b,(HL)     pc:4,pc+1:4,hl:3,hl:1,hl(write):3
    RES b,(HL)
    sro (HL)
    INC/DEC (ii+n) pc:4,pc+1:4,pc+2:3,pc+2:1 x 5,ii+n:3,ii+n:1,ii+n(write):3
    SET b,(ii+n)   pc:4,pc+1:4,pc+2:3,pc+3:3,pc+3:1 x 2,ii+n:3,ii+n:1,ii+n(write):3
    RES b,(ii+n)
    sro (ii+n)
    POP dd         pc:4,sp:3,sp+1:3
    RET
    RETI           pc:4,pc+1:4,sp:3,sp+1:3
    RETN
    RET cc         pc:5,[sp:3,sp+1:3]
    PUSH dd        pc:5,sp-1:3,sp-2:3
    RST n
    CALL nn        pc:4,pc+1:3,pc+2:3,[pc+2:1,sp-1:3,sp-2:3]
    CALL cc,nn
    JR n           pc:4,pc+1:3,[pc+1:1 x 5]
    JR cc,n
    DJNZ n         pc:5,pc+1:3,[pc+1:1 x 5]
    RLD            pc:4,pc+1:4,hl:3,hl:1 x 4,hl(write):3
    RRD
    IN A,(n)       pc:4,pc+1:3,IO
    OUT (n),A
    IN r,(C)       pc:4,pc+1:4,IO
    OUT (C),r
    EX (SP),HL     pc:4,sp:3,sp+1:4,sp(write):3,sp+1(write):3,sp+1(write):1 x 2
    LDI/LDIR       pc:4,pc+1:4,hl:3,de:3,de:1 x 2,[de:1 x 5]
    LDD/LDDR
    CPI/CPIR       pc:4,pc+1:4,hl:3,hl:1 x 5,[hl:1 x 5]
    CPD/CPDR
    INI/INIR       pc:4,pc+1:5,IO,hl:3,[hl:1 x 5]
    IND/INDR
    OUTI/OTIR      pc:4,pc+1:5,hl:3,IO,[hl:1 x 5]
    OUTD/OTDR
                                                  The above information is correct for the 48K ZX Spectrum -
                                                  for
                                                  the
                                                  128k/+2 models the contention sequence starts at cycle
                                                  14361.
  
                                              
                                             - Contended
                                                            Input/Output
 
                                                  It takes four T states for the Z80
                                                  to
                                                  read a value from an I/O port, or write a value to a port.
                                                  As is
                                                  the
                                                  case with memory access, this can be lengthened by the ULA. There are two effects
                                                  which
                                                  occur
                                                  here:
  
                                                  
                                                       - If the port address being accessed has its low bit
                                                            reset, the
                                                            ULA is required to
                                                            supply
                                                            the
                                                            result, which leads to a delay if it is currently
                                                            busy
                                                            handling the screen.
 
                                                       - The address of the port being accessed is placed on
                                                            the
                                                            data
                                                            bus. If this is in the range 0x4000 to 0x7fff, the
                                                            ULA treats this as
                                                            an
                                                            attempted access to contended memory and therefore
                                                            introduces a delay. If the port being accessed is
                                                            between
                                                            0xc000 and 0xffff, this effect does not
                                                            apply,
                                                            even
                                                            on a 128K machine if a contended memory bank is
                                                            paged
                                                            into
                                                            the range 0xc000 to 0xffff.
 
                                                    
                                                  These two effects combine to lead to the following
                                                  contention
                                                  patterns:
                                                      High byte   |         |
    in 40 - 7F? | Low bit | Contention pattern
    ------------+---------+-------------------
         No     |  Reset  | N:1, C:3
         No     |   Set   | N:4
        Yes     |  Reset  | C:1, C:3
        Yes     |   Set   | C:1, C:1, C:1, C:1
                                                  The 'Contention pattern' column should be interpreted from
                                                  left
                                                  to
                                                  right. An "N:n" entry means that no delay is applied at this
                                                  cycle,
                                                  and the Z80 continues
                                                  uninterrupted for
                                                  'n' T states. A "C:n" entry means that the ULA halts the Z80; the delay is exactly
                                                  the
                                                  same as
                                                  would occur for a contended memory access at this cycle (eg
                                                  6 T
                                                  states
                                                  at cycle 14335, 5 at 14336, etc on the 48K machine). After
                                                  this
                                                  delay,
                                                  the Z80 then continues for
                                                  'n'
                                                  cycles.
  
                                                  For reference, the following changes have been made to the
                                                  previous
                                                  two sections since version 1.1.4 of the FAQ (10 April
                                                  2004):
  
                                                  
                                                       - Version 1.1.5
                                                            
                                                                 - Correct the values for the first
                                                                      contended
                                                                      cycle to
                                                                      be 14335 and 14361 for the 48K and 128K
                                                                      machines
                                                                      respectively.
 
                                                                 - The table above now includes any prefixes
                                                                      on
                                                                      the
                                                                      instruction.
 
                                                                 - The pc+2:3 entry in CALL cc,nn applies
                                                                      when
                                                                      the
                                                                      condition is false.
 
                                                                 - The hl:4 entry in BIT b,(HL), INC/DEC
                                                                      (HL),
                                                                      SET
                                                                      b,(HL), RES b,(HL) and sro (HL)
                                                                      corrected to
                                                                      hl:3,hl:1.
 
                                                                 - The hl:7 entry in RLD and RRD corrected
                                                                      to
                                                                      hl:3,hl:1 x 4.
 
                                                                 - The sp+1(write):5 entry in EX (SP),HL
                                                                      corrected to
                                                                      sp+1(write):3,sp+1(write):1 x 2.
 
                                                                 - Added information about the (IX+n) and
                                                                      (IY+n)
                                                                      instructions.
 
                                                                 - Corrected information on INI, IND, INIR,
                                                                      INDR,
                                                                      OUTI, OUTD, OTIR and OTDR.
 
                                                                 - Added information on the delays that port
                                                                      address
                                                                      being between 0x4000 and 0x7fff
                                                                      introduces.
                                                                 
 
                                                             
                                                        
                                                    
                                                  | special thanks to  Jonathan
                                                            Needle for correcting and clarifying the
                                                       previous
                                                       two
                                                       entries |  
                                              
                                         
                                        ZX Interface I: 
                                             The ZX Interface I 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
                                             0x0008 or 0x1708, the error and close# routines.
                                             It is inactivated when the Z80
                                             executes
                                             the
                                             RET at address 0x0700.
  
                                             Geoff
                                                  Wearmouth provides complete assembly listings of version
                                             1
                                             and 2 (used after serial number 87315) of the ZX Interface I ROM
                                             at
                                             his web site.
                                             You may find these helpful while reading this
                                             section.
  
                                             There are 3 subsections available:
                                             Port 0xe7,
                                             Port 0xef and
                                             Port 0xf7. 
                                        
                                             - Port 0xe7
 
                                                  I/O Port 0xe7 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'.
 
  
                                             - Port 0xef
 
                                                  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.
  
                                                  
                                              
                                             - Port 0xf7
 
                                                  If the microdrive is not being used, the COMMS DATA output
                                                  selects the
                                                  function of bit 0 of OUT-Port 0xf7:
  
                                                  
                                                  TXDATA and RXDATA are the input and output of the RS232
                                                  port.
                                                  COMMS
                                                  DATA determines whether bit 0 of 0xf7 is output
                                                  for the RS232 or the network.
                                              
                                         
                                        | please note that the busy signal on Port
                                             0xef
                                             is
                                             not used by software - just hardware. Thanks to Geoff Wearmouth
                                             for
                                             pointing this out | 
                                        Tape Data
                                                       Structure: 
                                             The SAVE command produces two blocks on tape: a 19 byte header
                                             block
                                             and a variable length data block. 
                                        Each block has the following structure: 
                                        
                                             -  A leader consisting of 8063 (for header blocks) or 3223
                                                  (data blocks) pulses, each of which has a duration of 2168
                                                  tstates.
                                             
 - A first sync pulse of 667 tstates.
                                             
 - A second sync pulse of 735 tstates.
                                             
 - The block data: a reset bit is encoded as two pulses of
                                                  855 tstates each, a set bit as two pulses of 1710 tstates
                                                  each. The lowest byte in memory is first on tape, with the
                                                  most significant bit first within each byte.
                                        
  
                                        Notes: 
                                        
                                             - The TZX
                                                       format specification incorrectly states that header
                                                  pulses
                                                  contain 8064 leader pulses and data blocks 3220.
                                             
 - All timings above are without taking output
                                                       contention into account.
                                        
  
                                        Within each block, the data has the following structure: 
                                        
                                             - A flag byte: this is 0x00 for header blocks and 0xff for
                                                  data blocks.
                                             
 - The actual data.
                                             
 - A checksum byte, calculated such that XORing all the data
                                                  bytes together (including the flag byte) produces 0x00.
                                        
  
                                        The structure of the 17 byte tape header is as follows. 
                                        Byte    Length  Description
---------------------------
0       1       Type (0,1,2 or 3)
1       10      Filename (padded with blanks)
11      2       Length of data block
13      2       Parameter 1
15      2       Parameter 2
 
                                        These 17 bytes are prefixed by the flag byte (0x00) and suffixed by
                                             the checksum byte to produce the 19 byte block seen on tape. The
                                             type
                                             is 0,1,2 or 3 for a PROGRAM, Number array, Character array or
                                             CODE
                                             file. A SCREEN$ file is regarded as a CODE file with start
                                             address
                                             16384 and length 6912 decimal. If the file is a PROGRAM file,
                                             parameter 1 holds the autostart line number (or a number >=32768
                                             if no
                                             LINE parameter was given) and parameter 2 holds the start of the
                                             variable area relative to the start of the program. If it's a
                                             CODE
                                             file, parameter 1 holds the start of the code block when saved,
                                             and
                                             parameter 2 holds 32768. For data files finally, the byte at
                                             position
                                             14 decimal holds the variable name. 
                                        For example, SAVE "ROM" CODE 0,2 will produce the following data on
                                             tape (the vertical bar denotes the break between blocks): 
                                        00 03 52 4f 4d 7x20 02 00 00 00 00 80 f1 | ff f3 af a3
^^ ................ flag byte
   ^^ ............. first byte of header, indicating a code block
      ^^^^^^^^^^^^^ file name
header info ........^^^^^^^^^^^^^^^^^
checksum of header ...................^^
flag byte .................................^^
first two bytes of rom .......................^^^^^
checksum ...........................................^^
                                        
                                        
                                        
      |