           Z80TubeDoc for !Z80Tube - Z80 Emulator Version 1.14
           ===================================================
         J.G.Harston, 70 Camm Street, Walkley, Sheffield, S6 3TR
                 http://mdfs.net/Apps/Emulators/Z80Tube/
                            Date: 13-Nov-2008

!Z80Tube emulates a Z80 coprocessor attached to a ARM computer in the same
way that !65Tube emulates a 6502 coprocessor. !Z80Tube runs on Arthur, RISC
OS and on the ARM CoPro connected to a BBC or Master.

Opening a RISC OS filer window containing !Z80Tube sets up alias commands
*Z80 and *CPM to start Z80 emulation, and a pathname Z80Tube: pointing to
the resources inside !Z80Tube.

Double-clicking on !Z80Tube starts the emulator with default settings. These
can be altered with a Choices:Z80Tube.Choices file.


*Z80 command
============
The *Z80 command enters Z80Tube and starts running the Z80 emulator. It can
be given the following command line options:

        *Z80 [-debug] [-rma] [-app] [-mos file] [file [params]]

-debug  If given, after every opcode executed, a register dump is displayed
        at the top of the screen. This also slows the emulator down
        considerably.

-rma    Claim memory from the RAM for the Z80 environment. This is the
        default option, and if you want to run a Z80 Wimp task you should
        use this option. If no RMA space exists then application space will
        be used instead.

-app    Use application space memory for the Z80 environment. Z80Tube
        currently won't run as a Wimp task if run in the application space.

-mos    Provide a MOS file to load to the top of memory. This can provide
        some interface facilities between the Z80 environment and the host.
        The default MOS code just passes all calls over. The MOS provided
        within !Z80Tube provides some command line facilities that need to
        be executed from with the Z80 environment to work properly.

If a file is given, it is loaded into the Z80's memory according to its
filetype. Any extra parameters are copied to the command buffer at &0080 for
the loaded program to collect and deal with. An example command line would
be:

        Z80 -mos Z80Tube:MOS TestProg This is a command line

This would start the emulator using the MOS file provided with !Z80Tube,
load the file TestProg into memory, copy the text 'This is a command line'
to &0080, and enter the code at the relevant entry point.

If a BASIC file is specified, with filetype &FFB (BASIC) or &1C7 (Basic8),
the emulator looks for a file specified by <Z80Tube$Basic>, and passes the
pathname of the BASIC file to it. In effect, it alters the command line
from:

        *Z80 basicfile Parameters
to
        *Z80 <Z80Tube$Basic> basicfile Parameters


*CPM command
============
The *CPM command enters Z80Tube and boots CPM by loading the Acorn CPM
system tracks from drive 0 or the disk image file pointed to with
<Z80Tube$Drive0>. It has no command line options.

Provided within the !Z80Tube application is a *CPM command which can be run
with *Run Z80Tube:CPM. It attempts to load CPM system tracks in Acorn format
from the Z80's drive 0, and then enter it. There is also a CPM command in
the Z80 Host MOS, so doing *CPM from within the emulator will enter CPM. A
future version will include a rewritten BDOS to pass CPM file calls direct
to the host OS.


Filetypes Recognised
====================
Filetype:     &201
Name:         CPMCOM
Description:  A CPM .COM file, intended to load and execute at &0100.
Run Action:   Loads the default MOS file (or any specified with the -mos
              switch) to high memory. Any parameters are copied to the
              parameter buffer at &0080. Zero page pointers are set up
              with (0001/2)=>MOS_start+6 and (0006/7)=>MOS_start. Code
              is loaded to and entered at &0100 with SP=MOS_start-2 and
              a return address of &0000 on the stack.

Filetype:     &2F8
Name:         Z80MOS
Description:  MOS interface code between the Z80 environment and the host.
Run Action:   Loads to &10000-filelength. Zero page pointers are set up
              with (0001/2)=>MOS_start+6 and (0006/7)=>MOS_start. Code
              is entered at MOS_start+3 with SP=MOS_start-2 and a return
              address of &0000 on the stack. MOS files should be of a
              length so that the first byte is loaded at the address
              implied by the filetype, ie at &F800 in the Z80.

The emulator will also recognise files with a filetype of &2F0-&2FF as MOS
files and loads them as above. I have used type &2FF for test purposes in
developing. Type &2F0 can be used as a 4K MOS file.

Filetype:     &1C7
Name:         Basic8
Description:  BBC BASIC program in Russell format.
Load Action:  If passed as a parameter to *Z80, loads the default MOS file
              (or any specified with the -mos switch) to high memory. The
              file specified with <Z80Tube$Basic> is loaded to memory at
              &0100 The filename and any parameters are copied to the
              parameter buffer at &0080. Zero page pointers are set up with
              (0001/2)=>MOS_start+6 and (0006/7)=>MOS_start. The code is
              entered at &0100 with SP=MOS_start-2 and a return address of
              &0000 on the stack.

Filetype:     &FFB
Name:         BASIC
Description:  BBC BASIC program in Acorn/Wilson format.
Load Action:  If passed as a parameter to *Z80, loads the default MOS file
              (or any specified with the -mos switch) to high memory. The
              file specified with <Z80Tube$Basic> is loaded to memory at
              &0100 The filename and any parameters are copied to the
              parameter buffer at &0080. Zero page pointers are set up with
              (0001/2)=>MOS_start+6 and (0006/7)=>MOS_start. The code is
              entered at &0100 with SP=MOS_start-2 and a return address of
              &0000 on the stack.

The emulator also recognises untyped files with load address < &10000 and
execution address < &10000, ie a code file intended to load into language
processor memory. If this type of file is given as a parameter to *Z80, or
is *Run from inside the Z80 environment, it is loaded into Z80 memory at the
load address, parameters are copied to &0080, and it is entered at it's
execution address. If it is given as a parameter to *Z80, then the default
or any specified MOS file is loaded, SP=MOS_start-2 and a return address of
&0000 is on the stack.

When within !Z80Tube, attempting a *command that runs a file from disk will
first check to see if it can be recognised as a Z80 file. If so, it is
loaded into the Z80's memory and executed there. Otherwise, it is passed on
to the MOS to deal with.

Due to a bug in the host code, the real Z80 coprocessor enters runnable code
with the stack unbalanced. A POP is needed before returning otherwise a
crash will occur. Some later coprocessor hosts and the emulator enters code
with the stack balanced. To differentiate, the Zero flag is set differently.
If the stack is unbalanced, the zero flag is set; if it is balanced, the
zero flag is clear. For code to be able to run on both the emulator and the
Z80 coprocessor properly, a transient program should start with the
following two instructions:

        JR  NZ,P%+3:POP AF:\ Balance stack

Code that starts with a ROM header is entered correctly.


The Z80 Environment
===================
By default, Z80Tube starts by running BBC BASIC(Z80) for the BBC Tube. This
is Richard Russell's BBC BASIC(Z80) for CP/M on the Tube converted to use
BBC I/O. Also supplied is a disk image file containing the BBC BASIC(Z80)
for Tube CP/M distribution. Setting BASIC/DSK as Z80Tube drive 0 with

        *Set Z80Tube$Drive0 <Z80Tube$Dir>.^.BASIC/DSK

and then starting CP/M gives you access to them.

BBC BASIC(Z80) is copyright (C) Richard Russell (http://www.rtrussell.co.uk).
Richard has given permission for full distribution of BBC BASIC(Z80) to be
freely distributed as long as the full distribution is distributed.


Zero Page Locations
~~~~~~~~~~~~~~~~~~~
0000:  JP RESET         Jumping to location &0000 is used to quit a program.
                        The emulator sets this to point to MOS_start+3, the
                        entry to quit the emulator, and starts running
                        programs with the return address &0000 on the
                        stack. After a successful call to *CPM, jumping
                        to this location will cause a call to LD_CCP to
                        reload the CCP and BDOS. The value at &0001/2, the
                        destination of the jump, can also be used as the
                        value BIOS+3, the I/O interface part of the MOS. If
                        a non-CPM application calls &0000, the emulator
                        quits.

0003:   DEFB 0          IOBYTE within CP/M
0004:   DEFB 0          Drive and User within CP/M

0005:   JP BDOS         Jumping to location &0005 is used to call a CPM BDOS
                        routine. The emulator sets this to point to
                        MOS_start, which returns with all registers
                        unchanged. When CPM is running, the BDOS points
                        this entry to the BDOS service routine. The value at
                        &0006/7, the destination of the jump, can also be
                        used as the value of BDOS+6, the byte after the
                        highest byte in memory available to the user.

0008:
 to                     These locations are not set to anything.
000D:

000E:   POP HL          Calling location &000E with load the HL register
                        with the address of the location after the call, ie
                        CALL &000E can be thought of as LD HL,PC, as a
                        complement to JP (HL) which can be thought of as
                        LD PC,HL.
000F:   JP (HL)         Calling location &000F will jump to the address in
                        the HL register, ie CALL &000F can be thought of as
                        CALL (HL) as a complement to JP (HL).

0010:
 to                     These locations are not set to anything.
0037:

0038:                   Error restart. The MOS initialises this to the
 to                     default error handler, and any foreground program
003A:                   will set it to its own error handler.

003B:
 to                     These locations are not set to anything.
007F:

0080:                   Parameter buffer. This byte contains the length of
                        any passed parameter string, ie zero if no
                        parameters present.
0081:                   This buffer contains any passed parameters. Note
 to                     that there may not be a CR at the end of this
00FF:                   string.


Error Handling
~~~~~~~~~~~~~~
If an error occurs on the host, the error message and the low byte of the
error number is copied to the error buffer with a RST &38 instruction before
it, and then the RST &38 is jumped to. This is slightly different to the
actual Z80 coprocessor, which sets up a call to the address of the jump at
RST_38. An error can be created within the Z80 environment with RST &38 if
the jump at &0038 has been initialised. The default MOS initialises this to
a default error handler. The form of an error is as follows:

        RST     &38
        DEFB    error_number
        DEFM    "Error string"
        DEFB    0


OSWORD
~~~~~~
!Z80Tube provides the following OSWORD calls to programs calling from within
the Z80 environment:

OSWORD &06, &07 - Read I/O memory, Write I/O memory
These calls read a write a byte to or from the ARM memory.


OSWORD &7F (127) - FM Disk Access
Calls &4B and &53 to read and write sectors are supported. Drive surfaces
are numbered as for DFS:
    0 - drive 0, side 0       2 - drive 0, side 1
    1 - drive 1, side 0       3 - drive 1, side 1

The variables Z80Tube$Drive* can be set to point to a floppy drive number or
to an image file. For example, if '*Set Z80Tube$Drive1 0' is used, access to
the Z80's drive 1 will access physical drive 0. If '*Set Z80Tube$Drive0
ADFS::IDEDisc4.Z80.CPMImage0' is used, access to the Z80's drive 0 will
access the disk image file.


OSWORD &C8 (200) - Do SYS call
This Osword executes an ED 0D sequence to do a SYS call, as detailed below.


OSWORD &FF (255) - Z80 Memory Transfer
A real Z80 coprocessor copies some code into the 6502 host to provide a
memory transfer routine. This is used by CPM to buffer the disk's directory
in the i/o processor and speed up disk accesses. !Z80Tube provides Osword
&FF, addressing a restricted buffer of &1000 bytes, ie accessing &2000 is
the same &3000, &4000, etc. This is adequate as CPM uses &A00 bytes from
&2500 to buffer the directory.


MOS File Header
~~~~~~~~~~~~~~~
A MOS file, which is loaded into high memory, should have some defined
entry points at the start:

MOS_BDOS:       JP DoBDOS       Location 5/6/7 points to here
MOS_RUN:        JP DoRUN        Enters here if MOS file is executed
MOS_RESET:      JP DoRESET      Location 0/1/2 points to here

When the emulator starts, SP is set to the start of the MOS, and then the
return address of &0000 is pushed on it. This way, code can finish with
either a RET or a JP 0. The code at &0000 is set up to point to MOS_RESET
which usually terminates the emulator and returns to the previous caller.

If a MOS file is executed, then it is entered at MOS_RUN.


Z80 MOS Entry Points
~~~~~~~~~~~~~~~~~~~~
As well as the standard MOS entry points which are documented in Appendix J
of the CP/M manual, and listed in the Z80-BBCBASIC manual, there exists some
other very useful entry points. This is a complete list of them.  The ones
implemented in the default MOS are PR_HEX, PR2HEX, USERINT, PR_TEXT, PRNT_C,
CLI_COM, RST_38, INIT_ERR, and the standard MOS entries.

ESCFLG    &FF80  Escape flag
TERMFLG   &FF81  TERM flag
FAULT     &FF82  Fault pointer
DEF_ERR   &FF84  Address of default error handler

PR_OUT    &FF9E  Print a character to OSWRCH or TERMOUT
On entry: A = character to be printed
On exit:  with TERM set to OSWRCH:
              all registers preserved.
          with TERM set to TERMOUT:
              C is corrupted
              HL is corrupted after sending ESC &3F (clear to end of screen)
                 or ESC &40 (clear to end of line)

Calling this routine either calls the OSWRCH code, or the TERMOUT code,
depending on the setting of TERM. Altering TERM alters the address field of
this entry to point to the required code. When TERM is set to TERMOUT, the
following ESCape sequences are obeyed:

          ESC, &3D ('='), Y, X        move cursor to X-32,Y-32
          ESC, &3E ('>'), C, C ... 0  print characters C-32, until C=0
          ESC, &3F ('?')              clear to end of screen
          ESC, &40 ('@')              clear to end of line

Any other ESC, char sequence is ignored. ESC ? and ESC @ only work correctly
in 80 column screen modes

INIT_FF   &FFA1  Set up OSWORD &FF in host
On entry: -
On exit:  HL, DE, B, A are corrupted

Calling this routine sets up the code to handle OSWORD &FF (block transfer)
in the host processor. It is called by the TUBE OS on startup, and should
not be called again, as then the vector daisy-chaining will end in a loop.
The JGH BBCBASIC(Z80) ROM initialisation removes this call by putting a RET
opcode at location &FFA1.

M_OSWD_7F &FFA4  Multiple OSWORD &7F call
On entry: HL points to the OSWORD &7F control block
On exit:  A holds the result byte from (HL+10). A=0 means ok.
          B, C, DE are corrupted.

This routine tries to access a disk drive. The call is made up to 40 times
before giving up and returning with the failure result byte in A. Every ten
unsuccessful attempts, the routine tries to seek to track zero, sector zero
on the drive being accessed, before continuing to attempt to access the
drive. If the routine succeeds, then zero is returned in the A register,
otherwise A holds the disk error number.

LD_CCP    &FFA7  Load CCP and BDOS
On entry: -
On exit:  A holds zero if successful.
          BC, DE, HL are corrupted.

This routine loads the Acorn CP/M CCP and BDOS from the disk in drive zero,
using the code of the multiple OSWORD &7F call detailed above. If a disk
error occurs, the error 'Disk fault', number 0 is generated. The memory
loaded is:
          Track 0, sectors 8 and 9 loaded to &D400 to &D5FF
          Track 1, sectors 0 to 9 loaded to &D600 to &DFFF
          Track 2, sectors 0 to 9 loaded to &E000 to &E9FF
In effect, the routine loads sectors 0/8 to 2/9 to memory &D400 to &E9FF.
The Acorn BIOS calls this on a soft CPM reset to reload the CCP.

PR_HEX    &FFAA  Print A in hex
On entry: A = value to be printed
On exit:  A is corrupted

This routine prints out the A register in hexadecimal to two digits with
leading zeros. This routine is overwritten by the Acorn BIOS in CPM.

PR2HEX    &FFAD  Print HL in hex
On entry: HL = value to be printed
On exit:  A is corrupted

This routine prints out the HL register in hexadecmial to four digits with
leading zeros. This routine is overwritten by the Acorn BIOS in CPM.

USERINT   &FFB0  User interupt routine
On entry: -
On exit:  -

This call is made if an unrecognised interupt occurs. By default it just
points to a RET instruction. Any routine that intercepts this call MUST
preserve ALL registers. As it is called on an interupt, it should not last
longer than about 5 msecs. at the maximum.

PR_TEXT   &FFB3  Print in-line text
On entry: -
On exit:  -

This routine prints out the text following the call to OSASCI. The text
should be terminated with a zero byte, which also gets printed, eg:
          CALL PR_TEXT
          DEFM "HELLO THERE":NOP
          \ continue here
This routine is overwritten by the Acorn BIOS in CPM.

PRNT_C    &FFB6  Send C to TERMOUT
On entry: C = character to be printed
On exit:  A is corrupted
          HL is corrupted after sending ESC &3F and ESC &40

Calling this routine prints the character in the C register using TERMOUT.
See the description of PR_OUT at address &FF9E.

CLI_COM   &FFB9  Enter CLI processor
No entry parameters
No exit from call

Calling this routine enters the CLI processor. This presents a '*' prompt
and sends all input to OSCLI.

RST_38    &FFBC  Default error jump
On entry: -
On exit:  -

The default error jump code to initialise locations &0038 to &003A with.
Enters the default error handler which displays the error message and then
enters the CLI processor.

INIT_ERR  &FFBF  Initialise default error code
On entry: -
On exit:  -

Copies the default error jump code at &FFBC to locations &0038 to &003A.

SEEK_0    &FFC2  Seek track zero
On entry: A=drive
On exit:  -

Temporarily sets SP to &FF80 and does an OSWORD &7F to seek track zero of
drive 0.

KBD_TST   &FFC5  Reads status of keyboard input
On entry: -
On exit:  A holds &00 if no characters pending
          A holds &FF if there are input characters pending

This routine tests if there are any characters waiting to be read, either in
the input buffer, or from a soft key expansion. A returns &00 if there are
no characters pending, or &FF if there are.

TERM      &FFC8  Read or set the TERM status
On entry: A read or set parameter
On exit:  A holds the old TERM status, or preserved if invalid parameter
          HL is corrupted or preserved if A holds an invalid parameter

The calls sets whether the PR_OUT routine at address &FF9E calls OSWRCH or
TERM_OUT. The entry values for A are:
           A=0    Set PR_OUT to do OSWRCH
           A=1    Set PR_OUT to do TERM_OUT
           A=&FF  Read current setting
If A does not hold one of these values, then the routine does nothing.

OSWRD2    &FFCB  Do an OSWORD call, reading the control block to DE
On entry: A is the OSWORD call number
          HL points to the control block
          DE points to where to receive the returned control block
On exit:  -

This call does a standard OSWORD call, but the returned control block is put
into the memory pointed to by DE.

The following entry points are the standard BBC entries:

OSFIND    &FFCE  Open or close a file
OSGBPB    &FFD1  Multiple byte file access
OSBPUT    &FFD4  Put a byte to a file
OSBGET    &FFD7  Get a byte from a file
OSARGS    &FFDA  Read or set file arguments
OSFILE    &FFDD  Load or save file
OSRDCH    &FFE0  Input a character
OSASCI    &FFE3  Print a character, with CR converted to LF,CR
OSNEWL    &FFE7  Print a LF,CR sequence
OSWRCH    &FFEE  Print a character
OSWORD    &FFF1  Do an OSWORD call
OSBYTE    &FFF4  Do an OSBYTE call
OSCLI     &FFF7  Interpret a command

The following three addresses hold system vectors:

BRKV      &FFFA  Address of error handler
EVENTV    &FFFC  Address of event handler
INTV      &FFFE  Address of primary interupt handler


CPU Implementation
==================
All documented Zilog Z80 opcodes are implemented, as well as the unofficial
instructions SLS r, and accessing the upper or lower halves of the index
registers as a single byte register, ie IXL, IXH, IYL, IYH. Currently,
INI[R], IND[R], OTI[R] and OTD[R] are unimplemented and act as NOPs. An IN
instruction issues the Service_Z80TubeIN call and an OUT instruction issues
a Service_Z80TubeOUT call. A Reset issues a Service_Z80TubeReset call.

All indexed rotation/bit instructions manipulate (IX+n) or (IY+n), so, for
example, FDCBnn00 to FDCBnn05 and FDCBnn07 all perform as though they were
FDCBnn06, ie RLC (IY+nn). On a real Z80 the 8bit registers are stored to
after the operation. For instance, FDCBnn00 does a RLC (IY+nn) and then
stores the result in B. This is usually written as RLC (IY+nn)->B.

Sixteen extra instructions have been added to control the emulator and to
comunicate with the host, EDF0 to EDFF.

The bottom seven bits of the R register are incremented every time R is
loaded from, ie every LD A,R instruction, rather than on every instruction
cycle. Bit 7 of R remains the same value as from the last LD R,A
instruction.

The flags register is manipulated as specified. Unoffical flag effects, such
as bit 5 following bit 5 of an arithmetic result, are not implemented.


Undefined Instruction Traps
~~~~~~~~~~~~~~~~~~~~~~~~~~~
If an undefined DD, ED or FD instruction is encountered, then a trap may be
executed. The three traps are EDtrap, IXtrap and IYtrap, and they may be set
and read with pseudo-opcodes ED 0E and ED 0F. Initially, all traps are
disabled. This makes undefined ED instructions act as a NOP, and undefined
index instructions perform the unindexed opcode, as on a hardware Z80.

The traps must be set and read with the 32-bit calls, ie with A set to &80+x
and HL pointing to a 4-byte block containing the address.

The bottom two bytes specify the address within the Z80 memory map, and the
top two bytes specify how that address is used, as follows:

        &0000aaaa       jumps to address aaaa
        &0001aaaa       jumps to contents of address aaaa and aaaa+1
        &FFFFFFFF       trap unset, treated as NOP, only bit 31 significant

The trap is entered with the return address (the address after the
unrecognised opcode) and AF pushed on the stack, and A holding the
unrecognised opcode. The following bit of code shows how to initialise
EDtrap to jump to a null routine:

        Trap with a jump        Trap through a vector

                                LD      HL,EDTrap
                                LD      (EDVector),HL
        LD      HL,Block        LD      HL,Block
        LD      A,&87           LD      A,&87
        DEFW    &0FED           DEFW    &0FED
        :                       :
        .Block                  .Block
        DEFW    EDTrap          DEFW    EDVector
        DEFW    &0000           DEFW    &0001
                                :
                                .EDVector
                                DEFW    &0000
        :                       :
        .EDTrap         :\ On entry, A=unrecognised opcode
        POP     AF      :\ Retrieve AF
        RET             :\ Return


Host Interface
==============
Sixteen extra instructions have been added to control the emulator and to
comunicate with the host, ED F0 to ED FF:

ED FF - Quit    Executing this will terminate the emulator. The jump to
                RESET at &0000 points to code that executes this opcode.

Standard MOS interface calls:
ED FE - CLI     Passes the command line pointed to by HL to the host. If
                the command results in a file being run from disk that can
                be recognised as a Z80 file, it is loaded directly into the
                Z80 and entered.
ED FD - BYTE    Does OSBYTE A, L, H; returning results in A, L, H and
                Carry. The memory value request OSBYTEs &82, &83 and &84
                are trapped and returned with values appropriate to the Z80
                environment. &82 (High order address) returns &0000, &83
                (Lowest address of memory) returns &0100, &84 (top of user
                memory) returns the contents of &0006/7.
ED FC - WORD    Does OSWORD A with HL pointing to the parameter block.
                OSWORD 0 (read line) returns values in H and Carry.
ED FB - WRCH    Outputs character in A.
ED FA - RDCH    Read character to A and Carry.
ED F9 - FILE    A=function, HL=>control block.
ED F8 - ARGS    A=function, E=channel, HL=>control block.
ED F7 - BGET    H=channel, returns character in A and Carry.
ED F6 - BPUT    A=character, H=channel.
ED F5 - GBPB    A=function, HL=control block
ED F4 - FIND    A=0 and H=channel or A<>0 and HL=>filename

Emulator control calls:
ED F3 - MISC    Miscellaneous control functions. A=function on entry. On
                exit, A=0 if operation completed, A<>0 if call failed. The
                only one currently defined is A=0, run <Z80Tube$Basic>. If
                successful, the call does not return, BASIC is entered.

ED F2 - SYS     Do a SYS call, HL=>control block as for OSWORD 200:
                0:      In bytes, regs*4+8
                1:      Out bytes, regs*4+8
                2:      Z80->Arm translate flags, b0-b7 => r0-r7
                3:      Arm->Z80 translate flags, b0-b7 => r0-r7
                4-7:    SWI number
                8-11:   r0
                11-15:  r1
                :
                36-39: r7
                If the relevant bits are set in byte 3 and 4, then the
                values given for the registers are translated from 16-bit
                Z80 address to 32-bit ARM addresses before calling the SYS
                function, and vis versa after calling. The X flag of the
                SYS call is forced on. If no error occurs, A=0, Z is set,
                zero is returned in bytes 4 to 7 of the control block and
                the returned registers are placed in bytes 8 onwards. If an
                error is returned, the 32-bit error number is placed in
                control block bytes 0 to 3, the error string terminated with
                a <CR> is returned in bytes 4 onwards, the bottom byte of
                the error number is placed in A and the Z flag is cleared.
ED F1 - RDINF   Read system information
ED F0 - WRINF   Write system information
                A=&00..&7F Reads/write 16-bit address to/from HL
                A=&80..&FF Reads/write 32-bit address to/from (HL)

Read calls with A=&00..&7F call the corresponding &80..&FF function, then
subtract the address of mem[0] to get the Z80 address returned in HL. Carry
is set if the returned address is invalid because it is outside the Z80
memory map.

Write calls with A=&00..&7F add the address of mem[0] to the value in HL,
then call the corresponding &80..&FF function.

The system information block contains the following information:

     Offset     Contents                Default value
        0: Address of start of memory     &0000
        1: Address of error buffer        &FF00
        2: Address of escape flag         &FF80
        3: Address of error vector        &FFFA
        4: Address of event vector        &FFFC
        5: Address of INT vector          &FFFE
        6: Address of NMI routine         &0066
        7: Value of EDtrap                unset
        8: Value of IXtrap                unset
        9: Value of IYtrap                unset

For compatability with earlier versions of Z80Tube, ED00 to ED0F perform the
same functions as EDFF to EDF0 (in the reverse order). Future versions of Z80Tube
will support Z280 and later CPUs which have instructions in the ED00-ED0F region.


Memory Addresses
~~~~~~~~~~~~~~~~
MOS calls WORD, FILE and GBPB whose control blocks contain addresses that
refer to memory have these addresses checked before passing them on to the
host, and on return. If the address if < &10000, it is translated to the ARM
address before being passed on. If it is > &FFFF, it is left unchanged to
refer to ARM memory.


Z80Tube Information
===================
Z80Tube:!Boot contains Z80Tube's default startup settings. If a file
Choices:Z80Tube.Choices exists it can override the default settings. The
Choices file should be an Obey file containing commands similar to the
contents of Z80Tube:!Boot. The simplest way to create a Choices file is to
copy the !Boot file to Choices:Z80Tube.Choices and edit the contents.

!Z80Tube can be run from a read-only media (eg CD-ROM), as long as the files
have the appropriate Read attributes.

!Z80Tube is 32bit compliant. Analysing the code reveals only one suspicious
instruction: OS_ReadLine. In a 26bit environment, this is called with a
26bit address with no flags in the top bits. In a 32bit environment, this is
called with a 32bit address, and OS_ReadLine assumes no flags have been
passed, which is correct.

!Z80Tube is 26/32bit clean, and should operate on any version of RISC OS,
and also on Arthur. It has been tested extensively on RISC OS 2.01, 3.11,
3.50, 3.60, and 4.03.


Z80 Service Calls
~~~~~~~~~~~~~~~~~
!Z80Tube issues service calls to access any emulated hardware that may be
present. Other software can respond to these calls to provide services to
!Z80Tube, or, indeed, any other Z80 emulator, such as a Spectrum emulator,
as specified by the emulator in R4.


&80AC0  Service_Z80IN
---------------------
Issued by an IN A,(n) or IN r,(BC) instruction. If unclaimed, !Z80Tube
assumes a value of &FF has been returned.

In:  R0=z80mem[0], R1=&80AC0, R2=port, R4=address of module/program issuing
     call
Out: R1=0 if claimed, R3=value to return


&80AC1  Service_Z80OUT
----------------------
Issued by an OUT (n),A or OUT (BC),r instruction.

In:  R0=z80mem[0], R1=&80AC1, R2=port, R3=output value, R4=address of
     module/program issuing call
Out: R1=0 if claimed


&80AC2  Service_Z80Reset
------------------------
Issued at Reset, when all registers have been cleared, and before any data
has been loaded to memory. This call allows default values to be set up and
is the emulated equivalent of the ~RESET line.

In:  R0=z80mem[0], R1=&80AC2, R4=address of module/program issuing call
Out: R1 must be preserved


&80AC3  Service_Z80Halt
------------------------
Issued when HALT opcode is executed. Can be seen as the emulated equivalent
of the the ~HALT line.

In:  R0=z80mem[0], R1=&80AC3, R4=address of module/program issuing call
Out: R1 must be preserved


Z80Tube SWI Calls
~~~~~~~~~~~~~~~~~
!Z80Tube reponds to some SWI calls. Currently, only the following calls are
defined.

&54940  Z80Tube_Status
----------------------
In:  no parameters
Out: R0=version*100, eg version 1.09 returns 109 in R0
     R1=Z80 base address. 0 if Z80 not running, <>0 if Z80 is running


Emulator Memory Map
~~~~~~~~~~~~~~~~~~~
-1K  -400 System error block
-768 -300 String buffer/CLI string space/*Set,*UnSet workspace
-512 -200 Parity table
-256 -100 MOS_SWI workspace
-216 xx28 Previous handlers:
     xx28 Previous Error handler
     xx2C Previous Error R12
     xx30 Previous Error buffer
     xx34 Previous Escape handler
     xx38 Previous Escape R12
     xx3C Previous Exit handler
     xx40 Previous Exit R12
     xx44 Previous Upcall handler
     xx48 Previous Upcall R12
-180 xx4C ARM_SP
-176 xx50 ModuleBase - ARM address of my module
-172 xx54 PrivateWord - ARM address of my private word
-168 xx58 DummyWord - a dummy private word for when running as an application
-164 xx5C
-160 xx60
-156 xx64
-152 xx68
-148 xx6C
-144 xx70
-140 xx74
-136 xx78
-132 xx7C
-128 xx80 (&mem[0])     (&0000) (SysInfo 0)
-124 xx84 Error buffer  (&FF00) (SysInfo 1)
-120 xx88 Escape flag   (&FF80) (SysInfo 2)
-116 xx8C Error vector  (&FFFA) (SysInfo 3)
-112 xx90 Event vector  (&FFFC) (SysInfo 4)
-108 xx94 Int vector    (&FFEE) (SysInfo 5)
-104 xx98 NMI Address   (&0066) (SysInfo 6)
-100 xx9C EDtrap        (unset) (SysInfo 7)
-96  xxA0 IXtrap        (unset) (SysInfo 8)
-92  xxA4 IYtrap        (unset) (SysInfo 9)
-88  xxA8                       (SysInfo 10)
-84  xxAC                       (SysInfo 11)
-80  xxB0                       (SysInfo 12)
-76  xxB4                       (SysInfo 13)
-72  xxB8                       (SysInfo 14)
-68  xxBC                       (SysInfo 15)
-64  xxC0 \ used to be Previous Escape handler
-60  xxC4 \ used to be Previous Upcall handler
-56  xxC8 \ used to be Previous Exit handler
-52  xxCC \ used to be Previous Error handler
-48  xxD0
-44  xxD4
-40  xxD8 IX working value; IX spare, to align to word
-36  xxDC IY working value; IY spare, to align to word
-32  xxE0 BC copy   Z80 file header has this information:
-30  xxE2 DE copy
-28  xxE4 HL copy
-26  xxE6 AF copy
-24  xxE8 IX copy
-22  xxEA IY copy
-20  xxEC SP copy
-18  xxEE PC copy
-16  xxF0 BC'
-14  xxF2 DE'
-12  xxF4 HL'
-10  xxF6 AF'
 -8  xxF8 I
 -7  xxF9 R
 -6  xxFA IM       Interrupt mode 0, 1 or 2
 -5  xxFB IFF      IFF0 in b0, IFF1 in b1
 -4  xxFC &0000    Options
 -2  xxFE &0000
 00000000 Start of memory
 00010000 Start of CPM buffer
 00011000 End of memory+1


Extras
======
The Z80Tube:Extras directory contains a few useful extra items

!Z80Launch a simple icon-bar task that lets you quickly start up !Z80Tube.
           Files can be dragged to it, which will be passed to Z80Tube to
           run. AcornCPM disk images (filetyped &1A6) can be dragged on,
           where it will set Z80Tube$Drive0 to it, and enter CP/M.

ClockSp    BBC BASIC benchmark program that determines the speed of the
           interpreter relative to the original BBC B. Running on an A5000
           !Z80Tube reposts a speed of 2.48MHz. A real Z80 CoProcessor
           reports a speed of 2.68MHz.

RdSys      Demo showing how to read the emulator's system variables.

SWITester  Demo showing how to call SWIs from within the emulator.

Z80Mon     Z80 disassembler.

Z80Opcodes Opcodes implemented by Z80Tube.

Z80Task    Demo of a simple Z80 WimpTask. This simply polls the Wimp once a
           second and quits if told to. You can quit it from the Task
           Manager.


Notes, etc
==========
!Z80Tube started with *Z80 -app doesn't multitask properly and will hang as
soon as it calls Wimp_Initialise. Multitasking Z80 applications should be
started with *Z80 -rma.

To run on the ARM CoPro the following commands should be issued:

    *GOS
    LOAD Z80Tube 19400
    GO 19400 ;


Version History
===============
11-Aug-1992 v1.00 Initial version up and running on both Arc and Unix.
            <Went through some more versions>
04-Mar-1997 v1.03 Osw7F and OswFF working properly.
11-Aug-1998 v1.05 Finally squashed that CPI/D/R bug. Changing debug
                  setting from within emulator acted on.
04-Jun-1999 v1.06 WarmBoot quits or reboots CPM correctly. Osword127
                  can access disk images set with Z80Tube$DriveX
05-Jun-1999 v1.07 Z80Tube$DriveX can redirect to different drives. SWI
                  interface fully working. Z80Support no longer killed on
                  quit, so multiple Z80s can run concurrently.
12-Jun-1999 v1.08 Now a module, preparing for Mark 5.
22-Sep-1999 v1.09 RMA memory leak fixed, Alias$Z80 set and unset
                  appropriately. Reset, IN, OUT issue service calls.
10-Feb-2003 v1.10 Ensured 32bit compliance, *Z80, *Basic sequence works.
11-Feb-2003 v1.11 Register dump fits into 80 columns, Z80 MOS acts on *BASIC.
08-Mar-2007 v1.12 Sprow corrected code to work on ARM CoPro. OSWORD 127
                  falls back to calling host OSWORD 127, so calls work on
                  ARM CoPro. EDFx opcodes introduced, mirroring ED0x
                  opcodes, so ED0x codes can be selected to perform Z280+
                  instructions.
10-Sep-2008 v1.13 If no parameters and no system variables, uses embedded
                  code, runnable on ARM CoPro without needing to specify MOS
                  and BASIC file.
13-Nov-2008 v1.14 Moving workspace out of module to make ROM-able, service
                  handler uses workspace, DumpAndQuit and Debug uses string
                  buffer, *BASIC checks if "<Z80Tube$Basic>" exists, if not
                  uses embedded code, added external *CPM command.
