Changes and additions to the Interface 1 ROM

The file imc.i1rom contains a modified version of the Interface 1 ROM (the
newer of the two versions) and also an extra 8K of new commands.  All the
files ending with "T" are assembler source files made with Hisoft GENS and
in xzx format (in order to use these on xzx you should define LOAD_SAVE_2).
Warning: the source is incomplete, and even the source that does exist is
not guaranteed to give a working ROM!  In particular, at least one of the
entry addresses differs between the address table in "ROMHEX+ T" and the
address named in the separate source file (the latter appears to be
correct).  Note also that in order to compile this source you need a
version of GENS in which the ENT instruction works properly.

Tweaks and bug fixes in the Interface 1 (I1ALTER T)

 * In several places, the Interface 1 ROM needs to make some space within
   the BASIC memory map - for instance when making a microdrive channel
   or loading a program.  It does this by calling either 1655H or 0030H
   in the Spectrum ROM.  In the case of loading a program, it also calls
   1F05H to test whether there is enough room before performing the load.
   Unfortunately this does not work properly.  If there is not enough room
   then the Spectrum ROM will raise an error with the microdrive channel
   still open, the microdrive running and the interrupts disabled.  This
   will crash the machine [%].  Most of the bug fixes are concerned with
   changing the requests for memory so that they report any errors using
   the Interface 1's error routine, which closes channels, switches the
   microdrive off and enables the interrupts before reporting the error.

   [%] The Spectrum ROM reports an out-of-memory error by storing the error
   number in 23610 and clearing the stack.  It avoids using RST 8 in order
   to prevent a syntax marker from appearing in case the error occurred
   while a line was being entered.  Since the interrupts are disabled,
   the machine crashes at the HALT instruction at the start of the error
   routine.  Inserting an EI instruction here would prevent the crash but
   still leave the microdrive running and the channel open.  Changing the
   test-room routine so that it uses RST 8 to report the error would prevent
   the crash because the Interface 1 would be able to intercept it and clean
   up before reporting the error.  A file called "imc.rom" containing these
   changes (and others) is available.  The modified Interface 1 ROM will
   work without these changes, however.

 * The call that reclaims a microdrive map has been changed so that it
   ignores the case when a map is not present (this might happen when
   an error occurred because there was not enough memory); the machine
   would otherwise crash.

 * The length of data which is initially copied from 14B1 into a microdrive
   channel has been changed from 25 to 28 (for reasons which may become
   clear in due course...).

 * MERGEing a program which was saved with a LINE number is allowed.

 * The machine does not reset if you press the Break key while loading a
   "RUN" program.

 * MERGE "x" LINE and MERGE "x" CODE are disallowed at syntax time.

 * A "t" channel prints character 127 verbatim instead of as "?" (no doubt I
   did this before I had a real printer...).

 * If you OPEN a microdrive file which has an incorrect type, the original
   Interface 1 ROM would have left the microdrive channel unused in memory.
   The modified version does not.  If you MOVE something from or to a "t"
   or "b" channel, the original Interface 1 ROM would have left a temporary
   channel unused in memory after the command finished.  The modified
   version does not.

 * A call to the Spectrum ROM's NMI routine has been inserted at 0066H (the
   NMI address).

 * IOBORD has been set to 4 and the screen and border colours for CLS# have
   been changed to white-on-black.

 * This source file also contains the jump (at 01EC) which hooks in the new
   commands.

Parallel Printer Interface (PARALLEL T)

The interface in which I placed my EPROM is also a parallel printer
interface.  This can be switched on and off.  When it is switched on,
any output to the RS232 interface is automatically redirected to the
parallel interface.  The interface uses IN 127 to detect some inputs
from the printer (most importantly, the BUSY signal in bit 0) and OUT 127
to output a character to the printer (this one OUT does all the necessary
work; it is not necessary to activate STROBE separately, for example).  IN
127 is guaranteed not to equal 255 if the interface is switched on.

In order to disable this modification (for the benefit of the xzx RS232
hack), poke 060B2F into 0D07 and the following two locations.  Note that
in the newer Interface-1 version, the input address is 0B98 and the
output address is 0D07.  If xzx does not recognise this ROM version,
these values should be written in place of the older values 0C5A and
0B9A respectively.

CIRCLE (source missing)

Typing ".CIRCLE" followed by the usual three parameters draws a fast circle
(which is also more circle-like than those which the spectrum's CIRCLE
command usually draws).  Using ",CIRCLE" draws a filled circle.  These
commands are plug-compatible with the ordinary CIRCLE command, but they
can draw circles which go partially off-screen.

SYNTAX (source missing)

Typing ?0 turns normal syntax checking off, so you can enter a program which
is written in total gibberish (Sinclair BASIC still works though).  Typing
?1 puts the situation back to normal.  Don't ask why I added that...

LOAD (source missing)

Typing an exclamation mark (!) followed by a name (not in quotes) will load
that file (it must be a BASIC program) from microdrive 1.

AUTO (ROMAUTO T)

Typing ".a" gives auto line numbering starting from 10 and in steps of 10.
".a x" gives auto numbers starting at x and in steps of x, while ".a x,y"
gives auto numbers starting at x and in steps of y. To stop auto numbering,
delete the number and press enter.

CAT (ROMCAT T)

Typing a star (*) before a CAT command gives a catalogue which shows the
type of each file.  Hidden files are shown with a first character of "(c)"
(copyright).  The command *CAT "c" is also allowed; this reads tape headers
and displays the details.  The "c" must be written verbatim - *CAT a$ is not
allowed, for example.

Printer channel (ROMCHAN T)

Typing ".u" opens #4 to channel "b" and #3 to channel "u" (which is "t"
plus a bit extra).  Data sent to channel "u" is expanded by having all
graphic characters plus the characters "pounds", "copyright" and "vertical
bar" sent as graphics using "ESC K".  Also, poking anything into 23681
causes that character to be printed at the start of each line until it is
cancelled by poking zero there (this is useful for persistent expanded text,
for example, which requires character 14 to be printed at the start of each
line).

Copier (ROMCOPY T) [with apologies to the writer of that utility in the
ZX expansion pack, where I nicked most of the code from...]

Copy files by typing *MOVE source TO dest, where source is either
"c";;"filename" or "m";n;"filename", and dest is either "c" or "m";n.
Device "c" indicates a cassette file.  The filename of a cassette file
may be blank, in which case every file which is played in will be copied
until a break-in (or a tape loading error) occurs.  Source and destination
may not both be "c".  If both are microdrive files and they refer to the
same microdrive, then the copier will pause for cartridges to be exchanged
between loading and saving.

RAMTOP should be below 26000 when the copier is used.  Files will be loaded
into memory starting at about that address.  Cassette files larger than
about 39K cannot be copied.

Screen copy (ROMDUMP T)

Type "COPY n", where n is a 2-bit number in which bit 0 gives a shaded copy
when set and bit 1 gives a large copy when set.  This program uses "ESC K"
to output graphic data, and the printer needs room for 576 columns of dots
in order to print a large copy, which is three times as high and wide as a
small copy.

Hex (ROMHEX+ T - this file also contains the address table for all the
commands)

The ampersand (&) prefix may be used in any expression for hex numbers
having 1-4 digits.  The command "PRINT ~" works just like PRINT but prints
any numbers in hex instead of in decimal (all the numbers should be between
0 and 65535).

INKEY5 (ROMINKEY T)

The command ".i1" turns INKEY5 on and ".i0" turns it off.  When INKEY5 is
turned on and #5 is open, any incoming data on #5 acts as if it had just
been typed in.  If no data is available at #5, the keyboard works normally.
This can be used with the xzx RS232 hack to type in spectrum programs from
the tty rather than the spectrum keyboard (use -crlf true in this case).
Tokens can be spelled out in capital letters; they will be assembled when
Enter is pressed (warning - the tokeniser is not terribly intelligent.
Almost any word will be tokenised if it appears in capitals, even if it
is within another word).

KEY (ROMKEY T)

".k1" turns KEY on, and "CLOSE #5" turns it off.  When KEY is active,
any key on the keyboard may be redefined by adding a REM line to the
start of the current program saying

   REM k=definition

where k is the key being defined.  Control keys may be redefined or used in
the definition by saying |K, where K is the character which is 64 above the
key code - for example, |M is the "enter" key, which must be placed at the
end of a line if the line is to be entered automatically.  The vertical bar
character must be written |SGN (with SGN written as a token) unless it is
the last thing on the left- or right-hand side of a definition.

A sample set of key definitions is supplied in the program REMs (which is
in xzx format).  One of these is a definition of INKEY$ which waits for
you to press a key and then tells you what it is in vertical-bar notation.
This can be an extended key (when you press both shifts a flashing E will
appear).  (For some reason, this sometimes doesn't appear to work on xzx
0.5 unless you edit line 90 and press enter before doing it).

SAVE (ROMSAVE T)

This is just a utility for lazy typists, really.  The commands are:

*Lname  =  LOAD *"m";1;"name"
*Sname  =  SAVE *"m";1;"name": VERIFY *"m";1;"name"
*Vname  =  VERIFY *"m";1;"name"
*Mname  =  MERGE *"m";1;"name"
*Ename  =  ERASE "m";1;"name"
*Rname  =  ERASE "m";1;"name": SAVE *"m";1;"name": VERIFY *"m";1;"name"

Any space coming after the command letter counts as part of the name.  The
command letters may be typed in upper or lower case.

The *r command doesn't bother erasing if the file doesn't already exist,
so it is faster than typing the commands individually.

The *v and *l commands do not require you to specify the type information
(for instance, CODE or DATA a$()).  If you do not specify the type, then
they will load or verify any kind of file.

SECTOR (ROMSECTORT)

This is a utility for examining and attempting to fix broken microdrive
cartridges (which should be placed in microdrive 1).

Start off by typing "/M".  This will create a map of the cartridge which
will remain in memory until you have finished examining it (if you don't,
then the first SECTOR command you type will execute /M instead of its usual
function.  It is supposed to do that "as well" rather than "instead", but
there appears to be a bug).

The SECTOR commands work on microdrive channels, just like the one
illustrated on page 47 of the microdrive manual.  You can open such a
stream with the OPEN # command, but it is easier just to let SECTOR open
it by using one of the commands (SECTOR does not do anything special to
open it - it just reserves the memory).  Each command may be followed by a
hash (#) and a number; if it isn't, then #4 is assumed (if the command has a
parameter, the hash and number come first, followed by a semicolon (;) and
then the parameter).

Data may be poked into a channel, using the address of the channel and the
numbers in the manual (for instance, set a variable IX to the channel's
start address, then POKE IX+68,2 [set RECNUM to 2] or POKE IX+71,0 [clear
the first character of RECNAM] etc.).  Use the /DATA command to check that
it has gone in correctly.  Note: in the manual it is not stated that bit 1
of RECFLG is used to signal "end of file".  This must be set to 1 at the end
of the file and 0 in the middle, or the file will not function correctly.

The SECTOR commands are:

/DATA (with DATA as a keyword) print out the given microdrive channel's
      contents.  This consists of the channel address, the contents of
      the important fields of the channel, the microdrive map with the
      amount of free memory, and the contents of the data buffer.  You
      may break in at the "scroll?"  message, as usual.
/N    Create a "null" sector in the given microdrive channel.
/L n  Load sector n of the cartridge into the given microdrive channel.
/L "file";n Load record n of "file" into the given microdrive channel.
/S    Save the given microdrive channel in the next free sector on the
      cartridge.
/S n  Save the given microdrive channel in sector n of the cartridge,
      overwriting whatever was there.
/V n  Verify the given microdrive channel against sector n of the cartridge.
/P a  Put the data from the given microdrive channel into memory at address a.
/G a  Get the data from memory at address a into the given microdrive channel.
/M    Make a new map (do this if you change cartridges).
/CLOSE# (with CLOSE# as a keyword) Finish editing.

Notes:

Any of the command letters may be typed in upper or lower case.

If you save a null sector from /N on the cartridge, it will appear as a free
sector.  If you poke RECFLG to 1 before saving it, it will appear as a full
sector (in this case you should poke RECNAM to zeros or else that name will
appear on the catalogue).  Do this to mark any bad sectors that appear.

The checksum of a sector will be calculated automatically before the sector
is saved.  If a loaded sector has an incorrect checksum, a message will
be printed but the sector is still loaded in the state in which it was
found.

After a sector is saved, the /DATA command will tell you which sector of the
cartridge it was saved in.

The first nine bytes of record number zero of any file which is not a PRINT
file will contain data relating to the file (same as HD_00 to HD_11 in the
system variables section of the manual).  This is important for calculating
the address parameter of the /P and /G commands.  Make sure that the record
flag and the record number are correct before you use these commands and
calculate the address carefully.

Sector numbers decrease as the cartridge goes round, and files are usually
saved on every other sector, not every sector.  This means that the next
record of a file is most likely to be on the sector with the number 2 less
than the present sector.  Historians might like to note that the format of
sectors is described in detail in Microdrive File, p.148, Your Computer June
1984.

To finish editing, type /CLOSE# and also close all the microdrive
channels.

Tape copy (ROMTCOPY T)

Type ".c" to enter the tape copier.  Play a tape, and when the border turns
green, start recording and press a key.  In theory, this should copy any
normal file or headerless file, but it won't work too well with xzx and
I'm not sure that it works anyway...
