0% found this document useful (0 votes)
305 views

Spectrum Operating System The

This chapter discusses useful call addresses in the Spectrum's 16K ROM and how to use them, including routines for printing characters, opening and closing output streams, reading and writing to memory, controlling the cursor, and more. It emphasizes the importance of saving and restoring registers before and after calling ROM routines. The information provided can help programmers access the versatility of machine code without needing to write it themselves.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
305 views

Spectrum Operating System The

This chapter discusses useful call addresses in the Spectrum's 16K ROM and how to use them, including routines for printing characters, opening and closing output streams, reading and writing to memory, controlling the cursor, and more. It emphasizes the importance of saving and restoring registers before and after calling ROM routines. The information provided can help programmers access the versatility of machine code without needing to write it themselves.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 71

THE SPECTRUM OPERATING

SYSTEM

This book will be a valuable asset to all Spectrum owners.


There is a wealth of material enabling you to employ versatile
techniques which are normally the domain of the
professional. The author shows how short machine code
routines can be written and used very easily. A number of
programs which are ready to type in are also included.
For the machine code programmer, this book will be a
constant source of reference. Instead of 're-inventing the
wheel' for each new program, the author shows you how to
make full use of ROM routines and the existing facilities.
Both the Spectrum and the microdrive interface are covered,
and there is a detailed description of extending the operating
system for microdrive users.
The Author
Steve Kramer has been working with computers for twelve
years. He acts as an independent software consultant to a
number of software houses in the field of business
applications. He is also the author of several games and
home-use programs written for popular micros.

^ ._
^^,'
^ —

---•e^^
GB f NET +095.95 ■■■■
111111■■
ISBN 0 - 7447 - 9019 - 1
00595
The Spectrum
Operating System
The Spectrum
Operating System

Steve Kramer

/W/ MICRO PRESS


Contents

First Published 1984 by Chapter 1 Getting Started 1


Micro Press
Chapter 2 Useful Call Addresses and How to Use Them: the
Castle House, 27 London Road
Tunbridge Wells, Kent 16K ROM 3

© Steve Kramer 1984


Chapter 3 The 8K Interface ROM 25
Chapter 4 The System Variables 42
All rights reserved. No part of this
Chapter 5 Input and Output Ports and Channels 62
publication may be reproduced, stored in a
retrieval system, or transmitted in any form Chapter 6 Using the Interrupts 70
or by any means, electronic, mechanical,
Chapter 7 Extending BASIC with Interface 1 75
recording or otherwise, for commercial
gain without the prior permission of the Chapter 8 The Calculator 80
publishers.
Appendix A Hex to Decimal Conversions 93
British Library Cataloguing in Publication Data Appendix B The Spectrum Memory Map 95
Kramer, Steve
Appendix C The Spectrum Screen Map 96
The Spectrum operating system.
1. Sinclair ZX Spectrum (Computer)—Programming Appendix D The Keyboard Map 98
2. Operating systems (Computers)
Appendix E The Spectrum Character Set 99
I. Title
001.64'25 QA76.8.S625 Appendix F ROM Interrupt Vectors 102
Appendix G Useful Subroutines 104
ISBN 0-7447-0019-1
Index 129

Typeset by Key set Composition, Colchester


Printed by MacKays of Chatham Ltd
Chapter One

Getting Started
While this book is primarily aimed at those people who have a
reasonable understanding of assembly language programming,
there will be a considerable amount of information which will be
of use to the uninitiated programmer who would like to be able to
gain access to the versatility of machine code, without having to
learn how to write it. If you belong to the latter group I hope that
this book will whet your appetite, an d prompt you to start
learning a little about assembly language programming. With the
minimum amount of knowledge an d using the routines in the
following chapters, sho rt machine code routines can be written
and used very easily.
For anybody not familiar with the operating system of the
Spectrum or who is basically bone idle (like me) and who prefers
to use ROM routines an d existing facilities — rather than
re-inventing the wheel every time they want to write a program—
I will be discussing how to use ROM calls in both the 16K ROM,
which is in the Spectrum, and in the 8K ROM in the Microdrive
Interface. In some cases, I shall give examples as well as
descriptions of how to use them, except where they are just a
simple CALL.
I shall also look at the system variables an d show how to use
them to advantage, and explain the use of interrupt-driven
routines, which can allow sprites to be used on the st an dard
Spectrum.
Unless you wish to convert the assembly language routines by
hand into numbers an d then poke them into your computer's
memory, a prerequisite to being able to use this book is an
Assembler program. I can recommend the Picturesque Editor
Assembler and also their Monitor/Disassembler programs,
which are both very easy to use an d fast. I can also recommend
Highsoft's Devpack 3 which will be even better with a few
improvements which will probably have been made by the time
2 The Spectrum Operating System

you read this chapter. For the more experienced user, the Chapter Two
Devpack (which contains both Monitor/Disassembler and Editor/
Assembler) is, in my opinion, at present unsurpassed. The latest
versions of both these programs are Microdrive-compatible.
It is not my intention to teach assembly language programming
Useful Call Addresses
as there are a great many books already available which cover this
in detail. Two that I can recommend are Rodnay Zaks'
and How to Use Them:
Programming the Z80 and Spectrum Machine Language for the
Complete Beginner. The first is not related to the Spectrum, but
the 16K ROM
goes into far more detail than the second and also has concise
descriptions of all the available op-codes.
To call a machine code program from BASIC you can either use
a RANDOMIZE USR NN, a PRINT USR NN or a LET V = USR
NN command, where NN is the entry point to the machine code It is important before using ROM routines always to save the H'
program and V can be any numeric variable. On return from the and L' registers, and restore them afterwards before a return to
machine code routine, the variable in the LET command will be BASIC is made. Also the IY register must always contain the
equal to the BC register pair on exit, and with the PRINT address of the system variable ERR NR 23610 (5C3Ah) whenever a
command the value in the BC register pair will be printed to the ROM routine is used.
current stream. In all cases the BC register pair will contain NN on
entry to the machine code program.
Whenever a machine code program is called, it is advisable to
save the contents of the H'L' register pair since the contents of Printing: RST 16 (10h)
this are necessary for a successful return to BASIC. The IY register
pair should not normally be used as the ROM uses this to index The character whose code is in the A register will be printed to
the system variables, but it can be used so long as the interrupts whichever stream is currently open. This can also be used to
are off and no ROM routines are used before it is restored to 'print' control codes (i.e. TAB, INK, OVER, etc.; see the Spectrum
holding 23610 (5C3Ah). manual for details).
This book is intended to be a reference work which you will
turn to for information for as long as you have your Spectrum. I
have made no attempt in the main text to be chatty or to hold your
hand, but I hope the information required is there. Obviously it Opening and Closing Streams (for RST 16 (10h)):
would be impossible to detail all the ROM routines and all the CALL 5633 (1601h)
ways they could be used, so I have selected those that I am asked
about most often and find most useful. Further reading for the CALL 5633 (1601h) sets the output for RST 16 (10h) to the stream
serious programmer must be Dr Ian Logan's Complete Spectrum held in the A register when called. Normally A = 2 will print to
ROM Disassembly. the main screen, A = 3 will print to the printer and A = 1 or 0
will print to the lower screen. With the Interface 1 connected,
other streams can be used for output to the Microdrives, network
or other devices. Details are given on how to divert streams for
your own purposes (e.g., for controlling an interface for other
uses such as the Kempston or other Centronics printer interface)
4 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 5

in the section on Expanding Tokens for Output later in this calling 5633 (1601h). Caution needs to be exercised on the last line
chapter. of the main screen as a scroll message will be generated after
printing on the last available position. This will cause a return to
BASIC if answered with 'n' or SPACE. In addition to this, any
Detecting if Break is Being Pressed: CALL 8020
attempt to print to stream 1 will cause scrolling up of the lower
(1F54h)
screen when the available space set up by the system variable DF
SZ (23659) has been filled. This can produce some very
This call will return with the car ry flag set if it is not being
unexpected results.
pressed, and with the car ry flag reset if it is being pressed. (Note:
Obviously when printing to a printer you cannot set a line
This call tests for both CAPS SHIFT and SPACE being pressed.) If
number so the B register is not used.
you want to test for SPACE alone see the section later on Getting a
Character from the Keyboard for full details but, for the time
being, you could use:
Clearing the Screen (Whole Screen): CALL 3435
LD A,7FH (D6Bh)
IN A (OFEH)
RRA This call will clear the whole screen and reset the attributes to
JP NC,PRESSED those in system variable AFIR P for the main screen and
BORDCR for the lower screen (23693 and 23624, respectively; see
the Spectrum manual for how these are made up).
Setting the Position for Printing Using RST 16
(10h): CALL 3545 (DD9h)
Clearing the Screen (Lower Screen): CALL 3438
This routine requires the B register to hold the screen line (D6Eh)
number in the form:
This will clear the lower screen only and reset the attributes.
B = 24 – line number
Note: Both 3435 (D6Bh) and 3438 (B6Eh) reset DF SZ to 2 and can
(i.e. if B = 24, this is the top line of the screen; if B = 1 this is the corrupt the current channel used by RST 16 (10h) so this will need
bottom line). Unfortunately due to an oversight in the writing of to be reset. The current print positions are set to the top left of the
the ROM, you cannot use lines 23 an d 24 for printing on the main respective screens.
screen. So you must use the lower section by setting up the
output stream for RST 16 (10h) to be 1, and using the top two lines
of the lower screen. Scrolling the Screen: CALL 3582 (DFEh)
C = 33 – column number This scrolls the screen up by one line, but leaves the current print
position unaffected. Therefore if you continually print to the
(i.e. if C = 33 this is the left-most column; if C = 2 is the right- same line, scrolling the screen at the end of each line, you will
most). have an effect like typing using a typewriter (with the printing
This call automatically updates the system variables for the taking place at the bottom and the print being moved up after a
print positions on whichever stream you are using, as set up by carriage return).
6 The Spectrum Operating System
Useful Call Addresses and How to Use Them: the 16K ROM 7

each number output is between 1000 and 9999, otherwise


Plotting to the Screen: CALL 8933 (22E5h)
spaces will be introduced.
The point addressed by the B register (Y 0-175) and the C register
Those of you who have the Spectrum Pocket Book and have read
(X 0-255) will be plotted to the screen. The INK and PAPER
about this call address, but not used it, will now be calling me an
colours can be set up previously by loading the system variables
idiot. In that book, the author points out that the E register
for the attributes with the colours you require or the current
controls the way the number is formatted, but if you have used
attributes will be used. OVER 1 can be set by SET 0,(IY + 87) or
the routine you will know that this is not quite the case, as the E
reset by RES 0,(IY + 87) and any point can be unplotted by SET
register is ignored. There are two ways round this problem.
2,(IY + 87).
Firstly, you could write your own routine to bypass the first
part of the ROM routine, such as:
Note: It is perfectly possible to plot to the lower screen and this
should be avoided, if not required, by setting the stream required
PUSH DE
with the 5633 (1601h) CALL.
LD D,(HL)
INC HL
LD E,(HL)
PUSH HL
Getting a Number to a Stream EX DE,HL
LD E,20H
This is the most complicated routine so far and does not have a
JP 1A30H
simple call address as such. There is a routine in the ROM for
taking a 16-bit number from two addresses and outputting it in
Note: The last instruction must be a jump (JP) and the routine you
decimal form, but this routine has the disadvantage that the bytes
have written must be called, otherwise the stack will be mixed up
must be stored 'about face' from the way that the Z80 stores them.
as the return address is stored on the stack and the routine POPs
This means that you must load the number into a register pair and
from the stack the PUSHes you have made. You will see that the E
then store it back into a space in memory the opposite way round
register is loaded in your routine and as this is a duplicate of the
(i.e. high-order byte first). A short program such as this would
start of the routine on ROM you can now see why the Spectrum
serve:
Pocket Book is wrong. Now you can change the LD E, instruction
LD DE,(address where No. stored) in this routine to be either 48 decimal, in which case leading Os
LD HL,SPARE WORD are printed, or 255 when anything not significant is not printed.
LD (HL),D
"But wait a minute," you will be saying, "now I can see why
INC HL
LD (HL),E the byte order has to be changed." Quite correct, if you reverse
the order of loading the DE register pair or even load HL directly
The ROM routine at 6696 (1A28h) can now be called with HL the number does not have to be reversed, so it is well worth while
rewriting this short piece of code for incorporation into your own
pointing to the address SPARE WORD which will then be output
program as a subroutine for outputting numbers.
in ASCII to the current stream, but there are two drawbacks.
There is one other part to this routine in the ROM worth
considering at this point and that is the part starting at 1A1Bh.
1) It will only be output correctly if it is less than 10 000 decimal
This simply takes the number in the BC register pair and outputs
and it must be an integer.
that with no leading Os or spaces; much more useful in many
2) The number will be output with leading spaces so that
cases.
chaining outputs to create a larger number will work only if
8 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 9
With a little thought, these routines now give you the possib- and (IY + 1) tested instead, as the IY register contains the address
ility of outputting any size of number from your program. It is of the system variable ERR NR (23610) (5C3Ah) and is used for
probably easier, however, to use the routines which take a value addressing the system variables by the ROM. This is why if you
from the calculator stack (for details see Chapter 8). use the IY register in your programs you must make sure the
interrupts are off or directed to your own routines, and you must
Getting a Character from the Keyboard also reset the IY register to the correct address before using the
ROM or reverting to the normal interrupt mode.
The RST 56 (38h) instruction is used by the Spectrum to scan the The second problem is that you cannot test for more than one
keyboard and update the FRAMES system variables, and it is key being pressed at a time. This is because if a combination of
called by the maskable interrupt routine. If all that is required is keys which is not a valid character is being pressed the Spectrum
to see if a key has been pressed, bit 5 of FLAGS 23611 (5C3Bh) can will ignore them. To overcome this you will need to write your
be tested; if the bit is set a key has been pressed since it was last own keyboard-scanning routine. Firstly, if you only want to find
reset. Note that bit 5 needs to be explicitly reset. out if a key is being pressed without worrying about which key or
how many keys, you could do something like this:
The code of the last key pressed can be found from 23560
(5C08h) LAST K, detailed in Chapter 4. This is often sufficient for
XOR A ;make sure that A contains 0
getting input from the keyboard, but it has disadvantages.
to scan all keys
Firstly, it is updated only 50 times a second (60 if the mains IN A,(FEH) ;FEH is input port from keyboard etc.
frequency is 60 Hz, as in the USA) so you cannot do a RES 5 LD D,31
instruction immediately followed by a look at the bit since almost AND D ;Get rid of the etc.(the 3 high bits)
certainly, even if a key is being pressed, the keyboard will not XOR D ;Flip the remaining bits
JR Z,NO_KEY
have been scanned by an interrupt. Otherwise, if the interrupts
are off, the keyboard will never be scanned unless you do so.
Therefore something along the lines of: The keyboard can be scanned properly to discover which keys
are being pressed by loading the A register with the value of the
LD HL,23611 ;FLAGS system Variable lines to be scanned prior to the IN A,(FEH) instruction.
RES 5, (HL) Chapter 23 of the Spectrum manual explains how the keyboard
LD A,FFH is laid out, and it is also shown in Appendix D in this book, but in
LD (23552),A ;23552 is part of the brief this is the layout. The first character in each case is BIT 0 and
system variable KSTATE
the second BIT 4, the hex number is to be loaded into the A
PUSH HL
RST 56 register to set the bit for the line being scanned low:
POP HL
XOR A CAPS SHIFT — V FEH
BIT 5,(HL)
A—G FDH
JP Z,NO KEY
LD A,(23560) ;LAST K system variable Q T EBH
NO KEY ( whatever ) 1-5 F7H
0-6 EFH
will return in the A register the code of the key being pressed at P—Y DFH
the label NO KEY or 0 if no key is being pressed. In the above ENT'ER — H BFH
routine, the LD HL,23611 instruction could have been omitted SPACE — B 7FH
10 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 11

So, for example, to read the keyboard for EN'T'ER being pressed INPUTF and if the program is entered (or just this section of it)
the program would be: the problem can be demonstrated by pressing CAPS SHIFT and
SYMBOL SHIFT to go into EXTENDED MODE. The last line that

LD A,OBFH was typed in from the keyboard will then appear at the bottom of

IN A,(OFEH) the screen.
AND 1
When using these routines to read from the keyboard the
JR Z, ENTER PRESSED
interrupts must be on and the normal interrupt routine at 56 (38h)
called within the interrupt cycle, otherwise no input will ever be
To see if more than one key is being pressed you could use the received.
logical operators AND, OR, etc. if they are on the same line or bit
test instructions. See the next CALL 5598 (15DEh) for getting
normal characters easily.
Screen Copy to Printer: CALL 3756 (EACh)

This routine requires no presetting and a straightforward CALL


Wait Input: CALL 5598 (15DEh) will output a screen copy to the ZX printer.

This is a most useful routine which allows for input from any
stream that has an input address. Before use the stream from
which the input is required must be opened by the routine at
Printing Graphics to Printer: CALL 3789 (ECDh)
5633, described earlier. When the Wait Input routine is CALLed,
This is similar to the screen copy routine in that it uses the printer
it in turn calls the input routine of the current channel. On return
buffer and outputs its contents to the printer. It is used by the RST
from this the carry flag is checked, if set the main CALLing
16 routine which normally treats the buffer as one screen line
program is returned to. If the carry flag was not set the 0 flag is
(eight pixels high). If you place your graphics into the buffer one
then checked, and if set the process is repeated.
line at a time and then make a CALL to this address, the printer
The routine is used by the Spectrum as the control for the will copy the buffer to the printer.
current input subroutine, normally the keyboard input, but if
CURCHL is set to point to a channel with the input address Note: The layout is 32 bytes per pixel line with the next pixel line
pointing to your input subroutine this will be used. (How to do following immediately and not as the screen. The buffer is also
this is explained in Chapter 5.) When used with stream 1 (the cleared to Os after a CALL.
keyboard and lower screen), the routine will wait for a key to be
pressed and return its code in the A register. This use is demon-
strated in the DeBASE program in the Appendix G. Clearing the Printer Buffer: CALL 3807 (EDFh)
There is, however, a problem when using this to read the
keyboard if the mode is changed. Each time the routine is called, This simply clears the buffer to Os.
TV FLAG 23612 (5C3Ch) IY + 2 is checked and if bit 3 is set the
input buffer is copied to the edit area of the screen. This can be
overcome by using the Key Input routine at 4264 (10A8h) directly Using the Beep: CALL 949 (3B5h)
and not via the Wait Input routine, as shown in the DeBASE
program in Appendix G at the label INPUT. The program dupli- The DE register pair holds the length of the output and the HL
cates the Wait Input routine but ensures the MODE CHANGE register pair the frequency. 0 is high for frequency and FFFFh is
flag is always reset. The Wait Input routine is used at the label low. The problem with this routine is that the duration is
12 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 13

frequency-dependent, hence if you halve the frequency you PR_MES LD DE,MESSAGE


CALL 3082
double the duration for a given value in DE. The actual figures are
RET
calculated as follows: MESSAGE DEFD 80
DEFM "ENTRY"
HL = (437 500/frequency) – 30.125 DEER " "+80H
DE = duration* frequency DEFM "ENTRY 2"
(duration should be in seconds) DEFB " "+80H

This would print to the current stream at the current position the
The reason why the 30.125 is taken away from the HL calculation message <EN'I RY > . To print <ENTRY 2 >, the A register would
is that the routine itself takes 120.5 T states actually to generate
hold 1. The chevrons are only to show the limits of what will
the note and amend its own registers, etc.
actually be printed, and will not appear when a message is
Middle C is approximately 261 Hz so the value for HL would be
printed. This is the routine used by the ROM to expand tokens
about 1646 decimal and DE for one second would be about 261
and generate error messages when called from another routine at
decimal.
2898 (B52h). The DeBASE program (see Appendix G) makes
Remember that the interrupts from the ULA will occur 50 times
extensive use of this routine.
a second (60 times in the USA) and they will corrupt the sound
output if the routine is in the bottom 16K of RAM.

Expanding Tokens for Output: CALL 2898 (B52h)

Whenever the Spectrum comes across a token code (anything


with bit 7 set) it has to decide what to do with it, as it could either
Printing Messages: CALL 3082 (COAh)
be a User-Defined Graphic, a block graphic or a word from the
On entry the DE register pair must hold the address of the BASIC vocabulary. Normally this is taken care of automatically
message table's start marker, which must have BIT 7 set, and the when using RST 16 (10h) (which is directed through this routine).
A register must hold the entry number in a table of messages, If you have changed the address for output on a stream (e.g. to
each with BIT 7 set on the last byte. The first message has entry output to your own printer interface), whenever your routine is
number 0. being used the A register will hold the code for the token and if
If you wanted to print the message " I am " you might have a you wish to expand it you will have to do it yourself. If you leave
line in your program such as: MESSAGE DEFM " I am ", but this it as it stands you may get some peculiar results from the printer.
would carry on printing after the last space until it came to a byte This routine can be used to expand the keywords, but you will
with bit 7 set. You should therefore change the program line to have to deal with the graphics yourself and make sure that no
'MESSAGE DEFB 80H : DEFM " I am" : DEFB " " + 80H'. The graphic codes are sent to the routine, otherwise the machine may
lock up.
routine will subtract the 80H and print the last space correctly,
but will know that it has reached the end and return to the calling
routine. So, the whole program might look something like this: Note: When expanding, the routine itself makes repeated calls to
the address pointed to by the stream in use and returns only after

LD A,0 ;(to print first message in table) all the letters have been output. This means you will most likely
CALL PR_MES
jump to the routine so as to ensure the code in the A register on
REST OF PROGRAM GOES HERE the final return is not output. This is shown in the following
typical program for output to a printer interface:
14 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 15

INIT LD HL, (23631) ; CHANS (address of channel This program is a very basic one; if you wish to send any printer
data) control codes, it will not print them. To get round this you will
LD BC,15 ; offset for stream 3
(printer) have to carry out further checks and act accordingly. The first
ADD HL,BC ; HL now points to the section only needs to be called once as it permanently alters
location holding the where output to stream 3 is sent. The only times it needs re-
address to be called with initialising are either after a NEW command from the keyboard or
output on this stream
if the output has been changed by another part of the program.
LD BC,START ; START = address of the
start of your 0/P routine
LD (HL)BC
INC HL Expanding Block Graphics: CALL 2878 (B3Eh)
LD (HL),B
RET ; stream three is now
initialised to send its
If you want to create from the code of a block graphic the block
output to your routine graphic itself, the routine at 2878 (B3Eh) will do it for you. On
entry the base address of eight spare bytes where you want the
START LD B, A ; save the ASCII code in B graphic constructed should be in the HL register pair, and the B
CP 165
expansion routine in ROM
register should contain the code of the block graphic. Two CALLs
JP NC,B52H
CP 13 need to be made, the second immediately after the first, as each
JR Z,CRLF carriage return & line CALL constructs four bytes of the character. The first byte of your
feed eight-byte block will be the top of the block graphic and HL will
CP 32 point to the byte after the last byte of the graphic. The register
RET C anything below 32 is an
unprintable control code pairs altered by this routine are AF, HL and BC; no others are
CP 129 used by it.
JR C, PRINT must be normal character
anything left here is a
graphic, and you must
deal with it as you wish
Drawing Circles: CALL 9005 (232Dh)
PRINT your 0/P routine comes
here The routine to draw a circle requires the parameters of the circle to
RET go back for next be on the calculator stack of the Spectrum. Thus the first thing to
character, if there
do is put the details onto the calculator stack. A routine located at
isn't one execution will
return to the original 11560 (2D28h) will do this for us if we put the number we wish to
calling program stack into the A register (see Chapter 8 for fuller details on Use of
the Calculator). All you need to know now is that it resets the IY
register to point to ERR NR and corrupts most of the other
registers so you should save them before calling this routine.
The parameters must be saved onto the calculator stack in the
order X,Y,Z (Z = radius). The circle-drawing routine updates the
system variables COORDS so if you do not want them changed
16 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 17

you should save them before drawing your circle and restore The machine code equivalent to the BASIC line DRAW 0,175
them afterwards. Thus, the routine to draw a circle would look would look like this:
something like this:
LD BC,AFOOH ; 175,0
LD DE,0101H;+
LD HL,(23677) ;COORDS CALL 24BAH

PUSH HL ;SAVE COORDS Or to DRAW -255,0

LD A,X ;WHERE X = 0 — 255 LD BC,OOFFH ; 0,255

CALL 2D28H ;STACK A ROM ROUTINE LD DE,01FFH ; +,-

LD A,Y ;Y0-175
CALL 2D28H Note that these will draw from the current COORDS, and no

LD A,Z ;Z = RADIUS (MAKE SURE THAT attempt has been made to save them or alter them. After running
THERE IS ROOM ON THE SCREEN the routine they will point to the last point plotted while drawing
OTHERWISE YOU WILL GET AN the line and an error will occur if you try to draw off the screen.
ERROR REPORT)
CALL 2D28H
CALL 232DH ;DRAW CIRCLE Finding the Address of a Pixel: CALL 8874
POP HL (22AAh)
LD (23677),HL ;RESTORE COORDS
To find the address of the byte holding the pixel for a PLOT
If you wanted to draw your circle round the current COORDS command this routine can be called with the BC register pair
holding the X and Y coordinates (Y 0-175 in B and X 0-255 in C)
position, you could have placed these onto the calculator stack,
will return with the HL register pair holding the address and the
but you would still have to save them to the machine stack if you
A register holding the bit position.
want to restore them unaffected.

Clearing Part of the Screen: CALL 3652 (E44h)


Drawing a Line: CALL 9146 (23BAh)
This routine will clear the number of lines set by the B register
The ROM line-drawing routine proper starts at 9399 (24B7h) and from the bottom of the screen (e.g., if B contained 1 then just the
takes its parameters from the calculator stack in the same way as bottom line would be cleared, or if B contained 10 then the bottom
the circle routine. In this case, however, it is easier to bypass the ten lines would be cleared). The bottom of the screen is always
part which uses the calculator stack. The routine takes its start line 24, not the lowest line of the main screen.
from COORDS so if you want to start from somewhere else you
will have to load COORDS with your start position after first
saving them if required for later restoration. Otherwise they will Scrolling Part of the Screen: CALL 3584 (E00h)
point to the end of your line. On entry the DE registers hold the
signs of the DRAW parameters which are held in the BC registers: To scroll part of the screen, first the B register has to be set to the
-1 (FFh) for negative, +1(01h) for positive. The registers C and E number of lines to be scrolled - 1. Then the routine can be called.
hold X, whereas B and D hold Y. The bottom line after each call will be cleared and at least two lines
18 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 19

must be scrolled. Lines are again counted from the bottom of the Byte 1 is always 00 for a header and the last byte is a parity byte
full screen. which is generated within the routine, so there is no need to
worry about it. Byte 2 holds a type number:

0 for a BASIC program 2 for a string array


Input to Current Ch an nel: CALL 5606 (15E6h) 1 for a numeric array 3 for a block of code
This routine picks up the address of the current channel from the
Bytes 3 to 12 hold the name. Bytes 13 and 14 hold the length of the
system variable CURCHL, finds the address of the input sub-
main block. For a BASIC program this would be E LINE — PROG
routine from the channel information area and then calls the
system variables. Bytes 15 and 16, for a code block, will hold the
required routine.
start address for loading the block. Bytes 15 and 16 for a BASIC
program, will hold the auto-start line number if applicable or the
start address if not. For an array, byte 16 holds the array name in
Clearing the Calculator Stack and Workspace: the form of:
CALL 5823 (16BFh)
Bits 0 4 the name (A = 1 to Z = 26)
This routine can be very useful to ensure that the calculator has
Bit 5 reset if the array is numeric
the maximum workspace and that there is nothing inadvertently
left on the calculator stack. It uses only the HL register pair and Bit 6 set if the array is a string
will return with the contents of the system variable STKEND in Bit 7 set
this.
Bytes 17 and 18 hold the length of the program for a BASIC
program (i.e. VARS – PROG system variables). The last byte is
SAVEing, LOADing and VERIFYing a parity byte, and this is created as the actual SAVEing or
LOADing is being carried out.
The Spectrum SAVE and LOAD routines are fairly straight-
forward and very easy to use if both saving and loading are to be
carried out from within the program, if the exact length of the
data is known and if it does not matter if control is returned to The Header
BASIC in the event of an error or BREAK being pressed. If the
length is not known, or something other than data is to be
BYTES 1 2 3 12 13 14 15 16 17 18 19
handled, things become more complicated.
Normally when loading the Spectrum expects a header to be FLAG TYPE PROGRAM DATA START PROGRA I PARITY
received before the main block, and it is this header that tells the NAME LENGTH LENGTH
I I 1 1 1 1 1 1 1 I I 1
Spectrum how to deal with the main data block which follows. It IX+
00 1 10 11 12 13 14 15 16 17
is much easier to save and load without the header but, as
mentioned previously, this can only be done if the exact
parameters are known. To save onto tape either a header must be created as above and
The header is 19 bytes long (not 17 as most books will tell you), saved followed by the main data block, or if the parameters of the
but only the 17 middle bytes need to be set up as the routines for main data block are known, and will still be known when it comes
SAVEing and LOADing create the first and last bytes themselves. to be loaded, the data block alone can be saved.
20 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 21

There are a number of entry points to the SAVE routine which data block. The first thing that this routine does is preload the
can be used and each has its own merits and disadvantages. The machine stack with the address of the SAVE/LOAD RETURN
first entry point to be considered is perhaps the easiest, but also routine. The SAVE/LOAD RETURN routine enables the inter-
the most fraught with problems. It is used by setting the IX rupts then looks to see if BREAK has been pressed. The error-
register to point to the start of the header (byte 2 as described in handling routine is called in with an RST 8 if BREAK has been
the header information above) and the HL register pair must be pressed, thereby making a return to BASIC. If BREAK has not
set to point to the start of the main block to be saved. Once these been pressed return is to the original RETURN address, put onto
registers have been set a CALL can be made to 2416 (0970h) and the stack by the calling routine.
SAVEing of both the header and the main block will take place. If the instructions to place the SAVE/LOAD RETURN routine
The problems are as follows: are bypassed, the RETURN address on the machine stack will be
that of your calling program, and control will be returned to that
1) The message "Start tape then press any key" will appear. If
on exit from SAVEing, with the carry flag reset if there has been
any key except BREAK is pressed all will be well, otherwise
an attempt to BREAK into the SAVEing process, or set if not, and
control will be returned to BASIC via the error-handling
the interrupts will be off, so they must be re-enabled. You will
routine.
also have to organise some form of message to make sure that the
2) The BREAK key is periodically tested during the SAVE
tape has been started, perhaps by using the message printing and
routine. If pressed, a premature return is made to the BASIC
Wait Key routines detailed elsewhere in this chapter.
error-handling routine, which can be embarrassing.
To save a block of code by this method, the IX register must
3) The header is saved in such a form so as to ensure that the
point to the start of the block, and the DE register must hold the
SAVEd material can be loaded back by BASIC. Under some
length. The A register must hold either FFh for a data block or 00
circumstances, this may be regarded as an advantage not a
for a header. A direct CALL can then be made to 1222 (04C6h).
problem.
Remember that the DE register pair will have to hold 17 (11h) if a
The next entry point can be regarded as the same as the last standard header is being saved. Blocks of data can be saved by
with the exception that it does not ask for or wait for a key to be this method without a header, but can only be loaded back if the
pressed. This must be accessed via a subroutine in the calling length is known.
program because correct operation depends upon correct loading If a return to BASIC is not a worry, or is an advantage, then the
of the machine stack. First set the IX and HL register pairs as same routine can be used, but from the start, which is at 1218
above, then CALL the following routine from your program: (04C2h). If BREAK is pressed control will then be returned to
BASIC. Again you will have to make sure the tape is running.
SAVE PUSH HL
JP 2436 (0984H)
LOADing and VERIFYing
The return after SAVEing is complete will be made to the location
following the CALL to SAVE. This is a neat way of SAVEing Data on tape can be loaded into the Spectrum in two forms: either
several successive blocks complete with headers, as repeated with a header or without. Where there is a header this can be used
'start tape' messages are avoided. either to provide all the parameters for the loading of the main
To SAVE without the possibility of BREAKing into the SAVE data block to follow or, as when loading from BASIC, only the
routine to return to BASIC, the normal start must be bypassed, details which are either unknown, known and definitely correct,
and the header and data saved separately as blocks. The routine or to ensure that the correct data is being loaded. Where there is
SA_BYTES located at 1218 (04C2h) is normally called to do any no header, all the details that would have been in the header
SAVEing, with the A register holding 00 for a header or FFh for a section must be known before the data can be loaded.
22 The Spectrum Operating System Useful Call Addresses and How to Use Them: the 16K ROM 23

It is possible to create a different type of header from that used whereas for a BASIC array, byte 15 will be ignored and byte 16
by the Spectrum, to define the parameters of the following data, will be the name of the array in the same form as when SAVEing.
by SAVEing a fixed length of data as a main data block and For a BASIC program, byte 15 will be 0 and byte 16 80h. The last
writing one's own decoding routine, which will furnish the bytes can be effectively ignored.
details when the main block is loaded. This is often a good idea as Before attempting to use the dummy header, the low byte of
it prevents the possibility of a block being lost, because you have the system variable T ADDR must be set to contain 01 to LOAD or
forgotten the length or where it was on the tape, and hence cannot set to 2 in order to VERIFY.
reload it. This will also prevent the code being loaded by an The HL register pair must contain the address to which the
'unauthorised' user, unless he takes the time to write his own main block is to be accepted, or 0 if the information in the tape
code to examine what you have done and manages to interpret it. header is to be used. For an existing BASIC array, this will be the
A routine which creates a special header is given in the DeBASE start of the array data, following the array name and length bytes
program in Appendix G. in the variables area of a BASIC program.
To load a data block preceded by a normal header the first thing Finally the IX register must be set to point to the first byte of the
that must be done is allocate a space of 34 bytes in memory. In the dummy header. The ROM routine at 1889 (761h) can now be
first 17 bytes of this a 'dummy' header must be created. This called to LOAD or VERIFY both the header and main data block
defines details which are required to match, before the following from the tape.
block is loaded. Once a match of the required details is made any LOADing or VERIFYing without a header can be achieved only
non-matching information will be checked against the real if the full parameters of the block to be accepted are known, when
header and, assuming that the changes are acceptable, these it is a very simple process.
details for the LOADing will be taken from the 'dummy' header. First the A register is loaded with FFh which signals that a main
Should the changes be unacceptable, a BASIC error report will be block is to be accepted. Next the DE register pair is loaded with
generated by an RST 8 instruction. The second 17 bytes will be the total length of the block to be accepted. Then the IX register is
filled from the tape with headers for comparison. Only when a set to point to the address to start LOADing or VERIFYing the
match is made will this area become free for use again. main data block. This followed by the carry flag being set,
The dummy header is made up in exactly the same manner as signalling a LOAD or reset to VERIFY. Finally, the ROM routine
the header saved on the tape and again, the first and last bytes of at 1366 (556h) is called to do the actual operation.
the full 19 are generated internally, so are not included in the The start of this routine preloads the machine stack in the same
17-byte specifier. The first byte must be the same identifier as the way as the SAVEing routine detailed earlier, giving an error
first byte in the header of the data to be loaded (i.e. the type must return in the event of BREAK being pressed. It can be bypassed
match). This is held in the A register on entry to the LOAD BYTES by CALLing the following short subroutine in your own
subroutine and need only be set if calling this directly. If the types program:
do not match, a new leader is waited for and the process repeated
until the types do match. The second byte (the first of the 17 that
need to be set up in the dummy header) again must match: 0 for a LOAD INC D ;RESET 0 FLAG
BASIC program, 1 for a numeric array, etc. If there is no match the EX AF,A'F'
next block will be waited for. The next ten bytes are the name. If DEC D ;RESTORE D
the name is to be disregarded then the first of these bytes must be DI ;THE INTERRUPTS MUST BE
FFh, the names will then be taken as matching. The next two OFF TO ENSURE THAT THE
bytes are the length, if this is set at 0 then the length will be taken TIMING IS CONSTANT. THEY
from the tape header otherwise the two lengths must match. For a ARE NOT TURNED ON BY THE
block of code, bytes 15 and 16 will be the start address to load to, ROM ROUTINE BEFORE RETURN
24 The Spectrum Operating System

LD A,OFH Chapter Three


OUT (FEH),A ;SET BORDER AND EAR PORTS
JP 562H ;JUMP TO MAIN LOAD ROUTINE

The OUT instruction sets the BORDER colour to white with the
The 81( Interface ROM
three low bits; these can be changed as required to give a
different colour. Bit 5 should be left set as this initialises the EAR
port for indication of anything coming from the tape prior to the
leader.
With the addition of the 8K ROM in the Microdrive interface,
A tape-loading error can be detected by the carry flag being
Sinclair have opened up the possibility of expansion in the form
reset on return to the calling routine and, as an attempt to BREAK
of sideways ROM as used in the BBC microcomputer, as well as
will result in an immediate return, if the test break routine is
an easy route to expansion of the Sinclair BASIC. The first thing
called after checking for errors this can be catered for.
that needs to be understood is the mechanism by which the Z80
CPU can be used to address memory outside its normal direct
Note: The interrupts will be off on return from loading.
addressing range of 64 kilobytes.
The routine can also be used to read in a header, instead of a The CPU has two sets of information lines — A 1-16 (which it
main data block, by loading the A register with 0 prior to calling uses to tell the memory which byte it wishes to use) — called the
address bus, and D 0-7, the data bus, which is used to read and
it. This can be useful if you wish to create a different type of
write to the memory location pointed to on the address bus.
header and read it with your own routine. This is demonstrated
Normally it would be impossible to access outside the 64K range,
in the DeBASE program in Appendix G.
so some form of interception must be made which substitutes a
different bank of memory in the same address range.
This is quite easy to do by choosing a byte of memory, looking
for its address on the address bus, and when a match is made
switching to the alternative memory. Execution will then
continue at the next address as the program counter will move on
to point to the next location as normal, but the data will be fetched
from the new bank of memory.
In the Spectrum this is done by looking at the address bus for
the program counter addressing location 8, which is the error-
handling routine. Since this address is reached only by a restart
(RST 8), the top of the stack will always hold the address of the
instruction following the calling instruction (i.e. the return
address). This is fetched by the shadow ROM routine, and the
contents of that memory location examined. Values in the range
00 to lAh cause a return to the 16K ROM as these are normal error
codes, but numbers between 1Bh and 32h are used as `hook
codes'. These call shadow ROM routines and will now be
detailed. To use a hook code use RST 8 followed by DEFB hook
code. All locations relate to the shadow ROM.
26 The Spectrum Operating System The 8K Interface ROM 27

Inputs the time allowed for a packet to be received has elapsed, there is a
checksum error. Alternatively, if BREAK is pressed, the carry flag
Get Key: Hook Code 1Bh, Location 6617 (19D9h) would be set.
Because of the problem inherent in this routine, it is easier to
This is similar to the GET command in some BASICs (although use the 16K ROM routine at 5606 (15E6h). Remember to preserve
the Sinclair BASIC does not have this command). It waits until a the IX register before calling this routine as it would be corrupted
key is pressed and then returns with the code of the key pressed otherwise. The carry flag will be set if the A register does not hold
in the A register. The maskable interrupt should be on as the 16K a received code.
ROM routine is used to scan the keyboard.

Outputs
RS232 Input: Hook Code 1Dh, Location 2945 (B81h)
Print to Screen: Hook Code 1Ch, Location 6636 (19ECh)
To use this routine, first the BAUD rate must be set using the
system variable BAUD 23747/8 (5CC3/4h) calculated as 3 500 000/ To use this the character code must be in the A register prior to
(26 x baud rate) — 2, 3 500 000 being the clock frequency of the calling the routine. This routine is a direct equivalent to the 16K
Spectrum. Next SER_FL 23751 (5CC7h) should be set to 0, and ROM routines for setting output to stream 2 (main screen) and
then the input routine can be called. The A register will hold the RST 16 printing to current stream, which actually uses these 16K
code of the character received and the carry flag will be set. The ROM routines. Used in connection with the Get Key routine (see
routine will wait for only a certain period for a code to be Inputs section above) you can create a sort of 'dumb terminal'.
received. If it has to wait too long, or if the space key is pressed, it The program to do this would look something like this:
will return, but without the carry flag set.
RST 8
DEFB 1BH
Network Input: Hook Code 2Fh, Location 6705 (1A31h) RST 8
DEFB 1CH
Before use, a network channel must be opened and made current
The first RST 8 will wait for a key to be pressed and return with the
by the use of the Open Channel routine described later (see
code in the A register, and the second RST 8 will echo the
Network Output section). This routine will read a packet from the
character to the main screen (or whatever output to stream 2 has
network, on entry the IX register should be set to the start of the
been directed to).
network area and IX + 11, IX + 12, and IX + 13&14 must be set to
the correct values for the block to be received (see the details on
the network header in the section on Network Output using hook Print to the Printer: Hook Code 1Fh, Location 6652 (19FCh)
code 30H). The block number in IX + 13&14 will be incremented
This is identical to the print-to-screen routine above except that it
after each block is successfully received.
It would appear that it was intended that the carry flag should uses stream 3 (normally the printer) instead of stream 2.
indicate if a packet has been read or, if there was an error, when
the return to the calling routine is made. However, the carry flag RS232 Output: Hook Code 1Eh, Location 3162 (C5Ah)
can be corrupted by the resetting of the border colour on exit from
the routine. A return will be made from this routine when a Again this is used by putting the code to be output in the A
packet has successfully been received, with the carry flag reset. If register, but using the RS232 output port on the interface. The
28 The Spectrum Operating System The 81( Interface ROM 29

baud rate is picked up from the system variable BAUD and the routine (see Close Network Channel below), which will send any
border colour from the system variable IOBORD (see Chapter 4 remaining buffer contents and reclaim the buffer area. It will not
for the settings of these). No information will be sent unless the close any streams attached to the network channel, and care must
D'lR (Data Terminal Ready) line is high. be exercised to ensure that other streams and channels are not
The main entry point called by the hook code allows any value corrupted.
of the A register to be output; care therefore needs to be taken to
avoid sending control codes unintentionally. The other useful
entry point is at 3132 (C3Ch) which looks for unprintable ASCII Send Packet: Hook Code 30h, Location 3530 (DB2h)
codes and intercepts them: any codes below 32 (20h) will cause an
immediate return, except for code 13 (0Dh) (carriage return) This CALL allows a 'packet' to be sent over the network. Before
which will be output and followed by a line feed code 10 (0Ah). use a network channel must be opened, the header and system
Codes from 128 (80h) are treated according to their type. Graphics variables must be set up, and the data to be sent placed in the
characters will be output as a '?' and tokens will be expanded by a buffer. To open a network channel use hook code 2Dh (see details
call to the 16K ROM routine at 3088 (C10h), which requires 165 above).
(A5h) to be subtracted from the code prior to its being called. On calling this routine, first a 'scout' is sent which claims the
network if it is free. Then the header is sent followed by the main
data block. The header is held in the front of the network channel
Network Output and is addressed by the IX register which points to the first
location in the channel. Bytes IX + 00 to IX + 10 are set up by the
Open Channel: Hook Code 2Dh, Location 3753 (EA9h) channel-operating routine and bytes IX + 11 to IX + 18 are the
header. The header is made up as follows:
Before any data can be sent or received on the network, a network
channel must be opened. This is done by using this call after first IX + 11 The station receiving
setting D S'I'R123766 (5CD6h) and NSTAT 23749 (5CC5h) system IX + 12 The station sending
variables to be the destination and sending station numbers, IX + 13 & 14 The block number
respectively. A network channel will then be created at the end of IX + 15 1 for the last block otherwise 0
the CHANS area, and everything from the address contained in IX + 16 The length of the buffer (0-255)
the PROG 23635/6 (5C53/4h) system variable to that in the IX + 17 Checksum for the data block
STKEND 23653/4 (5C65/6h) system variable will be moved up by IX + 18 Checksum for the header
276 bytes and the relevant system variables will be reset, IX + 19 & 20 USED FOR RECEIVING ONLY
assuming there to be room below RAMTOP 23730/1 (5CB2/3h). If IX + 19 The position of the last code taken from the buffer
there is not enough room, an error will be caused. IX + 20 The number of bytes available in the buffer
On return the IX register will point to the start of the new IX + 21 to IX + 275 are the data for sending, up to 255 bytes.
channel. The newly created channel is temporary and signified as
such by bit 7 of IX + 4 being set. To make it permanent this bit The checksums are created by the routine itself so do not have to
should be reset, and it can now be used to send by loading be inserted and IX + 15 is loaded from the A register on entry to
CURCHL 23633/4 (5C51/2h) with the address in the IX register the routine, but all the other details must be set by the user. In
and using the RST 16 (10h) routine in the 16K ROM to output addition to setting the header, the system variables D S I R1
data, a byte at a time. 23766 (5CD6h) must be the destination station number and
After the final data has been passed to the RST 16 (10h) routine, NTSTAT 23749 (5CC5h) the sending station number. On each call
the channel should be closed by the use of the hook code 2Eh to this routine the block number will be incremented. The base
30 The Spectrum Operating System The 8K Interface ROM 31

address of the network channel is returned in the IX register by LD HL,5C16H ;BASE ADDRESS OF STREAMS
the channel open routine. LD D,0 ;OFFSET FOR S STREAM TO THE DE
LD E,A ;REGIS"IER PAIR
ADD HL,DE ;NOW HL = STREAM LOCATION
PUSH HL ;SAVE IT
Close Network Channel: Hook Code 2Eh, Location 6692 (1A24h) RST 8 ;CALL HOOK CODE
DEFB 22H ;22 (OPEN CHANNEL/FILE)
If this routine is called after a send operation, it will transmit any PUSH HL ;ON RETURN FROM THIS ROUTINE
data remaining in the network buffer, marking it as an end-of-file
HL = STREAM DISPLACEMENT
block, but after a receive operation it will discard any remaining XOR A ;THE OPEN CHANNEL ROUTINE
data in the buffer. The 270 bytes of the buffer area will then be LEAVES THE
reclaimed using the 16K ROM routine at 6632 (19E8h) but the
RST 8 ;MICRODRIVE MOTOR RUNNING
channel information is left.
DEFB 21H ;SO IT MUST BE TURNED OFF
POP DE ;DE = STREAM DISPLACEMENT
POP HL ;HL = STREAM LOCATION
Microdrive Output LD (HL),E ;SET S STREAM TO CORRECT'
DISPLACEMENT
Open Ch an nel/Open File: Hook Code 22h, Location 6953 (1B28h) INC HL
LD (HL),D
Before data can be sent to a Microdrive, a Microdrive channel and RES 7,(IX + 4) ;ON RETURN FROM THE HOOK
a map area for the drive selected must be created. Hook code 2Bh CODE 22 IX = START OF CHANNEL
was intended to serve this purpose, but there was an error in the AREA. RESETTING (IX + 4) MAKES
program, although this hook code can be used to perform the THE CHANNEL PERMANENT
operation. First set D STR1 23766/7 (5CD6/7h) to contain the EXX ;RESTORE THE RETURN ADDRESS TO
drive number (1-8), N_S I R1 23770/1 (5CD4/5h) the length of the BASIC
file name and T_STR1 23772/3 (5CD6/71-i) to the start address of POP HL
the file name in memory. The H'L' register pair must then be EXX
saved and the hook code can then be called. RET ;FINISHED
The channel will be opened as a read channel if the file name
exists, otherwise it will be opened as a write channel. To make the
channel a permanent one, the data must be incorporated into the
STREAMs information. The following subroutine achieves this: To write to or read from a Microdrive, the channel created must
be made current by loading the system variable CURCHL 23633/4
EXX ;SAVE THE RETURN ADDRESS TO (5C51/2h) with the base address, returned in the IX register after
BASIC opening the channel. The cartridge can then be written to with
PUSH HL the 16K ROM RST 16 (10h) routine, or read from with the 16K
EXX routine at 5606 (15E6h), which returns with each character in the
LD A,S ;S IS THE STREAM NUMBER FOR THE A register. If it is required to SAVE, VERIFY, MERGE, or LOAD
CHANNEL with the Microdrive as opposed to using the cartridge as a file,
RLA ;DOUBLE IT this is explained later in this chapter.
32 The Spectrum Operating System The 81( Interface ROM 33

Write Record: Hook Code 26h, Location 4607 (11FFh) Microdrive Input

This hook code will write the contents of the Microdrive buffer to All the following 'read' routines return with the Microdrive motor still
the next free sector on the Microdrive cartridge. Before calling the running and the maskable interrupt off.
routine, the buffer must contain the information to be saved, the
IX register must point to the start of the Microdrive channel.
IX + 11 must contain the length of the data, IX + 13 the sector Read Print Record: Hook Code 27h, Location 6679 (1A17h)
number (starting at 0 for the first sector of a record and auto-
matically incremented each time a record is either sent or This will read a record from a print file, the record number of
received), IX + 14 to IX + 23 the record name and IX + 25 the drive which is held in IX + 13. The IX register must point to the start of
to be used. Locations IX + 82 to IX + 593 are available for the data the Microdrive channel, IX + 25 must hold the drive number and
to be placed for sending. IX + 14 to IX + 23 the record name. Assuming the record sector to
be present, it will be read into the buffer otherwise an error will
be caused.
Write Sector: Hook Code 2Ah, Location 6801 (1A91h)

This performs the same action as above but looks for a sector of a
Read Next Print Record: Hook Code 25h, Location 6665 (1A09h)
record with the sector number in IX + 13 and, if it exists,
overwrites it with the information currently in the buffer. If the
This is as above but, when used after the previous Hook Code, it
sector does not exist, a 'FILE NOT FOUND' error will be
will automatically read in the next record of a print file, if there is
generated. No check is made as to whether the sector is free or
one. Otherwise an error will be caused.
not, so care must be exercised to ensure that nothing that you
want is already on the sector.

Read Record Sector: Hook Code 28h, Location 6731 (1A4Bh)


Close Microdrive Channel: Hook Code 23h, Location 4777
(12A9h) This will read a record from a file. The IX register must point to the
start of the Microdrive channel, IX + 13 should be set, the record
This hook code performs the same action as the Close Network number (within the file) IX + 25 must hold the drive number and
Channel (hook code 2Eh) but for the Microdrive and on entry the IX + 14 to IX + 23 the file name. Assuming the record sector to be
IX register must hold the base address of the file. If the channel present, it will be read into the buffer. If it is a print file, a return
was used for sending, any information left in the buffer will be will be made with the carry flag reset and the record in the
sent as an 'end of file' message and the buffer will then be Microdrive buffer area. Should the record be other than a print
reclaimed, or if it was a read channel anything left in the buffer record the carry flag will be set and the record cleared from the
will be lost as the channel is reclaimed. buffer.

Erase File: Hook Code 24h, Location 7534 (1D6Eh)


Read Next Record Sector: Hook Code 29h, Location 6790 (1A86h)
This will erase a Microdrive file whose name is written in
memory and pointed to by T_STR1 with name length N_STR1 on This is as above but for the next sector of a file. It is similar to
Microdrive D_STR1. Hook Code 25h.
34 The Spectrum Operating System The 8K Interface ROM 35

Motor on/Motors off: Hook Code 21h, Location 6135 (17F7h) When the hook code is used, the address in HD_11 23789/90
(5CED/Eh) is put on the machine stack followed by the return
The A register should be loaded either with 0, to turn off any address for the 8K ROM to 16K ROM switchover (1792 (700h)). If
motors that are running, or with the drive number whose motor you make the address in HD_11 point back to your own program,
is to be started. If the drive is not present, an error will be caused. you can then 'POP' the two return addresses off the stack and
If the drive is present, the motor will be started and a return have the 8K ROM paged in, with your program in control. Any
made, with the interrupts off. registers can now be used freely with 8K routines. To return to the
16K ROM all that you need to do is to CALL 1792 (700h), and the
8K ROM will be switched out.
Reclaim Microdrive Channel: Hook Code 2Ch, Location 4292
(10C4h) Note: Many routines look at the syntax/run flag in FLAGS 23611
(5C3Bh) IY + 1, and cause a return to the BASIC interpreter in
The Microdrive channel area currently pointed to by the IX syntax time. Some of the Microdrive routines also return to
register will be reclaimed. Any streams currently using the BASIC via the address in ERR SP 23613/4 (5C3D/Eh) if they are
channel will be closed and the Microdrive map area is also completed successfully, or via an 8K ROM error if they have
reclaimed if not in use from another channel. All memory above failed. The 16K error can be diverted to point back to the calling
the reclaimed channel up to RAMTOP is moved down by the 627 routine by altering the address in ERR SP so that it points to the
bytes freed by the reclamation. return address of your routine on the machine stack. This is
demonstrated in the DeBASE program in Appendix G, in the
Microdrive SAVE/LOAD routines.
Keyscan: Hook Code 20h, Location 6657 (1A01h)
The following routines are called by the RST 8 DEFB 32h hook
This returns with the carry flag set if any key is being pressed.
code after putting the location into HD_ll.

Insert Variables: Hook Code 31h, Location 6568 (19A8h)


Catalogue Cartridge: Hook Code 32h, Location 7256 (1058h)
This inserts the extra system variables needed for the Interface 1.
Before use, save H'L' registers. D_SIR1 must contain the
In fact, it is a single RET instruction as the variables are created
Microdrive number and S_S I'R1 the stream number for the
automatically when the first 16K error occurs.
catalogue to be printed to. The call can then be made and after the
catalogue has been done H'L' registers are restored.
ROM 2: Hook Code 32h, Location 6564 (19A4h)

Perhaps this is the most useful of all the hook codes as it allows Format Cartridge: Hook Code 32h, Location 7022 (1B6EH)
the 8K ROM to be paged in at will; therefore any routine can be
called. To use it the location of the routine you want accessed Once again, before use the H'L' registers must be saved. N S'lR1
must be placed in the system variable HD_11, the hook code can must hold the length of the name to be given to the cartridge, and
then be used. Unfortunately, the only register that can be passed T STR1 the address of the first character of the name when the
directly by this hook code is the A register, but this is no real routine is CALLed. The H'L' registers should be restored
problem. afterwards for a successful return to BASIC.
36 The Spectrum Operating System The 8K Interface ROM 37

Run: Hook Code 32h, Location 2709 (A95H) INCHL


LD DE,DATA ;program length or variable name as
LD (HL),E ;described in chapter 2 in saveing
This is the simplest of the routines. It loads a program from
INCHL ;and loading
Microdrive 1 called 'Run'. All that is necessary is a jump to the LD (HL),D
routine in ROM. This can be made after the 16K ROM has been INCHL
paged out in the way described in the Hook Code 32h section LD DE,AUTO ;auto start line number, if any
LD (HL),E ;otherwise a number over 10000
above.
INCHL
LD (HL),D
The following routines for SAVEing, LOADing, VERIFYing and
GO_ON LD HL,23769 ;make it a microdrive operation
MERGing all require a header to be set up before they can be LD (HL),"M" ;it must be a captial letter
used. The details of the make-up of a Microdrive channel are SETBIT_,(IY+124);bit 4 to load, bit 5 to save
given in the Microdrive and Interface 1 manual (see pages 47 and bit 6 to merge, bit 7 to verify
48) so I shall not repeat this detail here. I shall, however, explain LD HL,NLEN ;length of file name (max 10
letters characters or tokens)
how a header is made so that the Microdrive can be used from (23770),HL;this is NSTR1
LD
machine code. LD HL,NAME ;start address of file name
LD (23772),HL;T STR1
LD HL,DRIVE ;the drive number (1 - 8)
LD (23766),HL;D_STR1
BIT 5,(IY+124);is it a save operation
Making a Microdrive Header JP NZ,1E7FH ;if so go into save routine in ROM
JP 08AF ;else ROM load/verify/merge routine
NAME DEFS 10 ;10 spare bytes for file name
The Microdrive header is made up in much the same way as the
tape header described in Chapter 2, but it is not necessary actually
to set up the header in the Microdrive channel, as there is a The subroutine above must be CALLed from the main
routine in the ROM which will do this for you. All that has to be program. The RETum after the operation has been performed is
done is to set the system variables correctly. The subroutine to do from the ROM routine to your calling routine, via the address on
this within your program would look something like this: the machine stack pointed to by ERR SP (see the DeBASE
program in Appendix G for details of how to ensure a return). The
LD HL,23782 ;HD_00 16K ROM will be paged in by the SAVE or LOAD routine.
LD (HL),T ;T = 0 for a program: 1 for a Any errors in the setting up of the header will cause either a
numeric array: 2 for a string
array: 3 for code
BASIC error or a machine crash, so great care must be taken. As
INC HL with most 8K ROM routines, it is important to save the H'L'
LD DE,LEN ;length of the main data block registers before using the routines and restore them afterwards.
LD (HL),E When a machine code program using ROM routines is being
INC HL
LD (HL),D written, it is very important to remember which ROM will be
INC HL switched in at any given time. Not only are all the routines in
LD DE,START ;start of data to be saved or dest ROM changed, but all the ReSTarts in the 8K ROM are different
LD (HL),E ;when loading. 0 if information on from those in the 16K ROM.
INC HL ;cartridge is to be used
It is possible to have a free exchange between the two ROMs by
LD ( HL ) , D
the rest of thi s need only be carried out for using Hook Code 32h from the 16K ROM and RST 10h from the 8K
BASIC programs and arrays. Otherwise jump to GO ON ROM. The use of Hook Code 32h has already been explained, but

38 The Spectrum Operating System The 8K Interface ROM 39

details of how to use RST 10h and the other ReSTarts (RST) in the 0081H LD E,(HL) ;PUT THE ADDRESS TO BE
8K ROM are given below: CALLED IN THE
INC HL ;16K ROM INTO DE
LD D,(HL)
RST 0 POP HL ;REMOVES THE RETURN
INC HL ;HL NOW HOLDS THE
ADDRESS FROM THE
RETURN ADDRESS AF 1 ER
MACHINE STACK
LD THE DEFW
(IY + 124),00 ;THIS IS FLAGS 3
JP 700H EX (SP),HL ;MAKE THIS THE NEW
;700H IS THE RETURN TO
RETURN ADDRESS
THE 16K ROM
EX DE,HL
LD HL,O ;THIS WILL LET THE RST 8
The address at the top of the stack at this stage should be the ROUTINE KNOW
return to the routine that originally called the 8K ROM. PUSH HL ;IT IS A RETURN FROM A
8K TO A 16K CALL
RST 8 LD HL,(CH_ADD) ;THIS HAS NO EFFECT LD HL,8 ;THE ERROR RESTART
WHEN CALLED FROM 16K PUSH HL ;ONTO THE STACK FOR A
POP HL ;THE ADDRESS OF THE LA 1 ER RETURN
ERROR CODE LD HL,5CB9H ;THE START OF THE
PUSH HL ;SAVE IT AGAIN SUBROUTINE
JP 009AH ;THIS WILL CHECK WHAT IS ;ONTO THE STACK FOR A
PUSH HL
BEING EXECUTED AND RETURN
EITHER RETURN TO A 16K JP 0700H ;A RET INS I RUCTION
ERROR, EXECUTE A HOOK THAT SWITCHES IN THE
CODE OR ACCESS A 16K ROM
CHANNEL. 0700H RET ;PAGE IN THE 16K ROM
AND RETURN
This is of no practical use when the 8K ROM is switched in.
The RST 16 (10h) in the 8K ROM CALLs a 16K ROM routine, the
I have given the full listing for this as it is an interesting method
address of which is held in a DEFined word (DEFW) after
of transferring control.
ReSTart. After the 16K routine has been executed control is
When the RETurn at 0700h is made, switching in the 16K ROM,
returned to the address after the DEFW in the CALLing routine.
the address collected from the stack is 5CB9h. This address
contains 21h, the instruction LD HL,NN. As can be seen above
RST 16 LD (5CBAH),HL ;SAVE HL FOR the NN was the value in HL when the ReSTart was made. The
RESTORATION AH ER next location — 5CBCh — contains CDh, the instruction CALL
RETURN NN. Again this address was loaded above, from the DEFW after
(10H) POP HL ;COLLECT IN HL THE the RST 16 (10h). The return from the 16K routine will be to 5CBFh
ADDRESS OF THE DEFW which contains 22h, the instruction LD (NN),HL. The NN in this
PUSH DE ;SAVE DE ON MACHINE case is 5CBAh, so the new value in the HL register is saved where
STACK the original value was. Finally there is the instruction RET. This
JR 0081H will be a return to the address on the top of the machine stack,
40 The Spectrum Operating System The 8K Interface ROM 41

now 8 (i.e. the error ReSTart). This time when the address for the ;THIS IS TV FLAG
DEFBs is 'POPped' off the stack i t will be 0. This will tell the ROM (28H) JR 0040H ;THIS WILL CHECK IF THE
(8K now) that the HL register has to be loaded from (5CBAh), and ERROR OCCURRED IN
after this there is yet another RETum, this time to the address SYNTAX OR RUN TIME. IF
after the two DEFBs after the RST 16 (10h), seemingly so long ago. IN RUN TIME IT WILL
The following ReSTart can be used to generate the shadow RETURN TO THE 16K
ROM error messages in the same way as the RST 8 in the main ERROR ROUTINE
ROM: OTHERWISE IT WILL
JUMP TO 0068H, AS
RST 24 BIT 7,(IY + 1) ;THIS IS FLAGS EXPLAINED ABOVE.
(18H) RET ;THE ZERO FLAG WILL BE RST 48 JP 01F7H ;CHECKS TO SEE IF THE
SET IF A BASIC LINE IS INTERFACE
BEING CHECKED FOR (30H) VARIABLES ARE PRESENT
SYNTAX AND IF NOT INSERTS
RST 32 RST 24 ;CHECK IF SYNTAX OR THEM.
PROGRAM RUN RST 56 EI ;THIS IS THE NORMAL
(20H) JR Z,0068H ;THIS WILL RESET THE MASKABLEINIERRUPT
STACK POINTER TO THE (38H) WHICH WOULD SCAN
ADDRESS IN ERR_SP SET THE KEYBOARD IF THE
X_PTR TO CH_ADD AND 16K ROM WAS PAGED IN.
RETURN TO THE MAIN RET NO 1 E THAT THE
ROM LINE INPUT KEYBOARD WILL NOT BE
ROUTINE VIA THE CLEAR SCANNED WITH THIS.
CALCULATOR ROUTINE,
AND INDICATE THE The non-maskable interrupt routine at 102 (66h) consists of the
POSITION OF THE single instruction RETN.
ERROR. More 8K ROM routines are discussed in Chapter 7 but there are
JR 003AH ;THIS WILL GENERAIE AN few routines that are of use for other purposes. Their use and
ERROR REPORT. THE locations have already been detailed in the hook codes section.
SHADOW ROM ERROR
CODE WILL BE
COLLECTED FROM THE
BYTE AF 1ER THE
RESTART.

This ReSTart can be used to generate a 16K error by loading


ERR_NR with the error code before calling it.
The System Variables 43

Chapter Four CAPS SHIFT code of the key being pressed will be saved in the
first location. The second location is set to 5 (the countdown to
free, which also se rv es to debounce the keyboard), the third
The System Variables location is loaded with the repeat delay REPDEL. The ASCII code
of the key pressed is decoded, saved in the last location and
copied into LAST K, bit 5 of FLAGS is set to signal a new key
press and a return to the calling routine made. When neither set is
free then a counter in the second byte of each set is decremented
and the calling routine is returned to.
The BASIC interpreter requires some means of keeping track of Once one of the counters reaches 0, the code of the key being
where information is stored, and what it is supposed to be doing, pressed (if any) is saved and a comparison is made between the
since it is located in ROM (Read-Only Memory) and has to use code of the keys in the two sets. If they match a key is being held
RAM (Random Access Memory) to store this information. Since down and then the routine allows for repeating of the key. This is
the ROM is unalterable, the addresses of the system variables not the key-debouncing routine, but the repeating key routine.
have to be predefined in such a way that they can be accessed on a The repeat delay being held in the third byte and initially loaded
regular basis. In the Spectrum, this is achieved both by having from the system variable REPDEL.
their locations fixed in particular area of memory and also by Once the delay for the first repeat is over (the routine must be
indexing them with the IY register, which always points to called the number of times set by the delay counter), if the match
5C3Ah (ERR NR). has been continuous then the third byte is loaded from the
system variable REPPER, the code is again passed to the system
variable LAST K, bit 5 of FLAGS set and a return to the calling
16K System Va ri ables routine made. On subsequent calls to the keyboard-scanning
routine, the whole process is repeated but with the shorter delay
KSTATE: Locations 23552-23559 (5C00h-5C07h) from REPPER until the codes no longer match. If the keys do not
match then the treatment is the same as for a free set.
These locations are used in reading the keyboard. They can be The net result of all this is that there is a two-key rollover,
divided into two sets of four, and each set is treated the same as which allows for a second key being pressed before the delay for a
the other. Which set is actually used depends upon the state of the repeat on the first set has elapsed, avoiding the loss of the second
other set. key if it is not held down long enough for the original set to
The CAPS SHIFT value of a key being pressed is stored in the become free.
first location of each set or, if no key is pressed, 255 (FFh) which
flags the set as free for use. The count down to a set being free is
stored in the second byte, initially set to 5, free when O. The
LAST K: Location 23560 IY – 50 (5C08h)
repeat delay is in the third byte, initially loaded from REPPER.
The ASCII code of the key pressed when a set was in use is in the This contains the code of the last key pressed.
last location of that set until the countdown to the set being free
reaches O. In order to try to make some sense of this I will explain
the routine that uses these va ri ables. REPDEL: Location 23561 IY – 49 (5C09h)
If a key is pressed, the scanning subroutine looks to see
whether the first set is empty. If it is it will then use this set, The number of times the keyboard-scanning routine must be
otherwise it will look at the second set. When a set is free then the called before a key repeats is contained at this location.
44 The Spectrum Operating System The System Variables 45

REPPER: Location 23562 IY – 48 (5COAh) The last valid ASCII code is 127 (7Fh), but the Spectrum uses
the remaining 128 values of the full eight-bit range for tokens.
This contains the number of times the keyboard scan must be These are dealt with separately and do not comprise part of this
called before a repeating key repeats. character set.

DEFADD: Locations 23563/4 IY – 47 (5COB/Ch) RASP: Location 23608 IY – 2 (5C38h)

These locations hold either the address of a user-defined function This contains the length of the buzz generated when a basic line
being evaluated or O. exceeds 22 lines or memory has run out.

K DATA: Location 23565 IY 45 (5CODh) PIP: Location 23609 IY – 1 (5C39h)

This is used as temporary storage of the colour information when This contains the duration of the beep whenever a key is pressed.
colour controls are being entered (i.e. the second byte, the colour
number, after the E shift).
ERR NR: Location 23610 IY + 0 (5C3Ah)

TVDATA: Location 23566/7 IY – 44 (5COE/Fh) This contains one less than the report code that will be generated
on an error. It can be used to generate your own reports or use the
These are as above but for output and used with AT and TAB resident reports for your own purposes (see Chapter 2 for details).
values as well, hence the two bytes.

FLAGS: Location 23611 IY + 1 (5C3Bh)


STRMS: Locations 23568-23605 IY – 42 (5C10h-5C35h)
Bit 0 is set to suppress a leading space when a token is being
These contain the addresses of the channels attached to streams. printed if a space immediately precedes it, but is reset if a space is
Initially streams –3 to 3 are in the first 14 bytes, but the infor- to be printed.
mation for extra streams (up to a total of 19) is added when they
are opened, in the relevant place. Bit 1 is set when stream 3 (normally the printer) is to be used for
output from the RST 16 routine, but is reset for stream 2 (normally
the main screen).
CHARS: Locations 23606/7 IY – 4 (5C36/7h)
Bit 2 is set when printing is to be using L mode and is reset for K
These contain the address of the theoretical start of the character mode.
set, each character comprising of eight bytes; in fact, 256 less than
the actual start as all characters are addressed relative to this Bit 3 is set to signal L mode, normally when getting an input, but
position by multiplying their ASCII code by eight and ASCII 0-31 is reset to signal K mode.
are not printable and thus are handled differently, not from this
table. Bit 5 is set if a new key has been pressed since it was last reset (see
46 The Spectrum Operating System The System Variables 47

details on Scanning the Keyboard in Chapter 2 and for KSTA'I E can be restored after automatic listing is completed. This is
system variable). necessary because the listing can be terminated at different
places, with different amounts on the machine stack (e.g., by a 'n'
Bit 6 is used to indicate if an expression is numeric or a string, in response to a 'Scroll?'.
being set for numeric and reset for a string, and is used by the
BASIC interpreter.
MODE: Location 23617 IY + 7 (5C41h)
Bit 7 is reset when the BASIC interpreter is checking a line for
syntax on entry and is set when the program is being run.
This determines the cursor used in an input, but it will only affect
the first key press except when changed to force the graphics
mode. However, it can be useful to get different cursors for input
TV FLAG: Location 23612 IY + 2 (5C3Ch)
(e.g., if you POKE MODE with 32 you will get a flashing graphics
input). Experimentation is the best way to make use of this
Bit 0 is set if handling the lower screen and is reset for the main
facility as the system will not crash.
screen.

Bit 3 signals that the current mode may have changed and needs
to be rechecked. NEWPPC: Locations 23618/9 IY + 8 (5C42/3h)

Bit 4 is set when an automatic listing is being printed, otherwise This contains the line number of the next statement to be inter-
it is reset. preted.

Bit 5 signals that the lower screen needs to be cleared (e.g. when a
report is about to be printed).
NSPPC: Location 23620 IY + 10 (5C44h)

ERR SP: Locations 23613/4 IY + 3 (5C3D/Eh) This is the number of the statement in the line to be evaluated
next. Poking first the line number then the statement number
These locations hold the address on the machine stack of the forces a jump in execution to that place.
RETurn to be used in the event of an error in a BASIC command
being executed. It is picked up by an error ReSTart and frequently
changed by BASIC. It can be changed from machine code to make PPC: Locations 23621/2 IY + 11 (5C45/6h)
an error go to your own routine, as demonstrated in the DeBASE
program in Appendix G, in the Microdrive SAVE/LOAD section. This contains the line number of the statement currently being
If an error occurs this must be reset and the error cancelled by evaluated. Also it is used by an auto-run program loaded from the
making ERR NR hold 255 (FFh). Note that 0 OK is counted as an header.
error.


LIST SP: Locations 23615/6 IY + 5 (5C3F/40h) SUBPPC: Location 23623 IY + 13 (5C47h)


LIST SP is used to save the address of the stack pointer so that it This contains the statement number currently being evaluated.
48 The Spectr u m Operating System The System Variables 49

BORDCR: Location 23624 IY + 14 (5C48h) PROG: Locations 23635/6 IY + 25 (5C53/4h)

This contains the value for the border colour *8 plus the attri- This is the address of the start of the BASIC program area, which
butes for the lower screen. Bits 7 and 6 can be used to make the will be the byte following the channel information area and any
lower screen fl ash or bright. input/output buffers being used by Interface 1.

NXTLIN: Locations 23637/8 IY + 27 (5C55/6h)


E PPC: Locations 23625/6 IY + 15 (5C49/Ah)

This is the address of the start of the next BASIC line in a program.
E PPC contains the number of the current line (i.e. the line that
will be displayed with the cursor and brought into the editing
area addressed by E LINE by an EDIT command). DATADD: Locations 23639/40 IY + 29 (5C57/8h)

This is the address of the terminator of the last data item used, or
VARS: Locations 23627/8 IY + 17 (5C4B/Ch) the start of the line given by a RESTORE command, or the first
after it if it does not exist. This keeps track of which data item is to
This contains the address of the start of the variables area. When be used next and if there are no more data after this pointer it will
it is used in conjunction with E LINE, the total length of a BASIC cause an 'out of data' error.
program's variables can be calculated.

E LINE: Locations 23641/2 IY + 31 (5C59/Ah)

DEST: Locations 23629/30 IY + 19 (5C4D/Eh) E LINE is the address of the start of the editing area, which will be
the start of anv line in the edit area.
This contains the address of the first letter of the name of the
variable currently in use. If a new variable is to be used, it is the
80h end marker immediately before the address in E LINE where K CUR: Locations 23643/4 IY + 33 (5C5B/Ch)
the start of a new variable is being placed.
This is the address of the cursor in the current line. It is used to
edit or to create a new line in the edit area.

CHANS: Locations 23631/2 IY + 21 (5C4F/50h)

CH ADD: Locations 23645/6 IY + 35 (5C5D/Eh)


This contains the address of the start of the channel information
area in which the details for open channels are kept.
This is the address of the next character to be interpreted by the
BASIC interpreter (n.b., any numerics are marked by a CHR$ 14
and these are skipped).
CURCHL: Locations 23633/4 IY + 23 (5C51/2h)
X PTR: Locations 23647/8 IY + 37 (5C5F/60h)
These locations hold the address of the start of information in the
channel information area for the channel currently in use. These locations hold the address at which BASIC syntax has
50 The Spectrum Operating System The System Variables 51

failed when entering a new BASIC program line, marked by a '?'. Bit 1 is set if the printer buffer has been used by a 16K ROM
It is also used to store information temporarily by the interpreter. routine and is reset after it is cleared by the Clea ri ng Printer
Buffer routine described in Chapter 2.

WORKSP: Locations 23649/50 IY + 39 (5C61/2h) Bit 2 set signals that the screen is clear.

Bit 3 set signals that CAPS LOCK is on.


This is the address of temporary workspace, the first byte of free
space created by a CALL 5717 (1655h) Make be Space routine (see Bit 4 set signals that K channel is in use.
Chapter 5 for details, given in the section on Standard Streams).

DF SZ: Location 23659 IY + 49 (5C6Bh)

STKBOT: Locations 23651/2 IY + 41 (5C63/4h)


This is the number of lines allocated to the lower screen. It can
cause the BASIC system to crash if set to less than three since one
These locations are the address of the bottom (start) of the calcu-
spare line is always left between the main screen and any reports.
lator stack. This is explained fully in chapter 8.
If there is nowhere for the reports to be printed, the interpreter
hangs up.

STKEND: Locations 23653/4 IY + 43 (5C65/6h)


S TOP: Locations 23660/1 IY + 50 (5C6C/Dh)
This is the address of the top (end) of the calculator stack. Again it
is fully explained in Chapter 8. This address contains the line number of the first program line to
be listed by a BASIC LIST command.

BREG: Location 23655 IY + 45 (5C67h)


OLDPPC: Locations 23662/3 IY + 52 (5C63/Fh)
This is the B register for use by the calculator (see Chapter 8 for
further details). This address holds the line number containing the statement
after that at which a BREAK or STOP was executed (i.e. the line
that will be interpreted after a CONTINUE command).
MEM: Locations 23656/7 IY + 46 (5C68/9h)
OSPCC: Location 23664 IY + 54 (5C70h)
MEM provides the address of the calculator memory area (see
Chapter 8 for further details).
This is as above but provides the statement number within the
line.

FLAGS2: Location 23658 IY + 48 (5C6Ah)


FLAGX: Location 23665 IY + 55 (5C71h)
Bit 0 is set if it is unnecessary for the main screen to be cleared
when a line is being input into the editing area. The FLAGSX system variable is a rough equivalent of the FLAGS
52 The Spectrum Operating System The System Variables 53

system variable (location 23611 (5C3Bh)) and is used in its place in time the normal interrupt routine is called. The least significant
the interpreter when INPUT commands are being executed. byte is in 23672 (5C78h).

Bit 1 is set if the BASIC interpreter is handling a new variable.


UDG: Locations 23675/6 IY + 65 (5C7B/Ch)
Bit 5 is set when the 16K ROM is in input mode and is reset when
in editing mode. This is the address of the first User - Defined Graphic.

Bit 6 is set if a string is being handled.


COORDS: Locations 23677/8 IY + 67 (5C7D/Eh)
Bit 7 is set if the BASIC interpreter is dealing with an INPUT LINE
command. COORDS provides the X and Y coordinates of the last point
plotted. This can be used to reset the start position for DRAWing
or CIRCLE without having to PLOT the start; X (across) is in
STRLEN: Locations 23666/7 IY + 56 (5C72/3h) 23677 (5C7Dh).

These locations hold either the length of an existing string


variable that is currently being used or, for a numeric or new
P POSN: Location 23679 IY + 69 (5C7Fh)
string variable, the low byte will hold the letter of the variable (in
the form described in the section on SAVEing and LOADing, see
This contains the column number of the next position to be used
Chapter 2).
in the printer buffer (as S POSN: Locations 23688/9 IY + 78 (5C88/
9h) below but for printer).

T ADDR: Locations 23668/9 IY + 58 (5C74/5h)

This normally holds the address of the next item in the syntax PR CC: Location 23680 IY + 70 (5C80h)
tables located from 6728 (1A48h) in the main ROM. However, it is
also used for other purposes by some routines. This is the low byte of the printer buffer current address. In effect,
this is identical to DF CC: Locations 23684/5 IY + 48 (5C84/5h)
and the printer buffer can be moved by changing the so-called
unused byte below, which is in fact the high byte of the PR CC
SEED: Locations 23670/1 IY + 60 (5C76/7h)
system variable. Unfortunately this is reset at the end of each
print line to point to the original address; care therefore needs to
This is the seed for a random number. It is taken from the low two
be exercised if it has been moved.
bytes of FRAMES if a RANDOMIZE command has no number,
otherwise it is taken from the RANDOMIZE number.

NOT USED: Location 23681 IY + 71 (5C81h)


FRAMES: Locations 23672-23674 IY + 62 (5C78h-5C7Ah)
In effect, this is not used if the printer buffer is in the normal place
At this address, a three-byte frames counter is held. It is set to 0 (see PR CC: Location 23680 IY + 70 (5C80h)) but not free for use,
when the Spectrum is first switched on and is incremented each except as above.
54 The Spectrum Operating System The System Variables 55

ECHO E: Locations 23682/3 IY + 72 (5C82/4h) high value since a machine code program could be broken into or
crashed, if a negative response is given.
As S POSN: Locations 23688/9 IY + 78 (5C88/9h) this is the
column and line number for the next print position, but for the
input buffer. It is used when entering a BASIC line. ATTR P: Location 23693 IY + 83 (5C8Dh)

This provides the global attributes for any screen printing,


DF CC: Location 23684/5 IY + 74 (5C84/5h) plotting, drawing, etc. It is set by a BASIC colour statement and
can be loaded from within a machine code program, in which
This contains the address of the top pixel line of the next print case all subsequent colours will be changed.
position. DF CC can be used to change the position of normal
printed characters, by altering this to the next line down, but it
can cause unexpected effects since the RST 16 (10h) routine MASK P: Location 23694 IY + 84 (5C8Eh)
simply adds 256 (100h) for each subsequent pixel line of a printed
item. The Spectrum screen map in the appendix can be used to This is used as a mask to discriminate between transparent colour
see the effect when moved down by more than one pixel line. items and colour items to be taken from ATTR P: Location 23693
IY + 83 (5C8Dh). For any bit set to 1, the attribute bit will be taken
from the screen attribute for the current position, otherwise it
DFCCL: Locations 23686/7 IY + 76 (5C86/7h) will come from A1"l'R P.

This is the lower screen version of DFCC: Locations 23684/5


IY + 74 (5C84/5h). ATTR T: Location 23695 IY + 85 (5C8Fh)

This provides the temporary attributes, set up by a colour item


S POSN: Locations 23688/9 IY + 78 (5C88/9h) printed by a RST16 (10h) instruction.

These locations hold column and line number for the next PRINT
MASK T: Location 23696 IY + 86 (5C90h)
position on the main screen and set up by the CALL 3545 (DD9h)
routine detailed in Chapter 2 (where 33 is left column and 24 is top
This is used as a mask to discriminate between transparent colour
line).
items and colour items to be taken from ATTR T: Location 23695
IY + 85 (5C8Fh). For any bit set to 1, the attribute bit will be taken
SPOSNL: Locations 23690/1 IY + 80 (5C8A/Bh) from the screen attribute for the current position, otherwise it
will come from A 1"1 R T.
Like S POSN: Locations 23688/9 IY + 78 (5C88/9H), these
locations hold the column and line number for lower screen.
P FLAG: Location 23697 IY + 87 (5C91h)

SCR CT: Location 23692 IY + 82 (5C8Ch) This is the flag used to discriminate between the print parameters
for any output to the screen by the ROM. The even bits are
This holds 1 more than the number of times the screen can be temporary bits, whereas the odd ones are permanent bits, each
scrolled without a 'scroll?' question. It should always be kept to a relating to the same items.
56 The Spectrum Operating System The System Variables 57

Bit 0/1 is set if OVER 1 is to be used. FLAGS3: Location 23734 IY + 124 (5CB6h)

Bit 2/3 is set if INVERSE is to be used. Bit 0 is set if an extended command is being executed.

Bit 4/5 is set if INK 9 is to be used. Bit 1 is set if a CLEAR# is being executed.

Bit 6/7 is set if PAPER 9 is to be used. Bit 2 is set if the ERR SP system variable has been altered by the
8K ROM.

MEMBOT: Locations 23698-23727 IY + 88 (5C92h-5CAFh) Bit 3 is set for NETWORK routines.

This is the area used by the calculator to store values which Bit 4 is set for LOAD routines by the 8K ROM.
cannot conveniently be kept on the calculator stack (see Chapter
8). Bit 5 is set for SAVE routines by the 8K ROM.

Bit 6 is set for MERGE routines by the 8K ROM.

Not Used: Locations 23728/9 IY + 118 (5CB0/1h) Bit 7 is set for VERIFY routines by the 8K ROM.

VECTOR: Locations 23735/6 IY + 125 (5CB7/8h)


RAMTOP: Locations 23730/1 IY + 120 (5CB2/3h)

This contains the address to be jumped to if syntax has failed both


The main use of this address, which contains the address of the
the 16K and the 8K ROM interpreters. It is normally set to 496
last byte of the BASIC area, will probably be to ensure that the
(1F0h) which will cause a 16K ROM error. It can be changed to
calculator stack has sufficient space (see Chapter 8). It is set by a
point to routines which check syntax further. This is covered in
clear number command from BASIC which also initiates the
machine stack to this address. Chapter 7.

SBRT: Locations 23737-23746 (5CB9h-5C2h)


P—RAMT: Locations 23732/3 IY + 122 (5CB4/5h)
Strictly this is not a system variable but a short subroutine used
This contains the address of the last byte of physical RAM. by the 8K ROM to call 16K routines. The full details of this are
given in Chapter 3 with the RST 16 routine in the 8K ROM.

8K System Variables BAUD: Locations 23747/8 (5CC3/4h)

There now follow the 8K ROM system variables which are only This is the value used to set the BAUD rate for RS 232 input/
present when inserted by the Microdrive interface. output. It is calculated as follows:
58 The Spectrum Operating System The System Variables 59

3 500 000 NTRESP: Location 23757 (5CCDh)


26 x baud rate 2 —BAUD
NTRESP is the response code given to the network.
3 500 000 being the clock rate of the Spectrum. This can be used to
send or receive at non-standard baud rates. The default value is The next eight bytes make up the network header which is
12 (0Ch) which gives a baud rate of about 19 200. explained in Chapter 3.

NTDEST: Location 23758 (5CCEh)


NTSTAT: Location 23749 (5CC5h)
This contains the station to which network output is directed.
This is the network station number currently assigned to the
Spectrum.
NTSRCE: Location 23759 (5CCFh)

This contains the station sending on the network.


IOBORD: Location 23750 (5CC6h)

This holds the colour for the border during input/output NTNUMB: Locations 23760/1 (5CD0/1h)
operations, and is loaded with the colour number. It is normally 0
for black, but can be changed. This contains the number of the network block currently being
passed.

SER_FL: Locations 23751/2 (5CC7/8h) NTTYPE: Location 23762 (5CD2h)

This is used during RS232 input. The first byte is a fl ag, set to 0 on This holds the identifier for a network block, 0 for a normal block
entry to the input routine and set to 1 when a byte has been or 1 for the final block.
received. The second byte is the received byte, on return from the
input routine.
NTLEN: Location 23763 (5CD3h)

This holds the length of the network block being transmitted.


SECTOR: Locations 23753/4 (5CC9 /Ah)

This is used by the 8K ROM to count Microdrive sectors. NTDCS: Location 23764 (5CD4h)

This contains the checksum for the data block to follow.


CHADD_: Locations 23755/6 (5CCB/Ch)
NTHCS: Location 23765 (5CD5h)
This is the 8K ROM equivalent to CI-LADD (Locations 23645/6)
for the 16K ROM. It is used to store the address of the CI-LADD This holds the checksum for the seven bytes of the header.
address while the extended syntax is being checked and then
replaced if necessary. The next eight bytes make up the first file specifier.
60 The Spectrum Operating System The System Variables 61

D_STR1: Locations 23766/7 (5CD6/7h) D_STR2: Locations 23774/5 (5CDE/Fh) to T_STR2: Location
23780/1 (5CE4/5h)
For Microdrive transactions, this provides the drive number (as
two bytes). These eight bytes are the same as previous eight which make up
the first file specifier.
For network transactions, this provides the destination station
number. The following bytes are direct equivalents to the header bytes for
the 16K ROM routines, but they are used by the 8K ROM (for an
For RS232 transactions, this provides the baud rate. explanation of their uses see Chapter 3).

(For a fuller description of the use of D_S1 R1 see Chapter 3, where


each use is discussed when explaining the routines which use it.) HD_00: Location 23782 (5CE6h)

This holds the file type where: 0, program; 1, numeric array; 2,


string array; 3, code.
S_STR1: Location 23768 (5CD8h)

This contains the stream number (0 - 15). HD_0B: Locations 23783/4 (5CE7/8h)

The length of data is held in these locations.

L_STR1: Location 23769 (5CD9h)


HD_OD: Locations 23785/6 (5CE9 /Ah)
This contains channel type in upper case.

This holds the start of data.

N_STR1: Locations 23770/1 (5CDA/Bh)


HD_OF: Locations 23787/8 (5CEB/Ch)
N_S'11 1 holds the length of the file name.
This holds the array name or program length.

T_STR1: Location 23772/3 (5CDC/Dh) HD_11: Locations 23789/90 (5CED/Eh)

This holds the auto-start line number. It can also be used by hook
code 32h (see Chapter 3).
T_STR1 holds the address of the start of the file name.

The next eight bytes are used by LOAD and MOVE commands. COPIES: Location 23791 (5CEFh)

This dictates the number of copies made by a SAVE command.


Input and Output Ports and Channels 63

Chapter Five Port 254 (FEh) 11111110 BIN


The keyboard is read through this port on bits 0 4. Each line of
Input and Output keys is split into two sections of five keys and for each section the
key on the outside is read on bit 0 and the key nearest the middle

Ports and bit4. Each bit is returned high (1) unless a key is being pressed, in
which case the respective bit is low (0).
The address lines are used to determine which half row is read

Channels by an IN instruction. The bit to be set low for each line is set out
below:

AO CAPS SHIFT to V 254 (FEH)


Al A to G 253 (FUH)
The standard Spectrum has all the address and data bus lines
A2 Q to T 251 (FBH)
A3 1 to 5 247 (F7H)
available on the edge connector at the back, and the BASIC allows
A4 0 to 6 239 (EFH)
for communication with the outside world by means of the IN
A5 P to Y 223 (DFH)
and OUT commands. These use the IN A,(C) and OUT A,(C)
A6 ENFER to H 191 (BFH)
instructions on the Z80 CPU allowing the full address bus to be
A7 BREAK/SPACE to B 127 (7FH)
used for discriminating which peripheral device is to be
controlled.
It is unfortunate that bits 5-7 of the data read in are set in an
Port 254 (FEh) is used as an output for the BORDER colour, for
unpredictable manner and, in fact, the reading of the keyboard
the tape output and to drive the internal loud (soft?) speaker. It also
has been changed in issue 3 Spectrums, giving rise to some
handles the keyboard and the tape input. A brief résumé of this
problems in programs which employ scruffy keyboard scanning
was given in the chapter on the 16K ROM, and I shall discuss it
which fails to exclude these. The Spectrum's own keyboard-
fully later in this chapter.
scanning routine ignores them. This last fact opens up possi-
Port 251 (FBh) runs the ZX printer and is used for both input and bilities for their use for other purposes: for example as defined
output. function keys as found on the BBC and other computers, scanned
by an interrupt-driven routine.
Port 247 (F7h) passes data for both the network and the RS232 It is possible to read more than one line of the keyboard at a
communications input/output. time, by setting the relevant bits low before reading in the data
Port 239 (EFh) controls the Microdrive and the handshaking on lines, but this does not allow discrimination between the
different lines of keys.
the RS232 input/output of the Interface 1.

Port 231 (E7h) handles the Microdrive data for both read and
Note: Extreme care needs to be used when reading for more than
write.
one key pressed at a time. Sinclair have not put any protection
This last port is one reason for some peripherals being incom- against feedback between lines on the keyboard. This means that
patible with the Microdrive interface. The Spectrum manual if, for example, the 'A', 'S' and 'W' keys are pressed at the same
failed to mention that it would be used. I shall now consider the time, a scan of the line Q to T will show Q as being pressed, even
details of the more useful ports in turn. though it is not. This is because while pressing two keys on
i
64 The Spectrum Operating System Input and Output Ports and Channels 65

different address lines but with the same data bit the lines are Bit 1 OUTPUT high (1) slows the motor, low (0) speeds it up again.
effectively connected together. Therefore any other key pressed
on either line, will set the respective bit low on both lines, so long Bit 2 OUTPUT low (0) starts the motor.
as both the other keys are being pressed.
Bit 6 is the input from the tape socket and has a tendency to stay Bit 6 INPUT high (1) if the printer is not connected.
low, although it can be reset by an OUT instruction. Care needs to
be exercised since any output to bits 0-2 will set the border Bit 7 OUTPUT high (1) does the actual printing, one bit at a time.
colour. The safest way of setting all bits to 1 is to output 248 (F8h),
but (1) it will only be temporary, and (2) it should never be
necessary if proper decoding is practised.
For the output, bits 0,1 an d 2 control the border colour, bit 0
controls the blue, bit 1 the red and bit 2 the green, all colours Port 247 (F7h) 11110111 BIN
being made up from a mix of these.
Bit 0 OUTPUT serial data for both network and RS232;
Colour Number Binary INPUT serial data from network.
BLACK 0 00000000 Bit 7 INPUT serial data from RS232.
BLUE 1 00000001
RED 2 00000010
MAGENTA 3 00000011
GREEN 4 00000100
CYAN 5 00000101 Port 239 (EFh) 11101111 BIN
YELLOW 6 00000110
WHILE 7 00000111 The write protect tab on a Microdrive cartridge can be checked by
IN A,(239) AND 1; the 0 flag will be set if the cartridge is
Bit 3 controls the microphone socket. Remember that to get protected.
anything more than a click this needs to be turned on and off The presence of a drive can be checked by reading bit 2 of port
repeatedly to give a tone. The 'MIC' printed on the rear of the 239, after selecting the drive to be checked; it will be reset if the
Spectrum is slightly misleading, since this gives output to the drive is present.
mic input of a tape recorder and plugging a microphone in would The RS232 D'1 R line is on bit 3 of port 239 and the CTS line is on
be a waste of time. bit 4 of port 239.
Bit 4 controls the loudspeaker inside the Spectrum an d the It is most unlikely that it will be necessary to use ports 247, 239
same comments as above regarding use apply. and 231, other than from within the 8K ROM with the exception
A program that demonstrates the use of the internal speaker of checking the presence of an ancillary device.
and the 'EAR' input by reading speech or music in, storing it in
memory and allowing its subsequent replay through the loud- The remaining po rt s are available for use by other ancillary
speaker is given at the end of this chapter. devices. Remember that if a printer or other interface is con-
nected it will use a po rt or po rt s for information transfer. Two of
the most common parallel printer interfaces are the MOREX
Port 251 (FBh) 11111011 BIN (which also has a bidirectional RS232 interface built in, and
which I can highly recommend) and the Kempston, which use the
Bit 0 INPUT is the busy line of the ZX printer, low (0) is busy. following ports:
66 The Spectrum Operating System Input and Output Ports and Channels 67

Morex Ports 251 (FBh) 11111011 BIN & 127 (7Fh) Port 58303 (E3BFh)
01111111 BIN
Bits 0-3 OUTPUTS Centronics strobe.
Port 251 (FBh) 11111011 BIN
Standard Streams
Bits 0-7 OUTPUT Centronics Data.
Stream K –3/253 (FDh) is a duplicate of streams 0 and 1.
Bit 0 INPUT Centronics Busy.
Stream S –2/254 (FEh) is a duplicate of stream 2.

Bit 1 INPUT RS232 DIR. Stream R –1/255 (FFh) is used to write to workspace, and will
place the code currently in the A register into the address con-
Bit 7 INPUT RS232 RX data. tained in the system variable K CUR 23643/4 (5C5B/Ch), and
increment the address in K CUR. This is not as useful as it seems
at first, since the make room routine is called first, and this moves
Port 127 (71711) 01111111 BIN
up all memory above the address in K CUR as far as RAMTOP,
making the stream useless for putting anything into anywhere
Bit 0 OUTPUT Centronics strobe.
above RAMTOP, or anywhere else that must not be moved. The
routine starts at 3969 (F81h) and the stream can be used only for
Bit 1 OUTPUT RS232 TX data. output; any attempt to use it for input will cause an error.

Bit 2 OUTPUT RS232 CTS. Stream 0 and Stream 1 K are normally attached to the lower
screen, and the keyboard. They also allow input to be made to
their channels.

Stream S 2 is for output only, normally to the screen.


Kempston Ports 58047 (E2BFh), 57535 (EOBFH) &
58303 (E3BF) Stream P 3 is for output only, normally the printer.

There are 19 streams available and each has to be attached to a


The Kempston interface can be used only with IN (C) and OUT channel; each stream has two bytes in the streams area of the
(C) instructions since it looks at the full 16 bits of the address bus. system variables, starting at 23569 (5C10h) for stream –3, con-
Routines to send a single character to each of these interfaces taining the displacement of the channel that it is attached to, from
Centronics output are given in the Useful Subroutines appendix. the base of the channels area. Remember that the first stream is
–3 so that to find the address of the channel for stream 0 you will
Port 58047 (E2BFh) have to look at 23574/5 (5C16/7h).
A channel consists of a minimum of five bytes; the first two
Bit 0 INPUT is the busy line. hold the address of the output routine, the second two the
address of the input routine and the final byte the upper case
letter of the channel code (S,K,P, etc.). The channels associated
Port 57535 (EOBFh) with the Microdrive Interface are substantially longer than the
minimum and their format is shown in the handbook provided
Bits 0-7 OUTPUTS Centronics data. with the interface.
68 The Spectrum Operating System Input and Output Ports and Channels 69
Record and Play Back Routine FE'_A 0E05 650 LD C,TIME
FETE OD 660 HOLD DEC C
PET" 20FD 670 JR NZ,HOLD
Pass 1 errors: 00
FE_9 10F6 680 DJNZ BITOUT
FETE C 1 690 POF' BC
10 ; THIS SHORT PROGRAM ALLOWS SPEECH
FETE OB 700 DEC BC
20 : TO BE RECORDED FROM THE TAPE RECORDE R INTO MEMORY
iii : THROUGH THE EAR INPUT FETID 79 710 LD AC
FETE BO 720 OR B
40 ; THE RECORDED SPEECH CAN THEN BE FLAYED BACK THROUGH
FESF CO 730 PUSH BC
50 : THE SPECTRUM'S SF'EAK:ER FROM MEMORY
FE40 20E8 740 JR NZ.BYTEOT
60 : THIS IS A VERY CRUDE PROGRAM BUT IS OUITE EFFECTIVE
FE42 CI 750 POE' BC
Iii
FE43 FB 760 EI
80 ;
FE44 C9 770 RET
03350 90 LIMIT EOU 50000 : THE BOTTOM LIMIT OF AVAILABLE MEMORY
0005 100 TIME EOU 5 ; THE DELAY BETWEEN EACH BIT
5 cD pO FDE6 110 FIRST EOU 64999 : THE FIRST BYTE OF MEMORY TO USE
Fass 2 errors: 100
^, FOES 120 ORE 65000
BITOUT FET1 BYTEIN FDFF
FDES 21E6FD 130 START LD HL,FIRST : CALCULATE THE AMOUNT OF MEMORY
BYTEOT FETA DELAY FE16
FDEB 1150C3 140 LD DE,LIMIT : AVAILABLE FOR USE
FIRST FDF6 HEAR FEO
FLEE ES 150 PUSH HL
HOLD FE36 LIMIT C350
FDEF A7 160 AND
LISTEN FDFE PAUSE FE14
FDFO ED52 170 SEC HL,DE
SPEAK:: FE1B START FOES
FDFO ES 190 PUSH HL
TIME 0005
FDFS CI 190 FOP BC
FDF4 EI 200 POF' HL
Table used: 170 from 025
FOES FT 210 DI INTERRUPTS OFF TO ENSURE EVEN TIMING
FDF6 3E7F 220 LISTEN LD A,#7F : WAIT FOR A SOUND
FDFS DBFE 230 IN A,(#FE)
FDFA CB77 240 BIT 6,A
FDFC 28E8 250 JR Z,LISTEN
FORE CS 260 PUSH BC
FDFF 0608 270 BYTEIN LD B,8 : READ IN 8 BITS
FE01 2B 280 DEC HL
FE02 DBFE 290 HEAR IN A,(#FE): A BIT AT A TIME
FE04 17 300 RLA
FE05 17 310 RLA
FE06 CB1E 320 RL (HL) : AND TRANSFER IT TO MEMORY
FE08 lOUA 330 DJNZ PAUSE : PAUSE AND GET NEXT BIT
FEOA Dl 340 FOP DE : BUT IF 9 BITS READ IN THEN CHECK.
FEOB 1B 350 DEC DE : ROOM AND DECREMENT COUNTER
FROC 7A 360 LD A,D
FEUD B3 370 OR E
FEUE D5 380 PUSH DE
FEOF 20EE 390 JR NZ,BYTEIN : IF STILL ROOM GO BACK: FOR ANOTHER BYTE
FE11 Cl 400 POP BC : OTHERWISE FINISH
FE12 FD 410 EI
FE13 C9 420 RET
FE14 0E05 430 PAUSE LD C,TIME
FE16 OD 440 DELAY DEC C
FE17 20FD 450 JR NZ,DELAY
FE19 18E7 460 JR HEAR
FEIB 21E6FD 470 SPEAK LD HL,FIRST : THIS IS THE SAME AS FOR LISTEN
FEIE 1150C3 490 LD DE,LIMIT
FE21 ES 490 PUSH HL
FE22 A7 500 AND A
FE23 ED52 510 SEC HL,DE
PETS E., 520 PUSH HL
FETE CI 530 POP BC
FE27 EI 540 POP HL
PETS C5 550 PUSH BC
FE29 FT 560 DI
FEOA 0608 570 BYTEOT LD 5,9 1 OUTPUT 9 BITS
FE2C 2B 580 DEC HL
FE2D 7E 590 LD A,(HL) , NOTE ALL BITS ARE PUT OUT AND THIS
FETE OF 600 RRCA : WILL CHANGE THE BORDER COLOUR
FETE OF 610 RRCA
PET() OF 620 RRCA
FE31 DOPE 630 BITOUT OUT (#FE),A : A BIT AT A TIME, AS READ IN
FE33 07 640 RLCA
Using the Interrupts 71

Chapter Six therefore hold a value which has the top two bits set in this
manner, in other words any number from 64 to 127 (40h to 7 Fh)
inclusive, if this break-up of the picture is to be avoided.

Using the Interrupts By setting IM2, it is possible to use the interrupts for your own
purposes, so long as you do a RST 56 (38h) at the end of your own
interrupt-servicing routine, which will enable the interrupts
before returning to the CALLing program — if you want the
keyboard scanned and frames counter updated — and end with a
RETI instruction.
The start-up sequence in the Spectrum, which clears the memory If you have not used the RST 56 (38h) within the interrupt
and sets the system variables, also initialises the interrupt routine, you must execute an EI instruction before the RETI if you
register to hold 63 (3Fh) and sets the interrupt mode to 1 (IM1). want the interrupts enabled to CALL the interrupt service routine
The setting of the I register appears unnecessary since the IM1 again. Remember that you will have to reset the IM1 mode and
mode has no use for it — because in this mode any interrupt does enable the interrupts before you return to BASIC unless you are
a RST 56 (38h) — but the novel manner in which the ULA in the using a RST 56 (38h) within the interrupt routine.
Spectrum handles the display makes bits 6 and 7 of the I register The IM2 mode is somewhat convoluted. On receipt of an
important. interrupt, which occurs 50 (60 in the USA) times a second, the
On every machine instruction cycle, the Z80 executes a CPU saves the address of the next instruction in the program that
memory refresh operation during which the contents of the I it is executing on the machine stack, and disables any further
register are put out on high eight bits of the address bus and the interrupts. It then looks at the location pointed to by the data
memory request line is activated. The ULA generates an interrupt bus + (256 x the I register) and jumps to the address which is
each time it wishes to update the screen. This makes the CPU contained in this location + (256 times the contents of the
execute the interrupt service routine, assuming the interrupts are following location). It is normally regarded as bad practice to
enabled. This is normally the keyboard scan and frames counter have bit 0 on the data bus high for use as a pointer in IM2 since the
update, but if the Interface ROM is switched in all that happens is vector should always start in an even numbered address, but
the interrupts are enabled and an immediate RETurn made, unfortunately with the Spectrum there is no choice.
without the keyboard being scanned or anything else done.
When the interrupt routine is completed the CPU returns to Example. The I register contains 10 (0Ah) and the data bus will
whatever it was doing previously. If this involves a read or write hold 255 (FFh). 10 x 256 = 2560 and 2560 + 255 = 2815, therefore
instruction to the memory between 16384 (4000h) and 32767 the address to be jumped to will be taken from the contents of
(7FFFh), which the ULA checks by looking at the top two lines of address 2815 + (256 x the contents of address 2816). Address 2815
the address bus, and the MREQ line, the ULA stops the clock on contains 34 and address 2816 contains 128. You can see this for
the CPU while it completes the screen update. yourself by PEEKing on your Spectrum, as these are in the ROM.
If the I register has the top bit reset and bit 6 set the ULA gets So the address jumped to will be 34 + (256 x 128), which is 32802.
confused, due to the refresh of dynamic memory during T3 and Similarly, if the I register held 6:
T4 of an Ml (instruction fetch) cycle. This activates the MREQ line
and causes the I register to be put out on the top eight bits of the 6 x 256 = 1536, and 1536 + 255 = 1791.
address bus. The ULA then thinks that the CPU is doing a read or 1791 contains 221 and 1792 contains 113.
write operation to this area of the RAM, even though it has tried
to stop this, and the ULA omits its own read to update the 221 + (113 x 256) = 29149, so the jump will be to 29149.
display, causing break-up of the picture. The I register cannot
72 The Spectrum Operating System Using the Interrupts 73

Alternatively, if you have a 48K Spectrum and the I register Typical uses of interrupt routines are SPRJ 1 E control and
held 200: 200 x 256 = 51200, and 51200 + 255 = 51455. So the jump CONTINUOUS SOUND within a program. Since it is known
will be to the address that you put into this and the following how often an interrupt will be generated, it is easy to calculate the
location, in normal Z80 fashion low byte first. speed of movement for a SPRITE and, since it will be indepen-
This can be represented by imagining the interrupt as an dent of any other operation within the program, the speed will
invisible instruction in the program being run. At the moment of normally remain constant.
the interrupt the invisible instruction is executed as if it were a DI The use of ROM routines within an interrupt routine is compli-
followed by a CALL instruction in the address immediately prior cated by the possibility of the interface ROM being switched in at
to the address pointed to by the I register and the data bus, the the time of the interrupt, and this must be allowed for when the
address being CALLed is in the next two bytes in the standard routine is written. For example, if a SPRITE routine relies on a
Z80 low byte first order. The instruction, being invisible, cannot 16K ROM call to plot the sprite to the screen by use of the
place its own return address on the machine stack, hence the PLOTting CALL at 8933 (22E5h) when the Interface ROM is paged
address after the last instruction executed in your program goes in, the CALL will be to 8933 in the Interface ROM. This is an
onto the stack, and it is this address that will be returned to after address that does not exist. This will inevitably cause the
the RETI instruction at the end of the interrupt service routine. program to crash.
The RETI instruction must be preceded by an EI instruction. One way of solving the problem is to incorporate into the
The reason for the DI being incorporated in the CALL performed interrupt routine a check to see which ROM is present. The
by the interrupt is to ensure that, should the interrupt service easiest way of checking is to look at a ROM address which
routine be longer in execution time than the delay between two contains a different value in each ROM. I tend to use address 20
interrupts, the program does not become tied up in a loop. (14h), which contains 213 (D5h) in the Interface ROM and 255
It is quite easy to write a program which changes the address (FFh) in the 16K ROM. The appropriate action for each ROM can
jumped to by an interrupt by loading the vector bytes (the two then be taken.
addresses looked at to determine where the jump is made to) with If the ROM call is to the 16K ROM, it can be called directly when
the desired address within the program. the 16K ROM is present and via the RST 16 instruction when the
8K ROM is paged in. For the 8K ROM, this can be used with hook
Note: Whenever interrupt routines are used it is of vital impor- code 32h (details are given in Chapter 3).
tance that any registers which are used by the interrupt routine I have given a simple SPRITE program in Appendix G. This
are preserved on entry, and restored before going back to the program moves a group of four pixels, bouncing them off the four
main program. No attempt should be made to pass data to and edges of the screen, emitting a sound and changing the border
from the interrupt routine in registers. colour, demonstrating this way round the problem.
Because of the limitation on the values that can be held in the I As a full understanding of how to use interrupts is so
register, there are only a limited number of addresses that can be important, if any use at all is to be made of them, I suggest that
jumped to in the 16K Spectrum, and these are dictated by the you enter the program, using your assembler. The listing is taken
contents of the ROM. An added problem when using ROM-
direct from my assembler to ensure that there are no errors; it is
vectored interrupts is caused by the Microdrive interface which slightly unusual in that hex numbers are prefixed by a # and binary
changes the vector whenever it is paged in. A list of the vectors numbers by a % in the source code. The routine can be relocated
for the Issue 2 Spectrum and the Issue 1 Microdrive interface is if a new vector is calculated and the I register is changed to suit.
given in Appendix F, but if you are unsure which issue you have, Once you have entered and assembled the program, before
or you have a different issue, these must be checked. For com- attempting to run it, turn back to this page and read on.
mercial software, it is dangerous to use ROM vectors as any The first problem you may encounter is, if you have a 16K
changes and future additions could make your software unusable. Spectrum, that the vector will have to be ROM-based. Unfortu-
74 The Spectrum Operating System

nately at the time of writing this I have found no way that a 16K Chapter Seven
Spectrum with the Microdrive Interface can be used.
Before doing anything further save both the source and the
object code to tape or Microdrive and, if you have a Microdrive,
remove the cartridge. To initiate the SPRITE the routine labelled
Extending BASIC with
SETUP in the listing must be called. If the vector has not been
changed, RANDOMIZE USR 51457. You should now be able to
Interface 1
see a single black dot moving about the screen. Should it not be
there check your code again. The presence of the SPRI'I E should
have no effect on anything else the computer is doing, so a
program can be entered and run as normal, as long as it does not
encroach on the memory used by the interrupt routine. With the addition of Interface 1, any BASIC instruction which
Some of the BASIC instructions that act on the interrupts can fails the Sinclair syntax checking is normally vectored back to the
now be demonstrated. Enter the BASIC line: error-handling routines, via the address held in the new system
variable VECTOR. This can be changed to point to an address in
10 BEEP 5,60: FOR N = 1 TO 100: NEXT N: LOTO 10
RAM. This allows a program to be written which can check
When this is run you will see that the SPRITE stops while the further, and act upon any instructions that it is programmed to
BEEP is being executed. Other commands which disable the deal with. Before any use can be made of this facility it is neces-
interrupts are those involved with SAVEing and LOADing. sary to understand the method by which lines are checked, so
The SPRI I E will travel at the rate of 50 pixels per second in the that the extra routine can make the same checks.
UK (60 pixels per second in the USA), so in the UK it will take 3.5 As soon as EN l ER is pressed after entering a BASIC line into
seconds to travel from the bottom of the screen to the top. the input buffer, the ROM interpreter is called into action. This
RUNs the line, but stops short of actually doing the commands,
because the syntax flag (bit 7 in FLAGS) is reset. If any error
occurs, it is flagged with a '?', and the error must be corrected
before the line can be inserted into a program.
The same process is carried out in run time but, since the
syntax flag is set, the command is acted upon. Remember that
whenever a routine in RAM is being used as part of the BASIC
interpreter, the 8K ROM will be paged in.
There are routines in both the ROMs which check for the syntax
flag and return to the calling routine only in run time. These are
most useful when adding commands, as demonstrated by the
routines at the end of this chapter. The basic (no pun intended)
criteria for checking the syntax are given below, and ROM
routines have been used as far as possible.
The address of the character at which the syntax failed, so far as
the ROM is concerned, will be present in the system variable
CI-LADD on arrival at the extended syntax checker in RAM.
Because of this it is important to ensure that the first character of
the added BASIC command fails normal syntax. If this was not
76 The Spectrum Operating System Extending BASIC with Interface 1 77

the case, the interpreter would start execution during run time, When evaluation is completed, a CALL 1463 (5B7h) will check
and it would be almost impossible to regain control. For this that the current character is the end (a colon or carriage return
reason, it is simplest to use a non-alphabetic character to start the code 13 (ODh)), and return to the interpreter in syntax time, or to
additional command, which gets the system out of the normal K your routine for execution in run time, if it is, and generate an
or command mode, ensuring syntax failure. The '*' and '!' error if not.
symbols are ideally suited to this. In run time, your routine will have to act upon the command,
The first thing that must be checked is the command collecting information from the calculator stack as necessary, and
characters. This is done by getting each character in turn and then return to the interpreter via a JP 1473 (5Clh) instruction,
ensuring that it is the one expected. The 16K ROM routine at 24 with CI-LADD pointing to the next character for interpretation.
(18h) will get the current character in the a register, and the To demonstrate the addition of commands the following
routine at 32 (20h) will collect the next character and advance program adds !CALLnn and !FRE. !CALLnn will call a machine
CH_ADD by one. Each character can then be checked and, if it is code routine at the address after the !CALL. !FRE will return the
not correct, the error handler can be called in by jumping to the free memory.
original VECTOR which was 496 (1F0h).
!CALL RST 16
DEFW 24 get character
Then: CF' is it a !
JR NZ,ERROR if not allow error
1) If there should be a numeric expression next, the 16K
CALL NEXT_CH get next character
routine at 7298 (1C82h) can be used. This evaluates the next CP "C" is it C
expression as numeric; if it is not an error will be caused. In JR NZ,!FRE if not, jump and see
run time it will also put the value onto the calculator stack. if it's a !FRE
2) If there should be two numeric expressions next separated CALL NEXT_CH

CP each character is
by a comma, the 16K routine at 7290 (1C7Ah) can be used. JR

NZ,ERROR checked, the error is
This acts as above but stacks both numbers in run time.
CALL NEXT_CH allowed to pass if

3) If there should be a string expression next (either in quotes CP "L" a match fails
or a $) then the 16K routine at 7308 (1C8Ch) can be used. JR NZ,ERROR
CALL NEXT_CH
Again this acts as above, but generating an error if the CP
expression is not a string, and in run time stacking the JR NZ,ERROR

string parameters as described at the end of Chapter 8. JR ISCALL to reach here the word
must match

'FRE CP same again for !FRE
Note: In all three of the above routines, the first character of JR NZ,ERROR
CALL NEXT_CH
the expression to be evaluated must be in the A register, and
CP
CH_ADD must contain its address, before CALLing the routine. JR NZ,ERROR
After the evaluation, the A register will contain the first character CALL NEXT_CH
after the expression and CH_ADD its address. Mathematical CP "E"
operators are allowed as are the use of variables in the expressions CALL NEXT_CH
JR Z,ISFRE ; it is !FRE
evaluated, and this can be used to advantage to find details of ERROR

JP 496 ; the original 'VECTOR'
variables. For example, the expression X$(1,4 TO 9) or A*(B + (C/ ISCALL CALL NEXT_CH
(D + E))) would be allowed, the result being stacked in run time. RST 16
78 The Spectrum Operating System Extending BASIC with Interface 1 79

DEFW 7298 ; evaluates next basic Normally extended BASIC commands or functions will be ended
expression as numeric. by a jump back to the main interpreter as above and it is most
causes error if not.
important that it is the 8K ROM which is switched when this
In run time value is
put on calc. stack
jump is made, otherwise the program will crash.
CALL 1463 ; checks for end of
basic statement.
and returns only in
RST 16 ; run time
DEFW 11682 ; stack to BC, see chap 8
JR ' C,ERROR ; carry set if over 65535
LD (DEST),BC; the address to CALL
RST 16

DEST DEFS 2 ; and put it here
JR FINIS 16K ROM will be present
when called routine is
executed
ISFRE CALL 1463 ; exits in syntax time
LD HL,OO ; clear HL
ADD HL,SP ; add the address in SP
LD DE,(23653);this is STKEND
SBC HL,DE sub from address in
PUSH HL SP to give free space
for basic
POP BC ; result now in BC
RST 16
DEFW 11563 stack BC, see chapt 8
RST 16
DEFW 11747 ; prints value on stack
FINIS JP 1473 return to basic
NEXT_CH RST 16
DEFW 32 ; ROM NEXT_CH routine
AND 223 make it upper case
RET
The Calculator 81

Chapter Eight right. It takes seven moves to the left to make the most significant
set bit on the right of the binimal point. To follow the process:

0 moves 0 1 1 1 1 1 1 0
The Calculator 1move 0111111.0
2 moves 0 1 1 1 1 1.1 0
3 moves 0 1 1 1 1.1 1 0
and so on until after
7 moves 0.1 1 1 1 1 1 0

The Spectrum contains a powerful calculator in the ROM which Any bits left to the left of the binimal point will always be reset
can be used to advantage by the machine code programmer. As it and so can be discarded, as can the binimal point since it is
has 66 different routines, I shall be examining in detail only the known where it is and it will always be there for any number. We
more useful ones. To use the calculator it is important to under- normally do this ourselves with decimal numbers, albeit
stand the form in which the Spectrum handles numbers, how to unknowingly, by not showing a decimal point to the right of an
place them so that the calculator can access them and how to integer (a whole number) as everybody knows that that is where
it would be.
retrieve the answer to the completed calculation.
This process gives us the part of the number known as the
All numbers being used by the calculator are stored as five
bytes in either binary floating point representation or small
mantissa which, for the example given, is 11111100 in binary and
the exponent (the number of times the binimal point has been
integer representation.
moved to the left) is seven. The most significant bit of the
mantissa will always be set so this bit can be used to show the
Small Integer Representation sign of the number; it is set for a negative number and reset for a
positive number.
The first byte is always 0. The exponent is expressed in signed binary, bit 7 set if the
The second byte is the sign, 255 (FFh) for negative or 0 for binimal point has been moved to the left, and reset if it has been
positive. moved to the right. Thus, for the example above the mantissa was
The third and fourth bytes are the actual number in standard Z80 7, binary 00000111, but the point was moved to the left so bit 7
format, low byte first. must be set giving 10000111 or 135 decimal. Now the number can
The final byte is always 0. be shown in its full five-byte form:
The number 0 is regarded as being positive. Exponent Mantissa
Binary 10000111 01111100 00000000 00000000 00000000
Decimal 135 124 0 0 0
Floating Point Representation Hex 87 7C 0 0 0

Normally the number given in the above example would have


The first byte is the exponent: this is the number of times the
been stored in small integer representation, but it has been used
binimal point has been moved to the left to make bit 7 set and to
for simplicity.
the right of the binimal point, and bit 7 of the exponent shows
which way the binimal point has been moved. If it is set, the
point has been moved to the left, as in the example below. The calculator uses its own stack on which it keeps any
Take the number 126 decimal, 7Eh, which in binary is numbers upon which it is working, and the first thing that must
01111110. The binimal point (were we to show it) would be on the be done before any calculations can be performed, is to put the
82 The Spectrum Operating System The Calculator 83

numbers to be manipulated onto the calculator stack. This can be CALL 11419 (2C9Bh)
tackled in three basic ways:
Whenever the BASIC interpreter comes across a number in a
1) A number can be placed on the stack from a register or BASIC line being entered, it places the five-byte binary form
register pair, using a ROM routine to convert it to the form of the number after the ASCII version, ready for use later
that the calculator requires. when the program is being run. The routine used for this
2) The number can be changed into the form that the calculator can be made to do the conversion for a machine code
understands and then put onto the stack. program written by the user. This saves all the problems of
3) The number can be written to memory in ASCII representa- converting numbers manually or writing a routine to
tion and the BASIC syntax checker used to read it and place convert them in your program, and is well worthy of
it onto the calculator stack in the correct form. detailed consideration.
To use this routine to load the calculator stack the BASIC
Each method has its own advantages and disadvantages and each system variable CI-LADD 23645 (5C5Dh) must contain the
lends itself to different types of numbers. I shall now consider address of the first character of the number to be stacked,
their use in turn. and the A register must hold the code of the character
pointed to by CHLADD. The first character will normally be
1) For small integers, there are two routines that can be used: the most significant digit of a decimal number but, because
the routine is that used for BASIC line scanning, it could be
CALL 11560 (2D28h)
the BIN token 196 (C4h) if the following digits are a binary
This is employed by putting the number to be transferred to number. A binary number can only be evaluated to 16
the calculator stack into the A register. Obviously the range digits, decimal 65535 (FFFFh). Any attempt to exceed this
is limited to 0-255 (0–FFh) and the number must be will result in a jump to the BASIC error-handling routine. E
positive. format can be used if it is so wished, and the number should
be arranged exactly as it would be in a BASIC line.
CALL 11563 (2D2Bh) After the characters comprising the number, and the
This will accept numbers in the range 0-65535 (0–FFFFh) exponent if used, a defined byte of value 13 (0Dh) should be
from the BC register pair. Again the number can only be added. This lets the routine know that it has reached the end
positive, unless the start of the routine is bypassed. The of the number and that there is nothing else to look at.
CALL is then made to 11569 (2D31h) with the A register
holding 0, and the E register set to 255 (FFh) and the number
will be transferred to the calculator as negative. There are two ROM routines the reverse of the two routines to
Stack A and Stack BC. These take the last entry on the calculator
2) For numbers in five-byte form ready for use by the calculator
stack and compress it into a rounded integer if possible. If the
the following routine is used:
number was too large then the carry flag will be set on return, and
CALL 10934 (2AB6h) if the number is negative the 0 flag is reset. For a positive number
the 0 flag will be set. The number will be deleted from the stack by
The five-byte representation of the number as described
changing the pointer, but the DE register pair still points to it in
above in Floating Point Representation must be in the
memory allowing it to be reclaimed if recovery was not success-
registers A, E, D, C, B; the exponent in the A register and the
ful, although it is easier to duplicate the number before
mantissa in the other four registers in order.
attempting recovery, and then delete the copy on a successful
3) ASCII representation operation. The call addresses are:
84 The Spectrum Operating System The Calculator 85

STACK TO A: CALL 11733 (2DD5H) CALL 11747 ; the routine to print


STACK TO BC: CALL 11685 (2DA5H) numbers

POP BC restore original address

There is also a reverse to the routine in (2) above located at POP HL and current channel

11249 (2BF1h) which returns the last value on the stack to the same LD (HL),C restore channel

INC HL destination
registers. This routine also deletes the number from the stack but
LD (HL),B
since it cannot fail to recover a number, the flags are not set. A ;REST OF PROGRAM GOES HERE
duplicate must be made on the stack if the number is still START LD HL,(SP_WO)
LD (HL),A
required to be on the stack after recovery.
INC HL
STACK TO A, E, D, C, B: CALL 11249 (2BF1H) LD (SP_WD),HL
RET
When numbers are generated inside the program the routine to SPACE DEFS 16
print a number from the stack can be used to 'print' the number to SF' WD DEFW SPACE
a space in memory — as opposed to printing it to the screen — in
This is the routine used above and mentioned previously. When
ASCII form. The maximum number of spare memory locations
called it takes the top entry from the calculator stack and outputs it
that will be needed for a single number is 14.
in ASCII, as a decimal number, to the current stream. The
This is achieved by writing a subroutine which places the
number is removed from the stack.
contents of the A register into the next memory location each time
Whenever the calculator is used it is important to ensure that
it is called, opening a channel which points to your own sub-
the calculator stack is kept balanced. The calculator itself always
routine, and making this channel current by putting its base
behaves in a predictable manner (when correctly used) and im-
address in CUR_CHL 23633 (5C51h). The ROM routine at 11747
balances can lead to erroneous results. Room must also be left
(2DE3h) can then be called to print the number. The subroutine
between RAMTOP and STKBOT for the calculator stack to expand
will then be called with each character of the number in turn,
upwards and the machine stack to grow downwards without
which it places into successive memory locations, ready for use
their colliding.
later. Remember that the indexing for the address in which the
Since some calculator routines use the calculator recursively, it
characters are being saved cannot be held in a register between
will be necessary to leave more space than that which will
calls to your subroutine, nor can it be saved on the machine stack,
apparently be used. It is best to err on the large side for the space
therefore two bytes of memory must be allowed for saving this
allowed because of this fact. Should there be any doubt as to what
address. A program to do this might look something like this:
is on the stack after completing a set of operations it can be
cleared by a CALL 5823 (16BFh), but remember that this will
SET_UP LD HL,SPACE
LD (SP_WD),HL delete everything that was on the stack.
LD HL,(23533) ;CUR_CHL
PUSH HL
LD DE,START ; make current channel to Use of the Calculator
LD C,(HL) ; your subroutine and save
LD (HL),E ; original address for
In order to understand how to operate the calculator, it may help
INC HL ; later restoration
LD B, (HL) to think of it as a separate processor, with its own instruction set,
LD (HL),D which is switched in by a RST 40 (28h) and switched out by an
PUSH BC ENDCALC, op-code 56 (38h).
86 The Spectrum Operating System The Calculator 87

During the time that the calculator is switched on, its op-codes 02 DELETE Removes Y from the stack. Z = X
are taken from the memory following the RST 40. These are a (STACK CH. –5)
series of DEFined Bytes in a normal Z80 program. When the 03 SUB'T'RACT X – Y = Z (STACK CH. –5)
calculator gets an ENDCALC instruction, control is returned to 04 MULTIPLY X * Y = Z (STACK CH. –5)
the Z80 and this continues execution of the program from the 05 DIVIDE X / Y = Z (STACK CH. –5)
address following the ENDCALC. Some op-codes require 06 TO POWER X ^ Y = Z (STACK CH. –5)
operands, and some can be used only at the start of a series, since 07 BINARY OR X OR Y. If = 0 then Z = X, otherwise Z = 1
they require the Z80 registers to be set in a particular manner in (STACK CH. –5)
order to operate. 08 BINARY AND X AND Y. Both X and Y must be numbers.
Each time the stack is used its size changes by five bytes. If Y = 0 then Z = 0, otherwise Z = X. There
Therefore, every time a number is placed on the stack a check is is a separate op-code to deal with strings
made to see that there is room. Should there be inadequate space 16 (10h)
a BASIC error will be caused. (STACK CH. –5)
The calculator is not limited to numeric operation, it is also The sequence of op-codes from 09 to 14 (0Eh) deals with numeric
used to perform the BASIC string and VAL functions. These will values. Each code can be used only as the first operation after the
be discussed later. rst 40 (28h) as the b register must contain the op-code at the
The op-codes that the calculator understands are set out below moment the actual operation is performed.
with descriptions of their operation. In each case the change to There is a second set of op-codes for string comparisons; all
the calculator stack is given in bytes — five bytes are used for each return Z = 1 if true or Z = 0 if false (STACK CH. –5).
value — for the calculator's execution of a single op-code.
X is the value below Y on the calculator stack, Y being the last 09 Y <= X 10 (0Ah) Y >=, X 11 (0Bh) Y<> X
value put onto the calculator stack. The result of a calculation is 12 (0Ch) Y > X 13 (0Dh) Y < X 14 (0Eh) Y = X
always left on the top of the calculator stack, and this result is 15 (OFH) ADDITION X+Y= Z (STACK CH. –5)
represented by Z. For example, for the subtract op-code (03) if
X = 5 and Y = 9, X would be placed onto the calculator stack In the following sequence of op-codes, one or both of the X and
followed by Y, the RST 40 (28h) would be followed by a defined Y values must hold the parameters of a string. Details of how to
byte 03. After the operation, the calculator stack is –5, the get these parameters and put them on the calculator stack are
answer is on the top as Z. Therefore both X and Y have been given later. The part or parts that are string parameters are shown
deleted. with a $ symbol.
Jumps are made from the location of the distance operand, the
standard Z80 manner.
Op-code Function Operation
Op-code Function Operation
16 (10h) $ AND No. X$ and Y. If Y = then Z$ will be an
00 JUMP I RUE Jumps the distance (2s complement empty string, otherwise Z$ = X$
notation) in the operand (the defined byte (STACK CH. –5)
after the 00 op-code) if Y is non-zero.
(STACK CH. –5) The op-codes 17-22 (11h-16h) are the string equivalents of op-
01 EXCHANGE Reverses the order of X and Y on the stack codes 09-14 (0Eh), called with the B register holding the op-code.
(STACK CH. 0) Again Z = 1 if true or Z = 0 if false. (STACK CH –5)
88 The Spectrum Operating System The Calculator 89

17 (11h) Y$ <= X$ 18 (12h) Y$ >= X$ 19 (13h) Y$ <> X$ 28 (1Ch) CODE Z = CODE Y$. As used by the
20 (14h) Y$ > X$ 21 (15h) Y$ < X$ 22 (16h) Y$ = X$ BASIC interpreter (STACK CH. 0)
29 (1Dh) VAL Z = VAL Y$. As used by the BASIC
23 (17h) ADDITION X$ + Y$ = Z$. The two Strings are interpreter and in fact accesses the
concatenated in workspace and the line scanner to get the result into Z.
new parameters are returned in Z$. Subject to BASIC errors.
Remember that if there is
(STACK CH. 0)
inadequate room for the two strings
30 (1Eh) LEN Z = LEN Y$. This is easier to do
to be copied into an expanded
without using the calculator, all it
workspace a BASIC error will be
does is stack the length bytes of the
caused (STACK CH. –5).
string parameters
24 (18h) VAL$ VAL$ Y$ = Z$. The new string is
(STACK CH. 0)
created in workspace in the same
manner as above. The op-code The following algebraic functions all return the answer (Z) on the
must also be contained in the B top of the calculator stack and the stack size is unchanged.
register at the time of use. Any
errors will cause a BASIC error. This Op-code Operation
is the routine used by the BASIC
31 (1Fh) Z = SIN Y
interpreter and is subject to all the
32 (20h) Z = COS Y
syntax checking procedure
33 (21h) Z = TAN Y
(STACK CH. 0)
34 (22h) Z = ASN Y
25 (19h) USR$ Z = USR$. Again used by the BASIC
35 (23h) Z = ACS Y
interpreter and subject to syntax
36 (24h) Z = ATN Y
checking. Y$ must contain the
37 (25h) Z = LN Y
parameters of a String containing a
38 (26h) Z = EXP Y
single letter from A to U. Z will be
39 (27h) Z = INTY
the address of that user-defined
40 (28h) Z = SQR Y
graphic on completion
41 (29h) Z = SGN Y
(STACK CH. 0)
42 (2Ah) Z = ABS Y
26 (lAh) READ IN This routine allows a single byte to
be put into WORKSPACE through 43 (2Bh) PEEK Z = PEEK Y. As used by the BASIC
any stream 0-15 (0Fh), taken from interpreter (STACK CH. 0)
Y. The byte is regarded as a string 44 (2Ch) IN Z = IN Y. This performs the Z80 IN
and Z$ is the parameters of this A,(C) instruction after taking Y
string. If the carry flag is not set by from the stack into the BC register
the input routine, no action is taken pair as an integer (STACK CH. 0)
and Z$ is returned as a null string 45 (2Dh) USR No. Caution This will cause an execution
27 (1Bh) NEGATE Z = Y but with the sign changed jump to the address Y. Used by
(STACK CH. 0) BASIC to jump to machine code.
The return address will be 11563
(2D2Bh), the stack BC routines
90 The Spectrum Operating System The Calculator 91

which will put the value in the BC bytes which follow to make the
register on return on the calculator mantissa, 00 BIN for 1 to 11 BIN for
stack. This is an interesting op-code 4. The floating point number is then
since it opens up the possibility of read to the calculator stack
using routines in ROM and RAM (STACK CH. +5)
recursively from within the 53 (35h) DEC JR NZ This is a direct equivalent to the Z80
calculator (STACK CH. 0) DJNZ op-code, but for the
46 (2Eh) S1 R$ Z$ = Y. The top value on the calculator. The B register is taken as
calculator stack is printed to being BREG system variable. Not
WORKSPACE and evaluated as a safe to use, since this routine is
string, the parameters of which are extensively used within the
then put on the calculator stack calculator for its own purposes, and
(STACK CH. 0) the value of BREG cannot be
47 (2Fh) CHR$ Z$ = CHR$ Y. If 0 < Y < 255 then a guaranteed (STACK CH. 0)
single space is made in 54 (36h) Y < 0 Z = 1 if Y < 0, otherwise Z = 0
WORKSPACE and the value (STACK CH. 0)
transferred there as one byte. This 55 (37h) Y > 0 Z = 1 if Y > 0, otherwise Z = 0
is then interpreted as a string and (STACK CH. 0)
the parameters returned as Z$ 56 (38h) ENDCALC Returns control to the Z80 at the
(STACK CH. 0) next address (STACK CH. 0)
48 (30h) NOT Z = 1 if Y = 0, otherwise Z = 0 57 (39h) GET ARGT Used internally to the calculator to
(STACK CH. 0) establish the value Y (which for the
49 (31h) DUPLICATE Z = Y. Y is duplicated purposes of Z being the result will
(STACK CH. +5) be Z) of SIN Y or COS Y
50 (32h) X MOD Y This returns Z = INT (X/Y) and (STACK CH. 0)
underneath Z (where X was 58 (3Ah) TRUNCATE Z = INT Y, where Z is Y truncated
originally) X – INT (X/Y) towards 0 (STACK CH. 0)
(STACK CH. 0) 59 (3Bh) FP CALC 2 Used by the interpreter to perform a
51 (33h) JUMP This simply does the equivalent of a single calculator operation. Of no
Z80 JR (Jump Relative) instruction, practical use for the purposes of this
but for the calculator. The jump book
length is taken from the location 60 (3CH) E TO F.P. Z = Y E (Exponent) A register
following the op-code. The (STACK CH. 0)
calculator stack is untouched 61 (3Dh) RE STACK Z = the floating point version of Y,
(STACK CH. 0) where Y could have been a small
52 (34h) STK DATA This allows a value to be read in integer (STACK CH. 0)
from the locations following the op- 62 (3Eh) SERIES Used internally to the calculator to
code. Bits 6 and 7 of the first byte generate a Chebyshev polynomial.
(the exponent) following the Of no practical use as it is called by
op-code determines the number of the routines that need it
92 The Spectrum Operating System

63 (3Fh) STACK NO. As above, but used to stack


Appendix A
constants
64 (40h) ST MEM. Used to store in the memory area.
On entry the A register must hold
CO to C5 according to which of the Hex to Decimal
five memory locations is to be used

65 (41h) REC MEM.


(STACK CH. —5)
Recall from memory. The reverse of
Conversions
the above routine
(STACK CH. +5)
For string operations the parameters can be passed to the
calculator stack using the routine at 10934 (2AB6h) mentioned MSB
earlier. The BC register pair holds the length of the string, the DE
register pair the start address and the A register the name (in the
0 0 256 512 768 1024 1280 1536 1792 2048 2304 2560 2816 3072 3328 3584 3840
form mentioned in chapter 2 under SAVEing LOADing and
1 4096 4352 4608
VERIFYing. 4864 5120 5316 5632 5888 6144 6400 6656 6912 1168 7424 7680 7936
2 8192 8448
To assist with the understanding of the calculator a routine that 8704 8960 9216 9472 9728 9984 10240 10496 10152 11008 11264 1I520 11116 12032

will allow experimentation with the calculator is given in the 3 12288 12544 12800 13056 13312 13568 13824 11080 11336 14592 11048 15104 15360 15616 15872 16128
Useful Subroutines appendix. 4 16384 16640 16896 17152 17408 17664 11920 18176 18432 18688 18944 19200 19156 19712 19968 20224

5 20480 20736 20992 21248 21504 21760 22016 22212 22528 22784 23040 23296 23552 23808 24064 24320

6 24576 24832 25088 25344 25600 25856 26112 26368 26624 26880 27136 27392 27648 27904 28160 28416

7 28672 28928 29184 29440 29696 29952 30208 30464 30720 30976 31232 31488 31744 32000 32256 32512
8 32768 33024 33280 33536 33792 34048 34304 34560 34816 35072 35328 35584 35040 36096 36352 36608
9 36864 31120 37376 37632 37888 38144 38400 38656 38912 39168 39424 39680 39936 40192 40448 40704
A 40960 41216 41412 41728 41984 42240 42496 42752 43008 43264 43520 43776 44032 44288 44544 44800
B 45056 45312 45568 15824 46080 46336 46592 46848 47104 47360 47616 47812 48128 48304 48640 48896

C 14152 49408 49664 44920 50176 50432 50688 50944 51200 51456 51712 51968 52224 52480 52736 52992
D 53248 51504 53760 54016 54212 54528 54784 55040 55296 55552 55808 56064 56320 56576 56832 57088

E 57344 57600 57856 58112 50368 58624 58880 59136 59392 59648 59904 60160 60416 60672 60928 61184

F 61440 61696 61952 62208 62464 62720 62976 63232 63480 63744 64000 64256 64512 64768 65024 65280
94 The Spectrum Operating System

LSB
Appendix B
0 1 3 4 5 6 7 8 9 A E F

0
1 16
0

V
I

HI
2

19
3

20 21
5

22
6

23
7

24
8

25
9 10

26
II

27
12

28
13

29
14

30
15

31
The Spectrum
Memory Map
2 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

3 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

4 64 65 66 67 68 69 70 71 72 73 74 75 77
76 78 19

5 80 8I 82 83 84 65 86 87 88 89 90 91 94
92 93 95
VARIABLE FIXED
6 96 97 99 99 100 101 102 103 104 105 106 107 108 109 110 Ill

7 112 113 114 115 116 III I18 119 120 121 122 123 124 125 126 127
I' RAMT FFFFH OR7FFFH
8 128 129 130 131 132 133 n5535 33767
134 135 136 137 138 139 140 141 142 143 (23675) UDG

9 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 (237301 RAMTOP

A 160 161 162 163 164 165 166 167 168 169 170 171 172 123653) STK END
173 174 175

B 116 117 178 179 180 181 182 183 184 185 186 187 188 189 190 191 CALCULATOR STACK

C 192 193 194 195 196 197 198 149 200 201 202 203 204 205 206 207 (23651) STK BOT

D 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 WORKSPACE

E 224 225 226 227 228 229 230 231 132 233 234 235 236 237 238 239 (23649) WORKSI'

F 240 241 242 243 , 244 245 246 247 248 249 250 251 252 253 254 255 EDIT AREA

(23641) E LINE

IV I E3BLES VARIABLES

HEX DEC BIN HEX DEC BIN (23627) VARS


0000 8 8 1000
1 1 0001 9 9 1001 BASIC
2 2 0010 A 10 1010
0011 8 11 1011 (23635) PROG
4 4 0100 C 12 1100
5 5 0101 D 17. 1 101 CHANNEL INFORMATION
6 6 0110 E 14 1110
7 0111 F 15 1111 (23631) CHANS

MICRODRIVE MAPS
5CEFH 23731 LAST BYTE OF
8K SYSTEM VARIABLES

5CB6H 23733 LAST BYTE OF


06K SYSTEM VARIABLES

5BFFH 23551 LAST BYTE OF


PRINTER BUFFER

5AFFH 23295 LAST BYTE OF


SCREEN ATTRIBUTE MAP

57FFH 22527 LAST BYTE OF


SCREEN MAP

3FFFH 16383 LAST BYTE OF


16K ROM
Appendix C 97

Appendix C

The Spectrum
Screen Map
81 4840H 5940H 137 5020H 5A20H
82 4940H 138 5120H
83 4040H 139 5220H
84 41340H 140 5320H
85 4C40H 141 5420H
The Spectrum screen is divided into 192 rows of 256 pixels. Each 86 4040H 142 5520H
87 4E40H 143 5620H
line comprises 32 bytes of memory in ascending order. Below are 88 4F40H 144 5720H
listed the addresses of the first byte of each screen line with the B9 4860H 5960H 145 5040H 5A40H
90 4960H 146 5140H
address of the attribute that controls the first byte. Line 1 91 4060H 147 5240H
92 41360H 148 5340H
represents the top line on the screen. 93 40601-1 149 5440H
94 4D60H 150 5540H
95 4E60H 151 5640H
LINE PIXEL ATTRIBUTE 96 4F60H 152 5740H
1 400014 5800H 41 400014 5800H 97 4880H 5980H 153 5060H 5A60H
2 4100H 42 4100H 98 4980H 154 5160H
3 4200H 43 420014 99 4A80H 155 5260H
4 430014 44 43AOH 100 4B80H 156 5360H
S 4400H 45 4400H 101 4C80H 157 5460H
6 4500H 46 4500H 102 4080H 158 5560H
7 4600H 47 4600H 103 4EBOH 159 5660H
8 4700H 48 4800H 104 4F80H 160 5760H
9 4020H 5820H 49 4000H 58C0H 105 480011 5900H 161 5080H 5080H
10 4120H 50 41COH 106 49AOH 162 5180H
11 4220H 51 42COH 107 4AAOH 163 5280H
12 4320H 52 43COH 108 4BAOH 164 5380H
13 4420H 53 44COH 109 4CAOH 165 5480H
14 4520H 54 45C01-1 110 4000H 166 5580H
15 4620H 55 46COH 111 4EAOH 167 5680H
16 4720H 56 47COH 112 4F0011 168 5780H
17 4040H 5840H 57 40EOH 58E0H 113 48COH 59COH 169 5000H 5000H
18 414014 58 41EOH 114 49COH 170 51AOH
19 4240H 59 42E0H 115 4ACOH 171 5200H
20 434014 60 43E0H 116 4BCOH 172 53AOH
21 4440H 61 44E0H 117 4000H 173 5400H
22 4540H 62 45E0H 118 4000H 174 55AOH
23 4640H 63 46E0H 119 4ECOH 175 5600H
24 4740H 64 47E0H 120 4FC0H 176 5700H
25 4060H 5860H 65 480014 5900H 121 48E0H 59EOH 177 5000H SACOH
26 4160H 66 4900H 122 49E0H 178 51COH
27 4260H 67 4000H 123 4AEOH 179 52COH
28 4360H 68 4BOOH 124 4BEOH 180 53COH
29 4460H 69 4000H 125 4CEOH 181 54COH
30 4560H 70 4000H 126 4DEOH 182 55COH
31 4660H 71 4EOOH 4EEOH 183 56COH
127
32 4760H 72 4FOOH 4FEOH 184 57COH
128
33 4080H 5880H 73 4820H 5920H SAEOH
129 5000H 5000H 185 50EOH
34 4180H 74 4920H 130 5100H 186 51EOH
35 4280H 75 40208 131 5200H 187 52E0H
36 4380H 76 4B20H 132 5300H 188 53E0H
37 4480H 77 4C20H 133 5400H 189 54E0H
38 4580H 78 4D20H 134 5500H 190 55E0H
39 4680H 79 4E20H 135 5600H 191 56E0H
40 4780H 80 4F20H 136 5700H 192 57E0H
Appendix D Appendix E

The Keyboard Map The Spectrum


Character Set

D4 D3 D2 D1 DO Code Character Special Notes


254 (FEH) V C X 0&1 None Used only after INK, PAPER,
Z C/S
253 (FDH) G F D S A OVER, INVERSE, FLASH, BRIGHT
251 (FBH) T R E W Q AT or TAB
247 (F7H) 5 4 3 2 1 2-5 None Used only after INK, PAPER, AT or
239 (EFH) 6 7 8 9 0 TAB
223 (DFH) Y U I O P 6 Does a TAB on the screen to the next
191 (BFH) H J K L ENT
127 (7FH) B N
half screen position.
M S/S B/S
7 EDIT Code returned by the keyboard
input routine is used if CAPS
SHIFT and 1 are pressed. Not
printable. Often the BELL code on
printers and terminals
8 BACKSPACE Code returned by the keyboard
input routine if CAPS SHIFT and '5'
are pressed. Can be printed to give
a backspace on the screen. Also
recognised by most printers, as it is
the ASCII backspace code
9 RIGHTSPACE Code returned by the keyboard
input routine if CAPS SHIFT and '8'
are pressed. Not usable to give a
screen rightspace as the Spectrum
does not update the print positions
after its use. ASCII horizontal TAB
code
10 DOWNSPACE As above but for CAPS SHIFT and
'6'. Is the ASCII code for line feed
11 UPSPACE As above for CAPS SHIFT and '7'.
ASCII vertical TAB code
100 The Spectrum Operating System Appendix E 101

12 DELE'T'E As above for CAPS SHIFT and '0'. codes 32 to 126 conforming to standard ASCII and these are
ASCII Form Feed code shown in the Spectrum manual.
13 EN'I ER Returned when the EN 1 ER key is
Code 127— the Spectrum copyright symbol — is the ASCII delete
pressed, performs a carriage return
and line feed when printed to the code, be careful!!
screen. Is also the ASCII code for
carriage return
14 Precedes a number in a BASIC
program line. Not of any practical
use. ASCII Shift Out code
15 Not used in the Spectrum. ASCII
Shift In code
16 Ink control code used to precede the
number for the INK colour. For
example to change the on-screen
printing colour for all following
characters to red, you would use the
RST 16 routine with the A register
holding 16 followed by 2. Note NOT
ASCII 2 but value 2. This is
demonstrated in the DeBASE
program.
17 As above but for PAPER
18 As above for FLASH, the following
code can be only 0 or 1
19 As above for BRIGHT
20 As above for INVERSE
21 As above for OVER
22 AT control code, must be followed
by the line and column values
23 As above but TAB, needing only
the column value

Codes 24 to 31 are not used by the Spectrum; code 27 however is


the escape code which is used by most peripherals, followed by a
letter to indicate the action required. While the CHR$ 27 has been
standardised as the escape code, the codes that follow it have not
been standardised.
The remaining codes are all character representations, with
Appendix F 103

16K ROM 8K ROM


Appendix F Mk 2 Spectrum Mk 1 Interface
I = 51 13256 21965
I = 52 1560 56790
I = 53 57124 45182

ROM Interrupt Vectors I = 54 34307 65535


I = 55 41231 57851
I = 56 65535 61947
I = 57 65535 60952
I = 58 6557,5 52189
I = 59 65535 16129
I = 60 255 6400
I = 61 0 4870
I = 62 255 65535
I = 63 60

16K ROM 8K ROM


Mk 2 Spectrum Mk 1 Interface
= ii 20430 23755
I = 1 52819 8501
I =_ 22269 25888
I = _. 39020 4196
I = 4 10419 52486
I = 2294 6701
I = 6 29149 51711
I = 16039 32459
I =8 2088 14353
I =9 65129 58170
I = 10 32802 1200
I = 11 58888 2039
I = 12 3183 59861
1 = 13 52503 8205
I = 14 14367 49921
I = 15 27928 58884
I = 16 51984 32742
I = 17 8729 32477
I = 18 52481 4831
I = 19 49749 21965
I = 20 25705 56790
I = 21 51673 45182
I = __ 51568 65535
I = 12493 57851
I = 24 15582 61947
I = _ 23842 60952
I = 26 13824 52189
= 27 7306 16129
I = 28 49947 6400
I = 29 2344 4870
I = 30 26573 65535
1 = 31 3360 57855
I = _2 52513 23755
I = 3_ 33485 8501
I = 34 544 25888
I = 49537 4196
I = 36 8527 52486
I = 37 23670 6701
I = 38 20444 51711
I = 39 288 32459
I = 40 _2348 14353
I = 41 58154 58170
I = 42 19754 1200
I = 43 23653 2039
I = 44 7117 59861
I = 45 55781 8205
I = 46 =371._ 49921
I = 47 4569 58884
I = 4B 60208 32742
I = 49 57640 2477
I = 50 13627 4871
Appendix G 105

Appendix G YOU CAN PUT A SERIES OF DEFINED BYTES HERE TO


EXPERIMENT WITH THE CALCULATOR

; END CALC
Useful Subroutines DEFB 38H
CALL 2DE3H


; PRINT RESULT
; PRINT STKBOT AND STKEND
CALL PRSTK
TO SEE IF THE STACK WAS
BALANCED

EXX ; RESTORE H'L'

Calculator Routines POP HL


EXX
RET
To assist with the understanding and use of the calculator the NUMBER
following routines will allow experimentation with the calcu- DEFM "1234.567"
; THERE MUST ALWAYS BE A
lator. The first routine is for demonstration purposes. DEFB 13
DEFB 13 TO LET THE
EXX ROUTINE KNOW THAT IT
YOU MUST ALWAYS SAVE
HAS FINISHED THE NUMBER
H'L'
PUSH HL ; IF A SUCCESSFUL RETURN IS
TO
EXX This subroutine will print the address of the start and end of the
; BE MADE
CALL PRSTK ; PRINT STACK START AND calculator stack:
END PRSTK LD BC, (23651) ; THIS IS STKBOT
LD BC,X ; FIRST NUMBER CALL 2D2BH ; STACK IT
PUSH BC ; SAVE IT LD A,"B"
CALL 2D2BH ; STACK X RST 10H
POP BC ; RESTORE X LD
CALL 2D2BH ; STACK X AGAIN RST 10H
CALL 2DE3H ; PRINT X CALL 2DE3H ; PRINT STKBOT
LD A,20H LD
RST 10H ; PRINT A SPACE RST 10H
LD HL, NUMBER ; BASE ADDRESS OF THE LD A, "T"
NUMBER IN ASCII FORM RST 10H
CALL STKNUM ; STACK NUMBER (THIS WILL LD
BE Y) RST 10H
RST 28H ; CALL THE CALCULATOR LD BC, (23653) ; THIS IS STKEND
DEFB 31H ; DUPLICA"I E Y CALL 2D2BH
DEFB 38H ; TURN OFF THE CALL 2DE3H ; PRINT STKEND
CALCULATOR LD A,ODH
CALL 2DE3H ; PRINT Y RST 10H
RST 28H ; TURN ON CALCULATOR RET
106 The Spectrum Operating System Appendix G 107

This routine will stack a number in ASCII form. OUT (7FH), A


XOR A
ON EN 'I RY THE HL REGISTER PAIR MUST CONTAIN THE
OUT (7FH), A
ADDRESS OF THE START OF THE NUMBER TO BE STACKED FINISHED
RET ;

STKNUM LD DE, (23645) ; THIS IS CH_ADD


PUSH DE ;SAVE IT This is the Kempston Interface Centronics Output Routine:
LD (23645), HL ; POINT CHLADD TO THE
PUSH BC ; SAVE BC REGIS 1ER PAIR
START OF THE NUMBER
AS THEY ARE USED FOR
LD A, (HL) ; PUT THE FIRST
I/O
CHARACTER IN A
PUSH AF ; SAVE CHARACTER
CALL 2C9BH ; STACK THE NUMBER
POP DE CODE
; RESTORE CH_ADD TO
ITS ORIGINAL LD BC, 0E2BFH ; BUSY PORT
LD (23645),DE ; VALUE BUSY IN A, (C) ; READ BUSY LINE
RET RRA ; BIT 0 TO CARRY
JR C, BUSY ; IF NOT LOW PRINT ER
BUSY
POP AF RESTORE CHARACTER
DEC B ; CHANGE PORT TO 02BFH
DEC B
OUT (C), A ; SEND CHARAC1 ER
LD A, 00EH ; S I ROBE DATA FOR
Morex and Kempston Interface Drivers SENDING
LD B4OE3H ; CHANGE PORT TO
On entry to these subroutines the ASCII code to be output to the E3BFH, SIROBE PORT
Centronics lines should be in the A register. No expansion will OUT (C), A ; S' 1 ROBE PRIN I ER
be made; see the section in Chapter 2 on EXPANDING TOKENS INC A
FOR OUTPUT if it is required. OUT (C), A
This is the Morex Interface Centronics Output Routine: POP BC ; RESTORE BC REGIS 1 ER
PAIR
RET ; FINISHED
PUSH AF ; SAVE CHARACTER
CODE
BUSY IN A, (OFBH) ; READ BUSY LINE FROM
PRINTER Interrupt Driven Sprite Routine
AND 1 ; I EST BIT 0
JR NZ, BUSY ; IF NOT LOW PRINTER ass 1 errors: 00

BUSY 10 ; DEMONSTRATION PROGRAM FOR SPRITES


_11 ; SEE CHAPTER 6
POP AF ; RESTORE CHARAC'1 ER =.n

40 ORG 51455
OUT (OFBH), A ; SEND IT C8FF

ENT 51455
CBFF 50
LD A, 1 ; STROBE PRIN'T'ER 60
108 The Spectrum Operating System Appendix G 109

70 : 51455 CONTAINS THE INTERRUPT VECTOR 770


80 790 : THE NEW CO-ORDINATES FOR THE SPRITE ARE SAVED
C8FF 2009 90 DEFW 51500 790
100 096A ED439309 800 CPLOT LD (000RD),BC : AND SO ARE THE FLAGS
C901 3E08 110 SETUP LD A,200 096E 228509 810 LD (FLAG),HL
090 33 5047 120 LE IA S'20
0905 ED488309 130 LD BC, )000RD) 0771 CD8709 830 CALL PLOT : PLOT THE NEW SPRITE POSITION
C909 CD3709 140 CALL FLOT 940
090C ED5E 150 IM 2 850 :
090E C9 160 RET 860 :ALL THE PLOTTING IS DONE SO THE SYSTEMS VARIABLES
170 970 :ARE NOW RESTORED TO THEIR; ORIGINAL STATE
190 :THIS IS THE ACTUAL PROGRAM, STARTING AT THE ADDRESS 980 1
190 : WHERE THE INTERRUPT HAS PEEN VECTORED 890
200 C974 El 900 NRET POP HL
092C 210 ORG 51500 0975 2?7D50 910 LD (23677),HL
220 097S Fl 920 POP AF
230 ; FIRST SAVE ALL REGISTERS THAT WILL BE USED 0979 323.050 930 LD (23612),A
240 940
0920 ES 250 PUSH HL 950 :THE REGISTERS ARE NOW RESTORED
092D C5 260 PUSH BC C970 F1 960 POP AF
092E D5 270 PUSH DE C970 DI 970 .POP DE
092F F5 280 PUSH AF 097E 01 980 FOP EC
290 097F El 990 POP HL
300: SAVE TV FLAG AS IT MAY BE ALTERED LATER 1000
310 ; 1010 :AND THE KEYBOARD SCANNED AS IT HAS NOT BEEN
0970 3A0050 320 LD A,(23612) 1020 :BECAUSE THE INTERRUPT WAS RELOCATED
0933 F5 330 PUSH AF 1030
340 0980 FF 1040 RST #38
350 : AND SAVE CO OFDS AS THEY WILL BE CHANGED AND THEY MUST EE 0991 ED4D 1050 RETI
360 : RESTORED BEFORE RETURNING C983 0000 1060 COORD DEFW ii
370 , 0995 0000 1070 FLAG DEFW 0
0904 2A7D50 380 LD HL,123677) 1080
0937 ES 390 PUSH HL 1090 : D IS GOING TO BE USED AS A COUNTER, AS B IS IN USE
C938 ED4883C9 400 LE 80,(000RD) : (THE SPRITE 00-ORDINATES) 1100
0930 05 410 PUSH BC : SAVE THEM 1110 ;
420 : 0907 1604 1120 PLOT LD 0,4
CALL THE ROUTINE TO PLOT THE SPRITE
430 : 1130 :
AS EACH PLOT OF THE SPRITE IS OVER I THIS WILL ERASE
440 : THE PREVIOUS POSITION 1140 ;
09.0 CD8709 450 CALL PLOT 1150 : SAVE THE C0-ORDINATES AS THEY ARE CORRUPTED BY THE R.C.M.
0940 C1 460 POP BC: 1160 ;ROUTINES
RESTORE THE SPRITE CUORDS
470 : 1170
490 :L 1180
IS USED AS A FLAG REGISTER
490 :TO TELL THE SPRITE WHICH WAY IT MUST MOVE 0939 05 1190 PUSH BO
500 :BIT 0 IS SET FOR UP, RESET FOR DOWN 095A 7A 1200 LOOP LD A, D
510 :BIT 1 IS SET FOR LEFT AND RESET FOR RIGHT 098B D5 1210 PUSH DE : SAVE THE-COUNTER
2'i; 1220
.30 . 1270 :THE ACTUAL PLOT IS MADE FOUR TIMES, MOVING EACH TIME
0941 2A8509 540 LE HL,(FLAG) 1240 :TO CREATE A LARGER SPRITE
0944 0E45 550 DIT 0,L C990 FEO4 1250 CF 4
0946 2807 560 JR Z,UF 098E 280F 1260 JR Z, LOOP4
C948 05 570 DOWN DEC 8; MOVE SPRITE DOWN I PIXEL 0990 EEO: 1270 CP _
0949 2000 580 JR NZ,LEFT: IF ZERO FLAG SET IT HAS REACHED THE C992 2001 1280 JR NZ,LOOF1
0948 CB85 590 RES 0,L; BOTTOM OF THE SCREEN AND ITS 0994 0C 1290 INC C
0940 1809 600 JR LEFT : DIRECTION IS CHANGED C995 FE02 1300 LOOP1 CP _
094F 04 610 UP INC B; UP ONE PIXEL 0997 2001 1310 JR NZ,LOOF2
78 620 LD A,B: HAS SPRITE REACHED TOP C999 04 1320 INC B
0951 FEAE 620 CP 174 099A FE01 1330 LOOP.? CF' I
0953 2002 640 JR NZ,LEFT C99C 2001 1340 JR NZ,LOOF4
0955 0805 650 SET O,LI IT HAS SO CHANGE DIRECTION 099E OD 1350 DEC C
C957 CB4D 660 LEFT BIT 1,L; SAME CHECKS AGAIN FOR LEFT/RIGHT 1360
0959 2807 670 JR Z,RIGHT 1370 ; A TEST MUST NOW BE MADE TO SEE WHICH F.O.M. IS PRESENT
0956 OD 680 DEC C 1380 1
C950 2000 690 JR NZ,CPLOT C99F 3A1400 1390 LOOF4 LD A,(#14)9 PICK A R.O.M. LOCATION THAT IS
095E CB80 700 RES 1,L 1400
0960 1808 710 JR CPLOT 1410 : DIFFERENT IN EACH R.O.M.
0962 00 720 RIGHT INC C C9A2 FDCS0286 1420 RES 0,(IY+2) , SIGNAL COLOURS TO BE FROM MAIN SCREEN
09633 79 730 LD A,C C9A6 05 1430 PUSH BC
0964 FEFE 740 CP 254 C9A7 FEDS 1440 CF #D5:
0966 2002 750 JR NZ,0FLOT C9A9 2900 1450 JR Z,ROM2; R.O.M. 2 IS PAGED IN SO DONT CALL THE
0968 OECD 760 SET 10L 1460 : MAIN R.O.M. ROUTINE DIRECT
110 The Spectrum Operating System
Appendix G 111
1470
Fass 2 errors: CVJ
1480 ; TO GET HERE THE MAON R.O.M. MUST BE PAGED IN
1490 ;SO DIRECT CALL O.K.
COL C9F5 CONTI C9BF
1500
C9AB CD4DOD 1510 COORD C987 CFLOT C96A
CALL #D4D ; COLLECT THE COLOURS FOR THE FLOT
DOWN C948 FLAG C995
C9AE FDCB57C6 1520 SET 0.(IY+87) , SET OVER 1 WITH P FLAG
C9B2 CDE522 LEFT C957 LOOP' C998
1530 CALL 8933; DO THE FLOT
C9B5 1808 LOOP: C995 LOOF2 C99A
1540 JR CONT1; JUMP THE INDIRECT 8K: TO 161 CALLS
LOOFA C99F NRET [974
1550
FING C9DA FINGL C9DD
1560 ; THE INTERFACE R.O.M. IS PAGED IN IF THIS IS REACHED
C987 D7 1570 ROM: PLOT C987 RIGHT C962
RST 16; THE 16 L ROUTINES MUST BE
0988 4DOD ROM2 C957 SETUP C901
1580 DEFW #D4D ; CALLED INDIRECTLY
UF' C94F
C98A FDC857C6 1590 SET 0,(IY+87)
C9BE D7 1600 RST 16
Table used: 228 from 690
C9BF FDCB5786 1610 CONT1 PEE 0, (IY+87); RESET OVER 1
C9C3 CI 1620 FOF BC ; RESTORE LATEST FLOT POSITION
C9C4 DI 1630 POP' DE ; AND THE COUNTER
C9C5 15 1640 DEC D
C9C6 20C2 1650 JR NZ.LOOP
1660
C9C8 C1 1670 POP BC ; RESTORE STARTING FLOT POSITION DeBASE
C9C9 79 1680 LD A,B ; AND SEE IF AN EDGE HAS BEEN
C9CA A7 1690 AND A ; REACHED
C9CB 280D 1700 JR Z,FING ; AND IF SO TAKE THE NECESSARY DeBASE is made up from a number of separate routines building
C9CD FEAE 1710 CP 174 ; ACTION
C9CF 2509 1720 JR Z,FING up to a crude, but efficient, data base program, with routines for
C9D1 .. 1770 LD A,C
C9D2 A7 1740 AND A
saving to and loading from both tape and Microdrive.
C9D7 2805 1750 JR ,PING The program will allow entries to be input, printed out, found,
C9D5 FEF E 1760 CF 254
2801 1770 JR ,PING erased and changed. There is no constraint on the number of
C9D9 09 1790 RET , OTHERWISE RETURN
1790 separate records nor on the size of each record, except that it must
C9DA 05
1800 FING PUSH BC ; SAVE THE FLOT CO-ORDINATES fit on the screen without scrolling it. Any part of any record may
C9DB 0600 1810 LD 5,0 ; 50 THAT B CAN BE USED AS A COUNTER
C9DD 7 8 1820 PINGL LD A.B ; SEND OUTPUT TO THE SPEAKER be found, and the cursor will be placed at the start of the details
1830
1840 ;SEND OUTPUT TO THE SPEAKER that were looked for. A record may be changed, enlarged or
C9DE DTFE 1850 OUT (#FE),A ;
09E0 1OFB 1860
REPEATEDLY CHANGING THE STATE shrunk after its original creation, without destroying or altering
DJNZ PINGL ; TO MAKE A NOISE
C9E2 CI 1870 POP BBC any other records. After a record deletion all space used by the
1590
1990 ;NOW SEE WHERE THE CALL CAME FROM record is reclaimed.
1900 ;
C9E3 2174C9 1910 LD HL,NRET The program uses only 1 byte of memory per character plus 1
C9E6 7D 1920 LD A.L
C9E7 EI 1,770
byte per record for the end marker of the record; 32 000 bytes are
FOP HL
C9E8 ES 1940 PUSH HL available for records as written, with plenty of room for added
C9E9 AD 1950 XOR L
1960 facilities.
1970 ; IF THE RETURN WAS NOT MADE HERE EVERY ALTERNATE TIME
1980 ; THIS ROUTINE WAS CALLED ONLY THE EVEN NUMBER COLOURS
1990 ;WOULD BE SET
2000 ; Fass 1 errors: 00
C9EA CB 2010 RET
2020 10 ; THIS SUBROUTINE WILL PRINT ANYTHING WHICH STARTS WITH
2030 1 INCREASE THE BORDER COLOUR, BITS 0-2 20 ; A BYTE WITH BIT 7 SET UP TO THE NEXT BYTE WITH BIT 7 SET.
2040 ; 30 ; IT HAS THREE MAIN ENTRY POINTS AND TWO METHODS OF USE
C9EB 3AF5C9 2050 LD A,(COL) 40 ; IF THE A REGISTER HOLDS 255 (#FF) ON ENTRY, THE DE REGISTER
C9EE 3C 2:60 INC A 50 ; MUST HOLD THE ADDRESS OF THE FIRST CHARACTER OF A MESSAGE
C9EF 32F5C9 2070 LD (COL),A 60 ; WHICH MUST BE PRECEEDED BY A BYTE WITH BIT 7 SET.
2080 7(1 ; FOR ALL OTHER VALUES OF A THE MESSAGE OF THAT NUMBER
2090 ; AND SET THE BORDER 80 ; FROM A TABLE OF MESSAGES STARTING WITH A MARKER BYTE
2100 90 ; WILL BE PRINTED
C9F2 D3FE 2110 OUT (#FE),A 100 ;
C9F4 C9 2120 RET 110 ;
C9F5 00 2130 COL DEFB ù F424 120 MCI ORG 62500
F424 F5 150 PMESS PUSH AF ; THIS ENTRY POINT SETS THE PRINT POSITION
F425 DS 160 PUSH DE TO THE TOP LEFT OF THE SCREEN
F426 3E02 170 LD A,2
112 The Spectrum Operating System Appendix G 113

F465 D1 750 POP DE


F428 CD0116 180 CALL #1601 : ENSURE MAIN SCREEN CURRENT, OTHERWISE
F466 D5 760 LOOK:MO PUSH DE
190 THE FRINT POSITION COULD BE SET
F467 EDB1 770 LDOLON CPIR : LOOK FOR THE FIRST CHARACTER
200 FOR THE WRONG SCREEN. LEAVING THE MAIN F469 2046 780 JR NZ,NOTFND : IF THE STRING IS NOT FOUND
210 : SCREEN AT ITS PREVIOUS POSITION F46B 28 790 DEC HL
F428 012119 220 LD BC.#1821 F46C 22EEF4 800 LD (LOCFND),HL I SAVE THE LOCATION WHERE FOUND
F42E CDD9UD 230 CALL 3545 : USE THE R.O.M. CALL DETAILED IN CHAPTER 2 F46F ED43ECF4 810 LD (LOCCNT),BC : AND THE COUNT LEFT TO GO
F431 DI 240 POP DE F47' DI 820 POP' DE
F452 F1 250 POP AF F474 D5 830 PUSH DE
_51 , F475 23 840 MAYBE INC HL : NOW EACH CHARACTER IS TESTED IN TURN
F476 EL 850 EX DE, HL
F433 F5 260 PRINAT PUSH AF : THIS ENTRY LEAVES THE CURRENT PRINT
F477 23 960 INC HL
F434 D5 270 PUSH DE ; POSITION AND USES THE MAIN SCREEN F478 7E 870 LD A,(HL)
F435 3E02 280 LD 0,2 F479 FEFF 880 CF' AND WHEN THE END OF THE STRING
F437 CD0116 290 CALL #1601
F478 280D 890 JR Z,FOUND : IS FOUND THEN THE STRING HAS
F430 _T•EFF 320 LD A,255 : SET SCROLLS BEFORE scroll ? MESSAGE 900 : BEEN FOUND
F43C 328C5C 330 LD (23692),A ; THIS IS THE SYSTEM VARIABLE SCR CT. F470 LB 910 EX DE,HL
F43F 3E0D 340 LD 0.13 : ENTER (CARRIAGE RETURN AND LINE FEED)
F47E BE 920 CF' (HL)
F441 D7 350 RST 16 : THE PRINT RESTART
F47F 28F4 930 JR Z, MAY BE
F442 DI 360 FOP DE
F481 2AEEF4 940 LD HL,(LOCFND) I IF THE MATCH FAILS THEN LOOK
F443 F1 370 POF AF
950 I FOR THE FIRST CHARACTER AGAIN
F444 3C 380 PRINT INC A : THIS ENTRY USES THE CURRENT STREAM
F484 23 960 INC HL
F445 18 390 DEC DE : SET DE TO POINT TO THE START MARKER
F485 3ACBF4 970 LD A,(SCHAR)
F446 2804 400 JR Z,PRINTP : IF A WAS #FF THEN USE THE ADDRESS IN DE
F488 1800 980 JR LOOKON
F448 3D 410 DEC A
990
F449 110000 420 LD DE,MESS-1 : POINT DE TO THE START OF THE MESSAGES
F480 El 1000 FOUND POF' HL
F44C CDOAOC 430 FRINTP CALL 3082 1 PRINT MESSAGE R.O.M. ROUTINE
F498 2AEEF4 1010 LD HL,(LOCFND) : FIRST IT IS CHECKED IF THE FIND
F44F C9 440 RET
F48E 28 10211 f>CCK DEC HL : IS IN THE ALLOWED AREA
0001 450 MESS EOU 1
F49F 22F0F4 1030 LD (MEMPOS),HL
F492 27 1040 INC HL
Fass 2 errors: 00 F493 E5 1050 PUSH HL
F494 ED5BF2F4 1060 LD DE,(LIMIT)
MCI C256 MESS 0001 F498 A7 1070 AND A
F'MESS F424 F'RINAT F433 F499 ED52 1090 SEC HL,DE
PRINT F444 PRINTP F44C F458 3014 1090 JR NC,NOTFND AND IF NOT IT IS DISALLOWED
F49D E1 1100 F'OF' HL
F49E 28 1110 BACK:MO DEC HL : BEFORE THE ENTRY CAN BE PRINTED
F49F CB7E 1120 BIT 7,(HL) THE START MUST BE FOUND
F4A1 29FB 1130 JR Z,BACK:MO
Fass 1 errors: 00
F4A3 23 1140 INC HL
F4A4 E5 1150 PUSH HL
450 I THIS SUBROUTINE WILL SEARCH MEMORY FOR A STRING WHICH F4A5 E5 1160 PUSH HL
460 : MATCHES THE STRING STARTING AT SCHAR (SEARCH CHARACTER)
F406 CD6BOD 1170 CALL 3435 . CLEAR THE WHOLE SCREEN
470 : AND ENDING WITH A MARKER BYTE OF 255 (#FF)
F4A9 D1 1180 POF' DE
480 : IF A MATCH IS FOUND THE START OF THE RECORD CONTAINING
F4AA 3EFF 1190 LD A, #FF ; SIGNAL TO PRINT ROUTINE THE ADDRESS
490 : THE MATCH IS THEN FOUND, BY STEPPING BACK TO A BYTE
F4AC CD24F4 1200 CALL PMESS I IN DE IS TO BE USED
500 :. WITH BIT 7 SET. IT IS THEN PRINTED BY THE PREVIOUS
F4AF CI 1210 POF' BC
510: SUBROUTINE.
F4E0 C9 1220 RET
Dn
F481 3E03 1230 NOTFND LD 0.3 : PRINT MESSAGE 3
530 : IF THE END OF EACH RECORD IS MARKED WITH A 88D
F483 CD33F4 1240 CALL F'RINAT
540 : THEN IF THE CONTENTS OF SCHAR IS #FF (IE FIND NOTHING)
F486 El 1250 POF' HL
550 : EACH RECORDS END WILL BE FOUND INSTEAD
F4E7 010000 1260 LD BC,O
560 ;
F48A C9 1270 RET
570 1 ON EXIT THE BC REGISTER PAIR WILL EITHER HOLD THE ADDRESS
1280
580 : OF THE START OF THE RECORD CONTAINING THE STRING
F4E8 21CBF4 1290 CONTLK LD HL,SCHAR : THIS IS THE ENTRY POINT TO LOOK FOR A
590 : OR 0 IF THE STRING WAS NOT FOUND
F4BE E5 1300 PUSH HL ; FURTHER OCCURENCE OF THE FIND STRING
600 :
F4BF 7E 1310 LD A,(HL)
610 :
F450 F4C0 ED4BECF4 1320 LD BC,(L000NT)
620 MC2 ORG #F450
F4C4 2AEEF4 1330 LD HL,(LOCFND)
F450 21CBF4 630 FINDIT LD HL,SCHAR : THE MAIN ENTRY POINT
F4C7 23 1340 INC HL
F453 7E 640 LD A,(HL)
F4C9 C367F4 1350 JF LOOKON
F454 FEFF 650 CF' #FF
F456 2006 1360
660 JR NZ,SEARCH
F458 2_, 1370 :
670 INC HL
F459 F4C8 1380 SCHAR DEFS
77 680 LD (HL),A
F4EC 0000 1590 LOCCNT DEFW 0 ; THE COUNT LEFT AFTER A SEARCH
F45A 28 690 DEC HL
F4EE 3275 1400 LOCFND DEFW 30002 THE LOCATION OF A FIND
F458 3EBD 700 LD 10,#8D
F4F0 3175 1410 MEMPOS DEFW 30001 : ONE BEFORE THE FIND LOCATION
F45D 77 710 LD (HL),A
F4F2 COF3 1420 LIMIT DEFW 6241 i0 : THE LIMIT OF MEMORY THAT CAN BE USED
F45E E5 720 SEARCH PUSH HL
F424 1430 PMESS EDU #F424 MESSAGE PRINTING ROUTINE, SEE PREVIOUS
F45F 213275 730 LD HL,30002
F433 1440 PRINAT EDU #F433 SUBROUTINE IN THIS APPENDIX
F462 01D084 740 LD BC, 34000
114 The Spectrum Operating System Appendix G 115

Fass 2 errors: 00 F511 010000 1910 LD BC,O


F514 C9 1920 RET
BACKMO F49E CONTLK:: F4BB F515 El 1930 NEXTR POF' HL : RESTORE THE OLD DETAILS AND LOOK ON
FINDIT F450 FOUND F43A F516 CI 1940 POF' BC
LIMIT F4F2 LOCCNT F4EC F517 CD17F5 1950 CALL CONTLK
LOCFND F4EE LOOk(MO F466 FSIA C3CEF4 1960 JF' XRECON
LOOKDN F467 MAYBE F475
MC2 0770 MEMFOS F4F0 Pass 2 errors: 00
NOTFND F481 FMESS F424
F'RINAT F433 SCHAR F4CB *WARNING* FINDIT absent
*WARNING* FRINAT absent
*WARNING* LIMIT absent
*WARNING* CONTLF absent
Fass 1 errors: 00
Table used: 147 From 267
1360 : THIS SUBROUTINE WILL ERASE A RECORD WHEN USED WITH THE
1370 ; PREVIOUS SUBROUTINE Fass 1 errors: 00
1380 :
1390 : ON EXIT THE BC REGISTERS WILL CONTAIN THE AMOUNT OF MEMORY 1970 ; THIS ROUTINE ALLOWS KEYBOARD INPUT TO BE PLACED INTO MEMORY
1400 ; RECLAIMED 1980 ; AS WELL AS ECHOED TO THE SCREEN.
1410 1990 :
1420 : 2000 ;
F4CB 1430 MC3 ORG #F4CB 2010 ; IT CATERS FOR FORWARD AND BACKWARD CURSOR MOVEMENT
F4CB CDCBF4 1440 XREC CALL FINDIT ; THIS IS USED TO FIND 2020 ; AND INSERTION AND DELETION OF CHARACTERS
F4CE 78 1450 XRECON LD 4,8 : THE ENTRY TO BE ERASED 2030
F4CF 81 1460 OR C 2040 ; IT ALSO OFFERS A HELF' PAGE AND A MENU
F4D0 C8 1470 RET Z : BC = 0 IF NOT FOUND 2050 :
F401 E5 1480 FUSH HL 2060 : AS SHOWN HERE IT IS FOR USE WITH THE OTHER ROUTINES
F4D2 C5 1490 PUSH BC 2070 : IN THIS SECTION AS A DATABASE,
F4D3 3E02 1500 LD A,2 : MESSAGE 2 2080: BUT IT CAN EASILY BE TAILORED TO SUIT MANY PURPOSES.
F4D5 CDD5F4 1510 CALL FRINAT 2090 ;
F4D8 3E7F 1520 CHECKB LD 4,127 ; THIS IS ONE WAY OF SCANNING 2100: THE ROUTINE CHECKS FOR MEMORY OVER THE LIMIT BEING USED
1530 ; FOR KEYS PRESSED, SEE CHAPTER 2 2110 : AND WILL STOP INPUT AT THIS STAGE
F4DA DBFE 1540 IN A,(#FE) 2120
F4DC 1F 1550 RRA 21=0 ; I HAVE FUT A SECOND INPUT ROUTINE IN FOR FIND INPUT
F4DD 3030 1560 JR NC,BREAK 2140 ; AS WELL AS EXTRA INPUT ROUTINES FOR SELECTION OF OPTIONS
F4DF 3E7F 1570 LD A,127 2150 ; THIS IS INTENDED TO DEMONSTRATE THE DIFFERENT WAYS
F4E1 DBFE 1580 IN A,(#FE) 2160 ; OF GETTING INPUT, AND SOME OF THE PROBLEMS MENTIONED
F4E3 CBSF 1590 BIT 3,4 2170 ; IN THE MAIN TEXT OF THE BOOK
F4E5 282E 1600 JR Z,NEXTR 2180 ;
F4E7 3EFE 1610 LD 4,254 2190 ;
F4E9 DBFE 1620 IN A,(#FE) 2200 ; THIS IS THE CALL ADDRESS FROM BASIC.
F4EB CB57 1630 BIT 2.A 2210 ;
F4ED 20E9 1640 JR NZ,CHECK::B F51D 2220 MC4 ORG #F51D
F4EF CI 1650 POF' BC F51D 3EA0 2230 USR LD A,#AO I FIRST FREE MEMORY IS CHECKED
F4F0 El 1660 POF' HL F51F 2A1FF5 2240 LD HL,(LIMIT)
F4F1 C5 1670 PUSH BC F522 ED5B22F5 2250 LD DE.(CHPOS)
F4F2 CS 1680 PUSH BC : BC = START OF RECORD F526 A7 2260 AND A
F4F3 El 1690 POF' HL F527 ED52 2270 SBC HL,DE
F4F4 010000 1700 LD BC,O F529 D234F5 2280 JP NC,NOTFUL
F4F7 CB7E 1710 F_END BIT 7,(HL) F52C 1E09 2290 LD A.9 ; MESSAGE 9
F4F9 23 1720 INC HL F52E CD2EF5 2300 CALL FRINAT
F4FA 03 1730 INC BC : THE END OF THE RECORD F531 C3DFF6 2310 JP PMESS4
F4FB 28FA 1740 JR Z,F END ; MUST BE FOUND F534 E5 2320 NOTFUL PUSH HL : AND ALL MEMORY ABOVE THE LAST RECORD
F4FD DI 1750 POE DE ; NOW EVERYTHING ABOVE THE F535 CI 2330 POP BC ; AND BELOW LIMIT IS CLEARED
F4FE C5 1760 PUSH BC : RECORD OF TO LIMIT CAN BE BROUGHT F536 D5 2340 PUSH DE : AND MARKED AS FREE
F4FF E5 1770 PUSH HL ; DOWN TO DELETE THE RECORD F537 El 2350 POP HL
F500 CI 1780 POF' BC F538 13 2360 INC DE
F501 E5 1790 PUSH HL F539 77 2370 LD (HL) , A
F502 2A02F5 1800 LD HL,(LIMIT) F53A EDBO 2380 LDIR
F505 A7 1810 AND A F530 2A22F5 2390 INFUTA LD HL,(CHPOS) : AND THE START OF THE NEXT RECORD
F506 ED42 1820 SEC HL,BC F53F 2B 2400 DEC HL
F508 E5 1830 PUSH HL F540 7E 2410 LD A,(HL)
F509 CI 1840 POP BC F541 FE8D 2420 CF #8D
F50A EI 1850 POP HL F543 2801 2430 JR Z,ATBEG
F508 EDBO 1860 LDIR F545 23 2440 INC HL
F5OD CI 1870 POP BC : THE AMOUNT OF GAINED SPACE F546 368D 2450 ATBEG LD (HL),#8D
F50E C9 1880 RET F548 2248F5 2460 LD (CUPOS),HL : IS MARKED, AND THE START NOTED
F5OF El 1890 BREAK POF' HL ; CLEAR THE STACK AND SHOW NOT FOUND F548 CD6BOD 2470 CALL 3435 ; THE SCREEN IS CLEARED
F510 Cl 1900 FOP BC 2480 CALL OF'EN1
F54E CD4EF5
116 The Spectrum Operating System Appendix G 117
F551 012118 2490 LD 80,81821 AND THE FEINT POSITION IN THE F5E9 CD02F7 3190 CALL CURSOR
F554 000900 2500 CALL 3545 : LOWER SCREEN SET TO THE TOP LEFT FSEC 3E08 3200 LD 04,8
F557 7E07 2510 LD 8,7 : MESSAGE 7 FSEE D7 3210 RST 16
F559 CD59F5 2520 CALL PRINT FSEF CDO2F7 3220 CALL CURSOR
F550 3E01 2530 LD 0,1 : THE COPYRIGHT F5F2 0371F5 3230 JP INPUT I BACK FOR NEXT CHARACTER
F55E CD5EF5 2540 CALL PRESS 3240 :
F561 AF 2550 XOR A : AND THE EDIT MODE FLAG IS CLEARED _250
F562 3262F5 2560 LD (WFLAG),A F5F5 ES 3260 STOP PUSH HL : IF STOP IS PRESSED THE END 0F THE
F565 012116 2570 LD 8C,#16^1 : SET LINE 2 COLUMN 0 F5F6 28 3270 DEC HL : RECORD MUST ONLY BE MARKED
F568 C00900 2580 CALL 3.545 ^ F5F7 7E 3280 ENDIS LD A,(HL) 1 IF IT WAS A NEW ENTRY, BUT IN ALL
F568 3E3E 2590 LD A,"T" F5F8 23 3290 INC HL : CASES THE START OF FREE MEMORY
F560 D7 2600 RST 16 F5F9 FEAO 3300 CF' #AO : FOUND AND THE POINTER UPDATED
F56E CD02F7 2610 CALL CURSOR FSFB 2OFA 3310 JR NZ,ENDIS
F571 CD4EF5 2620 INPUT CALL OPEN1 F5FD 28 3320 DEC HL
F574 CD0810 2630 INF'I CALL #1088 : THIS IS THE KEYBOARD INPUT FSFE 2222F5 3330 LD (CHEOS),HL
F577 3806 2640 JR C,KEYF'RE ROUTINE, CARRY SET IF NEW KEY PRESSED F601 El 3340 FOP HL
F5 7 9 FDCB029E 2650 RES 3,(IY+2) THIS IS TV FLAG, SEE WAIT INPUT CHAF.2 F602 3062F5 3350 LD 8,(WFLAG)
F570 1BF5 2660 JR INPI F605 87 3360 AND A
F57F FE08 2670 FEVERS CF' 8 : NOW ANY SPECIAL FUNCTION KEYS PICKED F606 23 3370 INC HL
F581 284E 2680 JR Z.BRCK1 F607 2007 3380 JR NZ,STOEON
F583 FE09 2690 CP 9 F609 2222F5 3390 LD (CHFOS),HL
F585 CA11F7 2700 JF' Z,RIGHT1 F600 28 3400 DEC HL
F588 FEOC 2710 CP 12 : CAPS SHIFT AND 0 F600 3E8D 3410 LD 0,#80
F580 CA5CF7 2720 JP Z,DELETE F60F 77 3420 LD (HL),A
F580 FEC5 2730 CP 197 OR F610 CD6BOD 3430 STOPON CALL 3435 : THE SCREEN IS CLEARED
F58F C8 2740 RET Z F613 AF 3440 XOR A : THE MODE FLAG CLEARED
F590 FECD 2750 CF' 205 . STEP F614 3262E5 3450 LD (WFLAG),A
F592 CACFF7 2760 JF' Z,HELF' F6I7 3E04 3460 LD A,4 : AND THE MENU DISPLAYED
F595 FEC6 2770 CF' 198 F619 CD5EF5 3470 CALL FMESS
F597 CA8EF7 2780 JP Z.AND F610 CD4EF5 3480 MENUIN CALL OFEN1
F590 FEC3 2790 CP 195 ' NOT F61F CDDE15 3490 CALL #15DE : THE WAIT INPUT ROUTINE, SEE CHAPTER 2
F59C CAD9F6 2800 JF' Z,LOOKM F622 FEOD 3500 CP 13
F59F FECC 2810 CP 204 : TO F624 CA1DF5 3510 JF' Z,USR
F501 CAB7F7 2820 JP Z,LFRINT F627 F620 7520 OR #2i
F5A4 2048F5 2830 LD HL,(CUPOS) F629 FE65 3530 CF' "e"
F587 23 2840 INC HL : NOW IT OS CHECKED THAT THE END OF A F628 2810 3540 JR Z,XINF'UT
F5A8 F5 2850 PUSH AF : RECORD HAS NOT BEEN REACHED, IF IT HAS F620 FE66 3550 CF' "f"
F589 3A62F5 2860 LD A,(WFLAG) , NO MORE INPUT IS ALLOWED F62F 281E 3560 JR Z,FINF'UT
F5A0 A7 2870 AND A F631 FE63 3570 CF' "c"
F58D 2806 2880 JR Z,OKTHEN ; BUT IF NOT IN EDIT MODE IT MUST BE F633 CAD9F6 3580 J F' Z,LOOKM
F5AF 7E 2890 LD A,(HL) FREE MEMORY F636 FE73 3590
F580 FE8D 2900 CF #80 F638 CA38F6 3600 JF' Z,SAVEL
F582 C040F7 2910 JP Z,ENDREC F638 18DF 3610 JR MENUIN
F585 Fl 2920 OSTHEN POP AF 3620
F5B6 FEE2 29330 CP 226 STOP WHICH ENDS INPUT 3630 1
F588 2838 2940 JR Z,STOF F630 CDA0F6 3640 %INPUT CALL FINFT THIS IS THE ERASE ENTRY ROUTINE START
F58A 77 2950 LD (HL),A I THE CHARACTER CODE IS PUT INTO THE F640 0D40F6 3650 CALL XREC
F588 2248F5 2960 LD (CUPOS),HL CURRENT MEMORY POSITION AND THIS IS 3660
F643 2022F5 LD HL,(CHEOS) THE GAINED SPACE IS ALLOWED FOR BY
2970 : UPDATED FOR NEXT TIME F646 A7 3670 AND A 1 MOVING THE START OF FREE MEMORY
FSBE FEOD 2980 CF' 13 F647 ED42 33680 SEC HL,80 : DOWN BY THAT AMOUNT
F5C0 2006 2990 JR NZ,KEYOUT IF AN ENTER REMOVE THE OLD CURSOR F649 2222F5 '690 LD (CHFOS),HL
F5C2 CDC'_FS 3000 CALL OPEN2 F640 C3DFF6 3700 JP FMESS4
F5C5 CD02F7 3010 CALL CURSOR 3710 :
F5C8 CD02F5 3020 KEYDUT CALL OPEN2
3720
F5CB D7 3030 RST 16 : ECHO THE KEY TO THE SCREEN F64F CDA0F6 3730 FINFUT CALL FINFT THE START OF THE FIND ENTRY ROUTINE
F500 0002F7 3040 CALL CURSOR I AND MOVE THE CURSOR ALONG F652 CD52F6 3740 CALL FINDIT
FSCF 1880 3050 JR INPUT : GO BACK FOR THE NEXT KEY F655 78 3750 FINEST LD 8,8 ; IF THE ENTRY IS NOT FOUND GOTO MENU
3060 ;
F656 81 3760 OR C
3070 :
F657 CADFF6 3770 JP Z,FMESS4
F501 2048F5 3080 8ACK.1 LD HL.)OUF'OS) THIS MOVES THE CURSOR AND CURRENT
F650 08 3780 DEC BC
F5D4 7E 3090 LD 8,(HL) ; MEMORY POSITION BACK:
F5D5 C87F F65B ED4348F5 3790 LD (CUPOS),BC : OTHERWISE SET EDIT MODE WITH THE
3100 BIT 7,A
F65F 2A5FF6 3800 LD HO.(MEMPOS) I CURSOR UNDER THE START OF THE FIND
F5D7 2098 3110 JR NZ,INPUT
F509 FEUD F662 A7 3810 AND A
3120 CP 13
F663 ED42 3820 SBC HL,BC
F5D8 2B 3130 DEC HL
F665 2265F6 3830 LD (CURSP),HL
F500 2248F5 3140 LD (CURDS), HL
FSDF 2005 F668 3E01 3840 LD 8,1
3150 JR NZ,B_ON
F5E1 CDE1F5 3160 CALL BACK : F660 3262F5 3850 LD (WFLAG),A
BUT GOING BACK: FAST AN ENTER
F5E4 186F 3170 JR FINRET MEANS A RE-PRINT AND CHANGE OF MODE F66D CD4EF5 3860 CALL OPEN!
F5E6 CDC2F5 3180 B ON CALL OPEN2 F670 012118 3870 LD 80,91821
118 The Spectrum Operating System Appendix G 119

F673 CDD90D F6EC F5 4580 OVER1 PUSH AF


3880 CALL 3545
F676 3E08 3890 F6ED E5 4590 PUSH HL
LD 4,8
F678 CD59F5 3900 F6EE 3E15 4600 LD 4.21
CALL PRINT
F678 7E07 F6F0 D7 4610 RST 16
3910 LD 4,7
F670 CD59F5 F6F1 3E01 4620 LD 4,1
3920 CALL PRINT
F680 CDC2F5 7930 F6F3 D7 4630 RST 16
CALL OPEN2
F683 012118 3940 F6F4 E1 4640 POP HL
LD EC,81821
F686 000900 3950 F6F5 F1 4650 POF' AF
CALL 3545
F689 3E0D F6F6 09 4660 RET
3960 LD 4,1:
F688 D7 F6F7 F5 4670 OVERO PUSH AF
3970 RST 16
F6BC CDO2F7 3980 F6F8 E5 4680 PUSH HL
CALL CURSOR
F69F ED4B65F6 3990 F6F9 3E15 4690 LD 4,21
LD BC,(CURSP)
F693 78 4000 R1MORE LD F6FE D7 4700 RST 16
8,8
F694 81 4010 F6FC 3E00 4710 LD 4,0
OR C
F695 C471F5 4020 F6FE D7 4720 RST 16
JF' Z,INPUT
F698 C5 4030 PUSH BC F6FF El 4730 POF' HL
F699 CD17F7 4040 F700 Fl 4740 POP AF
CALL RIGHTS
F69C CI 4050 POF' 8C F701 C9 4750 RET
F702 F5 4760 CURSOR PUSH AF : THIS PRINTS THE CURSOR AND MOVES
F690 OE 4060 DEC BC
F703 CDECF6 4770 CALL OVER1 ; THE PRINT POSITION BACK OVER IT
F698 18F3 4070 JR R1MORE
4060 : F706 785F 4780 LD 4,95
F708 D7 4790 RST 16
4090 ;
F680 CD6BOD F709 7E08 4900 LD 4.8
4100 FINPT CALL 3435 : THIS IS SIMILAR TO THE INPUT
F6033 3E05 F708 D7 4810 RST 16
4110 LD 4.5 : INPUT ROUTINE EARLIER BUT IT DOES NOT
F685 CD5EF5 F700 CDF7F6 4920 CALL OVERO
4120 CALL PRESS : ALLOW ANY ALTERATIONS
F6A8 3E3E F7OF Fl 4830 POP AF
4130 LD 8,62 ; AND LINITS THE INPUT BY STOPPING
F6AA D7 F710 C9 4940 RET
4140 RST 16 ; WHEN THE POSITION REACHES IN_LIM
F711 C017F7 4850 RIGHT1 CALL RIGHTS
F6A8 21CBF6 4150 LD HL,SCHAR*32
F6AE 22AEF6 F714 C7771F5 4860 JP INPUT
4160 LD (IN_LIM),HL
F717 CDC2F5 4870 RIGHTS CALL OPEN2 ; THIS SUBROUTINE MOVES THE CURSOR
F681 21A6F6 4170 LD HL,SCHAR
4190 : F710 2448F5 4880 LD HL,(CUPOS) ; RIGHT ONE POSITION AND POINTS THE
4190 ; F710 2_ 4890 INC HL : MEMOTY POINTER TO THE NEW CHARACTER
F684 E5 4200 INPUTF PUSH HL : F718 7E 4900 LD A,(HL)
THE ACTUAL INPUT SUBROUTINE
F6E5 CD4EF5 4210 F71F CB7F 4910 BIT 7,4
CALL OPEN1
F688 CDDE15 4220 CALL #15DE F721 CO 4920 RET NZ
F6B8 EI 4230 POP HL F722 FE7F 4930 CF 127
F6BC FEOD 4240 CP
13 : F724 CS 4940 RET Z
TERMINATED BY PRESSING ENTER
F6BE 2816 4250 JR Z,SETFIN F725 FEOD 4950 CF' 13
F6C0 FE20 4260 CP 32 F727 2803 4960 JR Z,ONRITE
F6C2 38F0 4270 JR C,INFUTF F729 FE20 4970 CF' 32
F6C4 77 4280 LD (HL),A F728 D8 4980 RET C
F605 23 4290 F720 2248E5 4990 ONRITE LD (CUPOS),HL
INC HL
F6C6 ES 4300 PUSH HL F72F CDO2F7 5000 CALL CURSOR
F607 CDC2F5 4310 CALL OPEN2 F732 FEOD 5010 CP 13
F6CA D7 4320 RST 16 F734 2905 5020 JR Z,RITEON
F608 El 4370 F736 CDECF6 5030 CALL OVER1
POP HL
F6CC EB 4340 F739 3E20 5040 LD 4,32
EX DE,HL
F6CD 2AAEF6 4350 LD F738 D7 5050 RITEON RST 16
HL,(IN_LIM)
F6D0 A7 4360 F73C CDO2F7 5060 CALL CURSOR
AND A
F6D1 ED52 4370 F73F C9 5070 RET
SEC HL,DE
F603 EB 4380 EX 5080 :
DE,HL
F6D4 200E 4390 JR 5090 ;
NZ,INPUTF
F606 36FF F740 E5 5100 ENDREC PUSH HL ; IF ENTRY IS ATTEMPTED BEYOND THE
4400 SETFIN LD (HL),255
F608 C9 F741 0603 5110 LD 8,3 : END OF A RECORD A WARNING IS FLASHED
4410 RET
F743 00440E 5120 CALL 3652 ; THE BOTTOM OF THE SCREEN IS CLEARED
4420 ;
4430 F746 3E06 5130 LD 4,6
F6D9 CDD9F6 4440 LOOKM CALL CONTLK ; F749 CD5EF5 5140 CALL PMESS
THIS LOOKS FOR A FURTHER OCCURENCE AF JUST IN CASE IF THEY WERE OFF
F6DC C355F6 4450 JP FINRET 9 F748 F8 5150 EI
A FIND STRING
4460 : F740 0632 5160 LD 6,50 ; THIS 1 SEC PAUSE WOULD BE FOREVER
4470 ; F74E 76 5170 WAIT1 HALT
F6DF 06033 4480 PMESS4 LD F74F 10FD 5180 DJNZ WAIT1
B,3 : CLEAR THE BOTTOM THREE SCREEN LINES
F6E1 00440E 4490 CALL 3652 : CHAPTER 2 EXPLAINS
F751 El 5190 POP HL
F6E4 3E04 4500 LD F752 F1 5200 POP AF
4,4 : THE MENU
F6E6 CD2EF5 4510 CALL PRINAT F753 2153F7 5210 REENTR LD HL,LOCFND
F6E9 C31CF6 4520 JP F756 35 5220 DEC (HL)
MENUIN
4530 F757 26 5230 DEC HL
4540 : F759 34 5240 INC (HL)
4550 ; F759 C3D9F6 5250 JF' LOO)M
OVER1 AND OVER 2 REPRODUCE THE
4560 ; 260
SAME BASIC COMMANDS, BY PRINTING
5270 i
4570 ; THE CONTROL CODES
120 The Spectrum Operating System Appendix G 121

F75C 2048F5 5280 DELETE LD HL,(CUPOS) 1 THIS WORKS THE SAME AS THE DELETE LD 0,10 : THE HELP PAGE
F7D2 3EOA 5980
F75F 27 5290 INC HL ; RECORD BUT FOR ONE CHARACTER CALL FMESS
F7D4 CD5EF5 5990
F760 7E 5700 LD A,(HL)
F7D7 3EBF 6000 WAITE LD 0,88F
F761 C87F 5710 BIT 7.0 A,(#FE)
F7D9 DBFE 6010 IN
F767 C271F5 5320 JP NZ,INFUT
F708 E601` 6020 AND 1
F766 E5 5730 PUSH HL
F7DD 20F8 6030 JR NZ,WAITE
F767 ES 5740 PUSH HL
F7DF 2A48F5 6040 LD HL,(CUFOS)
F768 2AIFF5 5750 LE HL,(LIMIT) (LOCFND),HL
F7E2 2253F7 6050 LD
F768 D1 5360 POF' DE
F7E5 27 6060 INC HL
F76C A7 5770 AND A
F7E6 7E 6070 LD A,(HLI
F760 ED52 5780 SBC HL,DE
F76F E5 5790 F7E7 2108F6 6080 LD HL,SCHAR
PUSH HL
F770 Cl 5400 F7EA 77 6090 LD (HL),A
POF BC
F7E8 27 6100 INC HL
F771 D1 5410 POP DE
F7EC 36FF 6110 LD (HL),#FF
F772 DA71F5 5420 JP C. INPUT
F7EE C353F7 6120 JF' REENTR
F775 CA71F5 5430 JP Z,INPUT
F778 D5 5440 PUSH DE
F779 El 5450 FOP HL Fass 2 errors: 00
F770 27 5460 INC HL
F778 EDBI) 5470 *WARNING* LIMIT absent
LOIR
F77D 2822F5 *WARNING* CHFOS absent
5480 LD HL,(CHPOS)
F780 28 *WARNING* FRINAT absent
5490 DEC HL
F781 2222F5 *WARNING* CUFOS absent
5500 LD (CHPOS),HL
F7B4 21048F5 *WARNING* OPEN1 absent
5510 LD HL,(CUPOS)
F787 27 *WARNING* PRINT absent
5520 INC HL
F788 CDEIFS *WARNING* PMESS absent
5570 CALL BACK:
F788 C355F6 *WARNING* WFLAG absent
5540 JP FINRET
*WARNING* OPEN: absent
5550
*WARNING* BACK absent
5560
F7BE 2048F5 *WARNING* SAVEL absent
5570 AND LD HL.(CUPOS) : AND THIS IS THE SAME IN REVERSE
F791 27 *WARNING* XREC absent
5580 INC HL
F792 E5 *WARNING* FINDIT absent
5590 PUSH HL
F793 2AIFF5 *WARNING* MEMFOS absent
5600 LD HL,(LIMIT)
F796 DI *WARNING* CURSE absent
5610 FOP DE
F797 A7 5620 *WARNING* SCHAR absent
AND A
F798 ED52 *WARNING* IN_LIM absent
5630 SBC HL,DE
F79A E5 *WARNING* CONTLK absent
5640 PUSH HL
F798 Cl *WARNING* LOCFND absent
5650 POF' BC
F79C 135 *WARNING* PRINTP absent
5660 PUSH DE
F79D ED5B1FF5 5670 Table used: 751 from 1219
LD DE,(LIMIT)
F7A1 D5 5680 PUSH DE
F7A2 El 5690 POP HL
F7A3 28 5700 DEC HL 1 errors: 00
Fass
F7A4 EDB8 5710 LDDR
F7A6 20(22F5 5720 LD HL,(CHPOS) 6130 : THIS IS THE START OF THE SAVE AND LOAD ROUTINES
F7A9 27 5730 INC HL 6140
F7AA 2222F5 5740 LD (CHFOS),HL 6150 : FIRST THE LENGTH OF THE RECORDS IS CALCULATED,
F7AD El 5750 POP HL 6160 : WITH AN OVERHEAD FOR AN END-MARKER
F7AE 3E20 5760 LD A,32 6170 AND LENGTH BYTES FOR RE-ENTRY AFTER LOADING
F780 77 5770 LD (HL),A 6180
F781 CDEIFS 5780 CALL BACK 6190 :
F784 C355F6 5790 JP FINRET F7F1 6200 MC5 ORG #F7F1
5800 : F7F1 2AF1F7 6210 SAVEL LD HL,(CHPOS) : FIRST THE END OF RECORDS IS PUT INTO
5810 : F7F4 222E75 6220 LD (29998),HL ; THE START OF THE AREA TO 8E SAVED OR
F787 2A48F5 5820 LPRINT LD HL,(CUPOS) : THIS USES STREAM THREE IN AN IDENTICAL 112E75 6230 LD DE,29998 ; LOADED
F7F7
F78A 23 5830 INC HL ; WAY AS STREAM 2 FOR THE SCREEN, F7FA A7 6240 AND A
F788 CDE1F5 5840 CALL BACK: ; IF AN INTERFACE IS CONNECTED F7F8 ED52 6250 SBC HL, DE
F7BE C5 5850 PUSH BC : WHICH RECOGNISES LFRINT IT WILL WORK:: 6260 INC HL
F7FD 23
F7BF 3E03 5860 LD 0,3 6270 INC HL
F7FE 23
F7C1 CD0116 5870 CALL #1601 6280 PUSH HL
F7FF E5
F7C4 DI 5880 POP DE 7E0B 6290 LD 0.11
F800
F7C5 D5 5890 PUSH DE 6300 CALL PMESS
F802 CD02FB
F7C6 1B 5900 DEC DE 6310 LD 8,25 : 25 INTERRUPTS 1/2 SECOND
F805 0619
F7C7 AF 5910 XOR A EI , JUST IN CASE
F807 FB 6320
F7C8 CDC8F7 5920 CALL FRINTF' 6330
F7CB CI 5930 POP BC 6340
F7CC C355F6 5940 JP FINRET 6350 : THIS WOULD BE BAD PLANNING
5950 , 6360 BUT IT IS TO DEMONSTRATE THE
5960 : 6370 : USE OF THE HALT FOR TIMING
F7CF CD6BOD 5970 HELP CALL 3435 6380
122 The Spectrum Operating System Appendix G 123
F808 76 6390 HOLDIT HALT ; TO MAKE SURE THAT S IS NOT TAKEN Pass 1 errors: 00
F809 10FD 6400 DJNZ HOLDIT ; FROM THE MAIN MENU l:EYFUSH
6410 : NOW THE KEYBOARD IS SCANNED 6790 ;
6420 ; 6800 ; THIS PAGES OUT THE 16K R.O.M.
F808 3E6F 6430 SOLDEC LD A,#BF SEE CHAPTER 3 FOR FULL DETAILS
6810 ;
F800 DBFE 6440 IN A,(#FE) 6820
F8OF E602 6450 AND 2 6830 ;
F811 CA11F8 6460 JP Z,LOAD F838 6840 ORG #F838
F814 3EFD 6470 LD A,#FD F838 2149E8 6850 RSWAP LD HL,ROMOUT
F816 DBFE 6480 IN A,(#FE) THE SUBROUTINE USED BY THE R.O.M.
F838 22ED5C 6860 LD (23789),HL :
F818 E602 6490 AND 2 IS USED BY HOOK CODE 32
6870
F810 20EF 6500 JR NZ,SOLDEC SO SET TO RETURN TO THIS ROUTINE
6880 ;
6510 ; THE STACK IS TO BE MUCKED ABOUT
F83E D9 6890 EXX
F83F .23FF8 6900 LD (HLSAV),HL : SO IT IS SAFER THIS WAY
Fass 2 errors: 00
F842 D9 6910 EXX
F843 ED4343F8 6920 LD (BCSAV),BC
*WARNING* CHPOS absent USE THE HOOK CODE
F847 CF 6930 RST 8 ;
*WARNING* PMESS absent
F848 6940 DEFB #32
*WARNING* LOAD absent
F849 El 6950 ROMOUT POP' HL THE TWO RETURN ADDRESSES
*WARNING* M_OR_T absent MUST BE REMOVED
F84q EI 6960 POP HL
*WARNING* LORET absent
F848 DI 6970 POP DE AND THE RETURN FROM THIS SUBROUTINE
*WARNING* HLSAV absent
F84C 2A3D5C 6980 LD HL,123613) THIS IS ERR SP SEE CHAPTER 4
*WARNING* ECSAV absent SAVE THE POSITION OF THE ERROR RETURN
F84F E5 6990 PUSH HL ;
*WARNING* MHEAD absent
7000 ; ON THE STACK FOR LATER
Table used: 243 from 521
F850 216AF8 7010 LD HL,MSLRET
F853 ES 7020 PUSH HL STACK THE NEW ERROR RETURN ADDRESS
F854 ED73305C 7030 LD (23613),SP ; AND POINT ERR SP TO THAT
F858 D5 7040 PUSH DE ; RESTORE THE RETURN ADDRESS
Fass 1 errors: 00 RET
F859 C9 7050

6520 ; THIS IS THE DECISION MAKER FOR TAPE OR MICRODRIVE


6530 1 Fass 2 errors: 00
6540 ,
F910 6550 ORG #F81C *WARNING* HLSAV absent
F81C CI 6560 SAVE FOP BC *WARNING* 6CSAV absent
F910 CD1DF8 6570 CALL M_OR_T RETURNS WITH CARRY SET IF M PRESSED *WARNING* MHEAD absent
6580
0
ALSO SETS THE HEADER *WARNING* LORET absent
6590 1 Table used: 124 from 287
F920 3838 6600 JR C, MSAVE
6610
6620 : THIS IS TO SAVE A HEADER AND A MAIN DATA BLOCK TO TAPE Fass. 1 errors: 00
6630 ; THE HEADER IS SPECIAL, SEE SAVEing & LOADing
7060 1 THIS IS THE SUBROUTINE TO SAVE TO MICRODRIVE, SEE CHAP 3
6640 : IN CHAPTER 2
7(q0î ;
66500
F822 C5 7080 ;
6660 TSAVE PUSH BC BC = LENGTH OF THE MAIN BLOCK: F85A 7090 ORG #F85A
6670 : IX IS ALREADY SET TO THE START F850 CD5AF8 7100 MSAVE CALL RSWAP
FB23 110D00 6680 LD DE.13 . THE HEADER IS ONLY 13 BYTES LONG
F826 AF F85D CD5DF8 7110 CALL MHEAD : SET THE HEADER
6690 XOR A : A TO EE 0 SIGNALLING HEADER
F827 CDC604 F860 CD60F8 7120 CALL VARSET : -AND THE SYSTEM VARIABLES
6700 CALL 1222 . R.O.M. ROUTINE DETAILED IN CHAPTER 2
F863 FDC87CEE 7130 SET 5,1I0+124) ; SIGNAL SAVE WITH FLAGS 33
6710 TO SAVE HEADER
F82A DI F867 CD7F1E 7140 CALL #1E7F : IN FACT A CALL IS NOT NEEDED
6720 POP DE : RESTORE THE LENGTH OF THE MAIN BLOCS:
7150 ; AS RETURN IS VIA THE 16K ERROR 0 OK.
F828 DD212E75 6730 LD IX,29998 ; POINT IX TO THE
6740 F860 El 7160 MSLRET FOP HL ; RESTORE THE ERR SF' SYSTEM VARIABLE
ADDRESS TO START SAVEing FROM F868 223050 7170 LD (23613),HL : ERR SP
F82F 3EFF 6750 LD A,#FF ; SIGNAL MAIN BLOCK
F831 CDC604 F86E F6 7180 EI TOTALLY UNNECESSARY BUT SAFE
6760 CALL 1222 USE THE R.O.M. ROUTINE AGAIN
F834 FB F86F D9 7190 EXX
6770 EI IT RETURNS WITH INTERRUPTS OFF
F935 C335F8 F870 2A70F8 7200 LD HL,(HLSAV) ; AND THE HL' REGISTERS
6780 JF' LORET
F873 D9 7210 EXX NOTE THAT THE 16K R.O.M. IS NOW
F874 C374F8 7220 JF' LORET ; PAGED IN, BECAUSE OF THE RETURN VIA
7230 ; A BASIC ERROR IN THE 16K R.O.M.

Pass 2 errors: 00
Fass 2 errors: 00
*WARNING* M OR T absent
*WARNING* RSWAP absent
*WARNING* LORET absent
*WARNING* MHEAD absent
*WARNING* HLSAV absent
*WARNING* VARSET absent
*WARNING* ECSAV absent
*WARNING* HLSAV absent
*WARNING* MHEAD absent
*WARNING* LORET absent
Table used: 160 from 407 Table used: 99 from 188
124 The Spectrum Operating System Appendix G 125

Fass I errors: 00 F804 CD541F 7920 CALL 90_0


F8D7 DO 7930 RET NC ; BREAK PRESSED
F877 7240 ORG #F877 F809 DD2171F9 7940 TESTHE LD IX,SCHAR ; THE HEADER NAME IS NOW CHECKED
F877 210950 7250 VARSET LD HL,23769 ; THIS IS DETAILED FULLY IN CHAPTER 3 F8DC 2180F9 7950 LD HL,SCHAR+15
F870 364D 7260 LD (HL),"M" F8DF 0608 7960 LD 8,11
F870 210000 7270 LD HL,10 F8E1 7E 7970 TESTLP LD A,(HL)
F87F 220050 7280 LD (23770),HL F8E2 DDBE00 7980 CF' (I6+00)
F882 2172E9 7290 LD HL,SCHAR+1 F9E5 2000 7990 JR NZ.TLOAD : MISMATCH SO WRONG HEADER
F885 22DCSC 7300 LD (23772),HL F8E7 DD23 8000 INC IX : THE HEADER MATCHES SO DO THE LOAD
F888 210100 7310 LD HL,1 F8E9 23 8010 INC HL
F888 220650 7320 LD (23766),HL F8EA 10F5 8020 DJNZ TESTLP
F88E C9 7330 RET FBEC DD212E75 8030 LD IX,29999
7340 F8F0 5E 8040 LD E,(HL)
7350 F9F1 23 8050 INC HL
7360 : F8F2 56 8060 LD D,(HL)
7370 : THIS IS THE ROUTINE TO LOAD FROM A MICRODRIVE F8F3 37 8070 SCF , SIGNAL LOAD
7380 : FULL DETAILS ARE GIVEN IN CHAPTER 3 F8F4 3EFF 8080 LD A,#FF ; MAIN DATA BLOCK
7390 ; FBF6 14 8090 INC D
7400 ; F8F7 08 8100 EX AF,AF'
F88F 010000 7410 MLOAD LD 80,0 : THE DETAILS ON THE HEADER ARE TO F8F8 15 8110 DEC D
F892 CD92F8 7420 CALL RSWAP : 8E USED AS THEY ARE NOT KNOWN F8F9 F3 8120 DI
F895 CDA5F8 7430 CALL MHEAD FBFA CD6205 8130 CALL #562
F898 CD77F8 7440 CALL VARSET F8FD F8 8140 EI
F898 FDC870E6 7450 SET 4,(19+124) : THIS SIGNALS LOAD FBFE CD541F 9150 CALL 8020
F89F 0DAFOB 7460 CALL #8AF ; CALL THE LOAD ROUTINE F901 DO 8160 RET NC : BREAK PRESSED
F8A2 C3A2F8 7470 JP MSLRET ; IN FACT IT IS UNLIKELY TO GET HERE F902 C325F9 8170 JP LORET : LOADED SO RE-ENTER
7480 : 8180
7490 : 8190 :
7500 8200 ;
7510 : THIS SETS THE MICRODRIVE HEADER, FULL DETAILS ARE IN 8210 ; THIS ROUTINE ASKS FOR THE FILENAME AND IF MICRODRIVE
7520 : CHAPTER 3 8220 : OR TAPE IS TO BE USED
7530 : 8230
7540 : 8240
F805 21E650 7550 MHEAD LD HL,23782 F905 CD2EF9 8250 M_OR_T CALL SAVET
F8A8 3603 7560 LD (HL),' F908 C5 8260 PUSH BC
F8AA 23 7570 INC HL F909 DDES 8270 PUSH IX
F8A8 ED5B5CF9 7580 LD DE,(BCSAV) F908 3EOC 8280 LD A,12
F8AF 73 7590 LD (HL),E F9(ID CDODF9 9290 CALL PRINAT
F880 23 7600 INC HL F910 3E7F 8300 MIORTA LD A,#7F
F881 72 7610 LD (HL),D F912 DBFE 8310 IN A,(#FE)
F882 23 7620 INC HL F914 E604 8320 AND 4
F883 112E75 7630 LD DE,29998 F916 37 8330 SCF
F886 73 7640 LD (HL),E F917 2808 8=40 JR Z,MOTFIN
F887 2= 7650 INC HL F919 3EFB 8350 LD A,#FB
F888 72 7660 LD (HL),D F918 DBFE 8260 IN A,(#FE)
F?89 23 7670 INC HL F910 E610 8370 AND 16
F880 3680 7680 LD (HL ,#80 F91F 20EF 8380 JR NZ,MIORTA
F8BC C9 7690 RET F921 DDEI 8390 MOTFIN POF' IX
7700 ; F923 C1 8400 POP BC
7710 F924 C9 8410 RET
77201 8420 ;
7730 : 8430 :
7740 : THE LOAD DECISION BETWEEN MICRODRIVE AND TAPE 8440
7750 : 8450 : THIS PICKS UP THE LENGTH DETAILS FROM THE
7760 ; 8460 : START OF THE MEMORY LOADED
7770 ; LOADING FROM TAPE AS DETAILED IN CHAPTER 2 8470 ; OR FROM WHAT WAS PUT THERE WHEN IT WAS SAVED
7780 8480 :
FBBD CI 7790 LOAD POF' BC F925 2A2E75 8490 LORET LD HL,(29998)
F88E CDO5F9 7800 CALL M_OR_T F928 2260E9 8500 LD (CHPOS),HL
F8C1 38CC 7810 JR C,MLOAD F928 C328F9 8510 JP USR
F903 AF 7820 TLOAD XOR A : SIGNAL HEADER 8520 ,
F9C4 37 78:30 SCF SIGNAL LOAD 8530
F8C5 110000 7840 LD DE,13 8540
F908 14 7850 INC D 8550 : THIS ROUTINE CREATES A HEADER IN THE SCHAR AREA OF MEMORY
F8C9 08 7860 EX AF,AF' 8560
F800 15 7870 DEC D 8570 :
F8C8 F3 7880 DI F92E 2171F9 8580 SAVET LD HL,SCHAR
F8CC DD2180F9 7890 LD IX,SCHAR+15 F931 C5 8590 PUSH BC
F8D0 CD6205 7901 CALL #562 F932 [5 8600 PUSH HL
F8D3 FE; 7910 EI F933 E5 8610 PUSH HL
126 The Spectrum Operating System Appendix G 127

F934 3603 FAB6 454E5445 9320 MESS5 DEFM "ENTER DETAILS TO FIND"
8620 LD (HL).3
F936 C5 FA98 8D 9330 DEFB #8D
8630 PUSH BC
F937 060A FA9C 1002 9340 MESS6 DEFW #210
8640 LD 8,10
F939 3E20 FA9E OD 9350 DEFB 13
8650 LD A,32
F936 23 FA9F 454E4420 9360 DEEM "END OF RECORD. NO MORE INPUT"
8660 SETHED INC HL
F93C 77 FREE OD 9370 DEFE 13
8670 LD (HL),A
F93D 10FC FABC 504F5353 9380 DEEM "POSSIBLE"
8680 OJNZ SETHED
F93F E5 FRC4 8D 9390 DEFB #8D
9690 PUSH HL
FAC5 1001 9400 MESS7 DEFW #110
F940 2264F9 8700 LD (IN_LIM),HL
FAC7 50524553 9410 DEFM "PRESS "
F943 El 8710 POP HL
FACD 1002 9420 DEFW #210
F944 CI 8720 POP BC
F945 27 FACE 53544F50 9430 DEFM "STOP "
8730 INC HL
F946 71 FAD4 1001 9440 DEFW #110
8740 LD (HL),C
F947 23 FAD6 464E5220 9450 DEFM "FOR MENU,
8750 INC HL
FAEO 1002 9460 DEFW #210
F948 70 8760 LD (HL),B
FAE2 02 9470 DEFB 2
F949 CD6B1iD 8770 CALL 3435
F94C 3E0D FAE3 544E20 9480 DEFM "TO "
8780 LD 5,13
F94E CD4EF9 FAE6 1001 9490 DEFW #110
8790 CALL F'MESS
FAE8 544E2050 9500 DEEM "TO PRINTOR "
F951 El 8800 POF' HL
F952 23 FAF3 1002 9510 DEFW #210
9810 INC HL
FAFS 53544550 9520 DEFM "STEP "
F952 CD53F9 8820 CALL INPUTF
F956 3620 FAFA 1001 9530 DEFW #110
9830 LD (HL),32
F958 DDEI FAFC 464E5220 9540 DEFM "FOR HELP"
8840 POF' IX
F95A CI 8850 POF' BC F804 AO 9550 DEFB #A0
F956 C9 B860 EST E805 1003 9560 MESS8 DEFW #310
8870 7 FB07 594E5520 9570 DEFM "YOU ARE IN EDIT MODE"
8880 FB18 8D 9580 MC9 DEFB #8D
8890 i F81C 1002 9590 MESS9 DEFW #210
F950 0000 8900 BCSAV DEFW 0 FB1E 594F5520 9600 DEFM "YOU JUST RAN OUT OF MEMORY"
F95E 0000 8910 CUPOS DEFW 0 F838 OD 9610 DEFB 13
F960 3175 8920 CHPOS DEFW 30001 F839 53415645 9620 DEFM "SAVE THE RECORDS OR SOMETHING"
F962 0000 8930 HLSAV DEFW 0 F856 1000 9630 DEFW #10
F964 0000 8940 IN_LIM DEFW 0 F858 80 9640 DEFB #8D
F966 30E2 9950 LIMIT DEFW 62000 F859 5748454E 9650 MESS10 DEFM "WHEN YOU ARE IN EDIT MODE"
F968 0000 8960 LOCCNT DEFW ii FE72 OD 9660 DEFB 13
F96A OO(IO 8970 LOCFND DEFW 0 FB73 50524553 9670 DEFM "PRESSING
F96C 00 8980 WFLAG DEED 0 FE7C 1002 9680 DEFW #210
F96D 3175 8990 MEMPOS DEFW 30001 F87E 4E4F5420 9690 DEFM "NOT "
F96F 2118 9000 CURSP DEFW #1821 F882 1000 9700 DEFW #010
F971 9010 SCHAR DEFS 33 F884 57494C4C 9710 DEEM "WILL FIND THE NEXT OCCURENCE OF THE LAST STRING"
F992 E10 9020 MESSM1 DEFB #80 F883 20202020 9720 DEFM " THAT WAS SOUGHT"
F992 80 9030 MESS DEFB #80 FBC6 ODOD 9730 DEFW #0DOD
F994 44654241 9040 ME551 DEFM "DeBASE COPYRIGHT SGK 1984" FEC8 1002 9740 DEFW #210
F9AD BD 9050 DEF8 #BD FBCA 414E4420 9750 DEFM "AND "
F9AE 1001 9060 MESS2 DEFW #110 FBCE 1000 9760 DEFW #010
F980 50524553 9070 DEFM "PRESS SPACE TO ABORT" FBDO 57494242 9770 DEEM "WILL INSERT A CHARACTER"
F9C4 OD 9080 DEFB 13 FBE7 OD 9780 DEFB 13
F9C5 5820544F 9090 DEEM "X TO ERASE OR N FOR NEXT RECORD" FEES 41542054 9790 DEFM "AT THE CURRENT CURSOR POSITION."
F9E4 1000 9100 DEFW #10 FC07 ODOD 9800 DEFW #0DOD
F9E6 9D 9110 DEFB #8D FC09 44454245 9810 DEFM "DELETE WILL REMOVE THE CHARACTER"
F9E7 1002 9120 MES53 DEFW #210 FC29 OD 9820 DEFB 13
F9E9 4E4E5420 9130 DEFM "NOT FOUND" FC2A 41542054 9830 DEEM "AT THE CURRENT CURSOR POSITION."
F9F2 1000 9140 DEFW #10 FC49 ODOD 9840 DEFW #0DOD
F9F4 8D 9150 DEF6 #8D FC48 49462054 9850 DEEM "IF THERE IS NO SPACE IN A RECORD"
F9F5 1001 9160 MESS4 DEFW #110 FC68 OD 9860 DEFB 13
F9F7 20202020 9170 DEFM " MENU" FC6C 594E5520 9870 DEFM "YOU ARE ALTERING USE THE INSERT"
FAOA ODOD 9180 DEFW #0DOD FC88 OD 9880 DEFB 13
FAOC 50524553 9190 DEFM "PRESS" FC8C 46554E43 9890 DEFM "FUNCTION TO MAKE SOME SPACE."
F511 ODOD 9200 DEFW #ODOD FCA8 °DOD 9900 DEFW #0000
FAI3 46202020 9210 DEFM "F TO FIND" FCAA 54484520 9910 DEFM "THE CURSOR KEYS ALLOW YOU TO"
FA21 ()DOD 9220 DEFW #ODOD FCC6 OD 9920 DEFE 13
FA23 45202020 9230 DEFM "E TO ERASE" FCC7 4D4F5645 9930 DEFM "MOVE THROUGH THE TEXT BUT YOU"
F532 ODOD 9240 DEFW #0DOD FCE4 OD 9940 DEFB 13
FA34 43202020 9250 DEEM "C TO CONTINUE SEARCH" FCE5 43414E4E 9950 DEFM "CANNOT GO BACK PAST AN ENTER."
FA4D ODOD 9260 DEFW #0000 FD02 ODOD 9960 DEFW #0DOD
FA4F 454E5445 9270 DEEM "ENTER TO MAKE ANOTHER ENTRY" FDO4 1004 9970 DEFW #410
FA6B ODOD 9280 DEFW #000D FD06 50524553 9980 DEEM "PRESS ENTER TO RETURN TO TEXT"
FA6D 53202020 9290 DEFM "S TO SAVE OR LOAD" FD23 1000 9990 DEFW #10
FA83 1000 9300 DEFW #10 FD25 8D 10000 DEFE #8D
F585 3D 9310 DEFB #8D FD26 5052455' 10010 MESSII DEFM "PRESS S TO SAVE L TO LOAD"
128 The Spectrum Operating System
FD3F BD 10020 DEFB #8D
F040 50524553 10030 MESS12 DEFM "PRESS M FOR M/DRIVE"
FD53 OD 10040 DEF6 13
FD54 4F522054 10050 DEFM "OR T FOR TAPE"
FD61 BD 10060 DEFB #8D
FD62 494E5055
F071 BD
FD72 BD
10070 ME8513 DEFM "INPUT FILE-NAME"
10080
10090 ZEND
DEF6 #8D
DEFT( #80
Index
Fass 2 errors: 00

*WARNING* RSWAF' absent


*WARNING* MSLRET absent

address bus 25, 62, 70 2898 13


address lines 63 3082 12
alegebraic functions 89 3435 5
A register 3438 5
calculator 82, 84 3545 4
Interface 1 76 3582 5
8K ROM routines 26-9, 34 3584 17
16K ROM routines 3, 9, 13, 22-4 3652 17
standard streams 67 3756 11
ASC II code 6, 42-5, 82-5 3789 11
Assembler program 1 3807 11
assembly language programming 1 5598 10
automatic listing 46-7 5606 18
5633 3, 6
BASIC 2-3, 5, 18-23, 46, 51, 75-9 5823 18
error 18, 20, 22, 83, 86, 88 8020 4
interpreter 42, 46, 49, 52, 88-90 8874 17
BASIC LIST command 51 8933 6
BBC microcomputer 25 9146 16
BC register pair 2 calling routine 43, 75
beep 11-12 CAPS LOCK 51
binary numbers 83 CAPS SHIFT 4, 11, 42-3
binimal point 80-1 carriage return 100
block graphics 15 carry flag 4, 10, 23-4, 26-7, 33-4, 83,
BREAK key 20 89
B register 4-6, 17 Catalogue Cartridge routine 35
buffer 11, 30, 32-3 Centronics 3, 65-6
channels 18, 30, 32, 62-9
calculator 80-92,104-6 channel type 60
CALL 10934 82 characters 8-10
CALL 11419 83 character set 99-101
CALL 11560 82 Chebyshev polynomial 92
CALL 11563 82 circles 15
op-codes 86-91 Close Microdrive channel routine 32
routines 104-6 Close Network channel routine 30
use of 86-92 colours 44, 55, 58, 64, 100
calculator stack 15-16, 18, 56, 82-92, command mode 76
105 Complete Spectrum ROM Disassembly
Call addresses 3-24 (Logan) 2
949 11 CONTINUOUS SOUND 73
2878 15 COORDS 15-17

130 The Spectrum Operating System Index 131

C register 6 Reclaim Microdrive Channel MOREX Interface 65, 106-7 microdrive output 31-2
current channel 18 (2Ch) 34 Motor on/Motors off routine 34 network output 28-30
ROM 2 (32h) 34 MREQ line 70 output 27-8
data bus 25 RS232 Input (1Dh) 26 ROM interpreter 75-7
Data Terminal Ready 28 RS232 Output (lEh) 27 network channel 28-9 RS232 Input routine 26
Run (32h) 36 Network Input routine 26 RS232 Output routine 27
DeBASE program 10, 13, 22, 24, 35,
Send Packet (30h) 29 NN command 2 RST
111-28
Write Record (26h) 32 numbers 6-8 10h 38
DE register 21
DEFined word 39-40 Write Sector (2Ah) 32 16(10h) 3-4
H' register 3 Open Channel/Open File routine 30 56 (28h) 8
DI instruction 72
Open Channel routine 26, 28 Run routine 36
IM1 mode 71 opening and closing streams 3 run time 77
EI instruction 71-2
IM2 mode 71
ENDCALC instruction 86 Picturesque Editor Assembler 1 SAVE/LOAD RETURN routine 21
indexing 84
Erase File routine 32 pixels 11, 17, 54, 73, 74, 96 saving 18-21
INPUT commands 52
E register 6 plotting to the screen 6 screen 6, 10
input routine 58
exponent 81 clearing 17
Inse rt Variables routine 34 ports
Interface 1 75-9 Kempston 66-7 lower 5
file name 60 Morex 65-6 scrolling 5, 17
interrupts 8-9, 11, 21, 41, 53, 70-4
floating point representation 80-2, 127 66 whole 5
interrupt vectors 102-3
91 screen copy 11
I register 70-3 231 62
Format Cartridge routine 35 239 62, 65 screen map 54
IX register 20-1, 23, 26-9, 32-4
IY register 2, 3, 9, 15, 42 247 62, 65 scrolling 5, 17
Get Key routine 26-7 251 62,64-5 Send Packet routine 29
graphics 11, 13, 15 Kempston Interface 3, 65, 106-7 254 62-4 shadow ROM 25, 40
keyboard 8-9 57535 66 Sinclair BASIC 25-6
header 18-24,29,59 map 98 58047 66 small integer representation 80
dummy 22-3 scanning 43, 63 58303 66 Spectrum Machine Language for the
microdrive 36-41 key-debouncing routine 43 PRINT command 2 Complete Beginner (Zaks) 2
hex to decimal conversions 93-4 Key Input routine 10 printer 11, 45, 65 Spectrum Pocket Book 7
Highsoft's Devpack 3-4 Keyscan routine 34 buffer 11, 51, 53 SPRITE 73-4
HL register 40 print positions 4-5 standard streams 66-7
hook codes 25-36 LET command 2 Print to Printer routine 27 start-up sequence 70
Catalogue Cartridge (32h) 35 line-drawing 16 Print to Screen routine 27 stream number 60
Close Microdrive Ch an nel line feed code 28 Programming the Z80 (Zaks) 2 string operations 92
(23h) 32 LOAD BYTES subroutine 22 subroutines 36, 38, 84, 104-28
Close Network Channel (2Eh) 30 loading 18-24 random numbers 52 calculator routines 104-6
Erase File (24h) 32 L' register 3 Read Next Print Record routine 33 DeBASE 11-28
Format Cartridge (32h) 35 Read Next Record Sector routine 33 interrupt driven sprite
Get Key (1Bh) 26 machine code program 1, 2, 38, 55, Read Print Record routine 33 routine 107-11
Insert Variables (31h) 34 80, 83 Read Record Sector routine 33 Kempston Interface 106-7
Keyscan (20h) 34 machine crash 38 Reclaim Microdrive Channel Morex Interface 106-7
Motor on/Motors off (21h) 34 mantissa 81, 91 routine 34 syntax checking 88
Network Input (2Fh) 26 memory 25, 42 record deletion 111 syntax flag 75
Open Channel (2Dh) 28 memory map 95-7 repeating key routine 43 syntax/run flag 35
Open Channel/Open File (22h) memory request line 70 ReSTarts 38-41 system variables 1, 42-61
30-1 message printing 12-13, 21 RET inst ru ction 40 8K system 56-61
Print to Printer (1Fh) 27 Microdrive 30-1, 56, 72, 74, 111 RETI inst ru ction 71-2 16K system 42-56
Print to Screen (1Ch) 27 channel 33, 36 ROM 2 routine 34 ALI R P 55
Read Next Print Record (25h) 33 header 36-41 ROM, 8K 25-41 A1 1RT 55
Read Print Record (27h) 33 Interface 1, 62, 67 inputs 26-7 BAUD 26, 57-8, 60
Read Next Record Sector (29h) 33 microphone socket 64 microdrive header 36-41 BORDCR 48
Read Record Sector (28h) 33 MODE CHANGE flag 10 microdrive input 33-6 BREG 50
132 The Spectrum Operating System

CH ADD 49 N_STR1 60
CH_ADD 75-66, 83 NI 1 YPE 59
CHADD_ 58 NXTLIN 49
CHANS 48 OLDPPC 51
CHARS 44 OSPCC 51
COORDS 53 P FLAG 55
COPIES 61 PIP 45
CURCHL 10, 18, 48 PPC 47
DATADD 49 P POSN 53
DEFADD 44 P_RAMT 56
DEST 48 PR CC 53
DF CC 54 FROG 49
DFCCL 54 RAMTOP 56, 67
DFSZ 51 RASP 45
DSTRI 60 REPDEL 43
DSTR2 61 REPPER 42-4
ECHO E 54 S BRT 57
E LINE 48-9 SCR CT 54
EPPC 48 SECTOR 58
ERR NR 45 SEED 52
ERR SP 46 SEED_FL 58
FLAGS 45 S POSN 54
FLAGS 2 50 SPOSNL 54
FLAGS 3 57 S TOP 51
FLAGX 51 STRLEN 52
FRAMES 52 STRMS 44
HD_OB 61 SSTR1 60
HD_OD 61 STKBOT 50
HD_OF 61 STKEND 50
HD_00 61 SUBPPC 47
HD_11 61 T ADDR 52
IOBORD 58 T_STR1 60
K CUR 49, 67 TVDATA 44
KDATA 44 TVFLAG 46
KSTATE 42 UDG 53
LAST K 43 VARS 48
LIST SP 46 VECTOR 57, 75-6
L_STR1 60 WORKS P 50
MASK P 55 X PTR 49
MASK T 55
MEM 50 tape socket 64
MEMBOT 56 tape-loading error 24
MODE 47 token code 13
NEWPPC 47
NOT USED 53 ULA 70
NSPPC 47
NTDCS 59 verifying 21-4
NTDEST 59
Wait Input routine 10
NTHCS 59
Wait Key routines 21
NTLEN 59
workspace 18
NTNUMB 59
Write Record routine 32
NTRESP 59
Write Sector routine 32
NTSRCE 59
NTSTAT 58 Z80 6, 70, 72, 86

You might also like