SOFT968 - The Amstrad 6128 Firmware Manual

Download as pdf or txt
Download as pdf or txt
You are on page 1of 482

CPC464/664/6128

FIRMWARE
ROM routines and explanations
Bruce Godden and Paul Overell, Locomotive Software
David Radisic, Amstrad
CAS CATALOG CAS CHEGK CAS IN ABANDON CAS IN CHAR CAS IN CLOSE CAS IN DIRECT CAS IN OPEN CAS
INITIALISE CAS NOISY CAS OUT ABANDON CAS OUT CHAR CAS OUT CLOSE. CAS READ CAS RESTORE MOTOR
CAS RETURN CAS SET SPEED CAS START MOTOR CAS STOP MOTOR CAS TEST EOF CAS WRITE GRA ASK
CURSOR GRA GLEAR WINDOW GRA GET ORIGIN GRA GET PAPER GRA GET PEN GRA GET W HEIGHT GRA GET
W WIDTH GRA INITIALISE GRA LINE ABSOLUTE GRA LINE RELATIVE GRA MOVE ABSOLUTE GRA MOVE
RELATIVE GRA PLOT ABSOLUTE GRA PLOT RELATIVE GRA RESET GRA SET ORIGIN GRA SET PAPER GRA SET
PEN GRA TEST ABSOLUTE GRA TEST RELATIVE GRA WIN HEIGHT GRA WIN WIDTH GRA WR CHAR KL CURR
SELECTION HI KL L ROM DISABLE HI KL L ROM ENBLE HI KL LDDR HI KL LDIR HI KL POLL SYNCHRONOUS HI KL
PROBE ROM HI KL ROM DESELECT HI KL ROM RESTORE Hl KL ROM SELECT HI KL U ROM DISABLE HI KL U ROM
ENABLE IND GRA LINE IND GRA PLOT IND GRA TEST IND KM TEST BREAK IND MC WAIT PRINTER IND SCR READ
IND SCR WRITE IND TXT DRAW CURSOR INDTXT OUT ACTION IND TXT UNDRAW CURSOR INDTXT UNWRITE IND
TXT WRITE CHAR KL ADD FAST TICKER KL ADD FRAME FLY KL ADD TICKER KL CHOKE OFF KL DEL FAST
TICKER KL DEL FRAME FLY KL DEL SYNCHRONOUS KL DEL TICKER KL DISARM EVENT KL DO SYNC KL DONE
SYNC KL EVENT DISABLE KL EVENT ENABLE KL FIND COMMAND KL INIT BACK KL INIT EVENT KL LOG EXT KL
NEW FAST TICKER KL NEW FRAME FLY KL NEXT SYNC KL ROM WALK KL SYNC RESET KL TIME PLEASE KL TIME
CONTROL KM GET DELAY KM GET EXPAND KM GET JOYSTICK KM GET REPEAT KM GET SHIFT KM GET STATE
KM GET TRANSLATE KM INITIALISE KM READ CHAR KM READ KEY KM RESET KM SET CONTROL KM SET DELAY
KM SET EXPAND KM SET REPEAT KM SET SHIFT KM SET TRANSLATE KM TEST KEY KM WAIT CHAR KM WAlT
KEY EXT INTERRUPT LOW FAR GALL LOW FRM JUMP LOW INTERRUPT ENTRY LOW KL FAR CALL LOW KL FAR
PCHL LOW KL LOW PCHL LOW KL SIDE PCHL LOW LOW JUMP LOW PCDE INSTRUCTION LOW PCHL
INSTRUCTION LOW RAM LAM LOW RESET ENTRY LOW SIDE CALL LOW USER RESTART MC BOOT PROGRAM
MC BUSY PRINTER MC CLEAR INKS MC JUMP RESTORE MC PRINT CHAR MC RESET PRINTER MC SCREEN
OFFSET MC SEND PRINTER MC SET INKS MC SET MODE MC SOUND REGISTER MC START PROGRAM MC WAIT
FLYBACK SCR ACCESS SCR CHAR INVERT SCR CHAR LIMITS SCR CHAR POSITION SCR CLEAR SCR DOT
POSITION SCR FILL BOX SCR FLOOD BOX SCR GET BORDER SCR GET FLASHING SCR GET INK SCR GET
LOGATION SCR HORIZONTAL SCR INITIALISE SCR INK DECODE SCR INK ENCODE SCR NEXT BYTE SCR NEXT
LINE SCR PIXELS SCR PREV BYTE SCR PREV LINE SCR REPACK SCR RESET SCR SET BASE SCR SET BORDER
SCR SET FLASHING SCR SET INK SCR SET MODE SCR SET OFFSET SCR SW ROLL SCR UNPACK SCR
VERTICAL SOUND A ADDRESS SOUND AMPL ENVELOPE SOUND ARM EVENT SOUND CHECK SOUND CONTINUE
SOUND HOLD SOUND QUEUE SOUND RELEASE SOUND RESET SOUND T ADDRESS SOUND TONE ENVELOPE
TXT CLEAR WINDOW TXT CUR DISABLE TXT CUR ENABLE TXT CUR OFF TXT CUR ON TXT GET BACK TXT GET
CONTROLS TXT GET CURSOR TXT GET M TABLE TXT GET MATRIX TXT GET PAPER TXT GET PEN TXT GET
WINDOW TXT INITIALISE TXT INVERSE TXT OUTPUT TXT PLACE CURSOR TXT RD CHAR TXT REMOVE CURSOR
TXT RESET TXT SET BACK TXT SET COLUMN TXT SET CURSOR TXT SET GRAPHIC TXT SET M TABLE TXT SET
MATRIX TXT SET PAPER TXT SET PEN TXT SET ROW TXT STR SELECT TXT SWAP STREAMS TXT VALIDATE TXT
VDU DISABLE TXT VDU ENABLE TXT WIN ENABLE TXT WR CHAR KM SET LOCKS KM FLUSH TXT ASK STATE GRA
DEFAULT GRA SET BACK GRA SET FIRST GRA SET LINE MASK GRA FROM USER GRA FILL SCR SET POSITION
MC PRINT TRANSLATION KM SCAN KEYS

Published by
Amstrad Consumer Electronics plc
Brentwood House
169 Kings Road
Brentwood
Essex

All rights reserved


First edition 1986

Reproduction or translation of any part of this publication without the written permission of the copyright owner is unlawful,
Amstrad and Locomotive Software reserve the right to amend or alter the specification without notice. While every effort has heen
made to verify that this complex software works as descrihed, it is not possible to test any program of this complexity under all possible
conditions Therefore the program and this manual are provided “as is” without warranty of any kind, either express or
implied.
IBM is a trademark of International Business Machines Corporation.
CP/M. CP/M Plus and Dr Logo are trademarks of Digital Research Inc.

SOFT 968 Copyright © 1986 Locomotive Software Ltd and Amstrad Consumer Electronics plc
The Contents.
1 The Firmware.
1.1 The Hardware.
1.2 The Division of the Firmware.
1.3 Controlling the Firmware.
1.4 Jumpblocks.
1.5 Conventions.
1.6 Routine Documentation.
1.7 Example of Patching a Jumpblock

2 ROMs, RAM and the Restart Instructions.


2.1 Memory Map.
2.2 ROM Selection.
2.3 The Restart Instructions.
2.4 RAM and the Firmware.
2.5 Bank Switching.

3 The Keyboard.
3.1 Keyboard Scanning.
3.2 Key Translation.
3.3 Characters from the Keyboard.
3.4 Shift and Caps Lock.
3.5 Repeating keys.
3.6 Breaks.
3.7 Function Keys and Expansion Tokens.
3.8 Joysticks.

4 The Text VDU.


4.1 Text VDU Coordinate Systems.
4.2 Streams.
4.3 Text Pen and Paper Inks.
4.4 Text Windows.
4.5 The Current Position and the Cursor.
4.6 Characters and Matrices.
4.7 Character Output and Control Codes.

5 The Graphics VDU


5.1 Graphics VDU Coordinate Systems.
5.2 The Current Graphics Position.
5.3 Graphics Pen and Paper Inks.
5.4 Graphics Write Mode.
5.5 Graphics Window.
5.6 Writing Characters.
5,7 Drawing Lines.
5.8 Filling Areas.
6 The Screen.
6.1 Screen Modes.
6.2 Inks and Colours.
6.3 Screen Addresses.
6.4 Screen Memory Map.

7 The Sound Manager.


7.1 The Sound Chip.
7.2 Tone Periods and Amplitudes.
7.3 Enveloping.
7.4 Sound Commands.
7.5 Sound Queues.
7.6 Synchronisation.
7.7 Holding Sounds.

8 The Cassette Manager.


8.1 File Format.
8.2 Record Format.
8.3 Bit Format.
8.4 The Header Record.
8.5 Read and Write Speeds.
8.6 Cataloguing.
8.7 Reading Files.
8.8 Writing Files.
8.9 Reading and Writing Simultaneously.
8.10 Filenames.
8.11 Cassette Manager Messages.
8.12 Escape Key.
8.13 Low Level Cassette Driving.

9 AMSDOS
9.1 Features
9.2 Filenames
9.3 File Headers
9.4 Disc Organisation
9.5 Boot Sector
9.6 AMSDOS Messages
9.7 BIOS Facilities Available to AMSDOS
9.8 Store requirements
9.9 Extended Disc Parameter Blocks
10 Expansion ROMs, Resident System Extensions and
RAM Programs.
10.1 ROM Addressing.
10.2 The Format of an Expansion RUM.
10.3 Foreground ROMs and RAM Programs.
10.4 Background RUMs.
10.5 Resident System Extensions.
10.6 External Commands.
10.7 Examples.

11 Interrupts.
11.1 The Time Interrupt.
11.2 External Interrupts.
11.3 Nonmaskable Interrupts.
11.4 Interrupts and Events.
11.5 Interrupt Queues.

12 Events.
12.1 EventClass.
12.2 Event Count.
12.3 Event Routine.
12.4 Disarming and Reinitializing Events.

13 The Machine Pack.


13.1 Hardware Interfaces.
13.2 The Printer.
13.3 Loading and Running Programs.

14 Firmware Jumpblocks.
14.1 The Main Jumpblock.

14.1.1 Entries to the Key Manager.


14.1.2 Entries to the TextVDU.
14.1.3 Entries to the Graphics VDU.
14.1.4 Entries to the Screen Pack.
14.1.5 Entries to the Cassette Manager.
14.1.6 Entries to the Sound Manager.
14.1.7 Entries to the Kernel.
14.1.8 Entries to the Machine Pack.
14.1.9 Entries to Jumper.
14.1.10 FurtherEntries.
14.2 Firmware Indirections.

14.2.1 Text VDU Indirections.


14.2.2 Graphics VDU Indirections.
14.2.3 Screen Pack Indirections.
14.2.4 Keyboard Manager Indirections.
14.2.5 Machine Pack Indirections.
14.2.6 Further Indirections.

14.3 The High Kernel Jumpblock.


14.4 The Low Kernel Jumpblock.

15 The Main Firmware Jumpblock.


16 The Firmware Indirections.
17 Kernel High Entries.
18 Low Entries to the Kernel.
19 AMSDOS ‘BIOS’ Facilities
20 AMSDOS External Commands
Appendices

I Key Numbering.

II Key Translation Tables.

III Repeating Keys.

IV Function Keys and Expansion Strings.

V Inks and Colours.

VI Displayed Character Set.

VII Text VDU Control Codes.

VIII Notes and Tone Periods.

IX The Programmable Sound Generator.

X Kernel Block Layouts.

XI The Alternate Register Set.

XII Hardware and Hardware Variants.

XIII Hints, Tips, and Workarounds.

XIV Printer Translation Tables.


Preface.
The computers in the CPC range contain ROMs which hold the BASIC
interpreter and the firmware’. The firmware consists of low level routines
responsible for driving the hardware, handling the screen, handling real-time
events and other similar functions. This manual describes the firmware.

This manual is applicable to the full range of CPC machines; 464, 664, 6128
and 464+ DDI-1. The firmware in these machines is not identical. All 464s
contain V1.0 of the firmware, all 664s contain V1.1 and all 6128s contain
V1.2. All firmware calls are upwards compatible, that is, any firmware call
available in V1.0 is available in V1.1 and V1.2 and any firmware call available
in V1.1 is available in V1.2. Upwards compatibility will be maintained in any
future versions of the firmware.

As stated above this manual relates only to the firmware section of the ROMs.
Other AMSOFT publications describe the BASIC interpreter though not at a
system level and the various implementations of CP/M. However, the areas in
which CP/M and the firmware interact are covered in this manual. Also, areas
of the firmware that are affected by the addition of a disc interface are covered
in this manual.
1 The Firmware.
This manual describes the firmware of the Amstrad CPC 464/664/6128
microcomputers. It also describes the disc operating systems (CP/M and
AMSDOS). It does not describe either the BASIC language supplied with the
system or CP/M. The manual does describe certain aspects of the BASIC
where these affect other programs and it uses BASIC in certain example
programs when describing some features of the firmware. It also describes how
to call the firmware from CP/M.
Three versions of the firmware are described. V1.0 (on CPC464), V1.1 (on
CPC664) and V1.2 (on CPC6128). Apart from support for bank switching V1.1
and V1.2 are identical and are referred to as V1.1 throughout this manual. It
may be necessary for a program to deduce which firmware is fitted in a
computer, and this can be achieved by inspecting the on-board ROM’s version
number (as described in section 10.2) using KL ROM PROBE. This will return
a 0, 1 or 2 depending on the version of firmware.
The firmware is the program that resides in the lower ROM and the disc
controlling ROM (see section 2). Its function is to control the hardware of the
computer and to provide useful facilities for other programs to use. This avoids
every program written having to provide its own facilities.
This manual is expected to be of interest to anyone who would like to know
how the system works. It is indispensable for programmers writing machine
code programs, particularly system programs (e.g. other languages) and games.
The information presented can be extremely detailed. It covers the operation of
the firmware from the lowest level (e.g. driving the sound chip) to the highest
level (e.g. running a queue of sounds). It is not necessary to understand all the
information given to be able to use the firmware, however, a good grasp of
how the system works will aid the programmer in selecting the most
appropriate method for performing a particular task.
Two disc operating systems are provided: AMSDOS, which enables BASIC
programs to use disc files in much the same way as cassette files; and CP/M
2.2 the industry standard operating system (CP/M Plus in the CPC6128, but we
do not discuss the differences between the two in this manual). Both AMSDOS
and CP/M use the same file structure and may read and write each others file’s.
CP/M is invoked from BASIC by typing |CPM. Part of CP/M (the CCP and
BDOS) is loaded from the disc in drive A:. The CP/M BIOS resides in the disc
ROM.
AMSDOS is enabled whenever BASIC is first used. This intercepts most of the
cassette firmware routines and redirects them to disc. Thus existing BASIC
programs which use cassette files can use disc files with little or no
modification. AMSDOS also provides a number of external commands for
erasing and renaming files and redirecting the cassette firmware routines.
Provided with the disc system are a number of utility programs for formatting
and copying discs and for changing various system parameters. These all run
under CP/M.
1.1 The Hardware.
The diagram on the following page gives an indication of the different pieces
of hardware in the system and how they connect to each other. For more
information on how the hardware works see Appendix XII and the relevant
manufacturer’s data sheets.
The system centres around the CPU (Central Processing Unit) which is a
Z8OA microprocessor with a 4MHz clock. Next in importance is the gate array
which contains miscellaneous logic to control much of the system. In
particular, it controls ink colours, screen mode and ROM enabling (see section
10 and Appendix XII). In conjunction with the CRTC (Cathode Ray Tube
Controller), which is a 6845 chip, the gate array generates the video signals for
the monitor.
The PSG (Programmable Sound Generator) is an AY-3-8912. This chip has
three channels of sound generator, a noise generator, envelope control for each
channel and an I/O port. The way the sound generating hardware is used is
described in section 7. The I/O port is used in input mode to sense the state of
the keyboard and joystick switches.
The FDC (Floppy Disc Controller) is an NEC µPD765A chip. Only two disc
drives are supported, since the US1 line from the µPD765A is ignored. This
results in the two disc drives being accessed as drives 0 and 1 and again as 2
and 3. The FDC supports both single and double sided and single and double
density mini-floppy disc drives. Note that the clock frequency supplied to the
µPD765A CLK pin is 4MHz rather than the 8 MHz used with larger disc
drives.
Each disc drive takes a single 3” floppy disc. Either side of the disc may be
used, depending on which way up the disc is inserted into the drive. The disc
interface contains a 16K expansion ROM, 8K of which contains the disc
driving software, the remainder being used by DR LOGO.
The PPI (Parallel Peripheral Interface), which is an 8255 chip, is used to
control the remainder of the system. It has three ports. Port C is used as an
output port to control the cassette recorder motor, to write data to the cassette,
to strobe data in or out of the PSG and to select rows of the keyboard. Port B is
used as an input port to sense the frame flyback signal, the Centronics port
busy signal and various option links arid to read data from the cassette. Port A
is used to communicate with the PSG and is set into input or output mode as
required.
Accesses to memory are synchronised with the video logic - they are
constrained to occur on microsecond boundaries. This has the effect of
stretching each Z80 M cycle (machine cycle) to be a multiple of 4 T states
(clock cycles). In practice this alters the instruction timing so that the effective
clock rate is approximately 3.3 MHz.
Monitor Gate Array

Speakers CRTC RAM

CPU

PSG ROM

PPI

Keyboard Centronics
and FDC
Joysticks Port

Cassette Recorder Disc Drives

1.2 The Division of the Firmware.


The firmware is split into ‘packs’ each dealing with a particular part of the
system, usually a hardware device. Each pack has a section of this manual
devoted to it where its operation is explained in detail. The system components
and their associated packs are:

Keyboard: Key Manager.


Screen: Text VDU, Graphics VDU, Screen Pack.
Cassette/Disc: Cassette Manager/AMSDOS.
Sound: Sound Manager.
Operating System: Kernel, Machine Pack, Jumper.
a. Key Manager

The Key Manager is more fully described in section 3. It deals with scanning
the keyboard, generating characters, function keys, testing for break and
scanning the joysticks.

b. Text VDU

The Text VDU is more fully outlined in section 4. It deals with putting
characters on the screen, the cursor and obeying control codes.

c. Graphics VDU

The Graphics VDU is more fully presented in section 5. It deals with plotting
points, testing points drawing lines and filling areas on the screen.

d. Screen Pack

The Screen Pack is more fully detailed in section 6. It interfaces the Text and
Graphics VDUs with the screen hardware and deals with aspects of the screen
that affect both of these packs, such as screen mode or ink colours.

e. Sound Manager

The Sound Manager is more fully discussed in section 7. It deals with


queueing, enveloping, synchronising and generating sounds.

f. Cassette Manager/AMSDOS

The Cassette manager is more fully explained in section 8. It deals with reading
from tape, writing to tape and cassette motor control.
AMSDOS is explained more fully in section 9. It deals with reading from disc,
writing to disc and the disc motor control.

g. Kernel

The Kernel is more fully described in sections 2, 10, 11 and 12. It is the heart
of the operating system and deals with interrupts, events, selecting ROMs and
running programs.

h. Machine Pack

The Machine Pack is more fully documented in section 13. It deals with the
printer and the low level driving of the hardware.

i. Jumper

Jumper, or rather, the main firmware jumpblock is listed in section 14. The
entries in the jumpblock are described in detail in section 15. Jumper sets up
the firmware jumpblock.
1.3 Controlling the Firmware.
The firmware is controlled by the user calling published routines rather than by
the user setting the values of system variables. This will allow the firmware’s
variable layout to be changed in major ways without the user being affected.

The addresses of the routines the user is to call need to remain constant if the
firmware is altered. This is achieved by using jumpblocks (see below).

The advantage of a routine interface is that it allows a number of different


system variables to be altered by the firmware in a consistent way in one
operation. If the system variables had to be set by the user then the firmware
could be left in an indeterminate state if some variables had been set but not
others. Also, the routine type of interface ensures that all the required side
effects of a change are taken care of automatically without the user being
troubled with all the details. An example of this is changing the screen mode
(see section 6.1)- changing the size of the screen requires a number of other
people to be informed of the change so that illegal screen positions and inks are
not used.

1.4 Jumpblocks.
A jumpblock is a series of jump instructions placed in memory at well-known
locations. The jumps are to the various routines in the firmware that the user
might want to call. Programs that need to use the facilities provided by the
routines in the jumpblock should call the appropriate jumpblock entries.

If the firmware is altered then it is quite likely that the addresses of some of the
routines available to the user will change. By keeping the address of the
jumpblock constant but altering the entries in the jumpblock so that they jump
to the new addresses of the routines, the change is hidden from the user
(providing that the user is only calling routines via the jumpblock and is not
accessing the firmware directly).

To make the change to the firmware completely hidden from the user it is also
necessary to keep the entry and exit conditions of the routines accessed via the
jumpblock constant. The greater part of this manual is taken up with the
detailed entry and exit requirements of the jumpblock entries.

The jumpblock is placed in RAM so that the user can alter the entries in it. This
allows the user to trap particular entries and to substitute a new routine that will
replace the standard firmware routine. Provided that the new routine obeys the
entry and exit requirements of the firmware routine, the substitution will not
upset programs unaware of the change.
There are four jumpblocks. These are all listed in section 14. The first and
largest jumpblock is the main firmware jumpblock (see sections 14.1 and 15).
This allows the user to call most firmware routines. The second jumpblock is
the indirections jumpblock (see sections 14.2 and 16). The entries in this
jumpblock are used by the firmware at key moments in order to allow the user
to alter the action of the firmware. The last two jumpblocks are rather special.
They are to do with the Kernel and allow ROMs to be enabled and routines in
ROMs to be called. (See sections 14.3, 14.4, 17 and 18).

Section 1.7 below gives an example of how a jumpblock entry might be


changed to alter the action of the firmware.

1.5 Conventions.
a. Notation

Processor instructions are generally referred to by their standard Z80


mnemonics. The exceptions that prove the rule are the restart instructions. The
mnemonics RST 0 .. RST 7 are used rather than the more usual Z80
mnemonics RST #00 .. RST #38.

The registers are also referred to by their standard Z80 names. The flag register
as a whole is referred to as F but the individual flags are called by their full
name, e.g. carry. The flags are said to be true when they are set and false when
they are clear. Thus a JP NC instruction would jump if carry was false and not
if carry was true.

Hexadecimal numbers are indicated by prefixing the number with #, thus # 7F


is the number 127 in hex. All numbers not prefixed by # are in decimal.

Large numbers are often abbreviated by writing them as a multiple of 1024.


For example, 32K bytes means 32 times 1024 (i.e. 32768) bytes.

b. Usage

Routines, where possible, take and return values in registers. Where more
information than may be held in registers is to be passed to a routine, the
address of a data area is given. The location in memory of these data areas is
sometimes critical, see section 2.4.

Where a routine can succeed or fail this condition is normally passed back in
the carry flag. Carry true normally implies success, whilst carry false normally
implies failure.

The alternate register set, AF’ BC’ DE’ HL’, is reserved for use by the system.
The user should not execute either an EX AF,AF’ or an EXX instruction as
these will have unfortunate consequences. (See Appendix XI for a full
description.)
c. General

The logical values true and false are generally represented by # FF and #00
respectively. Often, however, any non-zero value is taken to mean true.

The bits in a byte are numbered 0..7, with bit 0 being the least significant bit
and bit 7 being the most significant bit.

Where two byte (word) values are stored (in tables ete) they are always stored
with the less significant byte first and the more significant byte second, unless
a specific indication to the contrary is given. This is in accordance with the
standard way the Z80 stores words.

Tables and the like are always laid out with byte 0 being the first byte of the
table. When the address of such a table is given this is the address of byte 0 of
the table unless otherwise indicated.

When the computer is turned on (or when it is reset) it completely initializes


itself before running any program. This initialization is known as early
morning startup, abbreviated to EMS from now on.

1.6 Routine Documentation.


Each routine described in this manual has entry and exit conditions associated
with it. Where there are other points of interest about the routine these are
normally given in a section after the entry and exit conditions. Such points
include whether interrupts are enabled and a fuller description of the
parameters and side effects of the routine.

There are two reasons for providing this information. Firstly it tells the user
what will happen when the routine is called. Secondly it tells the user what a
replacement routine is expected to do.

The entry conditions tell the caller of the routine what the routine expects
to be passed to it. When calling a routine all values specified must ‘be
supplied. Values may only be left out where the routine documents that
they are optional. When providing a replacement routine to fit this
interface only information that is specified may be used, although not all
of it need be used.

The exit conditions tell the caller what values the routine passes back and
which processor registers are preserved. Registers that are documented as
being corrupted may be changed by the routine or may not. The user
should not rely on their contents. When providing a routine to fit this
interface it is extremely important that registers documented as being
preserved are indeed preserved and that the values returned are
compatible with the original routine. Corrupting a register or omitting a
result will usually cause the system to fail, often,in subtle and unexpected
ways.
Often a routine will have different exit conditions depending on some
condition or other (usually whether it worked or not). In these cases the
specific differences in the exit conditions are given for each case and all
conditions that remain the same irrespective of the case are given in a
separate section (marked ‘always’).
There are abundant examples of routine interfaces in sections 15 to 18.

1.7 Example of Patching a Jumpblock.


The following is an example of how the jumpblocks may be used. At this stage
many of the concepts introduced may be unfamiliar to the reader. However,
since altering jumpblocks is an important technique for tailoring the system to
a particular purpose the example is given here. Later sections will explain the
actions taken here.

Suppose an assembler program is being written that is intended to use the


printer when it is finished. While this program is being written it would save
time and paper if the program could be made to use the screen instead of the
printer. However, changing the program itself to use the screen could introduce
bugs when it is changed back to using the printer. What is needed is a way of
altering the action of the firmware that drives the printer - and this is what a
RAM jumpblock is for.

The technique that will be used is to ‘connect’ the printer to a particular text
window. This can be achieved by writing a short routine to send the character
to the screen and patching the entry in the jumpblock for sending characters to
the printer, MC PRINT CHAR, so that it jumps to this routine instead of its
normal routine.

The substitute routine will have to obey the entry/exit conditions for MC
PRINT CHAR. These can be found in the full description of this entry in
section 15. Briefly they are as follows:

MC PRINT CHAR:

Entry conditions:

A contains character to print.

Exit conditions:

If the character was sent OK:


Carry true.

If the printer timed out:


Carry false.

Always:
A and other flags corrupt.
All other registers preserved.

The action of the substitute routine will be to select the screen stream that the
printer output is to appear on, to print the character on the stream and then to
restore the stream that was originally selected. To do this the substitute routine
will need to call the routines TXT STR SELECT and TXT OUTPUT. Once
again the full descriptions of these jumpblock entries can be found in section
15. The entry/exit conditions are as follows:
TXT STR SELECT:

Entry conditions:

A contains stream number to select.

Exit conditions:

A contains previously selected stream number.


HL and flags corrupt.
All other registers preserved.

TXT OUTPUT:

Entry conditions:

A contains character to print.

Exit conditions:

All registers and flags preserved.

The code for the substitute routine could be written as follows (stream 7 has
been chosen as the stream on which printer output is to appear):

PUSH HL
PUSH BC
LD B, A ;Save the character to print
LD A, 7 ;Printer stream number
CALL TXT_STR.SELECT ;Select the printer stream
LD C, A ;Save the original stream number
LD A, B ;Get the character again
CALL TXT_OUTPUT ;Send it to the screen
LD A, C ;Get the original stream number
CALL TXT_STRSELECT ;Reselect the original stream

POP BC
POP HL
SCF ;The character was sent OK
RET
Note the following points:

1/ MC PRINT CHAR preserves HL and BC. The routine above uses B and
C for temporary storage and HL is corrupted by TXT STR SELECT. HL
and BC are therefore pushed and popped to preserve them through the
substitute routine.

2/ MC PRINT CHAR returns a success/fail indication in the carry flag.


Since the routine above can never fail it always sets the carry flag to
indicate success.

3/ The routine above does not change which text stream is selected. It selects
the stream it is going to print on and restores the previously selected
stream when it has printed the character. The firmware is written in such a
way as to allow routines to restore the original state when they finish if
required.

To use the substitute routine it is necessary to patch it into memory and to


change the jumpblock entry for MC PRINT CHAR to jump to it. Assume that
some memory at #ABOO has been reserved for the substitute routine and that
the routine has been patched into memory. The MC PRINT CHAR entry in the
jumpblock is at location #BD2B (as can be seen by inspecting section 13.1.8).
The three bytes of the entry should be set to the instruction JP # ABOO by
patching as follows:

#BD2B #C3
#BD2C #00
#BD2D #AB

From now on all text sent to the printer will appear on the screen on stream 7.
Of course, stream 7 should have its window set so that it does not interfere with
any other streams using the screen.

This redirection will remain in force until the jumpblock entry is restored. This
can be achieved by patching the jumpblock back again or by calling JUMP
RESTORE or by causing an EMS initialization to take place by resetting the
system.
2 ROMs, RAM and the Restart
Instructions.
The system has 32K of ROM and 64K of RAM in the Z80’s 64K address
space. To allow this the ROM can be enabled or disabled as required.
Additional expansion ROMs can be selected giving up to 4128K of program
area.

All the Z80 restart instructions, except for one, have been reserved for system
use. RST 1 to RST 5 are used to extend the instruction set by implementing
special call and jump instructions that enable and disable ROMs. RST 6 is
available to the user.

2.1 Memory Map.


The memory map is complicated by the fact that into the Z80’s address space
of 64K bytes has been squeezed 64K bytes of RAM, 32K bytes of ROM and
provision for ROM expansion of up to 252*16K (nearly 4M) bytes. The
address space is divided as follows:

The sizes of the two background areas depend on the background ROMs fitted
to the machine (see section 10).
The upper foreground data area need not have its lower bound at # ACOO but
this is the default setting (as used by BASIC). The lower foreground data area
need only be reserved if it is needed (this area is not used by BASIC and is set
to zero length). The memory pooi left between the background data areas is
also for the foreground program to use (see section 10).

The 32K of on-board ROM is split into two sections which are handled
separately. Henceforth these will be discussed as if they were separate ROMs.
The firmware resides in the lower ROM. The BASIC resides in the upper
ROM. This upper ROM is bank switched so that up to 252 expansion ROMs
(see section 10) can replace it in the memory map.

2.2 ROM Selection.


There are two mechanisms for switching ROMs in and out of the address
space:

a. ROM State.

The upper and lower ROMs may be enabled and disabled separately.
When the upper ROM is enabled data read from addresses between
#C000 and #FFFF is fetched from the ROM. Similarly, when the lower
ROM is enabled data read from addresses between #0000 and #3FFF is
fetched from the ROM. When the ROMs are disabled data is fetched from
RAM.
Note that the ROM state does not affect writing which always changes the
contents of RAM.

b. ROM Select.

Expansion ROMs are supported by switching the upper ROM area


between ROMs. Expansion ROMs are addressed by a separate ROM
select address byte implemented in I/O space. ROM select addresses are
in the range 0...251, providing for up to 252 expansion ROMs.

When the machine is first turned on it selects ROM zero. This will usually
select the on board ROM, but an expansion ROM may be fitted at this
address, which will pre-empt the on-board ROM.
See section 10 for a description of the use of expansion ROMs.

2.3 The Restart Instructions.


The Kernel supports the store map in a number of ways. In particular a variety
of facilities are provided to handle subroutine addresses extended to include
ROM select and/or ROM state information. Some of the restart instructions are
used to augment the existing Z80 instruction set. The other restarts are
reserved.
The firmware area between #0000 and #003F is set up so that the restarts
operate whatever the current ROM state is. The user should not alter the
contents of this area except as indicated in section 18.

The restarts are as follows. A fuller description of their operation can be found
in section 18.

a. The Extended Instruction Set.


LOW JUMP (RST 1)
RST 1 jumps to a routine in the lower 16K of memory. The two bytes
following
the restart are assumed to be a ‘low address’ - so RST 1 can be considered
to be a three byte instruction, rather like a JP instruction.
The top 2 bits of the ‘low address’ define the ROM enable/disable state
required; the bottom 14 bits give the actual address (in the range #0000 to
#3FFF) to jump to once the ROM state is set up. Whenthe routine returns
the ROM state is restored to ith original setting.
The firmware jumpblock, through which firmware routines should be
called, makes extensive use of LOW JUMPs. These LOW JUMPS request
the lower ROM to be enabled, so that the lower ROM may be disabled
except when the firmware is active.

SIDE CALL (RST 2)


RST 2 calls a routine in an associated ROM. It has a very specialised use.
A foreground program (see section 10) may require more than 16K of
ROM. The side call mechanism allows for calls between two, three or
four associated ROMs without reference to their actual ROM select
addresses, provided that the ROMs are installed next to each other and in
order.
The two bytes following the restart instruction give the ‘side address’ of
the routine to call - so the RST 2 can be considered to be a three byte
instruction, rather like a CALL instruction. The top 2 bits of the ‘side
address’ specify which of the four ROMs to select; the bottom 14 bits,
when added to #C000, give the actual routine address. The upper ROM is
enabled, the lower ROM is disabled. Both the ROM state and the ROM
select are restored to their original settings when the routine returns.

FAR CALL (RST 3)


RST 3 calls a routine anywhere in memory, in RAM or in any ROM. The
two bytes following the restart are assumed to be the address of a ‘far
address’. The ‘far address’ is a three byte object, which takes the form:

Bytes 0..1: Actual address of routine to call.


Byte 2: ROM select/state required.

The ROM select/state byte may take the following values:


0. .251: Select the upper ROM at this ROM select address. Enable the
upper ROM, disable the lower ROM.
252. .255: No change of ROM select, enable/disable ROMs as follows:

252: Enable upper ROM, enable lower ROM.


253: Enable upper ROM, disable lower ROM.
254: Disable upper ROM, enable lower ROM.
255: Disable upper ROM, disable lower ROM.

Note that the ‘far address’ is not itself contained in the ‘instruction’, but is
pointed at. This is because the ROM select address will depend on the
particular order in which the user has chosen to install expansion ROMs
and must be established at run time.

Both the ROM state and the ROM select are restored to~ their original
settings when the routine returns.

RAM LAM (RST 4)


RST 4 reads the byte from RAM at the address given by HL. It disables
both ROMs before reading and restores the state afterwards. This
‘instruction’ avoids the user having to put a read routine into the central
32K of RAM to access RAM hidden under a ROM.
Writing to a memory location always changes the contents of RAM
whatever the ROM enable state.

FIRM JUMP (RST 5)


RST 5 turns on the lower ROM and jumps to a routine. The two bytes
following the restart are assumed to be the address to jump to - so RST 5
can be considered to be a three byte instruction, rather like a JP
instruction. The lower ROM is enabled before jumping to the routine and
is disabled when the routine returns. The state of the upper ROM is left
unchanged throughout.

b. The Other Restarts.


RESET (RST 0)
RST 0 resets the system as if the machine has just been turned on.

USER RESTART (RST 6)


RST 6 is available for the user. It could be used to extend the instruction
set in the same way that other restarts have been used, or it could be used
for another purpose such as a breakpoint instruction in a debugger.

Locations #0030 to #0037 inclusive in RAM may be patched in order to


gain control of the restart. If the lower ROM is enabled when the restart is
executed then the code in ROM at this address causes the current ROM
state to be saved in location #002B. Then the lower ROM is disabled and
the firmware jumps to location #0030 in RAM. If the lower ROM is
disabled then the restart calls #0030 as normal for this Z80 restart
instruction.
INTERRUPT (RST 7)

RST 7 is reserved for interrupts (see section 11), it must not be executed
by a program.

2.4 RAM and the Firmware.


The ROM state should be transparent to the user. If the current foreground
program (see section 10) is in ROM then the normal ROM state is to have the
upper ROM enabled and the lower ROM disabled. If the current foreground
program is in RAM then the normal state is to have both ROMs disabled.
These states allow the foreground program free access to the memory pool.
When a firmware routine is called the lower ROM is enabled and the upper
ROM is usually disabled. This allows the firmware free access to the default
screen memory (but not to all the memory pool). When the firmware routine
returns the ROM state is automatically restored to what it was.

The cases where the ROM state is important are:

a. Stack

The hardware stack should never be below #4000, otherwise serious


confusion will occur when the lower ROM is enabled and the stack is
used -for example, when interrupts occur or the firmware is called.

Similarly, it is inadvisable to set the stack above #C000 unless it is certain


that the upper ROM is never enabled when the stack is in use.

The system provides a stack area immediately below #C000 which is over
256 bytes long. This should be adequate for most purposes.

b. Communication with the firmware.

Most firmware routines take their parameters in registers. However, some


use data areas in memory to pass information. Most firmware routines
that use data areas in memory read these directly without using RAM
LAMs (see above) or the equivalent. These routines are affected by the
ROM state and the RUM select. They will read data from a RUM if the
RUM is enabled and the routine is given a suitable address. (Note that the
jumpblock disables the upper ROM when the firmware is called). Other
firmware routines that use data areas in memory always read from RAM.
They are unaffected by the ROM state and the ROM select.
Routines that always access RAM will mention this in the description of
the routine. Other routines may be assumed to be affected by the ROM
state. In particular the various data blocks used by the Kernel must lie in
the central 32K of RAM for the Kernel to be able to use them.
c. Communication between upper ROMs.

Programs in upper ROMs may call routines in other ROMs, using the
various Kernel facilities. There is no provision in the firmware, however,
for a program in one ROM to access constants in another.

The majority of firmware routines are called via the firmware jumpblock,
which starts at location #BB00, in the firmware RAM area. The Kernel
routines associated with the memory map are called via one of two other
jumpblock areas: the LOW area between #0000 and #003F, and the HIGH area
starting at #B900. All of these routines and jumpblocks are copied out of the
lower ROM into the firmware RAM area when the Kernel is initialized. Thus
they work independently of the ROM state.

2.5 Bank Switching


The ULA in the CPC6128 includes circuitry for bank switching 128K of RAM
into the 64K memory map described in section 2.1. The bank switched RAM
replaces the RAM in the memory map and behaves exactly like it; in particular,
it is hidden when a ROM is enabled.

The 128K of bank switched RAM is split into 8 16K blocks, numbered 0..7.
There are 8 memory organizations, also numbered 0...7, each of which
switches a different set of four blocks into the memory map at #0000.. #3FFF,
#4000.. #7FFF, #8000.. #BFFF and #C000.. #FFFF. The user can select an
organization by calling KL BANK SELECT.

The blocks available in each organization are as follows:


Organization Block accessed at memory address
#0000 #4000 #8000 #C000
0 0 1 2 3
1 0 1 2 7
2 4 5 6 7
3 0 3 2 7
4 0 4 2 3
5 0 5 2 3
6 0 6 2 3
7 0 7 2 3

During EMS the CPC6128 selects organization 0 and this is the organization
normally assocIated with the firmware. Note that blocks 0 and 2 contain
firmware variables, firmware jumpblocks and the stack. All these need to be in
their correct places for the firmware to run.
The documentation for a number of firmware routines specifies that data
blocks passed to them should be in the central 32K of memory. In most cases it
does not matter which blocks are switched into the memory map at these
places, however, the Kernel accesses data blocks passed to it (e.g. ticker blocks
or RSX command tables) at various times (e.g. during interrupts or event
processing) and it has no control over the bank switching at such times. It is up
to the user to ensure that the Kernel is only passed data blocks that remain
accessable. The simplest solution to this problem is to ensure that all Kernel
data blocks are located in block 2 (between #8000 and #BFFF).

Organizations 4.. 7 are the firmware organization with a new block switched
into the memory map at #4000. These organizations can be used to access
programs or data stored in blocks 4..7.

Organizations 1.. 2 are used by CP/M Plus and are not really suitable for
general use. In particular, if organization 2 is selected it is necessary to patch a
program into RAM at #0038 to catch interrupts and to bank switch back to a
more normal organization (e.g. organization 1) to run the standard interrupt
code.

Organization 3 is also used by CP/M Plus but it is of interest since it has the
RAM usually used for the screen located at #4000 where it can be accessed
without disabling the upper ROM.

Bank switching has no effect on the CRTC. Base addresses #0000, #4000,
#8000 and #C000 correspond to the screen being in blocks 0, 1, 2 and 3
respectively. It is not possible to locate the screen in blocks 4.7. However, the
firmware routines for accessing the screen memory are affected by bank
switching. For example, if a base address of #C000 is set in organization 3 then
the firmware will have to be told (using SCR SET POSITION) that the screen
memory can be accessed at #4000; if a base address of #4000 is set in
organization 3 then the firmware will be unable to access the screen memory
since block 1 is not in the memory map. (See section 6.4 for a full description
of the screen memory map).

Organizations 4...7 can be used to set up a complete screen in one go by using


SCR SET POSITION to make the firmware write to the memory at #4000
without sending a new base address to the screen hardware. Then, when the
screen has been finished, the contents of this block can be quickly copied into
the block actually being used by the CRTC (using KL LDIR perhaps). For
example, a title screen could be set up and bank switched out of the way and
then switched back in and copied at a later date when it is wanted.
3 The Keyboard.
The Key Manager is the pack associated with the keyboard. All the attributes
of the keyboard are generated and controlled by the Key Manager. These
attributes include repeat speed, shift and control keys, function keys and key
translation. The joysticks are also scanned by the Key Manager.

The Key Manager has three levels of operation. The lowest level scans the
keyboard, the middle level converts the key pressings into key values and the
top level converts the key values into characters. The user may access the Key
Manager at whichever level is most appropriate for a given program. It is
usually unwise, however, for a program to mix accesses at different levels.

3.1 Keyboard Scanning.


The keyboard is completely software scanned. This scan occurs automatically
every fiftieth of a second (see KM SCAN KEYS). The keyboard hardware is
read and a bit map noting which keys are pressed is constructed. This bit map
is available for testing if specific keys are pressed (see KM TEST KEY). As
the bit map is constructed keys that are newly pressed are noted and markers
are stored in a buffer until needed. If no newly pressed keys are found then the
last key pressed may be allowed to repeat if it is still down (see section 3.5).
The keyboard is ‘debounced’ in that a key must be released for two
consecutive scans before it is marked as released in the bit map. This
‘debouncing’ hides multiple operations of the key switch as it opens or closes.

At this stage only four keys are treated specially. The two shift keys and the
control key are not stored in the key buffer themselves. Instead, when any other
marker is stored the states of the shift and control keys are noted and put into
the buffer as well. The escape key generates a marker as normal but may also
have other effects depending on whether the break mechanism is armed (see
section 3.6).

There is a problem with scanning the keyboard. If three keys at the corners of a
rectangle in the key matrix are all pressed at the same time then the key at the
fourth corner appears to be pressed as well. There is no way to avoid this
problem as it is a feature of the keyboard hardware. All key combinations used
by the firmware (and the BASIC) have been especially designed to avoid this
effect.

3.2 Key Translation.


When the user asks for a key (KM WAIT KEY or KM READ KEY) the next
key pressed marker is read from the key buffer. The marker is converted to a
key number and this is looked up in one of three translation tables.
Which table is used depends on whether the shift and control keys were
pressed when the key was pressed. One table is used if the control key was
pressed, another is used if either shift key was pressed but control was not, the
third is used if neither shift nor control keys were pressed. The contents of
these tables can be altered by the user as required (by calling KM SET
CONTROL, KM SET SHIFT and KM SET TRANSLATE respectively).
The value extracted from the table may be a system token, an expansion token
or a character. Expansion tokens and characters are used by the top level of the
Key Manager (see 3.3 below) and are passed up from the middle level when
they are found in a table. There are three system tokens, which are obeyed
immediately they are found in a table. After obeying the token the next marker
is read from the buffer and translated.
The default translation tables are described in Appendix II. The immediately
obeyed System tokens are:

a. Ignore (# FF)
The key pressed is to be ignored.

b. Shift lock (# FE)


The shift lock is to be toggled (turned on if it is currently off and turned
off if it is on).

c. Caps lock(#FD)
The caps lock is to be toggled (turned on if it is off and off if it is on).

3.3 Characters from the Keyboard.


When the user asks the top level for a character (KM WAIT CHAR or KM
READ CHAR) a key is fetched from the middle level. If this is a character
(#00.. #7F or #AO.. #FC) then it is passed to the user. If it is one of the 32
expansion tokens (#80..#9F) then the string associated with the token is looked
up. The characters in this string are passed to the user one at a time with each
request for a character until the end of the string is reached.
There is only one character with a special meaning at this level. This is
character #EF which is produced when pressing the escape key generates a
break event (see section 3.6). It has no effects, it is merely a marker for the
place in the buffer where a break event was generated. It is intended to be used
to allow all characters before the break to be discarded. This character is not
generated by the translation tables and thus cannot be changed by altering
them.
A single ‘put back’ character is supported. When the user puts back a character
this character will be returned by the next call to the top level of the Key
Manager. This is intended for use by programs that need to test the next
character to be read from the keyboard without losing it (when processing
breaks perhaps).
In V1.1 firmware it is possible to call KM FLUSH to discard any unused or
unwanted characters so that subsequent calls to KM READ CHAR or KM
READ KEY will not return values from a previous input. The same effect can
be achieved in V1.0 Firmware by repeatedly calling KM READ CHAR until it
returns with carry false to indicate that there are no more characters available.
3.4 Shift and Caps Lock.
a. Shift lock
When shift lock is engaged then the keys pressed are translated as if a
shift key is pressed.
The shift lock is toggled by a system token (see 3.2 above) which is
normally generated by pressing CTRL and CAPS LOCK.

b. Caps lock
When caps lock is engaged then alphabetic characters read from the
keyboard are converted to their upper case equivalents. This case
conversion is applied before expansion tokens are expanded and so
expansions are not capitalised.
The caps lock is toggled by a system token (see 3.2 above) which is
normally generated by pressing CAPS LOCK (without control).

In V1.1 firmware it is possible to set the state of the locks as if the SHIFT or
CAPS LOCK keys had been pressed by calling KM SET LOCKS.

3.5 Repeating keys.


There is a table, which the user can alter as desired, that specifies which keys
are allowed to repeat when held down (see KM SET REPEAT). The default
setting for this table is described in Appendix III. Briefly, the default is to
allow all keys to repeat except the ESC, TAB, CAPS LOCK, SHIFT, ENTER
and CTRL keys and the 12 keys in the numeric keypad (the function keys). -

The speed at which keys repeat and the delay before the first repeat can be set
by the user (see KM SET DELAY), The default speed produces up to 25
characters a second with a 0.6 second start up delay.

A key is allowed to repeat if the following conditions are satisfied:

1/ The appropriate time has passed since the key was first pressed or it
last repeated.

2/ The key is still pressed.

3/ No other key has been pressed since the key was first pressed.

4/ The key is marked as allowed to repeat in the repeat table.

5/ There are no keys stored in the key buffer.

Condition 5 above means that the repeat speed and start up delay set the
maximum speed at which a key is allowed to repeat. If a program is slow about
removing keys from the buffer then the generation of keys will adjust itself to
this. Thus it is impossible to get a large number of keys stored in the buffer
simply by holding a key pressed.
3.6 Breaks.
Breaks can occur when the keyboard scanner detects that the ESC key is
pressed. When the escape key is found to be pressed the indirection KM TEST
BREAK is called to deal with the break. The default setting for this routine
tests whether the SHIFT, CTRL and ESC keys and no others are pressed. If so
then the system is reset (by executing an RST 0), otherwise the break
mechanism is invoked.

If the break mechanism is disarmed then no action is taken other than the
normal insertion of the marker for.the escape key into the key buffer. If the
break mechanism is armed then two additional operations take place. Firstly, a
special marker is placed into the key buffer that will generate character #EF
when it is found (irrespective of the translation tables). This is intended to be
used to allow the characters which were in the buffer before the break occurred
to be discarded. Secondly, the synchronous break event is ‘kicked’.

The break mechanism can be armed or disarmed at any time (by calling KM
ARM BREAK or KM DISARM BREAK). The default state is disarmed. When
a break is detected the mechanism is disarmed automatically which prevents
multiple breaks from occurring.
The method BASIC uses to handle breaks should serve as a model for other
programs. BASIC’s actions are as follows:

The break mechanism is armed. After each BASIC instruction the


synchronous event queue is polled and if a break event is found (because
it has been kicked as explained above) the break event routine is run.
The break event routine stops sound generation (SOUND HOLD) and
then it discards all characters typed before the break occurred by reading
characters from the keyboard (KM READ CHAR) until either the buffer
is empty or the break event marker (character #EF) is found. BASIC then
turns the cursor on (TXT CUR ON) and waits for the next character to be
typed (KM WAIT CHAR).
If the next character is the escape token (character # FC - the default value
generated by the ESC key) then a flag is set to make BASIC abandon
execution (or run the user’s ON BREAK GOSUB subroutine) and the
break event routine returns.

If the next character is any character other than escape then the break will
be ignored. If it is any character other than space then this is ‘put back’
(KM CHAR RETURN). Before the event routine returns the cursor is
turned off (TXT CUR OFF), sound generation is restarted (SOUND
CONTINUE) and the break mechanism is rearmed. BASIC then
continues as if nothing had happened.

When reading or writing from the cassette the ESC key is handled in a different
manner which is described in section 8.12.
3.7 Function Keys and Expansion
Tokens.
The Key Manager allows for 32 expansion tokens (values #80.. #9F) which
may be placed in the key translation tables. Each token is associated with a
string which is stored in the expansion buffer.

When the user asks the top level for a character a key is fetched from the
middle level. If this key is a character it is passed straight back. However, if it
is an expansion token then the string associated with the token is looked up.
The characters in this string are passed out one at a time with each request for a
character until the end of the string is reached. Values #80.. #9F and #EF,
#FD.. #FF in the expansion string are treated as characters and are not
expanded or obeyed.

The user may set the string associated with an expansion token (see KM SET
EXPAND) and may cause any key on the keyboard to generate an expansion
token. The default settings for the expansion tokens and the keys with which
they are normally associated are given in Appendix IV. The user may also set
the size and location of the expansion buffer (see KM EXP BUFFER); the
default buffer is at least 100 bytes long.

3.8 Joysticks.
There may be two joysticks connected to the system. These are both scanned in
the same way as keys on the keyboard. Indeed, the second joystick occupies
the same locations in the key matrix as certain other keys and is
indistinguishable from them. The state of the joysticks can be determined by
calling the routine KM GET JOYSTICK.
Because the joysticks are scanned like keys the pressing of joystick buttons can
be detected like any other key. Firstly, individual direction or buttons can be
tested in the key bit map (see section 3.1) by calling KM TEST KEY.
Secondly, the joystick buttons generate characters when they are pressed
(providing the translation tables are set suitably) and these characters can be
detected. The major problem with this latter method is that the rate of
generation of characters depends on how fast the keyboard is set to repeat. If
the repeat speed is increased to make the joystick more responsive then the
keyboard may become impossible to use.

See Appendix I for the numbering of the keys and joystick buttons and see
Appendix II for the default translation tables.
4 The Text VDU.
The Text VDU is a character based screen driver. It controls 8 different streams
each of which can have an area of screen allocated to it (a window). The Text
VDU allows characters to be written to the screen and read from the screen. It
also treats certain ‘characters’ as ‘control codes’ which can have various
effects, from moving the cursor to setting the colour of an ink.

4.1 Text VDU Coordinate Systems.


The Text VDU uses two coordinate systems - logical and physical. Generally
the user specifies positions to the Text VDU in logical coordinates. Physical
coordinates are used internally and occasionally by the user to specify positions
to the Text VDU. Both systems use signed 8 bit numbers and work in character
positions. Each character position is 8 pixels (dots) wide and 8 pixels high.
This means that the position of a coordinate on the screen depends upon the
screen mode.

Physical coordinates have columns running left to right and rows running top
to bottom. The character position at the top left corner of the screen is row 0,
column 0.

Logical coordinates are similar to physical coordinates except that the character
position at the top left corner of the text window is row 1, column 1.

4.2 Streams.
The Text VDU has facilities for handling up to 8 streams at once. Each stream
has an independent state (although some facilities are shared and thus affect all
streams when altered). The features that are stream dependent are:

VDU enable.
Cursor enable (enable or disable, on or off).
Cursor position.
Window size.
Pen and paper inks.
Character write mode (opaque or transparent).
Graphics character write mode.

The features that affect all streams include:

Character matrices.
Control code buffer.
Text VDU indirections.
Screen mode.
All these features are explained in detail in the sections below.
At anytime, the stream which is currently selected may be changed without
adverse effects provided that the control code buffer is not in use (see section
4.7 for further explanation). A stream will remain selected until another stream
is selected. This means that a program need not know which stream it is using.
The default stream, selected at EMS, is stream 0.
BASIC extends the stream concept to include the printer and cassette/disc files.
This extension is not part of the firmware.

4.3 Text Pen and Paper Inks.


Each stream has a pen and a paper ink associated with it. The text pen ink is
used to set the foreground pixels in characters (see section 4.6). The text paper
is used to set the background pixels in characters and to clear the text window.
The pens and papers can be set to any ink that is valid in the current screen
mode (see section 6.1). The default setting for a stream has the paper set to ink
0 and the pen set to ink 1. Changing a pen or paper ink does not change the
screen; it merely alters how characters will be written in the future.

4.4 Text Windows.


Each stream has a text window associated with it. This window specifies the
area of the screen where the stream is permitted to write characters. This allows
different streams to use different portions of the screen without interfering with
each other.
Windows are trimmed so that they fit within the current screen (whose size
varies with the screen mode, see section 6.1). The smallest size window
allowed is 1 character wide and 1 character high.
Before writing to the screen the position to write at is forced to lie inside the
window (see 4.5 below). This may cause the window to roll. Other operations,
such as obeying certain control codes also cause the write position to be forced
inside the window.
A text window which does not cover the whole screen is rolled by the firmware
copying areas of screen memory around. There is no alternate method
available. This makes rolling large windows a fairly time consuming process.
A text window which covers the whole screen is rolled by using the hardware
rather than by copying areas of memory. The offset of the start of the screen in
the screen memory can be set (see section 6.4). By changing this offset by +80
or —80 the whole screen can be rolled up or down by a line of characters.
It is obviously a good idea to prevent windows that are being used from
overlapping. If they are allowed to overlap then the portion in multiple use will
merely contain whatever was written to it last. There is no precedence of
windows one over another. A window occupying the whole screen will overlap
the other windows and so if this window is rolled it will move the contents of
the other windows.
The default windows, set up at EMS and after changing screen mode, cover the
whole of the screen. All eight windows overlap.

4.5 The Current Position and the Cursor.


Each stream has a current position associated with it. This is where the next
character to be printed on the screen is expected to be placed. However, if,
when a character is to be printed, the current position is found to lie outside the
text window then it is forced inside. The following steps are applied in turn to
force the current position inside the window:

1/ If the current position is left of the left edge of the window then it is
moved to the right edge of the window and up one line.

2/ If the current position is right of the right edge of the window then it is
moved to the left edge of the window and down one line.

3/ If the current position is now above the top line of the window then it is
moved to the top line of the window and the contents of the window
are rolled down one line.

4/ If the current position is now below the bottom line of the window then
it is moved to the bottom line of the window and the contents of the
window are rolled up one line.

When the cursor is enabled, the current position is marked by the cursor blob.
However, before placing the cursor blob on the screen, the current position is
forced to lie inside the current window just as it is before a character is placed
on the screen. This may cause the current position to move.

If the cursor is disabled then the current position may lie outside the window
and it will not be forced inside the window until, for example, a character is
printed.

The current position can be changed directly (by calling TXT SET CURSOR,
TXT SET ROW or TXT SET COLUMN) or by sending control codes to the
Text VDU. The location the current position is moved to is not forced inside
the window immediately, but only when the window is to be written to, as
described above. This allows the current position to be changed by moving via
a position outside the window, if required.

There are two ways to disable the cursor and prevent the cursor blob from
appearing on the screen. The first, cursor on off, is intended for use by system
programs. This is used by BASIC, for example, to hide the cursor unless input
is expected. The second, curs& enable disable, is intended for use by the user.
The cursor blob will only be placed on the screen if it is both on and enabled.

In V1.1 firmware it is possible to interrogate the current enable disable states of


the VDU and cursor for the current stream using TXT ASK STATE.
The cursor blob is normally an inverse patch. The character at the cursor
position is displayed with the text pen and paper inks reversed. This makes it
easy to restore the original form of the character position if the cursor is
moved. It is possible for the user to alter the form of the cursor blob, if
required, by changing the indirections TXT DRAW CURSOR and TXT
UNDRAW CURSOR.

4.6 Characters and Matrices.


A character is displayed on the screen in an area 8 pixels (dots on the monitor)
wide and 8 pixels high. Thus the maximum number of characters on the screen
depends upon the screen mode, (see section 6.1). Each character has a matrix
which is an 8 byte vector that specifies the shape of the character. The first byte
of the vector refers to the top line of the character and the last byte to the
bottom line of the character. The most significant bit of a byte in the vector
refers to the leftmost pixel on a line of the character and the least significant bit
refers to the rightmost pixel on a line of the character. If a bit in the matrix is
set then the pixel is in the foreground. If a bit is clear then the pixel is in the
background.
A foreground pixel in the character is always set to the pen ink. The treatment
of a background pixel depends on the character write mode of the VDU. In the
default mode, opaque mode, background pixels are set to the paper ink. There
is another mode, transparent mode, in which the background pixels are not
altered. Thus, in transparent mode, the character is written over the top of the
current contents of the screen. This is useful for annotating pictures or
generating composite characters.
The Text VDU is capable of printing 256 different characters, although special
effort is required to print the first 32 characters which are usually interpreted as
control codes. The matrices for the characters are normally stored in the ROM
but the user may arrange for any number of the characters to have matrices
stored in RAM where they may then be altered. The default setting, at EMS, is
to have all the matrices in ROM. (BASIC takes special action during its own
initialization to create 16 ‘user defined’ matrices.) The default character set is
described in Appendix VI.
When the user sets up a table of user defined matrices, by calling TXT SET M
TABLE, it is initialized with the current settings of the matrices from ROM or
RAM. This means that extending the table does not alter the current matrices.
Contracting the table will make the characters lost revert to their default
matrices in ROM.
When characters are read from the screen (by calling TXT RD CHAR) the
pixels on the screen are converted to the form of a matrix. This is compared
with the current character matrices to find which character it is. This means
that changing the character matrices or altering the screen may make a
character unrecognisable, in particular, changing the pen or paper ink can cause
confusion. Usually these problems. result in the character appearing to be a
space (character #20) and so special precautions are taken to avoid generating
spaces after some ink changes real spaces may be read as block graphic
-

characters #80 or # 8F.


To allow the user to change how characters are written to and read from the
screen, the indirections TXT WRITE CHAR and TXT UNWRITE are
provided.
4.7 Character Output and Control
Codes.
The main character output routine for the Text VDU is TXT OUTPUT. This
obeys controls codes (characters 0..31) and prints all other characters.
Characters sent to TXT OUTPUT pass through various levels of indirection
and can be dealt with by various output routines.
TXT OUTPUT uses the TXT OUT ACTION indirection to sort out whether
the character is a printing character, is a control code to be obeyed or is the
parameter of a control code.
TXT OUT ACTION normally calls TXT WRITE CHAR to print characters on
the screen. However, if the graphic character write mode is selected then
characters are printed using the Graphics VDU character write routine (see 5.6
below). This mode can be selected on a character by character basis using a
control code or on all characters sent (see TXT SET GRAPHIC). When
graphic character write mode is selected control codes are not obeyed but are
printed by the graphics routine instead.
TXT OUT ACTION deals with a control code in the following manner:
1/ The code is stored at the start of the control code buffer.
2/ The code is looked up in the control code table to find out how many
parameters it requires.
3/ If no parameters are required go directly to step 5.
4/ If one or more parameters are required then TXT OUT ACTION
returns but the next characters sent to it are added to the control code
buffer rather than being printed or obeyed. This continues until
sufficient parameter characters have been received.
5/ The code is looked up in the control code table to get the address of the
routine to call to perform the control code and this routine is then
executed.
6/ The control code buffer is discarded and the next character sent may be
printed or may be the start of a new control code sequence.
The user can change the operation of a control code by changing the entry for it
in the control code table (see TXT GET CONTROLS). This contains a 3 byte
entry for each code and entries are stored in ascending order (i.e. the entry for
#00 first, #01 next and so on).
Bits 0...3 of the first byte of each entry specifies the number of parameters
required. This must lie in the range 0..9 as the control code buffer is only
capable of storing up to 9 parameters.
In V1.1 firmware bit 7 specifies whether the code is affected when the VDU is
disabled. If bit 7 is set then the code is to be ignored when the VDU is
disabled, otherwise it is to be obeyed.
The second and third bytes are the address of the routine to call to obey the
code. This routine should lie in the central 32K of RAM or in the lower ROM
(which will be enabled). It shouild conform to the following entry/exit
conditions:
Entry:

A contains the last character added to the buffer.

B contains the number of characters in the buffer (including the control


code).

C contains the same as A.

HL contains the address of the control code buffer (points at the control
code).

Exit:

AF, BC, DE and HL corrupt.


All other registers preserved.

The control code buffer is shared between all the streams. A control code
sequence should be completed before the stream is changed otherwise
unexpected effects may occur.

The default control code actions, set at EMS and when TXT RESET is called,
are described in Appendix VII.

It is possible to disable a text stream by calling TXT VDU DISABLE. When


disabled the stream will not write any characters to the screen and in V1.1
firmware control codes may not be obeyed (as described above). Normal
operation can be restored by calling TXT VDU ENABLE. Note, however, that
calling these routines will empty the control code buffer. This effect may be
used to avoid problems when the state of the control buffer is unknown (when
printing an error message perhaps).
5 The Graphics VDU

The Graphics VDU allows individual pixels (dots) on the screen to be set or
tested and lines to be drawn. The plotting takes place on an ideal screen that is
always 640 points wide and 400 points high. This means that more than one
point on the ideal screen will map onto a particular pixel on the real screen.
The width of the ideal screen (640 points) is chosen to be the horizontal
number of pixels on the screen in the highest resolution mode (mode 2). The
height of the ideal screen (400 points) is chosen to be twice the vertical number
of pixels on the screen in all modes. This ensures that the aspect ratio of the
screen is approximately unity, i.e. a circle looks circular and not elliptical.

5.1 Graphics VDU Coordinate Systems.


The Graphics VDU uses 4 coordinate systems. The user specifies positions in
user coordinates or relative coordinates or occasionally in standard coordinates.
Internally the Graphics VDU uses base coordinates (or occasionally standard
coordinates).

User coordinates, relative coordinates and standard coordinates are all very
similar. They all use signed 16 bit numbers and work in points with X-
coordinates running left to right and Y-coordinates running bottom to top. The
screen is always 400 points high and 640 points wide whatever the screen
mode is. This means that a pixel (dot on the screen) is mapped onto by 8 points
in mode 0, 4 points in mode 1 and 2 points in mode 2. The origin (coordinate
(0,0)) of these systems vary:

In standard coordinates the origin is the point at the bottom left corner of
the screen.

The origin of user coordinates can be set by the user. The default origin is
at the bottom left corner of the screen. This makes the default user
coordinates the same as standard coordinates.

The origin of relative coordinates is the current position (see 5.2 below).
This allows plotting to be carried out independently of the position on the
screen and is useful if a particular shape is to be repeated on the screen a
number of times or if it is inconvenient to keep track of the current
location.

Base coordinates are a physical coordinate system which deals with pixels. X-
coordinates run left to right and Y-coordinates run bottom to top. Pixel (0,0) is
the pixel at the bottom left corner of the screen. Because this coordinate system
works in pixels the coordinates of positions on the screen depend upon the
screen mode. Base coordinates are unsigned 16 bit numbers and only
coordinates that refer to a pixel on the screen are valid.
Graphics routines convert from relative coordinates to user coordinates, if
necessary, and then from user coordinates to base coordinates before accessing
the physical screen. During the latter conversion there is a loss of accuracy
because of the mapping of multiple points onto a single pixel. This could make
shapes drawn on the screen appear asymmetrical (particularly circles) but the
Graphics VDU avoids this by rounding the coordinates towards the user origin.
Thus symmetrical shapes should be drawn symmetrically about the user origin
to take advantage of the rounding. If the shape is not centred on the user origin
then the asymmetry may reappear.

In V1.1 firmware it is possible to call GRA FROM USER to convert from user
to base coordinates - this will make using routines in the lower level screen
pack easier (e.g. SCR DOT POSITION, SCR HORIZONTAL, SCR
VERTICAL).

5.2 The Current Graphics Position.


The Graphics VDU stores a current position. This is the user coordinate of the
last point specified to the Graphics VDU (or the origin after clearing the
graphics window). The origin of relative coordinates is specified to be at this
point, thus relative coordinates are an offset from the current position.

When drawing a line one end is at the position specified while the other end is
at the current graphics position. When drawing a character on the screen using
the graphics character write routine the character is placed with the current
graphics position being the top left corner of the character.

After plotting or testing a point or drawing a line the current graphics position
is moved to the position specified. After writing a character the current
graphics position is moved right by the width of a character ready for the next
character to be written.

5.3 Graphics Pen and Paper Inks.


The Graphics VDU has a pen (foreground) ink and a paper (background) ink.
The graphics pen ink is used to plot pixels and to set foreground pixels when
writing characters (see 5.6 below) and drawing lines (see 5.7 below). The
graphics paper ink is used to clear the graphics window and to set background
pixels when writing characters or drawing lines.

The pen and paper can be set to any ink valid in the current screen mode (see
section 6.2). The default has the paper set to ink 0 and the pen set to ink 1.
Changing the pen or paper ink does not change the screen it merely alters how
pixels will be written in the future.

5.4 Graphics Write Mode.


Pixels plotted by the Graphics VDU are plotted using the current graphics write
mode. This specifies how the ink to be plotted interacts with the ink a pixel is
currently set to.
There are four write modes:

0: FORCE: NEW = INK


1: EXCLUSIVE-OR: NEW = INK xor OLD
2:AND: NEW = INK and OLD
3:OR: NEW = INK or OLD

NEW is the ink that the pixel will be set to.


OLD is the ink that the pixel is currently set to.
INK is the ink that is to be plotted.

The default Graphics write mode is FORCE mode. The Text VDU always sets
pixels as if it is operating in this mode. Also the graphics window is cleared by
writing in FORCE mode irrespective of the actual write mode.

Provided that suitable ink settings are chosen, AND mode and OR mode allow
particular bits in a pixel to be cleared or set. This allows the Graphics VDU to
write in ‘bit planes’ and by choosing the colours of the inks carefully
overlapping shapes can be drawn and automatically hidden behind one another.

If the inks are chosen suitably, EXCLUSIVE-OR mode can be used to plot
over the current contents of the screen. It is also useful because a shape can be
removed from the screen by redrawing it since exclusive-oring with the same
ink twice restores the original setting of a pixel.

The graphics write mode may be set by calling SCR ACCESS or by using a
control code (see Appendix VII).

5.5 Graphics Window.


The Graphics VDU allows a single window to be specified. This allows the
user to mix text and graphics on the screen without them interfering with each
other. If the text windows are allowed to overlap the graphics window then the
contents of the graphics window will be moved when the text windows are
rolled. The graphics window cannot be rolled.

When plotting points, drawing lines or writing characters no pixel outside the
graphics window is ever written. Unlike the text windows no action is taken to
force a point inside the window - actions outside the window will be lost.
Conversely, when testing points, points outside the window are all deemed to
be set to the current graphics paper ink. Points inside the window are written
and read as expected.

The graphics window is related to a specific area of the screen and not to the
user coordinate system. Thus, changing the origin of the user coordinate
system will not move the location of the window on the screen although it does
change the user coordinates of points in the window.

The default graphics window, set at EMS and after changing screen mode,
covers the whole of the screen.
5.6 Writing Characters.
The Graphics VDU write character routine draws a character with the current
graphics position at the top left corner of the character. The current position is
moved right by the width of a character in the current screen mode. The
distance moved varle8; in mode 0 it is 32 points; in mode 1,16 points; and in
mode 2,8 points. Control codes, characters 0..31, are printed and are not
obeyed.

In V1.0 firmware the character is always written opaquely irrespective of what


mode the Text VDU is using to write characters, i.e. The character background
is set to the graphics paper ink and the foreground is set to the graphics pen
ink. However, the current graphics write mode is used to plot the pixels in the
character (see 5.4 above).

In V1.1 firmware the foreground to the character is always written in the


graphics pen ink using the current graphics write mode. How the background
to the character is written depends on the background write mode set by calling
GRA SET BACK. If the background mode is opaque then the background to
the character is written in the graphics paper ink using the current graphics
write mode. If the background mode is transparent then the background pixels
are not plotted at all, the current settings of these pixels are left unchanged.

5.7 Drawing Lines (Only applicable toVl.1 firmware)


The Graphics VDU has a number of options that affect the way that lines are
drawn on the screen. These include the background write mode, the first point
mode, the line mask and the graphics write mode.

The line mask is an 8 bit, bit significant value that specifies whether pixels on
the line are foreground or background. If the bit of the mask corresponding to a
pixel is one then the pixel is foreground. If the bit is zero then the pixel is
background. The mask is used repeatedly along the length of the line. i.e. Bit 7
of the mask corresponds to pixels 1,9, 17, ... of the line, bit 6 to pixels 2, 10,18,
... etc.

Foreground pixels of a line are plotted in the graphics pen ink using the
graphics write mode. How background pixels are piotted depends upon the
background write mode. If the background mode is opaque then the
background pixels are plotted in the graphics paper ink using the graphics write
mode. If the background mode is transparent then the pixels are not plotted at
all, the current settings of the pixels are left unchanged.

The first point mode specifies whether the pixel at the current graphics position
is to be included in the line or not. Not plotting the first pixel of a line is
particularly useful for drawing lines when the graphics write mode is XOR. For
instance, the corner pixels of a box will be plotted twice if the first pixels of
lines are plotted and this will result in the pixels not being set in XOR mode.
5.8 Filling Areas (Only applicable to V1.1 firmware)
The Graphics VDU provides a generalised area fill routine. The user draws the
outline of the area to be filled using the standard line drawing and pixel
plotting routines and then moves the current position to any pixel inside the
area and calls the fill routine, GRA FILL This will set all pixels inside the
delimited area to the fill ink irrespective of what the current graphics write
mode is set to. (i.e. GRA FILL always works as if FORCE mode was selected).

The fill routine recognises pixels making up the edge of the area by the ink that
they are set to. All pixels set to either the current graphics pen ink or the ink
that is being used to fill the area with are treated as edge pixels. (These two
inks may be the same). Edge pixels need only lie diagonally adjacent to each
other, it is not necessary for them to be orthogonally adjacent. Of course, the
edges of the graphics window are also treated as edges of the area to fill and so
no pixels outside the graphics window will be affected.

GRA FILL uses a buffer supplied by the user for storing information. The more
complicated the area the longer the buffer will need be. If the supplied buffer is
too short then parts of the area will be ignored and will not be filled. By
supplying a long enough buffer any arbitrarily complicated shape may be
filled.
6 The Screen Pack.
The Screen Pack is used by the Text and Graphics VDUs to access the
hardware of the screen. It also controls the features of the screen that affect
both the Text VDU and Graphics VDU, such as what mode the screen is in.

6.1 Screen Modes.


The screen has three modes of operation, numbered 0, 1 and 2. The modes
have different resolutions and display different numbers of inks on the screen.

All modes have a vertical resolution of 200 pixels (picture elements or dots on
the screen). The horizontal resolution varies from 160 pixels to 640 pixels. As
each character is 8 pixels by 8 pixels the number of characters across the screen
varies with the mode - from 20 characters to 80 characters. The screen is
always 25 characters high.

The number of inks that can be displayed on the screen varies with the screen
resolution. When the screen is 640 pixels wide only 2 inks can be displayed,
when the screen is 320 pixels wide 4 inks can be displayed and when the
screen is 160 pixels wide 16 inks can be displayed.

In summary, the modes are:


Mode Pixel Size Character Size Inks
0 160x200 20x25 16
1 320x200 40x25 4
2 640x200 80x25 2

The default screen mode, set at EMS, is mode 1.

The screen mode is set by calling SCR SET MODE which also has other
effects.

Firstly, the screen is cleared to ink 0. If the text and graphics paper inks are not
set to ink 0 then this will become apparent on the screen when characters are
written or windows are cleared. If the user wishes to alter this screen clearing
operation for some reason then it may be intercepted at the SCR MODE
CLEAR indirection.

Secondly, the Text and Graphics VDUs are set into standard states. The
windows are all set to cover the whole screen. If the pen and paper inks are out
of range for the new mode then they are masked (with #01 or #03) to bring
them into range. The current text positions are moved to the top left corner of
the screen and the text cursors are turned off (see TXT CUR OFF). The current
graphics position and the user origin are moved to the bottom left corner of the
screen.
6.2 Inks and Colours.
The various screen modes allow pixels (dots on the screen) to be set to
different numbers of inks as follows:

Mode 0: 16 inks, 0..15


Mode l: 4 inks, 0..3
Mode 2: 2 inks, 0..1

How the ink for a pixel is encoded into a byte of screen memory is described in
section 6.4. The ink that a pixel is set to determines what colour the pixel is
displayed in. However, the colour associated with an ink is not fixed, it can be
changed.

There are 27 colours available. Each ink may be set to any of these colours.
The border to the screen acts much like an ink and can have its colour specified
as well. The display hardware fetches the ink value from the screen memory
for each pixel as it is displayed. This ink value is used to access a small area of
RAM inside the gate array called the ‘palette’. The palette contains the actual
colour which is to be displayed by the monitor for that particular ink. Changing
entries in the palette thus causes all pixels set to that ink to change colour when
they are next displayed (i.e. within 1/50th of a second or so).

In fact the Screen Pack allows two colours to be associated with an ink (or the
border). These are loaded into the palette alternately under software control. If
the two colours associated with an ink are different then the ink will flash, if
the colours are the same then the ink will be steady. The user can change the
rate of alternation, from the default of 5 cycles per second, if required (see SCR
SET FLASHING).

When specifying colours the Screen Pack uses an ordering that corresponds to
a grey scale on a monochrome monitor. This runs from the darkest colour
(black), colour 0, to the brightest colour (bright white), colour 26. The colours
do not appear to have any particular ordering when viewed on a colour
monitor.

The palette uses a different (and apparently nonsensical) numbering scheme for
the colours. The Screen Pack automatically translates the grey scale number to
the hardware number and vice versa when appropriate. Unless the user is
driving the hardware directly the hardware numbers will never be encountered.

The default settings for the colour of each ink and a list of the 27 colours
available are given in Appendix V.

6.3 Screen Addresses.


The Screen Pack does not use a coordinate system itself. It uses screen
addresses. However, itdoes work with the physical and base coordinate systems
of the Text and Graphics VDUs described in sections 4.1 and 5.1 respectively.
In particular, routines are provided to convert positions given in physical or
base coordinates to screen addresses.
A screen address is, prosaically enough, the address of a byte within the screen
memory. To specify a particular pixel a screen address is often passed to a
routine along with a mask that indicates exactly which pixel is required.
Routines are provided for stepping a screen address up, down, right and left
one byte. (The screen map makes this a non-trivial operation.)

6.4 Screen Memory Map.


The screen is a memory mapped pixel screen. The screen memory fills 16K of
RAM in all modes. The default location for the screen, set at EMS, is the 16K
of RAM starting at #C000. This lies underneath the upper ROM, when it is
enabled, which keeps the screen out of the way of the rest of the system.
However, this also means that the upper ROM has to be disabled whenever the
screen is read. The firmware jumpblock uses LOW JUMP restarts which turn
the upper ROM off to ensure that the screen memory is accessible if required.
It is possible to change the location of the screen memory to any of the 4 16K
memory blocks on 16K boundaries (see SCR SET BASE). However, only
#C000 and #4000 are useful; #0000 and #8000 both overlap firmware
jumpblocks or other system areas. The descriptions below all assume the
default screen location at #C000.
In V1.1 firmware it is possible to set the location of the screen that is used by
the screen pack routines independently of setting the hardware value. This will
then enable text and graphics to be produced in the ‘screen’ that isn’t currently
on view - switching to the other possible location (#4000 to #C000) will cause
the already prepared graphics etc. to instantly appear - thus avoiding flicker
and enabling smooth animation effects.
The screen memory map is not simple. Fortunately it is not necessary to
understand it because the Text and Graphics VDUs provide idealised models of
the screen. However, to achieve maximum speed for certain applications (such
as animated games) it may be necessary to access the screen memory directly.
The screen memory is divided into 8 blocks, each 2K bytes long. Block 0 runs
from # C000 to # C7FF, block 1 runs from #C800 to #CFFF, and soon. Each
line of pixels on the screen uses 80 consecutive bytes from a block. The top
line of the screen comes from block 0, the second line from block 1 and so on
until the eighth line which comes from block 7. The sequence starts with block
0 again on the ninth line and repeats in this fashion all the way down the
screen. The successive lines in a block are stored consecutively so there are 48
unused bytes at the end of each block.
There is a further complication to this screen map. The description above
assumes that the first byte displayed from the block is the first byte of the
block. In practice the offset in a block of the first byte to be displayed can be
set to any even value (see SCR SET OFFSET). The same offset applies to all
eight blocks. A block wraps around from its last byte to its first byte, thus
#C7FE, #C7FF and #C000 are consecutive bytes in block 0 and could all be on
the same line of the screen. Altering the offset by ± 80 MOD 2048 (the length
of a line) rolls the screen up or down by one character line (8 pixel lines). This
effect is used by the Text VDU when rolling the entire screen.
The meaning of the bytes accessed as described above varies with the screen
mode. Each byte stores the inks for 2,4 or 8 pixels. The bits used to encode
each pixel are not arranged in an obvious manner. The following table specifies
which bits of screen memory are used to encode which pixel in the various
modes. The bit numbers given in the table are the bits of the screen byte. They
are given in the order of bits in the pixel - the first bit given is most significant
bit of the pixel and the last bit is the least significant bit.

_______________ Mode 0 Mode l Mode 2

Leftmost pixel Bits 1,5,3,7 Bits 3,7 Bit 7


Bit 6
Bits 2,6 Bit 5
Bit 4
Bits0,4,2,6 Bits l,5 Bit 3
Bit 2
Rightmost pixel Bits 0,4 Bit 1
Bit 0

The following diagram illustrates the mapping from pixels on the screen to
addresses in screen memory for the simple case of a base address of #C000 and
an offset of 0.

On the CPC6128 the base address sets which block will be used for the screen
memory. Base addresses of #0000, #4000, #8000 and #C000 correspond to
blocks 0, 1, 2, and 3. It is not possible for the screen memory to be located in
blocks 4...7. Where the block being used for screen memory actually appears in
the memory map depends on the bank switching (see section 2.5).
7 The Sound Manager.
The Sound Manager deals with the sound chip. It allows various envelopes and
sounds to be set up and played under the control of the user. Most of the
control is achieved using software rather than the sound chip hardware.

7.1 The Sound Chip.


The sound chip used is the General Instruments AY-3-8912. This has three
channels and a pseudo-random noise generator that can be connected to any of
the channels. The chip has a limited number of amplitude envelopes available
(see Appendix IX) but the software enveloping, described below, can achieve
all that the hardware is capable of, and more. Tone enveloping is all done by
the software, there is no hardware support.

The sound generated by the chip uses square waveforms. There is no way to
generate any other waveform.

It is possible to access the sound chip threctly should the need arise. However,
the routine MC SOUND REGISTER should be used to write to registers of the
sound chip. This is because the keyboard is attached to the I/O port of the
sound chip and the keyboard scanning routine expects to find the sound chip in
a standard state (i.e. not in use). Also, there are timing constraints on accesses
to the chip; using MC SOUND REGISTER will avoid consideration of these
details.

The sound chip has three independent sound channels. The outputs from these
are mixed together to form two stereo channels - sound channels A and B are
mixed to form one stereo channel and sound channels B and C are mixed to
form the other stereo channel. The stereo sound is available on the output jack
on the back of the machine. However, there is only a single internal speaker
and so the two stereo channels are mixed together to drive this. The volume of
sound from the internal speaker can be controlled by the volume control knob
on the side of the machine near the on/off switch. This control overrides the
other volume control methods described below.

7.2 Tone Periods and Amplitudes.


The sound chip allows 16 different amplitudes in the range 0.. 15. Amplitude 0
is no sound at all, amplitude 15 is maximum volume.

The pitch of a note to be generated is specified by the period of the note rather
than by the frequency. This period is given in 8 microsecond units. Thus, the
tone period specified and the frequency of the tone generated are related by the
formula:
Tone period = 125 000 / Frequency

See Appendix VIII for a list of the suggested periods for generating musical
notes.

7.3 Enveloping.
Real sounds rarely have a constant volume. Enveloping allows an
approximation to the variation in volume of real sounds to be made. The sound
is split into a number of sections each of which can increase the volume,
decrease the volume, or keep it constant. The length of these sections can be
varied, as can the rate of increase or decrease in volume. For example, a note
generated by a musical instrument may be considered to have 3 sections as
follows:

Attack: The volume of the note rises rapidly to its peak.

Sustain: The volume of the note remains constant while the note is
played.

Decay: The volume falls away slowly to zero as the note finishes.

Attack Sustain Decay

The Sound Manager allows two types of envelopes; amplitude envelopes to


control a sound’s volume and tone envelopes to control its pitch (the pitch is
varied in much the same way as the volume). The user can set up to 15
different envelopes of each type. The exact formats of the data blocks
specifying envelopes are given in SOUND AMPL ENVELOPE and SOUND
TONE ENVELOPE.

a. Amplitude envelopes.
An amplitude envelope is used to control the volume and length of a
sound. It can have up to five sections. Each section can be either a
hardware or a software section. Software sections are either absolute or
relative.
Hardware sections write values into the sound chip registers 11,12 and 13
to set up a hardware envelope. (See Appendix IX for a description of the
sound chip registers). Generally a hardware section will be followed by a
software section that does nothing except wait for a time long enough for
the hardware envelope to operate.

An absolute software section specifies a volume to set and a time to wait


before obeying the next section.

A relative software section specifies an step size, a number of steps and a


time to wait. For each step requested, the current volume is changed by
the given step size and then the Sound Manager waits for the given time
after each step before obeying the next step.

Amplitude envelopes are set by calling SOUND AMPL ENVELOPE.

b. Tone envelopes.

A tone envelope controls the pitch of the sound. It can have up to five
sections. Each section can be either an absolute or a relative section. The
sections of a tone envelope are not necessarily related to those of an
amplitude envelope.

An absolute section specifies a tone period to set and a time to wait before
obeying the next section.

A relative section specifies an step size, a number of steps and a time to


wait. For each step requested, the current tone period is changed by the
given step size and then the Sound Manager waits for the given time after
each step before obeying the next step.

If the tone envelope is completed before the sound duration expires (see
section 7.40 then the final pitch is held constant. Alternatively, tone
envelopes can be set to repeat themselves automatically. This allows
tremulo effects to be created.

Tone envelopes are set by calling SOUND TONE ENVELOPE.

7.4 Sound Commands.


When a sound is given to the Sound Manager to be played, by calling SOUND
QUEUE, a lot of information needs to be specified. This is described briefly
below. The detailed layout of a sound command data block is described in
SOUND QUEUE.

a. Initial tone period.

The sound is issued with an initial tone period. The pitch of the sound can be
varied from this initial value using a tone envelope. If no tone envelope is
specified the pitch remains constant. An initial tone period of zero means no
tone is to be generated, presumably the sound is to be pure noise (see (e)
below).

b. Initial volume.
The sound is issued with an initial volume. The volume of the sound can be
varied from this initial value using an amplitude envelope. If no amplitude
envelope is specified then the volume remains constant.

c. Tone envelope.

This specifies which tone envelope to use. If no envelope is specified then the
pitch of the sound remains constant.

d. Amplitude envelope.

This specifies which amplitude envelope to use. If no envelope is specified


then default system envelope is used. This keeps the volume of the sound
constant and lasts for 2 seconds.

e. Noise period.

If the noise period is zero then no noise is to be added to the sound. Any other
value sets the period for the pseudo-random noise generator and adds noise to
the tone generated. Note that there is only one noise generator and so if two
sounds are to use it at the same time they will need to agree on the period.

f. Duration.

The length of a sound can be specified in two ways, either as an absolute time
(duration) or as a number of operations of the amplitude envelope. In the latter
case the envelope is run one or more times and the sound finishes when the
envelope has been executed the specified number of times. In the former case,
if the duration finishes before the envelope (if any) then the sound is cut short.
If the duration is longer than the envelope then the final amplitude is held until
the duration expires.

g. Channels and Synchronisation Bits.

The sound can be issued to one or more channels. If a sound is issued to more
than one channel then these channels automatically rendezvous with each
other. Rendezvous requirements can be set explicitly as well. Also the sound
can be held or the sound queue can be flushed (see section 7.6).

7.5 Sound Queues.


Each channel has a queue associated with it. Each queue has space to store at
least three sounds. The sound at the head of each queue may be running and
making music on its channel or it may be waiting for various synchronisation
requirements (see 7.6 below). When a sound command is issued the sound is
placed into the queues for the channels specified by the command. When the
sound reaches the head of the queue, and providing its synchronisation
requirements are met, it is executed.
If a sound that has the flush bit set is put into a queue then all sounds queued
for that channel are discarded and any executing sound is stopped immediately.
Thus a sound with the flush bit set will move to the head of the queue
immediately and may commence execution.

A routine (SOUND CHECK) is provided to test the status of the sound at the
head of a queue and to determine how much free space is in a queue. It is also
possible to set up a sound event for each queue (by calling SOUND ARM
EVENT). This synchronous event is ‘kicked’ when the queue has a free space
in it. The sound event mechanism allows the generation of sound to be carried
on aBa background task whilst some other action is being carried out.

7.6 Synchronisation.
There are two mechanisms to allow sounds on different channels to be
synchronised. These are holding sounds and rendezvous. The purpose of
synchronisation is to ensure that sounds start simultaneously. For example, a
simulation of an instrument might use one channel to generate the fundamental
note and another channel to generate the harmonics of the note. The
synchronisation mechanism, particularly rendezvous, may be used to ensure
that the fundamental and the harmonic sounds start exactly together.

A sound can be specified to beheld when it is issued. This means that when it
reaches the head of the sound queue it is not executed immediately. Instead it
waits until it is explicitly released (by calling SOUND RELEASE) before it
starts execution.

A sound can have rendezvous requirements set on it when it is issued. If a


sound is issued to more than one channel then these channels all set rendezvous
with each other automatically. When a sound with a rendezvous set reaches the
head of the sound queue it is not executed immediately. Instead it waits until
sounds with matching rendezvous requirements reach the head of their sound
queues. Only when all rendezvous sounds are found to be present and ready to
run do they start.

For instance, a sound on channel A marked to rendezvous with a sound on


channel B will not start until a sound on channel B marked to rendezvous with
channel A is ready to start - and vice versa! if a sound is ready to start on
channel B that is not marked to rendezvous with chsrnnel A then it starts but
the sound on channel A continues to wait for its rendezvous.

7.7 Holding Sounds.


It is possible to stop a sound while it is executing by calling SOUND HOLD.
This will stop a channel making any sound and will save the state of the sound.
The sound can be restarted from where it was held by calling SOUND
CONTINUE. However, if a hardware envelope was running when the sound
was held then it is impossible to predict the effect of restarting the sound. The
hardware envelope may or may not continue from where it was held.
Calling SOUND HOLD is different from setting the hold bit when issuing a
sound as described in section 7.6 above. SOUND HOLD stops all sounds being
generated at any time whilst the hold bit is a method for synchronising sounds
and prevents a particular sound starting when it reaches the head of the queue.
8 The Cassette Manager.
The Cassette Manager deals with reading files from and writing files to tape.
These operations can either be performed on a character by character basis or
on a whole file at once. There is no hardware support for the cassette, even
the timing for reading and writing bits is performed by software.

The format of data on the tape is described in great detail. This will only be of
academic interest to most users. More general information can be found in
sections 8.4 onwards. In the case of V1.1 machines or the CPC464 with a
DDI-1 fitted, a |TAPE command will have to be used to access the Tape
Operating System.

8.1 File Format.


A file on tape is split into blocks each with a header record and a data record
containing up to 2K (2048) bytes of data. The cassette motor which is under
software control is turned off between each file block to allow time to process
the data read or to generate the data to be written. The motor start-up gap also
serves to separate the blocks from each other.

The general format of a block is as follows:

Motor File header File data


Start-up record record

However, the first and last blocks of a file have an extra pause before and
after them respectively, to separate files on the tape. Their formats are thus:

First block:

Motor Pre-file File header File data


Start-up gap record record

Last block:

Motor Start- File header File data


Post-file gap
up record record
There is a strong distinction between the file header record and the file data
record. The header record is written using one synchronisation character
(#2C) and the data record with another (#16). This means that when the
Cassette Manager is searching for a ifie header it is impossible for it to find a
file data record by mistake, and vice versa. See 8.2 below for the use of the
synchronisation characters.

8.2 Record Format.


A record can contain any number of data bytes from 1 to 65536. The data is
split into segments each of which is 256 bytes long. The last segment is
padded out to 256 bytes with zeros when writing if necessary. When reading a
record any extra bytes are ignored although they are accumulated into the
CRC.

The layout of a record is as follows:

Leader Segment 1 …………. Segment N Trailer

There are N segments where 256*N is the length of data (plus padding) to be
written.

A file header record always contains one segment; a file data record contains
from one to eight segments (usually 8 segments).

a. Leader

At the start of all records a leader is written which has the following layout:

Pre-record 2048 one bits Zero bit Sync byte


gap

The leading gap is there to ensure the failure of any attempt to synchronise on
the end of a preceding record or on data that was on the tape and that has been
over-recorded.

The long sequence of one bits is used to calculate the speed at which the data
was written and hence to calculate the threshold value used to distinguish one
bits from zero bits.

The single zero bit is used to mark the impending end of the leader and is also
used to determine whether the recording has been inverted (see section 8.3).

The synchronisation byte is there to help prevent spurious synchronisation on


sequence of bits such as might be found in a record. If an incorrect value for
the sync byte is found then an attempt has been made to synchronise on the
middle of a record or on the wrong type of record. This byte is used to
distinguish header records from data records in afile block (header records use
#2C while data records use #16).
b. Segments
Each segment contains 256 data bytes and has the following format:

Byte 1 Byte 2 .….. Byte 256 CRC 1 CRC 2

‘CRC 1’ is the more significant byte and ‘CRC 2’ the less significant byte of
the logical NOT of the CRC calculated for the 256 bytes in the segment. (The
CRC polynomial used is ‘X15 +X12 +X5 +1’ with an initial seed of #FFFF).

c. Trailer

The trailer is simply an extra 32 one bits written to the end of the record.

8.3 Bit Format.


A bit is written to the tape as a period of low level followed by an equal
period of high level. A one is written to the tape with these periods twice as
long as those for a zero. The length of the period for a zero can be set by the
user (see CAS SET SPEED).

The tape circuitry has a tendency to move the positions of edges (transitions
from high to low or low to high) so as to balance out the difference between
ones and zeros written to tape. Precompensation is used - which adds to the
period of a one bit and subtracts from the period of a zero bit to make the
waveform closer to the ideal when it is read.

When reading, the speed at which the recording was made is determined by
timing the one bits in the record leader. As this is a long sequence of the same
bit the edges are not shifted and no precompensation is applied. Since the
speed is established independently for each record this automatically takes
into account most tape speed variations.

Data is written low-high but may be inverted when read (i.e. high-low). It is
important for the firmware to determine whether the waveform being read is
inverted or not. If this is not achieved then the bits will not be read properly as
the following example shows:

Inversion detected:

Inversion not detected:

The zero bit in the record leader is used to determine whether the recording
has been inverted.

Bytes written to the tape are written with the most significant bit first and the
least significant bit last.

8.4 The Header Record.


The header record in a file block contains information about the file and about
the data in the following data record. Some of the entries in the header are
used by the system for various purposes. The remaining entries are available
for the user to set when writing a file, and to read when reading a file. These
entries are the file type (byte 18) and all the user fields (bytes 24..63)
including the logical length (bytes 24..25) and the entry address (bytes
26..27). The user fields will all be set to zero if they are not used.

The header is laid out as follows:

System fields

Bytes 0..15 Filename Padded to 16 bytes with nulls.

Byte 16 Block number The first block is normally block 1 and


block numbers increase by 1 on successive
blocks.
Byte 17 Last block A non-zero value means that this is the last
block of a file.
Byte 18 File type A value recording the type of the file (see
below).
Bytes 19..20 Data length The number of data bytes in the data record.
Bytes 21..22 Data location Where the data was written from originally.
Byte 23 First block A non-zero value means that this is the first
block of a file.

User fields

Bytes 24..25 Logical length This is the total length of the file in bytes.

Bytes 26..27 Entry address The execution address for machine code
programs
Bytes 28..63 Unallocated These are unallocated and may be used as
required.

The file type (byte 18) is split into a number of fields:

Bit 0 Protection If this bit is set the file is protected in


some way.

Bits 1.3 File contents 0 = Internal BASIC.


1 = Binary.
2 = Screen image.
3 = ASCII.
4..7 are unallocated.

Bits 4..7 Version ASCII files should be version 1, all other


files should be version 0.
8.5 Read and Write Speeds.
The Cassette Manager is capable of reading and writing data at speeds
ranging from 700 baud to 2500 baud. There are two speeds commonly used
in this range, 1000 baud (the default speed selected at EMS) and 2000 baud.
The default speed is chosen to be near the slowest speed to give maximum
reliability. The reliability at 2000 baud is still good, however, particularly
when playing back on the same machine that was used to record a tape.

Bits are written to the tape as a single cycle of a tone. The tone for a one
always has half the frequency of the tone for a zero. Thus ones are twice as
long as zeros on the tape. This means that the baud rates given above are
only averages and vary according to the actual data written.

Even with the built in cassette mechanism the Cassette Manager has to
precompensate the waveform written to the tape to achieve the speeds
quoted. This means that the lengths of bits written are altered (ones
lengthened, zeros shortened) to try to make the waveform read closer to the
ideal after the edges of the waveform have been shifted by the cassette
circuitry.

It is only necessary to set the Cassette Manager’s write speed. When reading
a record from tape the record leader is used to calculate the speed at which it
was written. This also allows for tape speed variations between different
machines.

8.6 Cataloguing.
To generate a catalogue from the tape the Cassette Manager reads a sequence
of file blocks and prints information from them. The file blocks may come
from any file, in any order. Cataloguing continues until the user hits the
escape key.
The information is reported as follows:

FILENAME block N L Ok

FILENAME is either the name of the file or ‘Unnamed file’ if the filename
starts with a null.

The block number, N, indicates which block of the file it is. Normally block
1 is the first block of a file.

L is a character representing the file type and protection status of the file. It is
formed by adding #24 (character ‘$‘) to the file type from the header masked
with #0F. This gives the following characters:

$ an unprotected BASIC program.


% a protected BASIC program.
& a binary file.
' a protected binary file
* an ASCII file.
Other characters are possible but the above are the standard file types that are
written by the on board ROM.

The above information is printed when the header record is read correctly.

Ok is printed after the data record has been read correctly.

8.7 Reading Files.


Before a file can be read from it must be opened (by calling CAS IN OPEN).
This sets up the filename (see 8.10 below) and reads the first block of the file
so that the header can be inspected.
The file may either be opened for character input or for direct input, but not
both. The mode of input is set by the first access to the file and not when it is
opened. As soon as one mode is selected it becomes impossible to use the
other mode to access the file.
Character input (calling CAS IN CHAR) allows the user to read the file
sequentially one character at a time. Blocks of the file are read from tape into
the buffer as needed. This is intended for reading text files and similar
applications.
Direct input (calling CAS IN DIRECT) reads the whole of the file into
memory in one go. This is intended for loading machine code programs or
screen dumps and similar applications.
Interrupts are disabled whilst reading from tape because this has serious
timing constraints. Disabling interrupts will prevent the various timer
interrupts (as described in section 10.1) from occuring. In particular this
might leave the sound chip making a noise for a long period of time and so
the Sound Manager is shut down (see SOUND RESET).
In V1.1 firmware the cassette manager routines for reading files return error
codes to indicate the cause of the errors (for compatibility with AMSDOS):
#00: The user hit escape
#0E The stream is already/not in use
#0F: Have reached the end of the file

8.8 Writing Files.


Before a file can be written to it must be opened (by calling CAS OUT
OPEN). This sets up the filename (see 8.10 below) and the rest of the header
that will be written in each file block.

The file may either be opened for character output or for direct output, but
not both. The mode of output is set by the first write to the file and not when
it is opened. As soon as one mode is selected it becomes impossible to use
the other mode to write to the file.

Character output (calling CAS OUT CHAR) allows the user to write to the
file one character at a time. The characters are buffered until a complete
block (2048 characters) is ready to be written whereupon a file block is
written to the tape.
Direct output (calling CAS OUT DIRECT) writes the whole of the file from
memory in one go. The data written is still packaged into 2048 byte blocks.

Whichever output mode is used, it is important to close the output file


properly (using CAS OUT CLOSE) otherwise the lastblock of the file will
not be written.

Interrupts are disabled whilst writing to tape because this has serious timing
constraints. Disabling interrupts will prevent the various timer interrupts (as
described in section 10.1) from occuring. In particular this might leave the
sound chip making a noise for a long period of time and so the Sound
Manager is shut down (see
SOUND RESET).

In V1.1 firmware the cassette manager routines for writing files return error
codes to indicate the of the errors (for compatibility with AMSDOS):

#00: The user hit escape


#0E The stream is already/not in use

8.9 Reading and Writing


Simultaneously.
The Cassette Manager allows two files to be open simultaneously. One must
be open for reading and the other for writing. Thus it is possible to read from
one file and write to another file at the same time.
When the Cassette Manager is about to read a block it asks the user to press
PLAY and this implies that the tape with the file for reading should be
loaded. Similarly, when it is about to write a block it asks the user to press
REC and PLAY and this implies that the tape to which the file is to be
written should be loaded. The Cassette Manager assumes that the tape is not
changed and that the appropriate cassette controls remain pressed as
requested until a prompt is issued. It also assumes that pressing a key means
that the prompt has been obeyed.
It is unwise to attempt to read and write simultaneously with the Cassette
Manager messages turned off. The only notification given of which tape
should be loaded is in the promptmessages.

8.10 Filenames.
When the user opens a file for reading or writing the name of the file ko be
read or written is specified. The filename is a string of any 16 characters
(#00.. #FF). If the file name specified is longer than 16 characters then it is
truncated and if it is shorter than 16 characters it is padded to 16 characters
with nulls (character #00).
When opening a file for reading a zero length filename or one that starts with
a null has a special meaning - read the next file on the tape. The Cassette
Manager searches the tape until it finds the first block of a file and it reads
this file. Once the first block of a file has been found the Cassette Manager
will only read from that file and no other.

BASIC uses a slightly extended form of the filename. If the first character of
a BASIC filename is an exclamation mark (character #21) the BASIC turns
the prompt messages off (see 8.11 below) and removes the exclamation mark
from the name. This facility is not provjded at the Cassette Manager level.
8.11 Cassette Manager Messages.
The Cassette Manager issues a number of messages to prompt and inform the
user and to warn when errors have occurred. The messages that prompt or
inform the user may be turned on or off as desired (see CAS NOISY).
Messages that inform the user of errors cannot be turned off by this
mechanism.

a. Prompt messages.

Press PLAY then any key:

This message is issued when the Cassette Manager is about to read the
first block of a file from tape or when it is about to read a block after
having written to tape (see section 8.9). It indicates that the tape
containing the file to be read should be loaded and that the PLAY
button on the recorder should be pressed. The Cassette Manager does
not issue this message at other times since it assumes that the correct
tape is still loaded andthat the PLAY button is still pressed.

Press REC and PLAY then any key:

This message is issued when the Cassette Manager is about to write the
first block of a file to tape or when it is about to write a block after
having read from tape. It indicates that the tape on which the file is to
be written should be loaded and that the REC and PLAY buttons on the
recorder should be pressed. The Cassette Manager does not issue this
message at other times since it assumes that the correct tape is still
loaded and that the REC and PLAY buttons are still pressed.

b. Information messages.

Found FILENAME block N


This message is printed when reading from the tape if a header record
is found that for any reason does not match the record that was
expected. This may indicate that the tape is positioned incorrectly (too
early or too late) or that the wrong tape is being played.
Loading FILENAME block N
A block of the file has been found and is being read from tape.

Saving FILENAME block N


A block of the file is being written to tape.

FILENAME in the above messages is the name of the file or ‘Unnamed


file’ if the filename starts with a null.

The block number, N, indicates which block of the file is being read or
written. The first block of a file is normally block 1, the second block 2
etc.
c. Error messages

Rewind tape

While searching for a block of the file being read, a higher numbered
block than that required has been found. The required block has been
missed. This message is often produced after a read error in the required
block when the next block is found.

Read error X

An error of some kind occurred whilst reading from the tape. The tape
should be rewound and the block played again. The X is a single letter
indicating what kind of read error occurred:

‘a’ Bit too long An impossibly long one or zero has been
measured. This often indicates reading past
the end of the record.

‘b’ CRC error Data was read from tape incorrectly.

‘d’ Block too long The data record contains more than the
expected 2048 bytes of data.

Write error a

An error occurred whilst writing to the tape. There is only one possible
write error. This indicates that the Cassette Manager was unable to
write a bit as fast as was requested. This error will never occur unless
the user has set the write speed beyond the maximum possible.

8.12 Escape Key.


The escape key on the keyboard may be used to abandon cassette operations
at certain times.
When the Cassette Manager issues one of the prompt messages it calls KM
READ CHAR repeatedly to empty the key buffer out. Then it calls KM
WAIT KEY to wait until the user presses a key to acknowledge the prompt.
If the value generated from the key the user presses is #FC, which is the
value normally generated by the escape key, then the Cassette Manager will
abandon the read or write and will return an error condition to the caller.
When reading from or writing to the cassette interrupts are disabled and the
normal keyscanning mechanism is not active. While reading or writing the
record leader the Cassette Manager itself scans the keyboard to test whether
key 66, the escape key, is pressed. If this key is found to be pressed then the
Cassette Manager abandons the read or write and returns to the caller (with
an appropriate error condition). While reading or writing the data in the
record there is no way to interrupt the Cassette Manager, thus pressing ESC
may not be detected for several seconds.
8.13 Low Level Cassette Driving.
To allow the user to produce a new filing system the record read and write
routines, CAS READ and CAS WRITE, are in the firmware jumpblock.
There is a third routine at this level, CAS CHECK, whose facilities are not
used by the higher levels of the Casssette Manager. It allows the data that has
been written to tape to be compared with the data in store. This could be used
to perform a read after write check if so desired.

Also available in the firmware jumpblock are routines to turn the cassette
motor on and off (CAS START MOTOR and CAS STOP MOTOR). It is not
necessary to turn the motor on and off around a call of CAS READ, CAS
WRITE or CAS CHECK as these routines automatically turn the motor on
and off.
9 AMSDOS

AMSDOS is a disc operating system used with all the CPC range of computers,
of course, in the case of the 464 the DDI-1 has to be fitted. AMSDOS enables
programs to access disc files in a similar manner to cassette files, indeed
existing programs which currently use the cassette should be able to use disc
files with little or no modification. The main source of incompatability will be
filenames, AMSDOS filenames must conform to CP/M standards but cassette
filenames are far less restricted.

AMSDOS has been designed to complement CP/M, not to compete with it.
They share the same file structure and can read and write each other’s files.

AMSDOS resides in the same ROM as the CP/M BIOS.

9.1 Features
AMSDOS provides the following facilities:

Switching the cassette input and output streams to and from disc. So that
all the facilities available on the cassette become available on disc.

Displaying the disc directory.

Erasing disc files.

Renaming disc files.

Selecting the default drive and user.

Whenever AMSDOS creates a new file it is always given a name with a type
part of .$$$ regardless of the given name. When the file is closed any
previous version of the file is renamed with a B A K type part and the new
version is repamed from .$$$ to its proper name. Any existing .BAK
version is deleted. This gives an automatic one level file back-up.

For example, if the disc contains the files FRED.BAS and FRED.BAK and the
user opens a file called FRED.BAS then AMSDOS will create a new file
called FRED.$$$. When the file is closed the existing FRED.BAK is deleted,
FRED.BAS is renamed to FRED.BAK and FRED.$$$ is then renamed to
FRED.BAS.

All AMSDOS facilities are implemented either by intercepting the cassette


firmware calls or by external commands.
The intercepted firmware calls are:

CAS IN OPEN
CAS IN CHAR
CAS IN DIRECT
CAS RETURN
CAS TEST EOF
CAS IN CLOSE
CAS IN ABANDON
CAS OUT OPEN
CAS OUTCHAR
CAS OUT DIRECT
CAS OUT CLOSE
CAS OUT ABANDON
CAS CATALOG

The remaining cassette firmware calls are not intercepted and remain
unaffected.

Full descriptions of both the tape and disc versions of these routines are given
in section 15.

The AMSDOS external commands are:

A Select default drive A:


B Select default drive B:
CPM Coldboot CP/M
DIR Display disc directory
DISC Redirect cassette routines to disc
DISC.IN Redirect cassette input routines to disc
DISC.OUT Redirect cassette output routines to disc
DRIVE Select default drive
ERA Erase files
REN Rename a file
TAPE Redirect cassette routines to cassette
TAPE.IN Redirect cassette input routines to cassette
TAPE.OUT Redirect cassette output routines to cassette
USER Select default user

From BASIC all these commands must be preceded by a'|'

Some of these commands require parameters.

Full descriptions of these external commands are given in section 20.


9.2 Filenames
AMSDOS filenames are upwards compatible with CP/M filenames. But in
addition the user number may also be specified and non-significant spaces are
permitted before and after the name and any embedded punctuation.

Examples:

ANAME Default user, drive, and type


10:WOMBAT.TXT Default drive, and user number 10
2A:WOMBAT.TXT User 2,on Drive A:
*.* Default drive, user, and all files
5 B : P0SSUM .55$ A name with non-significant spaces
a:aard?ark Lowercase, AMSDOS will convert to
uppercase

If given, the user number must be in the range 0..15, the drive letter must be A
or B. If either the user or the drive is given they must be followed by a colon.

The following characters may be used in the name and type parts:

a—z A—Z 0—9 !“ # $ & ‘ + — @ ↑ ‘ } { ~

Any other characters will cause the command to fail with the message:

BAD COMMAND

The characters ‘?‘ and ‘*‘ are wildcards, that is, when placed within a filename
or type it will be interpreted as ‘any valid character’. For example if the
filename
'G??E??.B*' was used in the |DIR command then the files ‘GAME1.BAS’
‘GAME1.BAK’ ‘GAME29.BAS’ and ‘GREET.BAS’, and any other matching
combinations, would be displayed in the directory.

When parsing a filename, AMSDOS shifts lower case letters into upper case
and removes bit 7.

If the user or drive is omitted then the current default values are assumed.
These defaults may be set by the user.

If the type part is omitted then a default type is assumed. This depends on the
context in which the name is being used, but usually a default type part of three
spaces is assumed.

9.3 File Headers


Cassette files are subdivided into 2K blocks, each of which is preceded by
header. CP/M files do not have headers. AMSDOS files may, or may not, have
a header depending on the contents of the file. This will not cause problems for
programs written in BASIC but is an important difference between cassette and
disc files.
Unprotected ASCII files do not have headers. All other AMSDOS files have a
single header in the first 128 bytes of the file, the header record. These headers
are detected by checksumming the first 67 bytes of the record. If the checksum
is as expected then a header is present, if not then there is no header. Thus it is
possible, though unlikely, that a file without a header could be mistaken for
one with a header.

The format of the header record is as follows:

Bytes 0. .63 Cassette/Disc header (see below)


64. .66 Length of the file in bytes, excluding the header
record. 24 bit number, least significant byte in
lowest address
67..68 Sixteen bit checksum, sum of bytes 0..66
69.. 127 Undefined

The use that the cassette manager makes of the header is described in section
8.4. AMSDOS uses the header as follows:

Bytes

Filename 0 User number, #00.. #OF


1...8 Name part, packied with spaces
9...11 Type part, padded with spaces
12...15 #00

Block number 16 Not used, set to 0

Last block 17 Not used, set to 0

File type 18 As per cassette

Data length 19.. .20 As per cassette

Data location 21...22 As per cassette

First block 23 Set to #FF, only used for output files

Logical length 24.. .25 As per cassette

Entry address 26.. .27 As per cassette

Unallocated 28.. .63 As per cassette


When a file without a header is opened for input a fake header is constructed in
store as follows:

Bytes

Filename 0 User number, #00..#OF


1..8 Name part, padded with spaces
9.11 Type part, padded with spaces
12.15 #00
File type 18 #16, unprotected ASCII version 1
Data location 19..20 Address of 2K buffer
First block 23 #FF

All other fields are set to zero.

9.4 Disc Organization


AMSDOS and the CP/M 2.2 BIOS support three different disc formats:
SYSTEM format, DATA ONLY format, and IBM format. The CPIM Plus
BIOS supports the SYSTEM and DATA formats but not IBM format.

The BIOS automatically detects the format of a disc. Under CPIM this occurs
for drive A at a warm boot and for drive B the first time it is accessed. Under
AMSDOS this occurs each time a disc with no open files is accessed. To
permit this automatic detection each format has unique sector numbers as
detailed below.

3 inch discs are double sided, but only one side may be accessed at a time
depending on which way round the user inserts the disc. There may be different
formats on the two sides.

Common To All Formats


Single sided (the two sides of a 3 inch disc are treated separately).

512 byte physical sector size.

40 tracks numbered 0 to 39.

1024 byte CP/M block size.

64 directory entries.
System Format
9 sectors per track numbered #41 to #49.

2 reserved tracks.

2 to 1 sector interleave.

The system format is the main format supported, CP/M can only be loaded
(Cold Boot) from a system format disc. CPIM 2.2 also requires a system
format disc to warm boot. The reserved tracks are used as follows.

Track 0 sector #41: bootsector.


Track 0 sector #42: configuration sector
Track 0 sectors #43..#47: unused

Track 0 sectors #48..#49 and


Track l sectors #41..#49: CCP and BIOS

CP/M Plus only uses Track 0 sector #41 as boot sector


Track 0 sector #42... #49 and Track 1 are unused.

Note: Another format called ‘VENDOR’ format is a special version of system


format which does not contain any software on the two reserved tracks. It is
intended for use in software distribution.

Data Only Format


9 sectors per track numbered #C1 to #C9.

0 reserved tracks.

2 to 1 sector interleave.

This format is not recommended for use with CP/M 2.2 since it is not possible
to ‘warm boot’ from it. However, because there is a little more disc space
available it is useful for AMSDOS or CP/M Plus.

IBM Format
8 sectors per track numbered 1 to 8

1 reserved track

no sector interleave

This format is logically the same as the single-sided format used by CP/M on
the IBM PC. It is intended for specialist use and is not otherwise recommended
as it is not possible to ‘warm boot’ from it.
9.5 Boot Sector
In order that non-CP/M systems may be implemented at a later date the BIOS
initialization is performed, in part, by a boot program which is read from the
disc before attempting to load CPIM. In the non-CP/M case the boot program
would not jump to the warm boot routine but go its own way, using the BIOS
and firmware routines as desired.

The boot program is in the boot sector which is the first sector (sector #41) on
track 0. During a cold boot the BIOS is initialized into a minimum state before
loading and executing the boot program. This state is as follows.

All the routines in the ROM copy of the BIOS jumpblock and all routines
in the extended jumpblock are available.

Alternate and IY register saving is enabled.

Interrupts are indirected via the BIOS and run on the BIOS’s stack.

Disc messages are enabled.

The initial command buffer is empty.

The IOBYTE at #0003 is initialized to #81 (LST:=LPT:,PUN:=TTY:,


RDR:=TTY:,CON:=CRT:).

The current drive at #0004 is initialized to #00.

The serial interface is not initialized.

The CCP and BDOS are not in store.

The BIOS RAM jumpblock is not in store.

The CP/M jumps at #0000 and #0005 are not initialized.

The boot sector is read and loaded into store at #0100; the stack pointer is
initialized to a value immediately below the BIOS’s data (#AD33 is normal)
area and the boot program is entered at #0100. The boot program may use store
from #0100 upwards until it reaches the stack.

To run CP/M the boot program must, at least, jump to the warm boot entry in
the ROM jumpblock.

The boot program for CP/M 2.2 loads and obeys the configuration sector and
then warm boots CP/M.

The boot program for CP/M Plus searches for, loads and executes a file with
the type part .EMS.
The boot program has the following interface:

Entry:
SP= highest address available + 1 (a good place for the stack)
BC = address of ROM copy of BIOS jumpblock (BOOT)

Exit:
To run CP/M the program should jump to the WBOOT entry in the above
jumpblock

The ROM copy of the BIOS jumpblock should not be used at any other time
(indeed, only the boot program knows where it is).

9.6 AMSDOS Messages


AMSDOS uses the CP/M 2.2 BIOS in order to access the disc. Thus BIOS
messages will be displayed in the event of a disc error. This section explains
the meaning of the AMSDOS messages.

In the following <drive> means A or B, <filename> means an AMSDOS


filename.

Bad command

There is a syntax error in a command or filename.

<filename> already exists

The user is trying to rename a file to a name which is already in use.


<fi1ename> not found
The user is trying to open for input, erase or rename a file that does not exist.
Drive <drive>: directory full
There are no more free directory entries (64 directory entries per disc).
Drive <drive>: disc full
There are no more free disc blocks.
Drive <drive>: disc changed, closing <filename>
The user has changed the disc while files were still open on it.

<filename> is read only

The user is trying to erase or rename a file which is marked read-only. May
also be caused by closing a file when existing version of the file is read-only.
9.7 BIOS Facilities Available To
AMSDOS
AMSDOS uses the CP/M BIOS 2.2 to access the disc. In order that a program
running under AMSDOS may access the disc directly nine of the BIOS
extended ‘jumpblock routines are available.The routines are accessed as
external commands. An example of using these commands is given in section
10.6.

NOTE: The BIOS extended jumpblock itself is not available, indeed it does
not exist in an AMSDOS enviroment.

The BIOS routines available and their command names are as follows:

SET MESSAGE CtrlA (#01)


SETUP DISC CtrlB (#02)
SELECT FORMAT CtrlC (#03)
READ SECTOR CtrlD (#04)
WRITE SECTOR CtrlE (#05)
FORMAT TRACK CtrlF (#06)
MOVE TRACK CtrlG (#07)
GET DR STATUS CtrlH (#08)
SET RETRY COUNT CtrlI (#09)

These routines are described in section 19.

The word at #BE4O contains the address of the disc parameter header vector.
Disc parameter headers and extended disc parameter blocks may be patched as
required (see section 9.8).

Only the BIOS facilities mentioned here maybe used from a program
running under AMSDOS.

9.8 Store requirements


When initialized AMSDOS reserves #500 bytes of memory from the memory
pool and the kernel reserves another 4 for its external command chaining
information.

When loading a machine code program from disc into store using the
AMSDOS routine CAS IN DIRECT it is important that AMSDOS’s variables
are not overwritten. This presents a problem since in general it is not possible
to discover where these variables are! This is because variables for expansion
ROMs are allocated dynamically. Note that this problem does not arise when
loading from the cassette since the cassette manager’s variables are in the
firmware variable area.

AMSDOS reserves store from the top of the memory pool so the simplest
solution is to always load machine code programs into the bottom of store. The
program can then relocate itself to a higher address if required.
Alternatively the machine code program could be loaded in two stages: first
load and run a small loader in the bottom of store. The action of MC BOOT
PROGRAM will have shut down all RSXs and extension ROMs. The loader
program should now initialize AMSDOS using KL INIT BACK thus forcing
the AMSDOS variables to be wherever you so wish. The loader can now load
the machine code program using the AMSDOS routines CAS IN OPEN, CAS
IN DIRECT, and CAS IN CLOSE together with MC START PROGRAM.

In order to initialize AMSDOS using KL INIT BACK, AMSDOS’s ROM


number is required. To determine AMSDOS’s ROM number look at any of the
intercepted cassette jumpblock entries with the DISC routines selected. Each
entry is a far call, the address part of which points at a three byte far address,
the third part of the far address is the ROM number. Obviously this must be
done before AMSDOS is shut down.

Existing machine code programs, developed on cassette systems without any


expansion ROMs, frequently only use store to #ABFF in order to avoid
BASICs variables. These can easily be modified to use AMSDOS. Write some
machine code to initialize AMSDOS using KL INIT BACK. AMSDOS will
reserve RAM down to #ABFC, almost the same as used by BASIC.

9.9 Extended Disc Parameter Blocks


In order to facilitate reading and writing ‘foreign’ discs of differing formats,all
the parameters concerning a drive are kept in RAM in an extended CP/M disc
parameter block (XPB). The knowledgeable user may patch an XPB.

There are two XPBs, one per drive.

XPB structure:
bytes 0...14: standard CP/M 2.2 DPB (see below).
byte 15: first sector number.
16: number of sectors per track.
17: gap length (read/write).
18: gap length (format).
19: filler byte for formatting.
20: log2 (sector size) - 7, ‘N’ for µPD765A.
21: sector size/128.
22: reserved : current track (set by BIOS).
23: reserved: #00 ⇒ not aligned, #FF ⇒ aligned
(setbyBlOS).
24: #00 ⇒ autoselect format, #FF ⇒ don’t autoselect format.

The XPB for a drive may be found by accessing the Disc Parameter Header
(DPH) vector. The first word of the DPH is the address of the XPB for drive A,
the second word is the address of the XPB for drive B. The address of the DPH
is stored at location #BE40.
The values stored in the standard CP/M 2.2 DPB (Disc Parameter Block) are
often derived from the data block allocation size, BLS, which is the number of
bytes in a block and which may be 1024, 2048, 4096, 8192 or 16384. The
value of BLS is not stored in the DPB but it may be deduced from values
stored there. CP/M plus has a slightly different DPB. The CP/M 2.2 DPB is
laid out as follows:
Bytes 0.. 1 (SPT): Total number of 128 byte records on each track.
2 (BSH): log2 BLS-7.
3 (BLM): BLS/128 -1
4 (EXM): If DSM<256 then BLS/1024-1 else BLS/2048-1.
5..6 (DSM): Total size of disc in blocks excluding any
reserved tracks.
7. .8 (DRM): Total number of directory entries-1.
9.. 10 (ALO/1): Bit significant representation of number of
directory blocks (#0080 ⇒ 1, #00C0 ⇒ 2etc).
11..12 (CKS): Length of checksum vector. Normally DRM/4 + 1
but if checksumming is not required then 0.
13.. 14 (OFF): Number of reserved tracks. This is also the track
on which the directory starts.

The XPBs for the different formats are initialized as follows:

System Format
36 records per track
3 blockshift
7 block mask
0 extent mask
170 number of blocks-i
63 number of directory entries-i
#00C0 2 directory blocks
16 size of checksum vector
2 reserved tracks
#41 first sector number
9 sectors per track
42 gap length (read/write)
82 gap length (format)
#E9 fillerbyte
2 log2 (sector size)-7
4 records per track
0 current track
0 not aligned
0 do auto select format
Data Only Format
36 records per track
3 block shift
7 block mask
0 extent mask
179 number of blocks-1
63 number of directory entries-1
#00C0 2 directory blocks
16 size of checksum vector
0 reserved tracks

#C1 first sector number


9 sectors per track
42 gap length (read/write)
82 gap length (format)
#E9 filler byte
2 log2 (sector size)-7
4 records per track
0 current track
0 not aligned
0 do auto select format

IBM Format
32 records per track
3 blockshift
7 block mask
0 extent mask
155 number of blocks-1
63 number of directory entries-1
# 00C0 2 directory blocks
16 size of checksum vector
1 reserved tracks

#01 first sector number


8 sectors per track
42 gap length (read/write)
80 gap length (format)
#E9 fillerbyte
2 log2 (sector size)-7
4 records per track
0 current track
0 not aligned
0 do auto select format
10 Expansion ROMs, Resident
System Extensions and RAM
Programs.
The system can address up to 252 expansion ROMs, mapped over the top 16K
of memory, starting at #C000. The Kernel supports two varieties of expansion
ROM, foreground and background. A resident system extension (RSX) is
similar in use to a background ROM, but must be loaded into RAM before it
can be used.

A foreground ROM contains one or more programs, only one of which may be
running at one time. The on-board BASIC is the default foreground program.
Other possible foreground programs are:

- other systems, such as FORTH or CP/M.


- applications, such as a Word Processor or Spread Sheet.
- tools, such as an Assembler or Debugger.

A RAM program, once loaded, takes over the machine in much the same way
as a foreground ROM program. Games will generally be RAM programs.

There may be up to 16 background ROMs, each of which provides some sort


of service independent of the foreground program. It is expected that expansion
peripherals will each have an associated background ROM containing suitable
support routines. Other background ROMs may augment the existing machine
software; for example, by providing further graphics functions.

A resident system extension (RSX), once loaded, provides some sort of service
in the same way as a background ROM. An RSX might, for example, provide
special support for a given printer - where it is more economic to provide the
software on cassette rather than in ROM (or PROM).

10.1 ROM Addressing.


Expansion ROMs have ROM addresses in the range O..251. To select a given
ROM the Kernel sets its ROM address by writing to I/O address #DF00. If a
ROM is fitted at the address selected, then all further read accesses to the top
16K of memory will return data from the expansion ROM. If no ROM is fitted
at the currently selected ROM address the contents of the on-board ROM are
returned.

When the machine is first turned on ROM 0 is selected as the foreground


program. If no expansion ROM is fitted at ROM address 0, the on-board ROM
is used, and BASIC is entered. If an expansion ROM is fitted at ROM address
0 it takes precedence over the on-board ROM.
In V1.0 firmware background ROMs must be fitted at ROM addresses in the
range 1...7. Foreground ROMs must be fitted so that there are contiguous
ROMs from address 1. When searching for a foreground ROM the kernel starts
at address 0 and works upwards until the first unused address greater than 0 is
found.
In V1.1 firmware background ROMs may be fitted at ROM addresses in the
range 0.. .15. Foreground ROMs must be fitted contiguously from address 16
or at any background ROM address. When searching for a foreground ROM
the kernel starts at address 0 and works upwards until the first unused address
greater than 15 is found. In either case if an expansion ROM 0 is fitted the on-
beard ROM can still be accessed at the first unused ROM address.
The Kernel supports a ‘far address’ which may be used to call subroutines in
expansion ROMs. The ‘far address’ is a three byte object, the last byte of
which is a ROM select number. Since the arrangement of ROMs in an
expansion card is quite arbitrary the ROM select part of a ‘far address’ must be
established at run time. The ‘sideways’ ROM addressing facility allows a
foreground program to occupy up to four contiguous ROM select addresses,
and supports subroutine calls between the ROMs without requiring the
program to know the actual ROM address of any of them.

10.2 The Format of an Expansion ROM.


An expansion ROM may be up to 16K bytes long, the first byte being at
address #C000. The first few bytes of the ROM are the ‘ROM Prefix’ and must
take the form:
Byte 0: ROM Type.
Byte 1: ROM Mark Number.
Byte 2: ROM Version Number.
Byte 3: ROM Modification Level.
Byte 4: External Command Table.
The ROM type specifies what sort of ROM this is and must take one of the
following values:
0: Foreground ROM
1: Background ROM
2: Extension ROM
The on-board ROM must be unique in having bit 7 of the type byte set (thus its
type byte is #80). This marker is used to detect the end of foreground ROMs. If
a foreground program will not fit into a single ROM then the extra ROMs
required should be marked as extension ROMs.
The mark number, version number and modification level may be set to any
values required.
The external command table comprises a list of command names and a
jumpblock. Each comm~and name is implicitly associated with the same
numbered entry in the jumpblock. The table takes the form:
Bytes 0.. 1 : Address of command name table
Bytes 2. .4 : Jumpblock entry 0
Bytes 5..7 : Jumpblock entry 1
…etc : … etc
The command name table is a list of names, each of which may be up to 16
characters long. The last character of each name must have bit 7 set but no
other character may. The table is terminated by a null (character 0) after the
last character of the last name. Apart from the fact that all characters must be in
the range 0.. 127 and that the first character may not be a null, there are no
restrictions on the characters in command names. However, if unsuitable
characters are chosen it may prove impossible for programs such as BASIC to
access the commands. BASIC expects alphabetic characters in the command
names to be in upper case and will not allow characters such as space or
comma in the command name.

The ROM prefix for the on-board ROM is:


ORG #C000 ; Start of the ROM
DEFB #80+0 ; On board ROM, Foreground
DEFB 1 ; Mark l
DEFB 0 ; Version 0
DEFB 0 ; Modification 0
DEFW NAME_TABLE ; Address of name table.
JP START_BASIC. ; The only entry in the
jumpblock
NAME_TABLE: DEFB ‘BASI’,’C’+ #80 ; The only command name
DEFB 0 ; End of name table marker

The ROM prefix for a serial I/O card might be:


ORG #C000 ; Start of ROM
DEFB 1 ; BackgroundROM
DEFB 0 ; Mark0
DEFB 5 ; Version 5
DEFB 0 ; Modification 0

DEFW NAME_TABLE ; Address of name table

JP EMS_ENTRY ; 0 Background ROM power-up


entry
JP RESET ;1
JP SET_BAUD_RATE ;2
JP GET_CHARACTER ;3
JP PUT_CHARACTE ;4
…etc

NAME_TABLE: DEFB ‘SlO DRIVE’,’R’+ #80 ;0


DEFB ‘SIO.RESE’,’T’+ #80 ;1
DEFB ‘SIO.SET.BAU’,’D’+ #80 ; 2
DEFB ‘SIO.GET.CHA’,’R’+ #80 ; 3
DEFB ‘SIO.PUT.CHA’,’R’÷ #80 ; 4
…etc
DEFB 0 ; End of nametable marker
Note that the command name table entry for the power-up entry includes a
space.
This is still a legal name but the BASIC will never be able to generate it
because of the way it uses spaces. Because BASIC cannot generate the name it
is impossible for a BASIC user to call the power-up entry by mistake (see
section 10.4).

10.3 Foreground ROMs and RAM


Programs.
Each of the entries to a foreground ROM is expected to represent a separate
program, whose name is given by the corresponding entry in the name table.
The first entry of ROM 0 is the default power-up entry point at the end of
EMS.

Once a RAM program has been loaded it is treated much like a foreground
ROM, except that it does not have a ROM prefix, and the required entry point
is determined separately.

Just before a foreground program is entered the machine is reset to its EMS
state; i.e. all the hardware and all the firmware are initialized. The environment
and entry conditions are as follows:

Memory:
Section 2 describes the memory layout of the system. Three areas of
memory are available to the program:

1. The Static Variables Area.

The area from #AC00 to #B0FF inclusive is reserved for use by the
foreground program - although it may use more or less as it requires. It is
also possible to reserve a foreground data area starting at #0040 if this is
required.

2. The Stack.

The hardware stack is set to an area immediately below #C000 which is at


least 256 bytes long.

3. The Main Memory Pool.

Most of the rest of memory will be available to the foreground program,


depending on what memory is taken by any background ROMs which the
foreground program chooses to initialize.

Registers:
The base and limit of the free memory area are passed to the program in
registers.

BC = Address of the highest usable byte in memory. (# B0FF)


DE = Address of the lowest byte in the memory pool. (#0040)
HL = Address of the highest byte in the memory pooi. (#ABFF)
Note that the program is free to use any memory between the address
given in DE and the address in BC inclusive (i.e. #0040 to #B0FF). The
contents of HL reflect the standard allocation for static variables; the
program is free to use more, or less, as the mood takes it. Also a
foreground data area may be reserved at the bottom of store as well. The
program should set HL and DE to reflect the area it is using for variables
before initializing any background ROMs (see below).

SP is set to the machine provided area at #C000. The program can depend
on at least 256 bytes of stack.

The contents of the other registers is indeterminate. Note that the alternate
register set (AF’ BC’ DE’ HL’) is not available to the program. (But see
Appendix XI).

ROM select and state:


For ROM programs: The foreground ROM is selected.
The upper ROM is enabled.
The lower ROM is disabled.
For RAM programs: No ROM is selected.
The upper ROM is disabled.
The lower ROM is disabled.

General:
Interrupts are enabled.
All hardware and firmware is in its initial state. In particular any
expansion devices fitted have been reset, but not yet initialized.

It is the foreground program’s responsibility to initialize any background


ROMs required and to load and initialize any RSXs. The Kernel entry ‘KL
ROM WALK’ looks for background ROMs and initializes any that it finds.
The Kernel entry ‘KL INIT BACK’ will initialize a particular background
ROM. These entries must be passed the addresses of the lowest and highest
bytes in the memory pooi which is why the foreground program must reserve
its fixed data areas before winding up the background ROMs. The background
ROMs may allocate memory for their own use by moving either or both
boundaries. If, therefore, the foreground program does allow background
ROMs to function it must cope with a memory pool whose bounds are not
fixed until after all the background ROMs have been initialized. Note that the
location of the foreground program’s data areas are fixed whilst a background
program must deal with variable data areas.

If background ROMs are not initialized then the memory map is very simple,
but since discs, light pens, etc are likely to use background ROMs for support
software it is rather limiting not to allow background ROMs even for an
apparently ‘dedicated’ game.

The on-board BASIC initializes all background ROMs at EMS. The user
chooses whether to load any RSXs from tape.
10.4 Background ROMs.
Background ROMs lie dormant until initialized by the foreground program.
During initialization the background software may allocate itself some memory
and initialize any data structures and hardware. Providing the initialization is
successful the Kernel places the ROM on the list of possible takers for external
commands.
The first entry in a background ROM’s jumpblock is its initialization routine.
This routine must only be called by the firmware when the ROM is initialized
it is not meant for the user to call. Tricks such as including a space in the name
makes it impossible for BASIC to generate the correct name and hence
impossible for a BASIC user to call the entry. The entry and exit conditions for
the initialization routine are:

Entry:
DE contains the address of the lowest byte in the memory pool.
HL contains the address of the highest byte in the memory pool.

Exit:
If the initialization was successful:
Carry true.
DE contains the new address of the lowest byte in the memory pooi.
HL contains the new address of the highest byte in the memory pool.

If the initialization failed:


Carry false.
DE and HL preserved.

Always:
A, BC and other flags corrupt.
All other registers preserved.
Notes:

The upper ROM is enabled and selected.


The lower ROM is disabled.
The routine may not use the alternate register set.

The ROM may allocate itself memory either at the top or the bottom of
the memory pooi or both), simply by changing the appropriate register
and returning the new value. For example, to reserve 256 bytes given an
address of #AB7Fas the top of the pool the program would subtract 256
from HL giving a new top of pool address of #AA7F. The area reserved
would be from #AA8O to #AB7F inclusive.

The carry false return is only recognized in V1.1 firmware. In V1.0


firmware this will be treated as if carry was returned true.
When the initialization routine returns, the Kernel stores the address of the base
of the upper area which the ROM has allocated to itself (i.e. HL+l). Whenever
an entry in the ROM is called this address is passed in the IY index register.
This allows the ROM routines to access its upper variable area easily even
though it was allocated dynamically. Access to any lower variable area should
be done via pointers in the upper area. Since background ROMs do not use
absolute areas of memory, problems of background ROMs clashing with each
other or with the foreground program will never arise. Note that a background
ROM is very likely to expect that its upper data area lies above #4000 so that it
is accessible irrespective of whether the lower ROM is enabled or not.

If the initialization is successful then the Kernel also places the ROM on its list
of possible handlers of external commands (see below). Note that when the list
is scanned for external commands the latest addition is tried first. The entry KL
ROM WALK processes the ROMs in reverse address order (15, 14, ... 0),
ignoring any gaps or foreground ROMs, thus the ROMs will be searched in the
order 0, 1, .. .15.

10.5 Resident System Extensions.


An RSX is similar to a background ROM. Responsibility for loading an RSX
and providing it with memory lies with the foregroui~d program. To fit in with
the dynamic allocation of memory to background ROMs it is recommended
that RSXs should be position independent or relocated when loaded. An RSX
could be relocated by writing a short BASIC ‘loader’ program which reads the
RSX in a format which may be relocated easily and POKEs it into store.

Once an RSX is loaded it may be placed on the list of possible handlers of


external commands (see following page) by calling KL LOG EXT, passing it
the address of the RSX’s external command table and a four byte block of
memory (in the central 32K of RAM) for the Kernel’s use. The format of the
table is exactly the same as for a background ROM see section 10.2). The only
difference is in the interpretation of the table - the first entry in the jumpblock
is not called automatically by the Kernel and thus need not be the RSX’s
initialization routine.
For example, the way to add an external command table for a graphics
extension for BASIC might be:

INITIALIZE: LD HL,WORK_SPACE ;RSXpower-up Routine


LD BC,RSX_TABLE
JP KL_LOG_EXT

WORK_SPACE: DEFS 4 ;Area for Kernel to use

RSX_TABLE: DEFW NAME_TABLE

JP DRAW_CIRCLE ;0
JP DRAW_TRIANGLE ;1
JP FILL_AREA ;2

NAME TABLE: DEFB ‘CIRCL’,’E’+#80 ;0


DEFB ‘TRIANG’ , ‘L’ + #80 ;1
DEFB ‘FIL’ , ‘L’ + #80 ;2
DEFB #00

Note that when the list is scaned for external commands the latest addition is
tried first. Since RSX’s will, in general, be loaded after background ROMs
have been initialized, RSX commands will take precedence over those in
background ROMs. The entry and exit conditions for external commands are
discussed in the following section (section 10.6).

10.6 External Commands.


Once the foreground program has decided that it has an external command on
its hands it should call the Kernel entry KL FIND COMMAND, passing to it a
string giving the command name. This routine first attempts to find an RSX or
a background ROM whose external command table contains the command.
Only those RSXs and ROMs which have been suitably initialized are taken into
consideration. If the command is found then the ‘far address’ of the
corresponding jumpblock entry is returned (see section 2.3). If the command is
not found the routine starts at ROM 0 and searches for a foreground ROM
whose external command table contains the command. If a foreground ROM is
found, then the system resets and enters the appropriate foreground program. If
no match for the command can be found a failure indication is returned.
Note that the external command mechanism allows both for the finding of
background and RSX routines, and for the switching of foreground programs.
Note also that the first command name in a background ROM corresponds to
the implicit initialization entry, and should not be used as a command.

The first time a background or RSX routine is used the external command
mechanism should be used to establish its jumpblock address. This may then
be stored and used directly for subsequent calls of the routine. It is foolish to
assume that a particular background ROM is always plugged into the same
socket or that a relocatable RSX is always located at the same address.
The first time a background or RSX routine is used the external command
mechanism should be used to establish its jumpblock address. This may then
be stored and used directly for subsequent calls of the routine. It is foolish to
assume that a particular background ROM is always plugged into the same
socket or that a relocatable RSX is always located at the same address.
It is the foreground program’s responsibility to invoke the external command
once its address has been found, and to pass it parameters in a suitable form.
BASIC in the on-board ROM functions as follows, and should serve as a model
for other foreground programs if only to allow common use of commands by
other systems:

An external command is identified by a vertical bar (‘I’) followed by the


command name, optionally followed by a list of parameters. The bar does
not form part of the command name. The command name must consist of
alphabetic characters (which are converted to upper case), numeric
characters or dots.
Parameters are passed by value, that is each parameter may be a numeric
expression, the calculated value of which is passed, or an address. The
number and type of parameters must be agreed between the BASIC
program and the command because BASIC performs no checking.
Each parameter passed is a two byte number, whose interpretation
depends on its type:
Integer expression: two’s complement value of the Integer result.
Real expression: the Real result forced to Unsigned Integer.
Variable reference: address of the value of a variable (for a string
this is the address of the descriptor).
A string descriptor is three bytes long. Byte 0 contains the length of the
string. Bytes 1 and 2 contain the address where the string is stored. If the
string length is 0 then the address of the string is meaningless. String
variables may be changed provided that the string descriptor is not altered
in any way.
Entry:
A contains the number of parameters.
IX contains the address of the parameters.
IY contains the address of the ROM’s upper data area if the command
was found in a background ROM. If the command was found in an RSX’s
external command table then IY is undefined.
Exit:
AF, BC, DE, HL, IX and IY corrupt.
Alternate register set untouched.

Notes:
Index register IX contains the address of the parameters. If there are n
parameters then the ith parameter is at offset (n-i)X2 from the index
register address so the 1st parameter is at the largest offset, and the last
-

parameter is pointed to by IX.


The IY register is set by the Kernel and not by BASIC. The A and IX
registers
10.7 Examples
a) A simple external command
This example uses the BIOS routine SET MESSAGE that is available as an
external command under AMSDOS. SET MESSAGE turns on or off the disc
error messages and has the following interface:

SET MESSAGE Command name: Control A

Entry conditions:
A= #00 => Turndiscerrormessageson.
A = #FF => Turn disc error messages off.

Exit conditions:
A = Previous state.
HL and flags corrupt.

Before it is possible to use the external command it is necessary to establish


and store the far address of the routine. This may be performed as follows:

LD HL, CMD_NAME ;Pointer to command


name
CALL KL_FIND_COMMAND ;Ask Kernel where it is
JR NC, ERROR_ROUTINE ;Command not found
error
;
LD (CMD_FAR_ADDRESS + 0), HL;Store address
LD A,C
LD (CMD_FAR_ADDRESS + 2), A ;Store ROM number

CMD_NAME: DEFB #01+#80 ;Control A = #01


CMD_FAR_ADDRESS: DEFS 3 ;Area for storing far
address

Having found the far address of the routine it can now be called. For example:

LD A, 0 ;Enable messages
RST 3 ;Far CALL
DEFW CMD_FAR_ADDRESS ;Pointer to far address
b) A complex external command
This example uses the INCHAR external command provided by the Serial
interface. INCHAR reads a character from the Serial Interface and has the
following interface:

INCHAR Command name: INCHAR

Entry conditions:

A = Number of parameters (should be 2).


IX = Address of parameter block

IX +2 = Address to store status/


IX +0 = Address to store character read.

Exit conditoins:

AF, BC, DE, HL, IX AND IY corrupt.

Before it is possible to use the external command it is necessary to establish


and store the far address of the routine. This may be performed as follows:

LD HL, CMD_NAME ;Pointer to command


name
CALL KL_FIND_COMMAND ;Ask Kernel where it is
JR NC, ERROR_ROUTINE ;Command not found
error
;
LD (CMD_FAR_ADDRESS +0), HL :Store address
LD A,C
LD (CMD_FAR_ADDRESS +2),A ;Store ROM number

CMD_NAME: DEFB ‘INCHA’, ‘R’+ #80


CMD_FAR_ADDRESS: DEFS 3 ;Area for storing far
address

Having found the far address of the routine it can now be called. For example:

LD A, 2 ;2 parameters
LD IX, PARAM_BLOCK ;Address of parameter block
RST 3 ;FAR CALL
DEFW CMD_FAR_ADDRESS ; Pointer to far address
LD HL, (STATUS) ;HL Serial Interface status
LD A, (CHAR) ;A Characterread(ifany)

PARAM_BLOCK DEFW STATUS ;First parameter is status


DEFW CHAR ;Second parameter is
character
;
STATUS: DEFW #0000
CHAR: DEFW #0000
c) Passing different types of parameter

This example uses an invented external command which takes a string of


characters, looks these up in an index and returns a reference number. The
external command is assumed to be designed to be called from BASIC as
follows:

|REFNUM, @CHARSTRING$, INDEXNUM, @REFNUM

i.e. The first parameter is a string (whose address is passed) which is to be


looked up. The second parameter is a number specifying which index to use,
and the third parameter is a variable (whose address is passed) which is to be
set to the required reference number.

The far address of the routine can be established in the same way as was
described in the previous two examples. To call this routine from a machine
code program it is necessary to set up the parameter block and a string
descriptor. The following subroutine does this:

GET_REF_NUM: ;Entry: HL = Address of string.


A = Length of string.
DE = Index number.
;Exit: HL = Reference
number.
; AF,BC,DE,IX,IYcorrupt.
LD(STR_DESCRIPTOR + 0), A ;Store length of string
LD(STR_DESCRIPTOR + 1), HL ;Store address of string
LD(PARAM_BLOCK + 2), DE ;Store index number
LD A, 3 ;3 parameters
LD IX, PARAM_BLOCK ;Address of parameter block
RST 3 ;FAR CALL
DEFW CMD_FAR_ADDRESS :Pointer to far address
LD HL, (REFNUM) ;HL=Reference number
returned
RET

PARAM_BLOCK: DEFW STR_DESCRIPTOR ;First parameter is address of


;string descriptor
DEFW #0000 ;Second parameter is index no.
DEFW REFNUM ;Third parameter is address of store
;for reference number
;
STR_DESCRIPTOR DEFB #00 ;Length
DEFW #0000 ;Address
;
REFNUM DEFW #0000
The external command routine that is being called has to pick the parameters
out of the parameter block and it might work as follows:

LD L,(IX+0)
LD H, (IX + 1) ;HL = Address of string descriptor
;
LD A,(HL)
INC HL ;A = Length of the string

LD E,(HL)
INC HL
LD D, (HL)
EX HL, DE ;HL = Address of string
;
LD E,(IX+2)
LD D,(IX +3) ;DE Index number

… ;Look up string

LD (IX+4),L
LD (IX +5), H ;Store resulting reference number
RET
11 Interrupts.

There is only one source of interrupts in an unexpanded machine, namely a


regular time interrupt. Expansion boards may generate interrupts, but suitable
software must be provided to deal with the extra interrupts.

The system runs with interrupts enabled most of the time. It is inadvisable to
disable interrupts for a prolonged period if this is avoidable because the time
interrupts will be missed.
A number of firmware routines enable interrupts and this is remarked upon in
their descriptions. In particular the Kernel routines dealing with ROMs and the
restart instructions (e.g. LOW JUMP) enable interrupts.

11.1 The Time Interrupt.


The time interrupt occurs roughly once every 1/300th Qf a second. On
machines with PAL monitors (as in the UK) or SECAM monitors (as in
France) the timer is synchronised with frame flyback every sixth tick. On
machines using NTSC monitors (as in the US) the timer is synchronised with
frame flyback every fifth tick. The time interrupt is processed by the Kernel
and presented to the rest of the system in a number of ways:

a. Fast Ticker Interrupts. Period = 1/300th of a second.


For high resolution or very short period timing (not intended for general
use).

b. Sound Generation Interrupt. Period = 1/100th of a second.


This interrupt drives the sound generation firmware, but is otherwise not
visible to the system.

c. Frame Flyback Interrupt. Period = 1/50th or 1/60th of a


second.
For actions which must take place during frame flyback. Ink flashing is
performed during a frame flyback interrupt, for example.

d. Ticker Interrupt. Period = 1/50th of a second.


This is the general purpose ticker interrupt. The keyboard is scanned at
the start of each ticker interrupt.
e. System Clock.
There is a tinier that counts fast ticks i.e. 1/300ths of a second. This can
be used to measure elapsed time without setting up a relatively expensive
fast tick event. The timer is read by calling KL TIME PLEASE and may
be set by calling KL TIME SET.

11.2 External Interrupts.


The Z80 is run in interrupt mode 1. Which is to say that all interrupts cause an
RST 7 to be executed by the processor. The interrupt handling code in the
Kernel can distinguish between the time interrupt and an external interrupt. It
does this by re-enabling interrupts inside the interrupt routine. If the interrupt
repeats then it is assumed to be an external interrupt, otherwise it is taken to be
a time interrupt. Note that this requires that the source of external interrupts
should not clear the interrupt condition until the software resets it. Unless
special action is taken in hardware, Z80 peripheral chips will not obey this
requirement. In such cases the recommended course of action is described in
Appendix XIII.

Before an external interrupt is enabled its interrupt handler must be ‘installed’.


This is done by copying the 5 bytes at address #003B to a new location and
replacing them by suitable code (probably including a jump). When the Kernel
detects an external interrupt it calls address #003B in RAM to process the
interrupt:

Entry:

No conditions.

Exit:

AF, BC, DE and HL corrupt.


All other registers preserved.

Notes:
Interrupts are disabled and must remain disabled.
The lower ROM is disabled.
The upper ROM select and state are indeterminate.
The alternate register set must not be touched.

The interrupt routine must establish whether it can deal with the interrupt, and
if so it must at least clear it. If the interrupt is not the responsibility of the
routine then it should jump to the copy of the bytes taken from location #003B
which may be competent to deal with the interrupt. This requires the code
patched at location #003B to be position independent in case a second external
interrupt handler is installed. The code put at#003B at EMS is position
independent - it merely returns.

Note that interrupt handling code must be in RAM somewhere between #0040
and #BFFF. Interrupt handlers should be as short as possible. If an interrupt
requires a lot of processing beyond that required to clear it, then the interrupt
should kick an event to do the work outside the interrupt path.
11.3 Nonmaskable Interrupts.
There is no provision for handling a nonmaskable interrupt (NMI) in the
firmware (despite the fact that NMI is available on the external bus connector).
Various firmware routines (notably those connected with driving the
Centronics port, the PPI to access the sound chip and keyboard, and the
cassette) will have timing constraints violated if NMIs occur whilst they are
active. It is recommended that NMI should not be used.

11.4 Interrupts and Events.


As a general rule hardware interrupts should be transformed into their software
equivalents, ‘events’, as soon as possible. The handling of events is more
flexible than the handling of hardware interrupts - for example there are no
restrictions on where event routines may reside, or on interrupt enabling.

Events are described by an event block. This block contains the event class, the
event count and an event routine address. When an event occurs the event
block is ‘kicked’ and the Kernel arranges for the event, routine to be called
once for each kick (the number of kicks outstanding is kept in the event block).
The event routine is not necessarily called immediately. When the event
routine is actually run depends on the event class as follows:

a. Express Asynchronous Events.

This is an unusual class of event. The event routine is called


immediately during interrupt processing. The routine must be
accessible by the interrupt code, it may not enable interrupts, corrupt
the IX or IY registers or use the alternate register set. The routine
should be as short as possible.

b. Normal Asynchronous Events.

This is the most flexible sort of event. When the event is kicked the
event routine is not called, but the event block is placed on the interrupt
event pending queue.
Once the current interrupt has been processed, just before the Kernel
returns from the interrupt path, any events on the interrupt event
pending queue are processed. While the events are being processed the
system is running with interrupts enabled and may be regarded as no
longer being in the interrupt path. It is using its own stack rather than
the main system stack. This private stack is 128 bytes long.
The asynchronous event routine is, therefore, called shortly after the
event is kicked and is not restricted in what it may do or where it may
be located. The event routine may take as long to run as is needed. Any
further kicks received during the time that the event routine is running
will be added to the event count and will be processed before returning
to the interrupted program.
c. Synchronous Events.

Synchronous events are queued on the synchronous event pending


queue. They are not processed until the foreground program allows the
queue to be processed. This can be used to control interactions between
different parts of programs.

11.5 Interrupt Queues.


The various time interrupts provide three sources of ‘kicks’ for events. The
events to be kicked when each of the interrupts occur are stored on queues, one
queue for each source of kicks. The user provides an area of store for the
Kernel’s use. The size of the area depends on which queue it is for. The last 7
bytes of the area are always an event block which the user should initialize
appropriately. Appendix X describes the layout of these blocks in greater
detail.

a. Fast Ticker Events.

Events on the fast ticker queue are ‘kicked’ on each fast ticker interrupt,
i.e.
every 1/300th of a second. A fast ticker block is 9 bytes long.

b. Ticker Events.

Each event on the ticker queue is associated with a timer. The timer may
be a ‘one shot’, which goes off once, or a repeater, which goes off
periodically. The timer counts ticker interrupts, i.e. 1/50ths of a second,
and when sufficient have occurred it goes off. Each time the timer
associated with an event goes off the event is kicked. A ticker block is 13
bytes long.

c. Frame Flyback Events.

Events on the frame flyback queue are kicked on each frame flyback
interrupt, i.e. every 1/50th of a second on PAL or SECAM machines and
every 1/60th of a second on NTSC machines. A frame flyback block is 9
bytes long.
12 Events.

The event mechanism is primarily provided by the Kernel to support the


handling of interrupts and other external events. However, the mechanism may
also be used to handle internal events in complicated programs (such as a
simulation, for example). An event is characterised by the following:

a. Event Class (see section 12.1)

Events may be synchronous or asynchronous, express or normal.

b. Event Priority (see section 12.1)

Synchronous events have an associated priority.

c. Event Count (see section 12.2)

Each time an event occurs the count is incremented.


Each time an event is processed the count is decremented.
The event may be disarmed by setting the count negative.

d. Event Routine (see section 12.3)

The address of the routine which is called to process the event.

An event appears to the Kernel as a data block containing the above values (see
Appendix X for the exact layout of an event block). The block must be in the
central 32K bytes of memory, so that the Kernel can access it without worrying
about the ROM enable state.

When an event occurs the associated event block is kicked by calling KL


EVENT. If the event count is negative, the ‘kick’ is ignored, otherwise the
event count is incremented (up to a maximum of 127) and the event routine
will be called at some time in the future - depending on the event class. When
the event routine returns the event count is decremented, unless it has been set
to zero or negative in the meantime.

12.1 Event Class.


Events are either synchronous or asynchronous. Asynchronous events are
intended for the processing of external events which require almost immediate
service. The processing of asynchronous events pre-empts the main program.
The processing of synchronous events is under the complete control of the
main program, which will, in general, deal with them when it is convenient to
do so.
a. Asynchronous Events.
An asynchronous event is processed immediately the event is kicked - or
almost immediately if the kick occurs in the interrupt path - see section 11 on
interrupts. The Kernel does not provide any interlocks between asynchronous
events and the main program or other events, so care must be exercised to
avoid interactions. It is most unwise to call routines that are not re-entrant - for
example, the firmware screen driving routines.
If the event count is still greater than zero when the event routine returns, it is
decremented. If the count remains greater than zero then the process is repeated
(the event routine is called again and the event count is decremented) until the
count becomes zero or is set negative (see 12.2 below).

b. Synchronous Events.
Synchronous events are not processed when the event is kicked, but are placed
on the synchronous event queue, waiting to be processed. Events are queued in
descending order of priority - equal priority events after those already on the
queue.
The foreground program should poll the synchronous event queue regularly, to
see if there are any events outstanding. If there are then it should then process
them. The difference between synchronous and asynchronous events is,
therefore, that the foreground program decides when synchronous events
should be processed, but the event ‘kicker’ decides when asynchronous events
are to be processed. Provided that the foreground program takes suitable care,
there should be no difficulty in handling the interactions and resource sharing
between synchronous events and the foreground program.
When the foreground program finds the synchronous event queue is not empty
it should (but is not constrained to) instruct the Kernel to process the first event
on the queue. When a synchronous event routine is run the Kernel remembers
the priority of the event. In the event routine the synchronous event queue may
be polled, but the Kernel hides any events whose priority is less than or equal
to that of the event currently being processed. When the event routine returns
the previous event priority is restored - so the processing of events may be
nested.
The synchronous event priorities are split into two ranges, express and normal.
All express events have higher priorities than all normal events. The Kernel
provides a mechanism to disable the processing of normal events, without
affecting express events. This ma~ be used to implement ‘critical regions’
through which ‘normal events may interact. The synchronous event ‘kicked’ by
the Key Manager break handling mechanIsm is an example of an express
synchronous event.

12.2 Event Count.


The main purpose of the event count is to keep track of the difference between
the number of~times the event has been kicked, and the number of times the
event has been processed. This ensures that a kick is not missed if it occurs
before the previous kick has been processed. The event count is normally
incremented when the event is kicked and decremented when the event routine
returns. However the exact action depends on the event count as follows:
Increment.

-128..-2: The count is not changed - the event is ignored.

-1: This value is illegal.

0: The count is incremented and event processing is


initiated as required by the event class.

1..126: The count is incremented but no further action is taken.


The event is waiting for a previous kick to be processed
or for processing to complete.

127: The count is not changed - the kick is ignored.

Decrement.

-128: This value is illegal.

-127..0: The count is not changed - the event has been disarmed.

1: The count is decremented and event processing is


terminated.

2.. 127: The count is decremented and event processing


continues.

Note that the event routine may disarm itself by setting the count negative (by
convention to -64) and can discard unwanted kicks by setting its count to one.

12.3 Event Routine.


In general the address of the event routine is given as a 3 byte ‘far address’ (see
section 2 on the memory layout). This allows the routine to be located in any
ROM or anywhere in RAM.

A special form of the event class may specify the routine as at a ‘near address’.
This does not change the ROM state and so the routine must be located either
in the lower ROM or in the central 32K of RAM. The ROM select byte of the
‘far address’ is ignored and the other two bytes taken as the address of the
routine. Calling a ‘near address’ event routine requires a little less work than
calling a full ‘far address’, and is used by the firmware itself.

12.4 Disarming and Reinitia1izing


Events.
Before an event block may be reinitialized the event must be disarmed. This
ensures that the event is removed from the various event pending queues and
prevents the event queues being corrupted when the event block is initialized.
An asynchronous event must not be reinitialized from inside its asynchronous
event routine (because in this case disarming the event does not remove the
event from the interrupt event pending queue).
Synchronous and asynchronous events are disarmed in different manners.
a. Asynchronous Event..

An asynchronous event should be disarmed by calling KL DISARM


EVENT. This sets the event count to a negative value (-64) and thus
prevents kicks having any effect. If the event is on the interrupt event
pending queue then it will be discarded only when an attempt is made to
process the event and not immediately that the event is disarmed.

b. Synchronous Events.

A synchronous event should be disarmed by calling KL DEL


SYNCRRONOUS. This sets the eventcount to a negative value (-64) and
removes the event block from the synchronous event pending queue (if it
is on the queue).

The above procedures prevent the event being successfully kicked, they do not
prevent attempts being made to kick the event. A fast ticker, frame flyback or
ticker event (see section 11.5) will still be on its appropriate queue and will still
be receiving regular attempts to kick it. To prevent time being wasted (and the
system from being slowed down because of it) the event should be removed
from the interrupt queue by calling KL DEL FAST TICKER, KL DEL
FRAME FLY or KL DEL TICKER.
13 The Machine Pack.
The Machine Pack deals with the low level driving of the hardware. It also
talks to the Centromcs port (and hence the printer) and is in charge of running
‘load and go’ programs.

13.1 Hardware Interfaces.


The routines provided for driving the hardware are only to be used by those
who understand the hardware and how the firmware drives the hardware. The
user should not access the hardware directly when a Machine Pack routine is
provided for this purpose.

Often there are higher level roubines that accomplish the same effects but that
also keep the firmware informed of the current settings. Where possible these
higher level routines should be used and the Machine Pack routines avoided.
Using the Machine Pack routines may cause the firmware to make erroneous
assumptions about the current settings and may cause it to go wrong.

The Machine Pack makes certain assumptions about the state of the hardware
when it accesses it. In particular, PPI port A is assumed to be in output mode
and the sound chip, ULA, CRTC and Centronics port are assumed to be
inactive; that is, not halfway through setting a value into a chip register. It is
usually essential that interrupts be disabled when accessing the hardware
directly.

There are four main areas of the hardware that the Machine Pack deals with:

a. The screen.
There are three aspects of the screen display thatcan be set using Machine
Pack routines. These are the screen mode (set by calling MC SET
MODE) and the screen base and offset (set by calling MC SET
OFFSET).

The screen mode sets how many pixels are displayed on the screen and
how many inks may be used as follows:

Mode Resolution Inks


0 160x200 16
1 320x200 4
2 640x200 2

The screen base sets which 16K block of memory is used for the screen
memory. Theoretically, any of #0000, #4000, #8000 or #C000 could be
used but, in practice, other considerations mean that only #4000 and
#C000 are useful.
The screen offset sets which byte in the screen memory is to be displayed
first. Changing the offset will move the contents of the screen in one go.
This is used for rolling the screen.
A fuller description of the screen layout and its relationship to these
aspects can be found in section 6 on the Screen Pack.
If addresses are to be read back from the CRT controller chip, when using
a light pen for instance, then careful inspection of the way the screen
memory is addressed will be needed to translate the screen address read
from the chip to the actual position on the screen.
The Machine Pack also provides a routine (MC WAIT FLYBACK) to
wait until frame flyback occurs (the start of the vertical retrace period).
This may be used to ensure that operations on the screen are performed
with as little disruption as is possible to the picture on the monitor since
no picture is generated during this period. As an alternative to waiting for
frame flyback explicitly the user should consider setting up a frame
flyback event as described in section 11.5.
The vertical retrace period is not very long. Furthermore, approximately
100 microseconds from its start, a time interrupt occurs that will cause the
frame flyback events to be processed (see section 11). These may take a
significant length of time out of the retrace period.

b. The inks.

The Machine Pack deals with setting the colours of inks. There is a fuller
explanation of the relationship between inks and colours In section 6.2.
Briefly, the colour for each ink and the border can be specified
independently and changed at will. Note, however, that the Machine Pack
deals with the hardware representations of colours and not the grey scale
colours that the Screen Pack uses and also that an ink may only be set to
one colour, the flashing inks are made by the Screen Pack setting two
colours alternately.
Two routines are provided for setting the colours of inks. MC SET INKS
allows the colours of all 16 inks and the border to be set (although not all
of the inks may be visible on the screen in the current mode). MC CLEAR
INKS sets the colour of the border ink and sets all 16 inks to the same
colour. The latter is used when clearing the screen to make the operation
appear instantaneous.

c. The sound chip.

A routine, MC SOUND REGISTER, is provided to write to a register of


the sound chip. This is used by the Sound Manager for hardware access.

d. The Centronics port.

Two routines are provided to access the Centronics port. MC BUSY


PRINTER tests if it is busy. MC SEND PRINTER strobes data out of it.
Data should not be sent while the port is busy.
The Centronics port is used by the printer routines provided in the
Machine Pack and described,below.

13.2 The Printer.


There is a routine, MC PRINT CHAR, which calls an indirection, MC WAIT
PRINTER, for sending characters to the printer, or rather, to the Centronics
port. In V1.1 firmware, before sending the characters MC PRINT CHAR
translates them using the printer translation table. The user can set the
translations by calling MC PRINT TRANSLATION. The default translation
table (see Appendix XIV) only affects characters in the range #AO.. #AF and
is designed to make these characters print more reasonably on the DMP-1
printer for various language options.

MC WAIT PRINTER waits until the Centronics port is not busy and then
sends the given character to it. If the port remains busy for a long time then the
routine times out and returns indicating that it has failed to send the character.
This time out can be used to prevent programs ‘hanging’ because they are
waiting for a (possibly non-existent) printer to become ready.

MC WAIT PRINTER allows the user to intercept characters to be sent to the


printer. This could allow special escape sequences to be inserted if needed, or it
could allow the printer to be disabled or the length of the time out to be
changed.

13.3 Loading and Running Programs.


The Machine Pack provides two routines for running programs, MC START
PROGRAM and MC BOOT PROGRAM.

MC START PROGRAM is the simpler of the two routines. It completely re-


initializes all the firmware and then enters the given program.

MC BOOT PROGRAM is more complex. It is for loading a program into


RAM and running it. The user supplies a routine to MC BOOT PROGRAM
that will load the program and return its entry point. Before this load routine is
called as much of the firmware as is possible is reset so that the area of
memory between #0040 and the base of the firmware RAM at #B100 is
available for use. If the system were not reset then an active indirection, event
or interrupt routine might be overwritten with disastrous consequences.

If the program is loaded successfully by MC BOOT PROGRAM then the


firmware is completely initialized and the program is entered. However, if the
loading fails then an appropriate message is printed and the previous
foreground program is restarted. If the previous program was itself a RAM
program then the default ROM is entered instead because it is likely that the
previous program was corrupted when the attempt to load the new one was
made.
14 Firmware Jumpblocks.
There are a number of jumpblocks provided by the firmware. The largest of
these is the main firmware jumpblock. This is intended to be used by programs
to access the firmware routines in the lower ROM. BASIC, for instance, uses
these jumps. Note, however that the firmware does not use this jumpblock for
internal communication with itself. This means that altering the jumpblock will
cause BASIC to behave differently but will not cause the firmware to behave
differently.
The next most important jumpblock is the indirections jumpblock. The
indirections are jumps that are used by the firmware at key points. This allows
the user to alter the action of firmware routines. The entries in this jumpblock
are not intended for the user to call, only for the firmware to call. Altering an
indirection is the method to make the firmware behave differently.
The remaining two jumpblocks are associated with the Kernel. One is a
jumpblock to allow the user to call various useful Kernel routines to do with
changing ROM states and the like. The other is not a jumpblock as such, just
an area where the routines are at published addresses. These are general utility
routines and restarts. In general neither of these areas should be altered by the
user.
The routines in these jumpblocks are briefly listed below. More complete
descriptions of the routines can be found in sections 15, 16, 17, and 18.
AMSDOS provides a number of external commands which allow the user
access to the low level disc driving and to high level disc operations.
These commands are accessed using the external command mechanism
described in section 10, i.e. The caller passes the command name to KL FIND
COMMAND and far calls the resulting routine. More complete descriptions of
these commands can be found in sections 19 and 20.

14.1 The Main Jumpblock.


The main firmware jumpblock lies in RAM between addresses #BB00 and
#BD5D. Each entry in the jumpblock occupies three bytes and is initialized to
use LOW JUMP restarts (RST1) that cause the lower ROM to be enabled, so
that the firmware routines can be run, and the upper ROM to be disabled, so
that the screen memory is accessible while the firmware is running. Full
descriptions of these routines can be found in section 15.
After the jumpblock has been set up at EMS it is patched by the initialization
of the AMSDOS ROM to install the disc (rather than cassette) as default but is
not otherwise altered by the firmware until the system is reinitialized. If any
entries are changed then it is the user’s responsibility to undo the alterations.
This can be achieved by calling JUMP RESTORE which completely initializes
the jumpblock but this will lose any other patches, such as those made by
AMSDOS. It is better to copy the original contents of the changed entries back.

14.1.1 Entries to the Key Manager


The Key Manager deals with the keyboard and the joysticks.

INITIALIZATION
0 #BB00 KM INITIALISE Initialize the Key Manager.
1 #BB03 KM RESET Reset the Key Manager - clear
all buffers, restore standard key
expansions and indirections.
CHARACTERS

2 #BB06 KM WAIT CHAR Wait for next character from


the keyboard.
3 #BB09 KM READ CHAR Test if a character is available
from the keyboard.
4 #BB0C KM CHAR RETURN Return a single character to the
keyboard for next time.
191 #BD3D KM FLUSH Discard all pending characters
and keys.
5 #BB0F KM SET EXPAND Set an expansion string.
6 #BB12 KM GET EXPAND Get a character from an
expansion string.
7 #BB15 KM EXP BUFFER Allocate a buffer for expansion
strings.
KEYS

8 #BB18 KM WAIT KEY Wait for next key from the


keyboard.
9 #BB1B KM READ KEY Test if a key is available from
the keyboard.
10 #BB1E KM TEST KEY Test if a key is pressed.
190 #BD3A KM SET LOCKS Set the Shift Lock and Caps
Lock states.
11 #BB21 KM GET STATE Fetch Caps Lock and Shift Lock
states.
12 #BB24 KM GET JOYSTICK Fetch current state of the
joystick(s).

TRANSLATION TABLES

13 #BB27 KM SET TRANSLATE Set entry in key translation


table without shift or control.
14 #BB2A KM GET TRANSLATE Get entry from key translation
table without shift or control.
15 #BB2D KM SET SHIFT Set entry in key translation
table when shift key is pressed.
16 #BB30 KM GET SHIFT Get entry from key translation
table when shift key is pressed.
17 #BB33 KM SET CONTROL Set entry in key translation
table when control key is pressed
18 #BB36 KM GET CONTROL Get entry from key
translation table when
control key is pressed.
REPEATING

19 #BB39 KM SET REPEAT Set whether a key may


repeat.

20 #BB3C KM GET REPEAT Ask if a key is allowed to


repeat.
21 #BB3F KM SET DELAY Set start up delay and repeat
speed
22 #BB42 KM GET DELAY Get start up delay and repeat
speed.

BREAKS

23 #BB45 KM ARM BREAK Allow break events to be


generated.
24 #BB48 KM DISARM BREAK Prevent break events from
being generated.
25 #BB4B KM BREAK EVENT Generate a break event (if
armed).

14.1.2 Entries to the Text VDU


The Text VDU is a character based screen driver.

INITIALIZATION

26 #BB4E TXT INITIALISE Initialize the Text VDU.


27 #BB51 TXT RESET Reset the Text VDU - restore
default indirections and
control code functions.
28 #BB54 TXT VDU ENABLE Allow characters to be
placed on the screen.
29 #BB57 TXT VDU DISABLE Prevent characters from
being placed on the screen.
192 #BD40 TXT ASK STATE Get state of the text VDU.

CHARACTERS

30 #BB5A TXT OUTPUT Output a character or control


code to the Text VDU.
31 #BB5D TXT WR CHAR Write a character onto the
screen.
32 #BB60 TXT RD CHAR Read a character from the
screen.
33 #BB63 TXT SET GRAPHIC Turn on or off the Graphics
VDU character writing
option.

WINDOWS

34 #BB66 TXT WIN ENABLE Set the size of the current


text window.
35 #BB69 TXT GET WINDOW Get the size of the current
text window.
36 #BB6C TXT CLEAR WINDOW Clear current window.

CURSOR

37 #BB6F TXT SET COLUMN Set cursor horizontal


position.
38 #BB72 TXT SET ROW Set cursor vertical position.
39 #BB75 TXT SET CURSOR Set cursor position.
40 #BB78 TXT GET CURSOR Ask current cursor position.
41 #BB7B TXT CUR ENABLE Allow cursor display - user.
42 #BB7E TXT CUR DISABLE Disallow cursor display –
user.
43 #BB81 TXT CUR ON Allow cursor display –
system.
44 #BB84 TXT CUR OFF Disallow cursor display
- system.
45 #BB87 TXT VALIDATE Check if a cursor position is
within the window.
46 #BB8A TXT PLACE CURSOR Put a cursor blob on the
screen.
47 #BB8D TXT REMOVECURSOR Take a cursor blob off the
screen.

INKS

48 #BB90 TXT SET PEN Set ink forwriting characters.


49 #BB93 TXT GET PEN Get ink for writing
characters.
50 #BB96 TXT SET PAPER. Set ink for writing text
background.
51 #BB99 TXT GET PAPER Get ink for writing text
background.
52 #BB9C TXT INVERSE Swap current pen and paper
inks.
53 #BB9F TXT SET BACK Allow or disallow
background being written.
54 #BBA2 TXT GET BACK Ask if background is being
written.

MATRICES

55 #BBA5 TXT GET MATRIX Get the address of a character


matrix.
56 #BBA8 TXT SET MATRIX Setacharacter matrix.
57 #BBAB TXT SET M TABLE Set the user defined matrix
table address.
58 #BBAE TXT GET M TABLE Get user defined matrix table
address.

CONTROL CODES

59 #BBB1 TXT GET CONTROLS Fetch address of control code


table.

STREAMS

60 #BBB4 TXT STR SELECT Select a Text VDU stream.


61 #BBB7 TXT SWAP STREAMS Swap the states of two
streams.

14.1.3 Entries to the Graphics VDU


The Graphics VDU deals with individual pixels.

INITIALIZATION

62 #BBBA GRA INITIALISE Imtialize the Graphics VDU.


63 #BBBD GRA RESET Reset the Graphics VDU
-restore standard indirections.
193 #BD43 GRA DEFAULT Set default Graphics VDU
modes.

CURRENT POSITION

64 #BBC0 GRA MOVEABSOLUTE Move to an absolute


position.
65 #BBC3 GRA MOVE RELATIVE Move relative to current
position.
66 #BBC6 GRA ASK CURSOR Get the current position.
67 #BBC9 GRA SET ORIGIN Set the origin of the user
coordinates.
68 #BBCC GRA GET ORIGIN Get the origin of the user
coordinates.
197 #BD4F GRA FROM USER Convert user coordihates to
base coordinates.
WINDOW

69 #BBCF GRA WIN WIDTH Set left and right edges of the
graphics window.
70 #BBD2 GRA WIN HEIGHT Set the top and bottom edges of
the graphics window.
71 #BBD5 GRA GET W WIDTH Get the left and right edges of
the graphics window.
72 #BBD8 GRA GET W HEIGHT Get the top and bottom edges of
the graphics window.
73 #BBDB GRA CLEAR WINDOW Clearthe graphics window.

INKS

74 #BBDE GRA SET PEN Set the graphics plotting ink.


75 #BBE1 GRA GET PEN Get the current graphics
plotting ink.
76 #BBE4 GRA SET PAPER Set the graphics background
ink.
77 #BBE7 GRA GET PAPER Get the current graphics
background ink.
194 #BD46 GRA SET BACK Set whether background is to
be written.

PLOTTING

78 #BBEA GRA PLOT ABSOLUTE Plot a point at an absolute


position.
79 #BBED GRA PLOT RELATIVE Plot a point relative to the
current position.

TESTING

80 #BBFO GRA TEST ABSOLUTE Test a point at an absolute


position.
81 #BBF3 GRA TEST RELATIVE Test a point relative to the
current position.

LINE DRAWING

82 #BBF6 GRA LINE ABSOLUTE Draw a line to an absolute


position.
83 #BBF9 GRA LINE RELATIVE Draw a line relative to the
current position.
195 #BD49 GRA SET FIRST Set whether first point of a line
is to be plotted.
196 # BD4C GRA SET LINE MASK Set mask for drawing lines.
AREA FILLING

198 #BD52 GRA FILL Fill an area of the screen.

CHARACTER DRAWING

84 #BBFC GRA WR CHAR Put a character on the screen at


the current graphics position.

14.1.4 Entries to the Screen Pack


The Screen Pack interfaces the Text and Graphic VDUs to the screen
hardware. Screen functions that affect both text and graphics (e.g. ink colours)
are located in the Screen Pack.

INITIALIZATION

85 #BBFF SCRINITIALISE Initialize the Screen Pack.


86 #BC02 SCR RESET Reset the Screen Pack -
restore
standard indirections, ink
colours and flash rates.

SCREEN HARDWARE

87 #BC05 SCR SET OFFSET Set the offset of the start of the
screen.
88 #BC08 SCR SET BASE Set the area of RAM to use for
the screen memory.
199 #BD55 SCR SET POSITION Set the location of the screen
memory without moving the
screen.
89 #BC0B SCR GET LOCATION Fetch current base and offset
settings.

MODE

90 #BC0E SCR SET MODE Set screen into a new mode.


91 #BC11 SCR GET MODE Ask the current screen mode.
92 #BC14 SCR CLEAR Clear thescreen (to ink zero).
93 #BC17 SCR CHAR LIMITS Ask size of the screen in
characters.

SCREEN ADDRESSES

94 #BC1A SCR CHAR POSITION Convert physical coordinates to


a screen position.
95 #BC1D SCR DOT POSITION Convert base coordinates to a
screen position.
96 #BC20 SCR NEXT BYTE Step a screen address right one
byte.

97 #BC23 SCR PREV BYTE Step a screen address left one


byte.
98 #BC26 SCR NEXT LINE Step a screen address down one
line.
99 #BC29 SCR PREV LINE Step a screen address up one
line.

INKS

100 #BC2C SCR INK ENCODE Encode an ink to cover all


pixels in a byte.
101 #BC2F SCR INK DECODE Decode an encoded ink.
102 #BC32 SCR SET INK Set the colours in which to
display an ink.
103 #BC35 SCR GET INK Ask the colours an ink is
currently displayed in.
104 #BC38 SCR SET BORDER Set the colours in which to
display the border.
105 #BC3B SCR GET BORDER Ask the colours the border is
currently displayed in.
106 #BC3E SCR SET FLASHING Set the flash periods.
107 #BC41 SCR GET FLASHING Ask the current flash periods.

MISCELLANEOUS

108 #BC44 SCR FILL BOX Fill a character area of the


screen with an ink.
109 #BC47 SCR FLOOD BOX Fill a byte area of the screen
with an ink.
110 #BC4A SCR CHAR INVERT Invert a character position.
111 #BC4D SCR HW ROLL Move the whole screen up or
down eight pixel lines (one
character).
112 #BC50 SCR SW ROLL Move an area of the screen up or
down eight pixel lines (one
character).
113 #BC53 SCR UNPACK Expand a character matrix for
the current screen mode.
114 #BC56 SCR REPACK Compress a character matrix to
the standard form.
115 #BC59 SCR ACCESS Set the screen write mode for
the Graphics VDU.
116 #BC5C SCR PIXELS Write a pixel to the screen
ignoring the Graphic VDU
write mode.

117 #BC5F SCR HORIZONTAL Plot a purely horizontal line


118 #BC62 SCR VERTICAL Plot a purely vertical line.

14.1.5 Entries to the Cassette Manager/AMSDOS


The Cassette Manager handles reading files from tape and writing files to tape.
AMSDOS intercepts the starred entries and redirects them so that they read
from and write to disc. The external commands TAPEand DISC can be used to
switch between the tape and disc versions of these routines (see section 14.6).

INITIALIZATION

119 #BC65 CAS INITIALISE. Initialize the Cassette


Manager - close all streams, set
default speed and enable
messages.
120 #BC68 CAS SET SPEED Set the write speed.
121 #BC6B CAS NOISY Enable or disable prompt
messages.

MOTOR CONTROL

122 #BC6E CAS START MOTOR Start the cassette motor.


123 #BC71 CAS STOP MOTOR Stop the cassette motor.
124 #BC74 CAS RESTORE MOTOR Restore previous state of
cassette motor.
READING FILES

125 #BC77 *CASINOPEN Open a file for input.


126 #BC7A *CAS IN CLOSE Close the input file properly.
127 #BC7D *CAS IN ABANDON Close the input file
immediately.
128 #BC80 *CAS IN CHAR Read a character from the input
file.
129 #BC83 *CAS IN DIRECT Read the input file into store.
130 #BC86 *CAS RETURN Put the last character read
back.
131 #BC89 *CAS TEST EOF Have we reached the end of the
input file yet?

WRITING FILES

132 #BC8C *CAS OUT OPEN Open a file for output.


133 #BC8F *CAS OUT CLOSE Close the output file properly.
134 #BC92 *CAS OUT ABANDON Close the output file
immediately.
135 #BC95 *CAS OUT CHAR Write a character to the output
file.
136 #BC98 *CAS OUT DIRECT Write the output file directly
from store.

CATALOGUING

137 #BC9B *CAS CATALOG Generate a catalogue from the


tape.

RECORDS

138 #BC9E CAS WRITE Write a record to tape.


139 #BCA1 CAS READ Read a record from tape.
140 #BCA4 CAS CHECK Compare a record on tape with
the contents of store.

14.1.6 Entries to the Sound Manager

The Sound Manager controls the sound chip.

INITIALIZATION

141 #BCA7 SOUND RESET Reset the Sound Manager -shut


the sound chip up and clear all
sound queues.
142 #BCAA SOUND QUEUE Add a sound to a sound queue.
143 #BCAD SOUND CHECK Ask if there is space in a sound
queue.
144 #BCB0 SOUND ARM EVENT Set up an event to be run when
a sound queue becomes not full.

SOUNDS

145 #BCB3 SOUND RELEASE Allow sounds to happen.


146 #BCB6 SOUND HOLD Stop all sounds in mid flight.
147 #BCB9 SOUND CONTINUE Restart sounds after they
have been stopped.

ENVELOPES

148 #BCBC SOUND AMPL ENVELOPE Set up an amplitude


envelope
149 #BCBF SOUND TONE ENVELOPE Set up a tone envelope.
150 #BCC2 SOUND A ADDRESS Get the address of an
amplitude envelope.
151 #BCC5 SOUND T ADDRESS Get the address of a tone
envelope.

14.1.7 Entries to the Kernel

The Kernel handles synchronous and asynchronous events. It is also in


charge of the store map and switching ROMs on and off. Apart from the
entries listed below, the Kernel has its own jumpblock and a number of
routines whose addresses are published. These extra entries are listed in
sections 14.3 and 14.4 below.

INITIALIZATION

152 #BCC8 KL CHOKE OFF Reset the Kernel - clears all


event queues etc.
153 #BCCB KL ROM WALK Find and initialize all
background ROMs.
154 #BCCE KL INIT BACK Initialize a particular
background ROM.
155 #BCD1 KL LOG EXT Introduce an RSX to the
firmware.
156 #BCD4 KL FIND COMMAND Search for an RSX or
background ROM or
foreground ROM to process a
command.
FRAME FLYBACK LIST

157 #BCD7 KL NEW FRAME FLY Initialize and put a block onto
the frame flyback list.
158 #BCDA KL ADD FRAME FLY Put a block onto the frame
flyback list.
159 #BCDD KL DEL FRAME FLY Remove a block from the
frame flyback list.

FAST TICK LIST

160 #BCE0 KL NEW FAST TICKER Initialize and put a block onto
the fast tick list.
161 #BCE3 KL ADD FAST TICKER Put a block onto the fast tick
list.
162 #BCE6 KL DEL FAST TICKER Remove a block from the fast
tick list.

TICK LIST

163 #BCE9 KL ADD TICKER Put a block onto the tick list.
164 #BCEC KL DEL TICKER Remove a block from the tick
list.

EVENTS

165 #BCEF KL INIT EVENT Initialize an event block.


166 #BCF2 KL EVENT ‘Kick’ an event block.
167 #BCF5 KLSYNCRESET Clear synchronous event
queue.
168 #BCF8 KL DEL SYNCHRONOUS Remove a synchronous event
from the event queue.
169 #BCFB KL NEXT SYNC Get the next event from the
queue.
170 #BCFE KL DO SYNC Perform an event routine.
171 #BD01 KL DONE SYNC Finish processing an event.
172 #BD04 KL EVENT DISABLE Disable normal synchronous
events.
173 #BD07 KL EVENT ENABLE Enable normal synchronous
events.
174 #BD0A KL DISARM EVENT Prevent an event from
occurring
ELAPSED TIME

175 #BD0D KL TIME PLEASE Ask the elapsed time.


176 #BD10 KL TIME SET Set the elapsed time.

BANK SWITCHING

201 #BD5B KL BANK SWITCH Select a memory orgaization.

14.1.8 Entries to the Machine Pack


The Machine Pack provides an interface to the machine hardware. Most packs
use Machine to access any hardware they use. The major exception is the
Cassette Manager which, for speed reasons, performs its own hardware access.

PROGRAMS

177 #BD13 MC BOOT PROGRAM Load and run a foreground


program.
178 #BD16 MC START PROGRAM Run a foreground program.

SCREEN

179 #BD19 MC WAIT FLYBACK Wait for frame flyback.


180 #BD1C MC SET MODE Set the screen mode.
181 #BD1F MC SCREEN OFFSET Set the screen offset.
182 #BD22 MC CLEAR INKS Set all inks to one colour.
183 #BD25 MC SET INKS Set colours of all the inks.

PRINTER

184 #BD28 MC RESET PRINTER Reset the printer indirection.

200 #BD58 MC PRINT TRANSLATION Set the printer translation


table.
185 #BD2B MC PRINT CHAR Translate a character then
send it to the Centronics
port.
186 #BD2E MC BUSY PRINTER Test if the Centronics port is
busy.
187 #BD31 MC SEND PRINTER Send a character to the
Centronics port.

SOUND CHIP

#BD34 MC SOUND REGISTER Send data to a sound chip


14.1.9 Entries to Jumper
Jumper sets up the main jumpblock.

INITIALIZATION

189 #BD37 JUMP RESTORE Restore the standard


jumpblock.

14.2 Firmware Indirections


The firmware indirections listed here are taken at key points in the firmware
thus allowing the user to provide substitute routines for many firmware actions,
without having to replace a complete firmware package. These indirections are
not intended for the user to call - there is usually a higher level routine in the
main firmware jumpblock that is more suitable.
The indirections are set up by the pack to whom they apply whenever its reset
(or initialize) routine is called and during EMS; they are not otherwise altered
by the firmware.
The indirections are all three bytes long and use standard jump instructions
(#C3). If a ROM state other than upper ROMs disabled and lower ROM
enabled is required then the appropriate restart instruction might be substituted
(see section 2.3). The indirections are to be found between #BDCD and
#BDF6.
At this level of operation very little validation is carried out. If incorrect
parameters are passed or a substitute routine corrupts a register in defiance of
the documented interface then the firmware will probably cease to function as
expected.
More detailed descriptions of these routines can be found in section 16.

14.2.1 Text VDU Indirections


0 #BDCD TXT DRAW CURSOR Place the cursor blob on the
screen (if enabled).
1 #BDD0 TXT UNDRAW CURSOR Remove the cursor blob from
the screen (if enabled).
2 #BDD3 TXT WRITE CHAR Write a character onto the
screen.
3 #BDD6 TXT UNWRITE Read a character from the
screen.
4 #BDD9 TXT OUT ACTION Output a character or control
code.

14.2.2 Graphics VDU Indirections


5 #BDDC GRA PLOT Plot a point.
6 #BDDF GRA TEST Test a point.
7 #BDE2 GRA LINE Draw a line.
14.2.3 Screen Pack Indirections

8 #BDE5 SCR READ Read a pixel from the screen.


9 #BDE8 SCR WRITE Write pixel(s) to the screen
using the current graphics
write mode.
10 #BDEB SCR MODE CLEAR Clear the screen to ink 0.

14.2.4 Keyboard Manager Indirections

11 #BDEE KM TEST BREAK Test for break (or reset).


13 #BDF4 KM SCAN KEYS Scan the keyboard

14.2.5 Machine Pack Indirections

12 #BDF1 MC WAIT PRINTER Print a character or time out.

14.3 The High Kernel Jumpblock


The high Kernel jumpblock is provided to allow the user to turn ROMs on and
off and to access memory underneath ROMs while they are enabled. The
entries in this jumpblock are not all jump instructions, some entries are the start
of routines, thus the user should not alter any of the entries in this jumpblock.
The high Kernel jumpblock occupies store from #B900 upwards. More detailed
descriptions of the routines in it can be found in section 17.

0 #B900 KL U ROM ENABLE Turn on the current upper


ROM.
1 #B903 KL U ROM DISABLE Turn off the upper ROM
2 #B906 KL L ROM ENABLE Turn on the lower ROM.
3 #B909 KL L ROM DISABLE Turn off the lower ROM.
4 #B90C KL ROM RESTORE Restore the previous ROM
state.
5 #B90F KL ROM SELECT Select particular upper ROM.
6 #B912 KL CURR SELECTION Ask which upper ROM is
currently selected.
7 #B915 KL PROBE ROM Ask class and version of a
ROM.
8 #B918 KL ROM DESELECT Restore the previous upper
ROM selection.
9 #B91B KL LDIR Move store (LDIR) with
ROMs disabled.
10 #B91E KL LDDR Move store (LDDR) with
ROMs disabled.
11 #B921 KL POLL SYNCHRONOUS Check if an event with
higher priority than the
current event is pending.
14 #B92A KL SCAN NEEDED Ensure keyboard is scanned
at next opportunity.

(N.B. there are no entries 12 or 13).

14.4 The Low Kernel Jumpblock.


The Kernel provides a number of useful routines in the area of memory
between #0000 and #003F. These are available, in some cases, both as a
published routine address and as a restart instruction. In general the routines
are available both in ROM and in RAM so whether the lower ROM is enabled
does not matter. There are also a couple of areas available for the user to patch
to trap RST 6s and interrupts from external hardware.

The low Kernel jumpblock is not intended for the user to alter. However, it
may be necessary to alter it under certain circumstances. In particular a
program may need to intercept the INTERRUPT ENTRY (by patching the
jump at #0038) or the RESET ENTRY (by patching the bytes from #0000..
#0007). If a program does change any locations in this jumpblock (other than
those in the USER RESTART or EXT INTERRUPT areas) then it is the
program’s responsibility to ensure that the lower ROM is enabled or the
original contents are restored when any other program runs. In particular the
program must sort out the state when interrupts occur (hence the need to patch
the INTERRUPT ENTRY).

More detailed descriptions of the routines in this jumpblock can be found in


section 18.

#0000 RST 0 RESET ENTRY Completely reset the machine


as if powered up.
#0008 RST 1 LOW JUMP Jump to lower ROM or
RAM, takes an inline ‘low
address’ to jump to.
#000B KL LOW PCHL Jump to lower ROM or
RAM, HL contains the ‘low
address’ to jump to.
#000E PCBC INSTRUCTION Jump to address in BC.
#0010 RST 2 SIDE CALL Call to a sideways ROM,
takes inline ‘side address’ to
call.
#0013 KL SIDE PCHL Call to a sideways ROM, HL
contains ‘side address’ to
call.
#0016 PCDE INSTRUCTION Jump to address in DE
#0018 RST 3 FARCALL Call a routine in any ROM or
RAM, takes an inline address
of the ‘far address’ to call.
#001B KL FAR PCHL Call a routine in any ROM or
RAM, C and HL contain the
‘far address’ to call.
#001E PCHL INSTRUCTION Jump to address in HL.
#0020 RST 4 RAM LAM LD A,(HL) with all ROMs
disabled.
#0023 KL FAR ICALL Call a routine in any ROM or
RAM, HL points at the ‘far
address’ to call.
#0028 RST 5 FIRM JUMP Jump to lower ROM, takes an
inline address to jump to.
#0030 RST 6 USER RESTART ROM version saves current
ROM state in #002B, turns
the lower ROM off and
jumps to the RAM version.
RAM version may be patched
by the user between #0030
and #0037 inclusively.
#0038 RST 7 INTERRUPT ENTRY This restart is not available as
it is used for interrupts (Z80
interrupt mode 1).
#003B EXT INTERRUPT When an interrupt occurs on
the expansion port the
firmware calls location
#003B in RAM. The user
may patch between #003B
and #003F inclusive to trap
this occurence.
15 The Main Firmware Jumpblock.
This section describes in detail the entry and exit conditions and the effects of all
the routines in the main firmware jumpblock. The main firmware jumpblock is
described in section 14.1.

The user is advised to read the sections on each pack before attempting to
understand thejumpblock entries. The relevant sections are:

Key Manager (KM) Section 3.


Text VDU (TXT) Section 4.
Graphics VDU (GRA) Section 5.
Screen Pack (SCR) Section 6.
SoundManager (SOUND) Section7.
Cassette Manager (CAS) Section 8.
AMSDOS Section 9
Kernel (KL) Sections2,10,11 and 12.
Machine Pack (MC) Section 13.
The top line of each description has the following layout:

<Entry number>: <Entry name> <Entry address>

Entries in the jumpblock are numbered starting from zero. The entry address is the
address to call to invoke the firmware routine or the address of the three bytes to
patch to intercept the routine. The entry address can be calculated as:

Entry address = Start of jumpblock + 3 * Entry number

Each entry is named and is refered to by name throughout this manual.


The last section of each description is a list of related routines. The user is advised
to look at these as the list may include routines as the list may include routines
more suited for the application being considered. Conversely the routines may
shed further light on how the original routine should be used.

The descriptions of the routines are for the default routine that the entry jumps to.
The user may change the entry and this may alter the action of the routine. The
user is advised to stick to the entry/exit conditions described otherwise programs
that call the routine (BASIC for example) may cease to operate correctly.
0: KM INITIALISE # BB00

Initialize the Key Manager

Action:
Full initialization of the Key Manager (as used during EMS). All Key Manager
variables, buffers and indirections are initialized. The previous state of the Key
Manager is lost.

Entry Conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.

All other registers preserved.

Notes:
The Key Manager indirection (KM TEST BREAK) is set to its default routine.
The key buffer is set up (to be empty).
The expansion buffer is set up and the expansions are set to their default
strings.
The key translation tables are initialized to their default translations.
The repeating key map is initialized to its default state.
The repeat speeds are set to their default values.
Shift and caps lock are turned off.
The break event is disarmed.

See Appendices II, III and IV for the default translation tables, repeating key
table and expansion strings.
This routine enables interrupts.

Related entries:
KM RESET
1: KM RESET #BB03

Reset the Key Manager.

Action:
Reinitializes the Key Manager indirections and buffers.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The Key Manager indirection (KM TEST BREAK) is set to its default routine.
The key buffer is set up(to be empty).
The expansion buffer is set up and the expansions are set to their default strings
(see Appendix IV).
The break event is disarmed.

All pending keys and characters are discarded.

This routine enables interrupts.

Related entries:
KM DISARM BREAK
KM EXP BUFFER
KM INITIALISE
2: KM WAIT CHAR #BB06

Wait for next character from the keyboard.

Action:
Try to get a character from the key buffer or the current expansion string. This
routine waits until a character is available if no character is immediately
available.

Entry conditions:
No conditions.

Exit conditions:
Carry true.
A contains the character.

Other flags corrupt.


All other registers preserved.

Notes:
The possible sources for generating the next character are, in the order that they
are tested:

The ‘put back’ character.


The next character of an expansion string.
The first character of an expansion string.
A character from a key translation table.

Expansion tokens found in the key translation table are expanded to their
associated strings. Expansion tokens found in expansion strings are not
expanded but are treated as characters.

Related entries:
KM CHAR RETURN
KMREADCHAR
KM WAIT KEY
3: KM READ CHAR #BB09

Test if a character is available from the keyboard.

Action:
Try to get a character from the key buffer or the current expansion string. This
routine does not wait for a character to become available if there is no character
available immediately.

Entry conditions:
No conditions.

Exit conditions:
If there was a character available:
Carry true.
A contains the character.
If there was no character available:
Carry false.
A corrupt.
Always:
Other flags corrupt.
All other registers preserved.
Notes:
The possible sources for generating the next character are, in the order that they
are tested:
The ‘put back’ character.
The next character of an expansion string.
The first character of an expansion string.
A character from a key translation table.
Expansion tokens in the key translation tables will be expanded to their
associated strings. Expansion tokens found in expansion strings are not
expanded but are treated as characters.
This routine will always return a character if one is available. It is therefore
possible to flush out the Key Manager buffers by calling KM READ CHAR
repeatedly until it reports that no character is available.

Related entries:
KM CHAR RETURN
KM FLUSH
KM READ KEY
KM WAIT CHAR
4: KM CHAR RETURN #BB0C

Return a single character to the keyboard for next time.

Action:
Save a character for the next call of KM READ CHAR or KM WAIT CHAR.

Entry conditions:
A contains the character to put back.

Exit conditions:
All registers and flags preserved.

Notes:
The ‘put back’ character will be returned before any other character is
generated by the keyboard. It will not be expanded (or otherwise dealt with)
but will be returned as it is. The ‘put back’ character need not have been read
from the keyboard, it could be inserted by the user for some purpose.

It is only possible to have one ‘put back’ character. If this routine is called
twice without reading a character between these then the first ‘put back’ will be
lost. Furthermore, it is not possible to return character 255 (because this is used
as the marker for no ‘put back’ character).

Related entries:
KM READ CHAR
KM WAIT CHAR
5: KM SET EXPAND #BB0F

Set an expansion string.

Action:
Set the expansion string associated with an expansion token.

Entry conditions:
B contains the expansion token for the expansion to set.
C contains the length of the string.
HL contains the address of the string.

Exit conditions:
If the expansion is OK:
Carry true.

If the string was too long or the token was invalid:


Carry false.

Always:
A, BC, DE, HL and other flags corrupt.
All other registers preserved.

Notes:
The string to be set may lie anywhere in RAM. Expansion strings cannot be set
directly from ROM.
The characters in the string are not expanded (or otherwise dealt with). It is
therefore possible to put any character into an expansion string.
If there is insufficient room in the expansion buffer for the new string then no
change is made to the expansions.
If the string set is currently being used to generate characters (by KM READ
CHAR or KM WAIT CHAR) then the unread portion of the string is discarded.
The next character will be read from the key buffer.
This routine enables interrupts.

Related entries:
KM GET EXPAND
KM READ CHAR
KM WAIT CHAR
6: KM GET EXPAND #BB12

Get a character from an expansion string.

Action:
Read a character from an expansion string. The characters in the string are
numbered starting from 0.

Entry conditions:
A contains an expansion token.
L contains the character number.

Exit conditions:
If the character was found:

Carry true.
A contains the character.

If the token was invalid or the string was not long enough:

Carry false.
A corrupt.

Always:

DE and other flags corrupt.

All other registers preserved.

Notes:
The characters in the expansion string are not expanded (or otherwise dealt
with). It is therefore possible to put any character into an expansion string.

Related entries:
KM READ CHAR
KM SET EXPAND
7: KM EXP BUFFER #BB15

Allocate a buffer for expansion strings.

Action:
Set the address and length of the expansion buffer. Initialize the buffer with the
default expansion strings.

Entry conditions:
DE contains the address of the buffer.
HL contains the length of the buffer.

Exit conditions:
If the buffer is OK:

Carry true.

If the buffer is too short:

Carry false.

Always:

A, BC, DE, HL and other flags corrupt.

All other registers preserved.

Notes:
The buffer must not be located underneath a ROM and it must be at least 49
bytes long (i.e. have sufficient space for the default expansion strings). If the
new buffer is too short then the old buffer is left unchanged.

The default expansion strings are given in Appendix IV.

Any expansion string currently being read is discarded.

This routine enables interrupts.

Related entries:
KM GET EXPAND
KM SET EXPAND
8: KM WAIT KEY #BB18

Wait for next key from the keyboard.

Action:
Try to get a key from the key buffer. This routine waits until a key is found if
no key is immediately available.

Entry conditions:
No conditions.

Exit conditions:
Carry true.
A contains the character or expansion token.

Other flags corrupt.


All other registers preserved.

Notes:
The next key is read from the key buffer and translated using the appropriate
key translation table. Expansion tokens are not expanded but are passed out for
the user to deal with, as are normal characters. Other Key Manager tokens
(shift lock, caps lock and ignore) are obeyed but are not passed out.

Related entries:
KM READ KEY
KM WAIT CHAR
9: KM READ KEY #BB1B

Test if a key is available from the keyboard.

Action
Try to get a key from the key buffer. This routine does not wait if no key is
available immediately.

Entry Conditions:
No conditions.

Exit conditions
If a key was available:

Carry true.
A contains the character or expansion token.

If no key was available:

Carry false.
A corrupt.

Always:

Other flags corrupt.


All other registers preserved.

Notes:
__ The next key is read from the key buffer and translated using the appropriate
key translation table. Expansion tokens are not expanded but are passed out for
the user to deal with, as are normal characters. Other Key Manager tokens
(shift lock, caps lock and ignore) are obeyed but are not passed out.
This routine will always return a key if one is available. It is therefore possible
to flush out the key buffer by calling KM READ KEY repeatedly until it
claims no key is available. Note, however, that the ‘put back’ character or a
partially read expansion string is ignored. It is advisable to use KM READ
CHAR to flush these out when emptying the Key Manager buffers, or, in V1.1
firmware, to call KM FLUSH.

Related Entries:
KM FLUSH
KM READ CHAR
KM WAIT KEY
10: KM TEST KEY #BB1E

Test if a key is pressed.

Action:
Test if a particular key or joystick button is pressed. This is done using the key
state map rather than by accessing the keyboard hardware.

Entry conditions:
A contains a key number.

Exit conditions:
If the key is pressed:
Zero false.

If the key is not pressed:


Zero true.

Always:
Carry false.
C contains the current shift and control state.
A, HL and other flags corrupt.
All other registers preserved.

Notes:
The shift and control states are automatically read when a key is scanned. If bit
7 is set then the control key is pressed and if bit 5 is set then one of the shift
keys is pressed.

The key number is not checked. An invalid key number will generate the
correct shift and control states but the state of the key tested will be
meaningless.

The key state map which this routine tests is updated by the keyboard scanning
routine. Normally this is run every fiftieth of a second and so the state may be
out of date by that much. The key debouncing requires that a key should be
released for two scans of the keyboard before it is marked as released in the
key state map; the pressing of a key is detected immediately.

Related entries:
KM GET JOYSTICK
KM GET STATE
KM READ KEY
11: KM GET STATE #BB21

Fetch Caps Lock and Shift Lock states.

Action:
Ask if the keyboard is currently shift locked or caps locked.

Entry conditions:
No conditions.

Exit conditions:
L contains the shift lock state.
H contains the caps lock state.

AF corrupt.
All other registers preserved.

Notes:
The lock states are:

#00 means the lock is off


#FF means the lock is on

The default lock states are off.

Related entries:
KM SET LOCKS
KM TEST KEY
12: KM GET JOYSTICK #BB24

Fetch current state of the joystick(s).

Action:
Ask what the current states of the joysticks are. These are read from the key
state map rather than by accessing the keyboard hardware.

Entry conditions:
No conditions.

Exit conditions:
H contains the state ofjoystick 0.
L contains the state ofjoystick 1.
A contains the state ofjoystick 0.

Flags corrupt.
All other registers preserved.

Notes:
In normal operation the key state map is updated by the key scanning routine
every fiftieth of a second so the state returned may be slightly out of date.

The joystick states are bit significant as follows:

Bit 0 Up.
Bit 1 Down.
Bit 2 Left.
Bit 3 Right.
Bit 4 Fire 2.
Bit 5 Fire 1.
Bit 6 Spare joystick button (usually unconnected).
Bit 7 Always zero.

If a bit is set then the appropriate button is pressed.

Joystick 1 is indistinguishable from certain keys on the keyboard (see


Appendix I).

Related entries:
KM TEST KEY
13: KM SET TRANSLATE #BB27

Set entry in normal key translation table.

Action:
Set what character or token a key will be translated to when neither shift nor
control is pressed.

Entry conditions:
A contains a key number.
B contains the new translation.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
If the key number is invalid (greater than 79) then no action is taken.
Most values in the table are treated as characters and are passed back to the
user.
However, there are certain special values:

#80.. #9F are the expansion tokens and are expanded to character
strings when KM READ CHAR or KM WAIT CHAR is
called although they are passed back like any other
character when KM READ KEY or KM WAIT KEY is
called.
#FD is the caps lock token and causes the caps lock to toggle
(turn on if off and vice versa).
#FE is the shift lock token and causes the shift lock to toggle
(turn on if off and vice versa).
#FF is the ignore token and means the key should be thrown
away.

Characters #E0.. #FC have special meanings to the BASIC to do with editing,
cursoring and breaks.

See Appendix II for a full listing of the default translation tables.

Related entries:
KM GET TRANSLATE
KM SET CONTROL
KM SET SHIFF
14: KM GET TRANSLATE #BB2A

Get entry from normal key translation table.

Action:
Ask what character or token a key will be translated to when neither shift nor
control is pressed.

Entry conditions:
A contains a key number.

Exit conditions:
A contains the current translation.
HL and flags corrupt.
All other registers preserved.

Notes:
The key number is not checked. If it is invalid (greater than 79) then the
translation returned is meaningless.
Most values in the table are treated as characters and are passed back to the
user. However, there are certain special values:

#80.. #9F are the expansion tokens and are expanded to


character strings when KM READ CHAR or KM
WAIT CHAR is called although they are passed back
like any other character when KM READ KEY or
KM WAIT KEY is called.
#FD is the caps lock token and causes the caps lock to
toggle (turn on if off and vice versa).
#FE is the shift lock token and causes the shift lock to
toggle (turn on if off and vice versa).
#FF is the ignore token and means the key should be
thrown away.
Characters #E0.. #FC have special meanings to the BASIC to do with editing,
cursoring and breaks.
See Appendix II for a full listing of the default translation tables.

Related entries:
KM GET CONTROL
KM GET SHIFT
KM SET TRANSLATE.
15: KM SET SHIFT #BB2D

Set entry in shifted key translation table.

Action:
Set what character or token a key will be translated to when control is not
pressed but shift is pressed or shift lock is on.

Entry conditions:
A contains a key number.
B contains the new translation.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
If the key number is invalid (greater than 79) then no action is taken.
Most values in the table are treated as characters and are passed back to the
user.
However, there are certain special values:

#80.. # 9F are the expansion tokens and are expanded to


character strings when KM READ CHAR or KM
WAIT CHAR is called although they are passed
back like any other character when KM READ KEY
or KM WAIT KEY is called.
#FD is the caps lock token and causes the caps lock to
toggle (turn on if off and vice versa).
#FE is the shift lock token and causes the shift lock to
toggle (turn on if off and vice versa).
#FF is the ignore token and means the key should be
thrown away.

Characters #E0.. #FC have special meanings to the BASIC to do with editing,
cursoring and breaks.
See Appendix II for a full listing of the default translation tables.

Related entries:
KM GET SHIFT
KM SET CONTROL
KM SET TRANSLATE
16: KM GET SHIFT #BB30

Get entry from shifted key translation table.

Action:
Ask what character or token a key will be translated to when control is not
pressed but shift is pressed or shift lock is on.

Entry conditions:
A contains a key number.

Exit conditions:
A contains the current translation.
HL and flags corrupt.
All other registers preserved.

Notes:
The key number is not checked. If it is invalid (greater than 79) then the
translation
returned is meaningless.
Most values in the table are treated as characters and are passed back to the
user.
However, there are certain special values:

#80.. #9F are the expansion tokens and are expanded to


character strings when KM READ CHAR or KM
WAIT CHAR is called although they are passed
back like any other character when KM READ KEY
or KM WAIT KEY is called.
#FD is the caps lock token and causes the caps lock to
toggle (turn on if off and vice versa).
#FE is the shift lock token and causes the shift lock to
toggle (turn on if off and vice versa).
#FF is the ignore token and means the key should be
thrown away.
Characters #E0.. #FC have special meanings to the BASIC to do with editing,
cursoring and breaks.
See Appendix II for a full listing of the default translation tables.
Related entries:
KM GET CONTROL
KM GET TRANSLATE
KM SET SHIFT
17: KM SET CONTROL #BB33

Set entry in control key translation table.

Action:
Set what character or token a key will be translated to when control is pressed.

Entry conditions:
A contains a key number.
B contains the new translation.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
If the key number is invalid (greater than 79) then no action is taken.

Most values in the table are treated as characters and are passed back to the
user. However, there are certain special values:

#80.. # 9F are the expansion tokens and are expanded to


character strings when KM READ CHAR or KM
WAIT CHAR is called although they are passed
back like any other character when KM READ KEY
or KM WAIT KEY is called.

# FD is the caps lock token and causes the caps lock to


toggle (turn on if off and vice versa).
#FE is the shift lock token and causes the shift lock to
toggle (turn on if off and vice versa).
# FF is the ignore token and means the key should be
thrown away.
Characters #E0.. #FC have special meanings to the BASIC to do with editing,
cursoring and breaks.
See Appendix II for a full listing of the default translation tables.

Related entries:
KM GET CONTROL
KM SET SHIFT
KM SET TRANSLATE
18: KM GET CONTROL #BB36

Get entry from control key translation table.

Action:
Ask what character or token a key will be translated to when control is pressed.

Entry conditions:
A contains a key number.

Exit conditions:
A contains the current translation.
HL and flags corrupt.
All other registers preserved.

Notes:
The key number is not checked. If it is invalid (greater than 79) then the
translation returned is meaningless.
Most values in the table are treated as characters and are passed back to the
user. However, there are certain special values:

#80.. #9F are the expansion tokens and are expanded to


character strings when KM READ CHAR or KM
WAIT CHAR is called although they are passed
back like any other character when KM READ KEY
or KM WAIT KEY is called.

#FD is the caps lock token and causes the caps lock to
toggle (turn on if off and vice versa).

# FE is the shift lock token and causes the shift lock to


toggle (turn on if off and vice versa).

# FF is the ignore token and means the key should be


thrown away.
Characters #E0.. #FC have special meanings to the BASIC to do with editing,
cursoring and breaks.
See Appendix II for a full listing of the default translation tables.

Related entries:
KM GET SHIFT
KM GET TRANSLATE
KM SET CONTROL
19: KM SET REPEAT #BB39

Set whether a key may repeat.

Action:
Set the entry in the repeating key map that determines whether a key is allowed
to repeat or not.

Entry conditions:
If the key is to be allowed to repeat:

B contains #FF.

If the key is not to be allowed to repeat:

B contains #00.

Always:

A contains the key number.

Exit conditions:
AF, BC and HL corrupt.
All other registers preserved.

Notes:
If the key number is invalid (greater than 79) then no action is taken.

The default repeating keys are listed in Appendix III.

Related entries:
KM GET REPEAT
KM SET DELAY
20: KM GET REPEAT #BB3C

Ask if a key is allowed to repeat.

Action:
Test the entry in the repeating key map that says whether a key is allowed to
repeat ornot.

Entry conditions:
A contains a key number.

Exit conditions:
If the key is allowed to repeat:

Zero false.

If the key is not allowed to repeat:

Zero true.

Always:

Carry false.
A, HL and other flags corrupt.
All other registers preserved.

Notes:
The key number is not checked. If it is invalid (greater than 79) then the repeat
state returned is meaningless.

The default repeating keys are listed in Appendix III.

Related entries:
KM SET REPEAT
21: KM SET DELAY #BB3F

Set start up delay and repeat speed.

Action:
Set the time before keys first repeat (start up delay) and the time between
repeats (repeat speed).

Entry conditions:
H contains the new start up delay.
L contains the new repeat speed.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
Both delays are given in scans of the keyboard. The keyboard is scanned every
fiftieth of a second.

A start up delay or repeat speed of 0 is taken to mean 256.

The default start up delay is 30 scans (0.6 seconds) and the default repeat speed
is 2 scans (0.04 seconds or 25 characters a second).

Note that a key is prevented from repeating (by the key scanner) if the key
buffer is not empty. Thus the actual repeat speed is the slower of the supplied
repeat speed and the rate at which characters are removed from the buffer. This
is intended to prevent the user from getting too far ahead of a program that is
running sluggishly.

The start up delay and repeat speed apply to all keys on the keyboard that are
set to repeat.

Related entries:
KM GET DELAY
KM SET REPEAT
22: KM GET DELAY #BB42

Get start up delay and repeat speed.

Action:
Ask the time before keys first repeat (start up delay) and the time between
repeats (repeat speed).

Entry conditions:
No conditions.

Exit conditions:
H contains the start up delay.
L contains the repeat speed.

AF corrupt.
All other registers preserved.

Notes:
Both delays are given in scans of the keyboard. The keyboard is scanned every
fiftieth of a second.

A repeat speed or start up delay of 0 means 256.

Related entries:
KM SET DELAY
23: KM ARM BREAKS #BB45

Allow break events to be generated.

Action:
Arm the break mechanism. The next call of KM BREAK EVENT will generate
a break event.

Entry conditions:
DE contains the address of the break event routine.
C contains the ROM select address for this routine.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The break mechanism can be disarmed by calling KM DISARM BREAK (or
KM RESET).

This routine enables interrupts.

Related entries:
KM BREAK EVENT
KM DISARM BREAK
24: KM DISARM BREAK #BB48

Prevent break events from being generated.

Action:
Disarm the break mechanism. From now on the generation of break events by
KM BREAK EVENT will be suppressed.

Entry conditions:
No conditions.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
Break events can be rearmed by calling KM ARM BREAK.

The default state of the break mechanism is disarmed, thus calling KM RESET
will also disarm breaks.

This routine enables interrupts.

Related entries:
KM ARM BREAK
KM BREAK EVENT
25: KM BREAK EVENT #BB4B

Generate a break event (if armed).

Action:
Try to generate a break event.

Entry conditions:
No conditions.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
If the break mechanism is disarmed then no action is taken. Otherwise a break
event is generated and a special marker is placed into the key buffer. This
marker generates a break event token (#EF) when read from the buffer. The
break mechanism is automatically disarmed after generating a break event so
that multiple breaks can be avoided.

This routine may be run from the interrupt path and thus does not and should
not enable interrupts. Note, however, that using a LOW JUMP to call the
routine (as the firmware jumpblock is set up to do) does enable interrupts and
so the jumpblock may not be used directly from interrupt routines.

Related entries:
KM ARM BREAK
KM DISARM BREAK
26: TXT INITIALISE #BB4E

Initialize the Text VDU.

Action:
Full initialization of the Text VDU (as used during EMS). All Text VDU
variables and indirections are initialized, the previous VDU state is lost.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE andHLcorrupt.
All other registers preserved.

Notes:
The Text VDU indirections (TXT DRAW CURSOR, TXT UNDRAW
CURSOR, TXT WRITE CHAR, TXT UNWRITE and TXT OUT ACTION)
are set to their default routines.

The control code table is set up to perform the default control code actions.

The user defined character table is set to be empty.

Stream 0 is selected.

All streams are set to their default states:


The text paper (background) is set to ink 0.
The text pen (foreground) is set to ink 1.
The text window is set to the entire screen.
The text cursor is enabled but turned off.
The character writing mode is set to opaque.
The VDU is enabled.
The graphic character write mode is turned off.
The cursor is moved to the top left corner of the window.

The default character set and the default setting for the control code table are
described in ~ppendices VI and VII.

Related Entries:
SCR INITIALISE
TXT RESET
27: TXT RESET #BB51

Reset the Text VDU.

Action:
Reinitializes the Text VDU indirections and the control code table. Does not
affect any other aspect of the Text VDU.

Entry conditions:
No conditions.
Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.
Notes:
The Text VDU indirections TXT DRAW CURSOR, TXT UNDRAW
CURSOR, TXT WRITE CHAR, TXT UNWRITE and TXT OUT ACTION are
set to their default routines.

The control code table is set up to perform the default control code actions (see
Appendix VII).

Related Entries:
TXT INITIALISE
28: TXT VDU ENABLE #BB54

Allow characters to be placed on the screen.

Action:
Permit characters to be printed when requested (by calling TXT OUTPUT or
TXT WR CHAR). Enabling applies to the currently selected stream. The
cursor blob is also enabled (by calling TXT CUR ENABLE).

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The control code buffer used by TXT OUTPUT is emptied, any incomplete
control code sequence will be lost.

Related Entries:
TXT ASK STATE
TXT CUR ENABLE
TXT OUTPUT
TXT VDU DISABLE
TXT WR CHAR
29: TXT VDU DISABLE #BB57

Prevent characters being placed on the screen.

Action:
Prevents characters being printed on the screen (when TXT OUTPUT or TXT
WR CHAR is called). Applies to the currently selected stream. The cursor blob
is also
disabled (by calling TXT CUR DISABLE).

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The control code buffer used by TXT OUTPUT is emptied, any incomplete
control sequence will be lost.

In V1.0 firmware control codes are still obeyed by TXT OUTPUT. In V1.1
firmware only those control codes which are marked in the control code table
will be obeyed; other control codes will be ignored (see section 4.7).

Related Entries:
TXT ASK STATE
TXT CUR DISABLE
TXT OUTPUT
TXTVDU ENABLE
TXT WR CHAR
30: TXT OUTPUT #BB5A

Output a character or control code to the Text VDU.

Action:
Output characters to the screen and obey control codes (characters #00.. #1F).
Works on the currently selected stream.

Entry conditions:
A contains the character to send.

Exit conditions:
All registers and flags preserved.

Notes:
This routine calls the TXT OUT ACTION indirection to do the work of
printing the character or obeying the control code described below.
Control codes may take up to 9 parameters. These are the characters sent
following the initial control code. The characters sent are stored in the control
code buffer until sufficient have been received to make up all the required
parameters. The control code buffer is only long enough to accept 9 parameter
characters.
There is only one control code buffer for all streams. It is therefore possible to
get unpredictable results if the output stream is changed midway through
sending a control code sequence.
If the VDU is disabled then no characters will be printed on the screen. In Vi .0
firmware all control codes will still be obeyed but in Vi. i firmware only those
codes marked in the control code table as to be obeyed when the VDU is
disabled will be obeyed (see section 4.7).
If the graphic character write mode is enabled then all characters and control
codes are printed using the Graphics VDU routine, GRA WR CHAR, and are
not obeyed. Characters are written in the same way that TXT WR CHAR
writes characters.

Related Entries:
GRA WR CHAR
TXT OUT ACTION
TXT SET GRAPHIC
TXT VDU DISABLE
TXT VDU ENABLE
TXT WR CHAR
31: TXT WR CHAR #BB5D

Write a character to the screen.

Action:
Print a character on the screen at the cursor position of the currently selected
stream. Control codes (characters #00…#1F) are printed and not obeyed.

Entry conditions:
A contains the character to print.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
If the VDU is disabled then no character will be printed.

Before printing the character the cursor position is forced to lie within the text
window (see TXT VALIDATE). After printing the character the cursor is
moved right one character.

To put the character on the screen this routine calls the TXT WRITE CHAR
indirection.

Related Entries:
GRA WR CHAR
TXT OUTPUT
TXT RD CHAR
TXT WRITE CHAR
32: TXT RD CHAR #BB60

Read a character from the screen


Action:
Read a character from the screen at the cursor position of the currently selected
stream
Entry Conditions:
No conditions.
Exit Conditions:
If a recognisable character was found:
Carry true
A contains the character read.

If no recognisable character found:


Carry false
A contains zero

Always:
Other flags corrupt
All other registers preserved.

Notes:
In V1.1 firmware the cursor position is forced legal (inside the window) before
the character is read. This may cause the screen to roll. The same is not true for
V1.0 firmware where the cursor position is not forced legal and steps must be
taken to avoid reading characters from outside the window.
The read is performed by comparing the matrix found on the screen with the
matrices used to generate characters. As a result changing a character matrix,
changing the pen or paper inks, or changing the screen (e.g. drawing a line
through a character) may make the character unreadable.
To actually read the character from the screen the TXT UNWRITE indirection
is called.
Special precautions are taken against generating inverse space (character #8F).
Initially the character is read assuming that the background to the character was
written in the current paper ink and treating any other ink as foreground. If this
fails to generate a recognisable character or it generates inverse space then
another try is made by assuming that the foreground to the character was
written in the current pen ink and treating any other ink as background.
The characters are scanned starting with #00 and finishing with #FF

Related Entries:
TXT UNWRITE
TXT WR CHAR
33: TXT SET GRAPHIC #BB63

Turn on or off the Graphics VDU write character option.

Action:
Enable or disable graphic character writing on the currently selected stream.

Entry conditions:
If graphic writing is to be turned on:

A must be non-zero.

If graphic writing is to be turned off:

A must contain zero.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
When graphic character writing is enabled then all characters sent to TXT
OUTPUT are printed using the Graphics VDU (see GRA WR CHAR) rather
than the Text VDU (see TXT WR CHAR). Also all control codes are printed
rather than obeyed. Characters sent to TXT WR CHAR will be printed as
normal.

Character printing is not prevented by disabling the Text VDU (with TXT
VDU DISABLE) if graphic character writing is enabled.

Related Entries:
GRA WR CHAR
TXT OUTPUT
34: TXT WIN ENABLE #BB66

Set the size of the current text window.

Action:
Set the boundaries of the window on the currently selected stream. The edges
are the first and last character columns inside the window and the first and last
character rows inside the window.

Entry conditions:
H contains the physical column of one edge.
D contains the physical column of the other edge.
L contains the physical row of one edge.
E contains the physical row of the other edge.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The edge positions are given in physical screen coordinates. i.e. Row 0, column
0 is the top left corner of the screen and the coordinates are signed numbers.
The window is truncated, if necessary, so that it fits on the screen.
The left column of the window is taken to be the smaller of H and D. The top
row of the window is taken to be the smaller of L and E.
The cursor is moved to the top left corner of the window.
The window is not cleared.
If the window covers the whole screen then when the window is rolled the
hardware roll routine (see 5CR HW ROLL) will be used. If the window covers
less than the whole screen the software roll routine (see SCR SW ROLL) will
be used.
The default text window covers the whole screen and is set up when TXT
INITIALISE or SCR SET MODE is called.

Related Entries:
TXT GET WINDOW
TXT VALIDATE
35: TXT GET WINDOW #BB69

Get the size of the current window.

Action:
Get the boundaries of the window on the currently selected stream and whether
it covers the whole screen.

Entry conditions:
No conditions.

Exit conditions:
If the window covers the whole screen:
Carry false.

If the window covers less than the whole screen:


Carry true.

Always:
H contains the leftmost column in the window.
D contains the rightmost column in the window.
L contains the topmost row in the window.
E contains the bottommost row in the window.

A corrupt.
All other registers preserved.

Notes:
The boundaries of the window are given in physical coordinates. i.e. Row 0,
column 0 is the top left corner of the screen.

The boundaries returned by this routine may not be the same as those set when
TXT WIN ENABLE was called because the window is truncated to fit the
screen.

Related Entries:
TXT VALIDATE
TXT WIN ENABLE
36: TXT CLEAR WINDOW #BB6C

Clear current window.

Action:
Clear the text window of the currently selected stream to the paper ink of the
currently selected stream.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The cursor is moved to the top left corner of the window.

Related Entries:
GRA CLEAR WINDOW
SCR CLEAR
TXT SET PAPER
TXT WIN ENABLE
37: TXT SET COLUMN #BB6F

Set cursor horizontal position.

Action:
Move the current position of the currently selected stream to a new column.
The cursor blob will be removed from the current position and redrawn at the
new position (if the cursor is enabled and turned on).

Entry conditions:
A contains the required logical column for the cursor.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The required column is given in logical coordinates. i.e. Column 1 is the
leftmost column of the window.

The cursor may be moved outside the window. However, it will be forced to lie
inside the window before any character is written by the Text VDU (see TXT
VALIDATE) or the cursor blob is drawn.

Related Entries:
TXT GET CURSOR
TXT SET CURSOR
TXT SET ROW
38: TXT SET ROW #BB72

Set cursor vertical position.

Action:
Move the current position of the currently selected stream to a new row. The
cursor blob will be removed from the current position and redrawn at the new
position (if the cursor is enabled and turned on).

Entry conditions:
A contains the required logical row for the cursor.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The required row is given in logical coordinates. i.e. Row 1 is the topmost row
of the window.

The cursor may be moved outside the window. However, it will be forced to lie
inside the window before any character is written by the Text VDU (see TXT
VALIDATE) or the cursor blob is drawn.

Related Entries:
TXT GET CURSOR
TXT SET COLUMN
TXT SET CURSOR
39: TXT SET CURSOR #BB75

Set cursor position.

Action:
Move the current position of the currently selected stream to a new row and
column. The cursor blob will be removed from the current position and
redrawn at the new position (if the cursor is enabled and turned on).

Entry conditions:
H contains the required logical column.
L contains the required logical row.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The required position is given in logical coordinates. i.e. Row 1, column 1 is
the top left corner of the window.

The cursor position may be moved outside the window. However, it will be
forced to lie inside the window before any character is written by the Text
VDU (see TXT VALIDATE) or the cursor blob is drawn.

Related Entries:
TXT GET CURSOR
TXT SET COLUMN
TXT SET ROW
40: TXT GET CURSOR #BB78

Ask current cursor position.

Action:
Get the current location of the cursor and a count of the number of times the
window of the currently selected stream has rolled.

Entry conditions:
No conditions.

Exit conditions:
H contains the logical cursor column.
L contains the logical cursor row.
A contains the current roll count.

Flags corrupt.
All other registers are preserved.

Notes:
The cursor position is given in logical coordinates. i.e. Row 1, column I is the
top left corner of the window.

The roll count passed out has no absolute meaning. It is decremented when the
window is rolled up and is incremented when the window is rolled down. It
may be used to determine whether the window has rolled by comparing it with
a previous value.

The position reported may not be inside the window and is, therefore, not
necessarily the position at which the next character will be printed. Use TXT
VALIDATE to check this.

Related Entries:
TXT SET COLUMN
TXT SET CURSOR
TXT SET ROW
TXT VALIDATE
41: TXT CUR ENABLE #BB7B

Allow cursor display - user.

Action:
Allow the cursor blob for the currently selected stream to be placed on the
screen. The cursor blob will be placed on the screen immediately unless the
cursor is turned off (see TXT CUR OFF).

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
Cursor enabling and disabling is intended for use by the user. It is also used
when the VDU is disabled (see TXT VDU ENABLE and TXT VDU
DISABLE).

Related Entries:
TXT ASK STATE
TXT CUR DISABLE
TXT CUR ON
TXT DRAW CURSOR
TXT UNDRAW CURSOR
42: TXT CUR DISABLE #BB7E

Disallow cursor display - user.

Action:
Prevent the cursor blob for the currently selected stream from being placed on
the screen. The cursor blob will be removed from the screen immediately if it
is currently there.

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
Cursor enabling and disabling is intended for use by the user. It is also used
when the VDU is disabled (see TXT VDU ENABLE and TXT VDU
DISABLE).

Related Entries:
TXT ASK STATE
TXT CUR ENABLE
TXT CUR OFF
TXT DRAW CURSOR
TXT UNDRAW CURSOR
43: TXT CUR ON #BB81

Allow cursor display - system.

Action:
Allow the cursor blob for the currently selected stream to be placed on the
screen. The cursor blob will be placed on the screen immediately unless the
cursor is disabled (see TXT CUR DISABLE).

Entry conditions:
No conditions.

Exit conditions:
All registers and flags preserved.

Notes:
Turning the cursor on and off is intended for use by system ROMs.

Related Entries:
TXT ASK STATE
TXT CUR ENABLE
TXT CUR OFF
TXT DRAW CURSOR
TXT UNDRAW CURSOR
44: TXT CUR OFF #BB84

Disallow cursor display - system.

Action:
Prevent the cursor blob for the currently selected stream from being placed on
the screen. The cursor blob will be removed from the screen immediately if it
is currently there.

Entry conditions:
No conditions.

Exit conditions:
All registers and flags preserved.

Notes:
Turning the cursor on and off is intended for use by system ROMs.

Related Entries:
TXT ASK STATE
TXT CUR DISABLE
TXT CUR ON
TXT DRAW CURSOR
TXT UNDRAW CURSOR
45: TXT VALIDATE #BB87

Check if a cursor position is within the window.

Action:
Check a screen position to see if it lies within the current window. If it does not
then determine the position where a character would be printed after applying
the rules for forcing the screen position inside the window.

Entry conditions:
H contains the logical column of the position to check.
L contains the logical row of the position to check.

Exit conditions:
If printing at the position would not cause the window to roll:
Carry true.
B corrupt.

If printing at the position would cause the window to roll up:


Carry false.
B contains #FF.

If printing at the position would cause the window to roll down:


Carry false.
B contains #00.

Always:
H contains the logical column at which a character would be printed.
L contains the logical row at which a character would be printed.
A and other flags corrupt.
All other registers preserved.

Notes:
The positions on the screen are given in logical coordinates. i.e. Row 1, column
1 is the top left corner of the window.

Before writing a character or putting the cursor blob on the screen the Text
VDU validates the current position, performs any required roll then writes at
the appropriate position.
The algorithm to work out the position to print at, from the position to check, is
as follows:

1/ If the position is right of the right edge of the window it is moved to the left
edge of the window on the next line.

2/ If the position is left of the left edge of the window it is moved to the right
edge of the window on the previous line.

3/ If the position is now above the top edge of the window then it is moved to
the top edge of the window and the window needs rolling downwards.

4/ If the position is now below the bottom edge of the window it is moved to
the bottom edge of the window and the window needs rolling upwards.

Related Entries:
SCR HW ROLL
SCR SW ROLL
TXT GET CURSOR
46: TXT PLACE CURSOR #BB8A

Put a cursor blob on the screen.

Action:
Put a cursor blob on the screen at the cursor position for the currently selected
stream.

Entry conditions:
No conditions.

Exit conditions:
AFcorrupt.
All other registers preserved.

Notes:
TXT PLACE CURSOR is provided to allow the user to run multiple cursors in
a window. The indirection TXT DRAW CURSOR should be called for merely
placing the normal cursor blob on the screen. Higher level routines, such as
TXT OUTPUT and TXT SET CURSOR, automatically remove and place the
normal cursor when appropriate, the user must deal with any other cursors.

It is not safe to call TXT PLACE CURSOR twice at a particular screen


position without calling TXT REMOVE CURSOR in between because this
may leave a spurious cursor blob on the screen when the cursor position is
moved.

The cursor position is forced to be inside the window before the cursor blob is
drawn.

The cursor blob is an inverse patch formed by exciusive-oring the contents of


the screen at the cursor position with the exclusive-or of the current pen and
paper inks.

Related Entries:
TXT DRAW CURSOR
TXT REMOVE CURSOR
47: TXT REMOVE CURSOR #BB8D

Take a cursor blob off the screen.

Action:
Take a cursor blob off the screen at the cursor position of the currently selected
stream.

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
TXT REMOVE CURSOR is provided to allow the user to run multiple cursors
in a window. The indirection TXT UNDRAW CURSOR should be called for
merely removing the normal cursor from the screen. Higher level routines,
such as TXT OUTPUT and TXT SET CURSOR, automatically remove and
place the normal cursor when appropriate, the user must deal with any other
cursors.

TXT REMOVE CURSOR should only be used to remove a cursor placed on


the screen by calling TXT PLACE CURSOR. The cursor should be removed
when the cursor position is to be changed (rolling the window implicitly
changes the cursor position) or the screen is to be read or written. Incorrect use
of this routine may result in a spurious cursor blob being generated.

The cursor position is forced to be inside the window before the cursor blob is
removed (this should not matter as TXT PLACE CURSOR has already done
this).

The cursor blob is an inverse patch formed by exciusive-oring the contents of


the screen at the cursor position with the exclusive-or of the current pen and
paper inks.

Related Entries:
TXT PLACE CURSOR
TXT UNDRAW CURSOR
48: TXT SET PEN #BB90

Set ink for writing characters.

Action:
Set the text pen ink for the currently selected stream. This is the ink that is used
for writing characters (the foreground ink).

Entry conditions:
A contains ink to use.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The ink is masked to bring it within the range of legal inks for the current
screen mode. That is with #0F in mode 0, #03 in mode land #01 in mode 2.

The cursor blob will be redrawn using the new ink (if enabled).

Related Entries:
GRA SET PEN
SCR SET INK
TXT GET PEN
TXT SET PAPER
49: TXT GET PEN #BB93

Get ink for writing characters.

Action:
Ask what the pen ink is set to for the currently selected stream. This is the ink
used for writing characters (foreground ink).

Entry conditions:
No conditions.

Exit conditions:
A contains the ink.
Flags corrupt.
All other registers preserved.

Notes:
This routine has no other effects.

Related Entries:
GRA GET PEN
SCR GET INK
TXT GET PAPER
TXT SET PEN
50: TXT SET PAPER #BB96

Set ink for writing text background.

Action:
Set the text paper ink for the currently selected stream. This is the ink used for
writing the background to characters and for clearing the text window.

Entry conditions:
A contains the ink to use.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The ink is masked to bring it within the range of legal inks for the current
screen mode. That is with #OF in mode 0, #03 in mode land #01 in mode 2.

The cursor blob will be redrawn using the new ink (if enabled).

This ink will be used when clearing areas of the text window (by TXT CLEAR
WINDOW and certain control codes).

This routine does not clear the text window.

Related Entries:
GRA SET PAPER
SCR SET INK
TXT GET PAPER
TXT SET PEN
51: TXT GET PAPER #BB99

Get ink for writing background.

Action:
Ask what the paper ink is set to for the currently selected stream. This is the
ink used for writing the background to characters and for clearing the text
window.

Entry conditions:
No conditions.

Exit conditions:
A contains the ink.
Flags corrupt.
All other registers preserved.

Notes:
This routine has no other effects.

Related Entries:
GRA GET PAPER
SCR GET INK
TXT GET PEN
TXT SET PAPER
52: TXT INVERSE #BB9C

Swap current pen and paper inks over.

Action:
Exchange the text pen and paper (foreground and background) inks for the
currently selected stream.

Entry conditions:
No conditions.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
In V1.l firmware the cursor blob is removed and replaced and so the current
position is forced legal (inside the window) which may cause the screen to roll.
In V1.0 firmware the cursor blob is not redrawn and so it should not be on the
screen when this routine is called.

Related Entries:
TXT SET PAPER
TXT SET PEN
53: TXT SET BACK #BB9F

Allow or disallow background being written.

Action:
Set character write mode to opaque or transparent for the currently selected
stream. Opaque mode writes background with the character. Transparent mode
writes the character on top of the current contents of the screen.

Entry conditions:
If background is to be written (opaque mode):

A must be zero.

If background is not to be written (transparent mode):

A must be non-zero.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
Writing in transparent mode is intended for annotating diagrams and similar
applications. It can have unfortunate effects if it is used generally because
overwriting a character will not remove the character underneath thus creating
an incomprehensible jumble on the screen.

Setting the character write mode does not affect the Graphics VDU. In V1.1
firmware the routine GRA SET BACK sets the equivalent graphics background
write mode.

Related Entries:
GRA SET BACK
TXT GET BACK
TXT WR CHAR
TXT WRITE CHAR
54: TXT GET BACK #BBA2

Ask if background is being written.

Action:
Get the character write mode for the currently selected stream.

Entry conditions:
No conditions.

Exit conditions:
If background is to be written (opaque mode):

A contains zero.

If background is not to be written (transparent mode):

A contains non-zero.

Always:

DE, HL and flags corrupt.


All other registers preserved.

Notes:
This only applies to the Text VDU, the Graphics VDU always writes opaque.

Related Entries:
TXT SET BACK
55: TXT GET MATRIX #BBA5

Get the address of a character matrix.

Action:
Calculate a pointer to the matrix for a character and determine if it is a user
defined matrix.

Entry conditions:
A contains the character whose matrix is to be found.

Exit conditions:
If the matrix in the user defined matrix table:

Carry true.

If the matrix is in the lower ROM:

Carry false.

Always:

HL contains the address of the matrix.


A and other flags corrupt.
All other registers preserved.

Notes:
The matrix may be in RAM or in ROM. The Text VDU assumes that the
appropriate ROMs are enabled or disabled when it calls this routine to get the
matrix for a character. (The lower ROM is on, the upper ROM is normally off).

The matrix is stored as an 8 byte bit significant vector. The first byte describes
the top line of the character and the last byte the bottom line. Bit 7 of a byte
refers to the leftmost pixel of a line and bit 0 to the rightmost pixel. If a bit is
set in the matrix then the pixel should be written in the pen ink. If a bit is not
set then the pixel should either be written in the paper ink or left alone
(depending on the character write mode).

Related Entries:
TXT SET MATRIX
56: TXT SET MATRIX #BBA8

Set a character matrix.

Action:
Set the matrix for a user defined character. If the character is not user defined
then no action is taken.

Entry conditions:
A contains the character whose matrix is to be set.
HL contains the address of the matrix to set.

Exit conditions:
If the character is user definable:
Carry true.

If the character is not user definable:


Carry false.

Always:
A, BC, DE, HL and other flags corrupt.
All other registers preserved.

Notes:
The matrix is stored as an 8 byte bit significant vector. The first byte describes
the top line of the character and the last byte the bottom line. Bit 7 of a byte
refers to the leftmost pixel of a line and bit 0 to the rightmost pixel. If a bit is
set in the matrix then the pixel should be written in the pen ink. If a bit is not
set then the pixel should either be written in the paper ink or left alone
(depending whether the character write mode is opaque or transparent
currently).

The matrix is copied from the area given into the character matrix table without
using RAM LAMs thus the matrices can be set from ROM providing it is
enabled. (Note however that the jumpblock disables the upper ROM.)

Altering a character matrix changes the matrix for all streams. It does not alter
any character on the screen; it changes what will be placed on the screen the
next time the character is written.

Related Entries:
TXT GET MATRIX
TXT SET M TABLE
57: TXT SET M TABLE #BBAB

Set the user defined matrix table address.

Action:
Set the user defined matrix table and the number of characters in the table. The
table is initialized with the current matrix settings.

Entry conditions:
DE contains the first character in the table.
HL contains the address of the start of the new table.

Exit conditions:
If there was no user defined matrix table before:

Carry false.
A and HL corrupt.

If there was a user defined matrix table before:

Carry true.
A contains the first character in the old table.
HL contains the address of the old table.

Always:

BC, DE and other flags corrupt.


All other registers preserved.

Notes:
If the first character specified is in the range 0. .255 then the matrices for all
characters between that character and character 255 are to be stored in the user
defined table.

If the first character specified is not in the range 0.255 then the user defined
matrix table is deemed to contain no matrices (and the table address passed is
ignored).

The table must be (256 - first char) * 8 bytes long. The matrices are stored in
the table in ascending order. The table is initialized with the current matrix
settings, whether they were previously in RAM or in the ROM.

The table should not be located in RAM underneath a ROM.

It is permissible for the new and old matrix tables to overlap (thus allowing the
table to be extended or contracted) providing that matrices in the new table
occupy an address earlier or equal to the address that they occupied in the old
table.

All streams share the matrix table so any changes to it will be reflected on all
streams.

Related Entries:
TXT GET M TABLE
TXT SET MATRIX
58: TXT GET M TABLE #BBAE

Get user defined matrix table address.

Action:
Get the address of the current user defined matrix table and the first character
in the table.

Entry conditions:
No conditions.

Exit conditions:
If there is no user defined matrix table:

Carry false
A and HL corrupt

If there is a user defined matrix table:

Carry true
A contains the first character in the table
HL contains the address of the start of the table.

Always:
Other flags corrupt
All other registers preserved.

Notes:
The matrices for characters between the first character and 255 are stored in the
table in ascending order. Each matrix is 8 bytes long.

Related Entries:
TXT GET MATRIX
TXT SET M TABLE
59: TXT GET CONTROLS #BBB1

Fetch address of control code table.

Action:
Get the address of the control code table.
Entry conditions:
No conditions.
Exit conditions:
HL contains the address of the control code table.
All other registers and flags preserved.
Notes:
All streams share one control code table so that any changes made to the table
will affect all streams.
The control code table has a 3 byte entry for each control code. The entries are
stored in ascending order, so the entry for #00 is first and that for # 1F is last.
The first byte of each entry is the number of parameters the control code
requires, the other two bytes are the address of the routine to call to process the
control code when all its parameters have been received. The routine must be
located in the central 32K of RAM and it must obey the following interface:
Entry:
A contains the last character added to the buffer.
B contains the length of the buffer (including the control code).
C contains the same as A.
HL contains the address of the control code buffer (points at the control
code).
Exit:
AF, BC, DE, HL corrupt.
All other registers preserved.
As the control code buffer only has space to store 9 parameter characters the
number of parameters required should be limited to 9 or fewer.
The control code table is reinitialized to its default routines when TXT RESET
is called.
In Vl.1 firmware the first byte of each entry also specifies whether the control
codes is to be disabled when the VDU is disabled or whether it is always to be
obeyed. Bit 7 of the byte is set if the code is to be disabled.

Related Entries:
TXT OUTPUT
60: TXT STR SELECT #BBB4

Select a Text VDU stream.

Action:
Make a given stream the currently selected stream (if it isn’t already).

Entry conditions:
A contains the required stream.

Exit conditions:
A contains the previously selected stream.
HL and flags corrupt.
All other registers preserved.

Notes:
The requested stream number is masked (with #07) to make it into a legal
stream number.
Many attributes of the Text VDU may be set independently on different
streams. It is important to ensure that the correct stream is selected when any of
these are altered. These attributes are:
Pen ink.
Paper ink.
Cursor position.
Window limits.
Cursor enable/disable.
Cursor on/off.
VDU enable/disable.
Character write mode.
Graphic character write mode.
If the stream is already selected then this routine returns quickly. It is not
unreasonable to repeatedly select a stream (before each character sent, for
example).

Related Entries:
TXT OUTPUT
61: TXT SWAP STREAMS #BBB7

Swap the states of two streams.

Action:
The stream descriptors for two streams are exchanged. The currently selected
stream number remains the same (although its descriptor may have been
altered).

Entry conditions:
B contains a stream number.
C contains another stream number.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The stream numbers passed are masked (with #07) to ensure that they are legal
stream numbers.

The attributes that are exchanged are:

Pen ink.
Paper ink.
Cursor position.
Window limits.
Window roll count.
Cursor enable/disable.
Cursor on/off.
VDU enable/disable.
Character write mode.
Graphic character write mode.

Related Entries:
TXT STR SELECT
62: GRA INITIALISE #BBBA

Initialize the Graphics VDU.

Action:
The Graphics VDU is fully initialized (as during EMS). All Graphic VDU
variables and indirections are set to their default values.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The full operation is:

Set the Graphics VDU indirections (GRA PLOT, GRA TEST and GRA
LINE) to their default routines.
Set the graphic paper to ink 0.
Set the graphic pen to ink 1.
Set the user origin to the bottom left corner of the screen.
Move the current position to the user origin.
Set the graphics window to cover the whole screen.
The graphics background write mode is set to opaque.
The line mask is set to #FF and the first pixel of lines are plotted.
The graphics window is not c1eared.

Related entries:
GRA DEFAULT
GRA RESET
SCR INITIALISE
63: GRA RESET #BBBD

Reset the Graphics VDU.

Action:
Re-initialize the Graphics VDU indirections to their default routines and set
default modes.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
Sets the Graphics VDU indirections (GRA PLOT, GRA TEST and GRA
LINE) to their default routines. V1.1 firmware also sets the graphics
background mode to opaque, sets the line mask to #FF and sets the first pixel
of lines to be plotted.

Related entries:
GRA DEFAULT
GRA INITIALISE
64: GRA MOVE ABSOLUTE #BBC0

Move to an absolute position.

Action:
Move the current position to an absolute position.

Entry conditions:
DE contains the required user X coordinate.
HL contains the required user Y coordinate.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The new position is given in user coordinates. i.e. Relative to the user origin.

The new position can be outside the graphics window.

The Graphic VDU plotting, testing and line drawing routines all move the
current graphics position to the point (or endpoint) specified automatically.

Related entries:
GRA ASK CURSOR
GRA MOVE RELATIVE
65: GRA MOVE RELATIVE #BBC3

Move relative to current position.

Action:
Move the current position to relative to its current position.

Entry conditions:
DE contains a signed X offset.
HL contains a signed Y offset.

Exit conditions:
AF, BC, DE andHL corrupt.
All other registers preserved.

Notes:
The new position can be outside the graphics window.

The Graphic VDU plotting, testing and line drawing routines all move the
current
graphics position to the point (or endpoint) specified automatically.

Related entries:
GRA ASK CURSOR
GRA MOVE ABSOLUTE
66: GRA ASK CURSOR #BBC6

Get the current position.

Action:
Ask where the current graphics position is.

Entry conditions:
No conditions.

Exit conditions:
DE contains the user X coordinate.
HL contains the user Y coordinate.

AF corrupt.
All other registers preserved.

Notes:
The current position is given in user coordinates. i.e. Relative to the user
origin. The Graphic VDU plotting, testing and line drawing routines all move
the current graphics position to the point (or endpoint) specified automatically.
Thus, the position returned is probably where the last point was plotted or
tested.

Related entries:
GRA MOVE ABSOLUTE
GRA MOVE RELATIVE
67: GRA SET ORIGIN #BBC9

Set the origin of the user coordinates.

Action:
Set the location of the user origin and move the current position there.

Entry conditions:
DE contains the standard X coordinate of the origin.
HL contains the standard Y coordinate of the origin.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The origin position is given in standard coordinates in which (0,0) is the
bottom left corner of the screen.

The default origin position is at (0,0). Whenever the screen mode is changed,
by calling SCR SET MODE, the origin is restored to its default position.

Related entries:
GRA FROM USER
GRA GET ORIGIN
68: GRA GET ORIGIN #BBCC

Get the origin of the user coordinates.

Action:
Ask where the user coordinate origin is located.

Entry conditions:
No conditions.

Exit conditions:
DE contains the standard X coordinate of the origin.
HL contains the standard Y coordinate of the origin.

All other registers preserved.

Notes:
The origin position is given in standard coordinates in which (0,0) is the
bottom left corner of the screen.

Related entries:
GRA SET ORIGIN
69: GRA WIN WIDTH #BBCF

Set the right and left edges of the graphics window.

Action:
Set the horizontal position of the graphics window. The left and right edges are
respectively the first and last points that lie inside the window horizontally.

Entry conditions:
DE contains the standard X coordinate of one edge.
HL contains the standard X coordinate of the other edge.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The window edges are given in standard coordinates in which (0,0) is the
bottom left corner of the screen and coordinates are signed 16 bit numbers.

The left edge of the window is deemed to be the smaller of the two edges
supplied. The window will be truncated, if necessary, to make it fit the screen.
The edges are moved to screen byte boundaries so that the window only
contains whole bytes (the left edge is moved left, the right edge is moved
right). This moves the coordinates of the edges as follows in the various
modes:

Mode Left Edge Right Edge


0 Multiple of 2 Multiple of 2 minus 1
1 Multiple of 4 Multiple of 4 minus 1
2 Multiple of 8 Multiple of 8 minus 1

The default window covers the whole screen. Whenever the screen mode is
changed the window is restored to its default size.

All Graphics VDU point plotting and line drawing routines test whether the
points they are about to plot lie inside the window; if they are not then the
points are not plotted.

Related entries:
GRA GET W WIDTH
GRA WIN HEIGHT
70: GRA WIN HEIGHT #BBD2

Set the top and bottom edges of the graphics window.

Action:
Set the vertical position of the graphics window. The top and bottom edges are
respectively the last and first points that lie inside the window vertically.

Entry conditions:
DE contains the standard Y coordinate of one edge.
HL contains the standard Y coordinate of the other edge.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The window edges are given in standard coordinates in which (0,0) is the
bottom left corner of the screen and coordinates are signed 16 bit numbers.

The top edge will be deemed to be the higher of the two edges supplied.

The window will be truncated, if necessary, to make it fit the screen. The edges
will be moved to lie on screen line boundaries so that only whole screen lines
are included in the window (the top edge will be moved up, the bottom edge
will be moved down). This moves the bottom edge to an even coordinate and
the top edge to an odd coordinate.

The default window covers the whole screen. Whenever the screen mode is
changed the window is restored to its default size.
All Graphics VDU point plotting and line drawing routines test whether the
points they are about to plot lie inside the window; if they do not then the
points are not plotted.

Related entries:
GRA GET W HEIGHT
GRA WIN WIDTH
71: GRA GET W WIDTH #BBD5

Get the left and right edges of the graphics window.

Action:
Ask the horizontal position of the graphics window. The left and right edges
are respectively the first and last points that lie inside the window horizontally.

Entry conditions:
No conditions.

Exit conditions:
DE contains the standard X coordinate of the left edge of the window.
HL contains the standard X coordinate of the right edge of the window.

AF corrupt.
All other registers preserved.

Notes:
The window edges are given in standard coordinates in which (0,0) is the
bottom left corner of the screen.

The edges may not be exactly the same as those that were set using GRA WIN
WIDTH as the window is truncated to fit the screen. and the edges are moved
to screen byte boundaries so that the window only contains whole bytes.

Related entries
GRA GET W HEIGHT
GRA WIN WIDTH
72: GRA GET W HEIGHT #BBD8

Get the top and bottom edges of the graphics window.

Action:
Ask the vertical position of the graphics window. The top and bottom edges are
respectively the last and first points that lie inside the window vertically.

Entry conditions:
No conditions.

Exit conditions:
DE contains the standard Y coordinate of the top edge of the window.
HL contains the standard Y coordinate of the bottom edge of the window.

AF corrupt.
All other registers preserved.

Notes:
The window edges are given in standard coordinates. i.e. With (0,0) being the
bottom left corner of the screen.

The edges may not be exactly the same as those passed to GRA WIN HEIGHT
as the window is truncated to fit the screen, and the edges are moved to lie on
screen line boundaries so that only whole screen lines are included in the
window.

Related entries:
GRA GET W WIDTH
GRA WIN HEIGHT
73: GRA CLEAR WINDOW #BBDB

Clear the graphic window.

Action:
Clear the graphics window to the graphics paper ink.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.

All other registers preserved.

Notes:
The current graphics position is moved to the origin of the user coordinates.

Related entries:
GRA SET PAPER
GRA WIN HEIGHT
GRA WIN WIDTH
SCR CLEAR
TXT CLEAR WINDOW
74: GRA SET PEN #BBDE

Set the graphics plotting ink.

Action:
Set the graphics pen ink. This is the ink used by the Graphics VDU for plotting
points, drawing lines and writing characters.

Entry conditions:
A contains the required ink.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The ink is masked to bring it in the range of inks for the current screen mode.
In mode 0 the mask is #0F, in mode lit is #03 and in mode 2 it is #01.

In V1.1 firmware the graphics pen ink is taken to delimit the edge of the area to
fill when flood filling areas of the screen.

Related entries:
GRA GET PEN
GRA SET PAPER
SCR SET INK
TXT SET PEN
75: GRA GET PEN #BBE1

Get the current graphics plotting ink

Action:
Ask what the current graphics pen ink is set to. This is the ink used by the
Graphics VDU for plotting points, drawing lines and writing characters.

Entry conditions:
No conditions.

Exit conditions:
A contains the ink.
Flags corrupt.
All other registers preserved.

Notes:
This routine has no other effects.

Related entries:
GRA GET PAPER
GRA SET PEN
SCR GET INK
TXT GET PEN
76: GRA SET PAPER #BBE4

Set the graphics background ink.

Action:
Set the graphics paper ink.

Entry conditions:
A contains the required ink.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The ink is masked to bring it in the range of inks for the current screen mode.
In mode 0 the mask is #0F, in mode lit is #03 and in mode 2 it is #01.

The paper ink is the ink that is used for clearing the graphics window, and
writing the background to characters. It is assumed to cover everywhere
outside the graphics window when testing points.

In Vl.1 firmware the graphics paper ink is used to plot pixels corresponding to
a zero bit in the line mask when drawing lines.

Related entries:
GRA GET PAPER
GRA SET PEN
SCR GET INK
TXT SET PAPER
77: GRA GET PAPER #BBE7

Get the current graphics background ink.

Action:
Ask what the current graphics paper ink is set to.

Entry conditions:
No conditions.

Exit conditions:
A contains the ink.

Flags corrupt.
All other registers preserved.

Notes:
The paper ink is the ink that is used for clearing the graphics window, and
writing the background to characters. It is assumed to cover everywhere
outside the graphics window when testing points.

Related entries:
GRA GET PEN
GRA SET PAPER
SCRGETINK
TXT GET PAPER
78: GRA PLOT ABSOLUTE #BBEA

Plot a point at an absolute position.

Action:
The current graphic position is moved to the position supplied. If this lies
inside the graphics window then the point is piotted in the current graphics pen
ink using the current graphics write mode. If the point lies outside the graphics
window then no action is taken.

Entry conditions:
DE contains the user X coordinate to plot at.
HL contains the user Y coordinate to plot at.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The position to plot at is given in user coordinates. i.e. Relative to the user
origin.

This routine calls the GRA PLOT indirection to plot the point. In its turn GRA
PLOT calls the SCR WRITE indirection to set the pixel (if it is in the window).

Related entries:
GRA PLOT
GRA PLOT RELATIVE
GRA TEST ABSOLUTE
79: GRA PLOT RELATIVE #BBED

Plot a point relative to the current position

Action:
The current graphic position is moved to the position supplied. If this lies
inside the graphics window then the point is plotted in the current graphics pen
ink using the current graphics write mode. If the point lies outside the graphics
window then no action is taken.

Entry conditions:
DE contains a signed X offset.
HL contains a signed Y offset.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The position to plot at is given in relative coordinates. i.e. Relative to the
current graphics position.

This routine calls the GRA PLOT indirection to plot the point. In its turn GRA
PLOT calls the SCR WRITE indirection to set the pixel (if it is in the window).

Related entries:
GRA PLOT
GRA PLOT ABSOLUTE
GRA TEST RELATIVE
80: GRA TEST ABSOLUTE #BBF0

Test a point at an absolute position.

Action:
The current graphic position is moved to the position supplied. If this lies
inside the graphics window then the pixel is read from the screen and the ink it
is set to is decoded and returned. If the position lies outside the graphics
window then the current paper ink is returned.

Entry conditions:
DE contains the user X coordinate to test at.
HL contains the user Y coordinate to test at.

Exit conditions:
A contains the ink of the specified point (or the graphics paper ink).

BC, DE, HL and flags corrupt.


All other registers preserved.

Notes:
The position to test is given in user coordinates, i.e. Relative to the user origin.

This routine calls the GRA TEST indirection to test the point. In its turn GRA
TEST calls the SCR READ indirection to test the pixel (if it is in the window).

Related entries:
GRA PLOT ABSOLUTE
GRA TEST
GRA TEST RELATIVE
81: GRA TEST RELATIVE #BBF3

Test a point relative to the current position.

Action:
The current graphic position is moved to the position supplied. If this lies
inside the graphics window then the pixel is read from the screen and the ink it
is set to is decoded and returned. If the position lies outside the graphics
window then the current paper ink is returned.

Entry conditions:
DE contains a signed X offset.
HL contains a signed Y offset.

Exit conditions:
A contains the ink of the specified point (or the graphics paper ink).

BC, DE, HL and flags corrupt.


All other registers preserved.

Notes:
The position to test is given in relative coordinates. i.e. Relative to the current
graphics position.

This routine calls the GRA TEST indirection to test the point. In its turn GRA
TEST calls the SCR READ indirection to test the pixel (if it is in the window).

Related entries:
GRA PLOT RELATIVE
GRA TEST
GRA TEST ABSOLUTE
82: GRA LINE ABSOLUTE #BBF6

Draw a line to an absolute position.

Action:
Move the current graphics position to the endpoint supplied. All points
between this position and the previous graphics position that lie inside the
graphics window may be plotted. Points that lie outside the graphics window
are ignored.

Entry conditions:
DE contains the user X coordinate of the endpoint.
HL contains the user Y coordinate of the endpoint.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The position of the end of the line is given in user coordinates. i.e. Relative to
the user origin.
In V1.0 firmware the points will be plotted in the current graphics pen ink
using the current graphics write mode.
In Vl.l firmware the setting of the line mask determines how pixels on the line
will be plotted. The line mask is bit significant and is used repeatedly in the
order bit 7, bit 6 down to bit 0 for each pixel in the line. If the bit is one then
the pixel is plotted in the graphics pen ink using the current graphics write
mode. If the bit is zero then the action taken depends on the graphics
background write mode. If the background mode is opaque then the pixel is
plotted in the graphics paper ink using the current graphics write mode. If the
background mode is transparent then the pixel is not plotted.
In V1.1 firmware the first pixel of the line (that at the previous graphics
position) is not plotted if the first point plotting mode is set false.
This routine calls the GRA LINE indirection to draw the line. In its turn GRA
LINE calls the SCR WRITE indirection to write the pixels (for pixels in the
graphics window).

Related entries:
GRA LINE
GRA LINE RELATIVE
GRA SET BACK
GRA SET FIRST
GRA SET LINE MASK
83: GRA LINE RELATIVE #BBF9

Draw a line relative to the current position.

Action:
Move the current graphics position to the endpoint supplied. All points
between this position and the previous graphics position that lie inside the
graphics window may be plotted. Points that lie outside the graphics window
are ignored.
Entry conditions:
DE contains the signed X offset of the endpoint. HL contains the signed Y
offset of the endpoint.
Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The position of the end of the line is given in relative coordinates. i.e. Relative
to the current graphics position.
In V1.0 firmware the points will be plotted in the current graphics pen ink
using the current graphics write mode.
In V1.1 firmware the setting of the line mask determines how pixels on the line
will be plotted. The line mask is bit significant and is used repeatedly in the
order bit 7, bit 6 down to bit 0 for each pixel in the line. If the bit is one then
the pixel is plotted in the graphics pen ink using the current graphics write
mode. If the bit is zero then the action taken depends on the graphics
background write mode. If the background mode is opaque then the pixel is
plotted in the graphics paper ink using the current graphics write mode. If the
background mode is transparent then the pixel is not plotted.
In V1.1 firmware the first pixel of the line (that at the previous graphics
position) is not plotted if the first point plotting mode is set false.
This routine calls the GRA LINE indirection to draw the line. In its turn GRA
LINE calls the SCR WRITE indirection to write the pixels (for pixels in the
graphics window).
Related entries:
GRA LINE
GRA LINE ABSOLUTE
GRA SET BACK
GRA SET FIRST
GRA SET LINE MASK
84: GRA WR CHAR #BBFC

Put a character on the screen at the current graphics


position.

Action:
Write a character on the screen at the current graphics position.

Entry conditions:
A contains the character to write.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The character is written with its top left corner being the current graphics
position.

All characters are printed, even control codes (characters #00.. #1F).

The current position is moved right by the width of the character (ready for
another character to be written). In mode 0 this move is 32 points right, in
mode 1 the move is 16 points and in mode 0 it is 8 points.

The character will be plotted in the graphic pen ink. In the case of V1.0
firmware, or V1.1 firmware when the background write mode is set to opaque,
the background to the character will be plotted in the graphics paper ink. In the
case of V1.1 firmware when the background write mode is set transparent the
background pixels are not plotted. Pixels in the character that lie outside the
graphics window will not be plotted. The pixels are plotted using the SCR
WRITE indirection so they are written using the current graphics write mode.

Related entries:
GRA SET BACK
TXT SET GRAPHIC
TXT WR CHAR
85: SCR INITIALISE #BBFF

Initialize the Screen Pack.

Action:
Full initialization of the Screen Pack (as used during EMS). All Screen Pack
variables and indirections are initialized, also the screen mode and the inks are
initialized to their default settings.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The screen indirections (SCR READ, SCR WRITE and SCR MODE CLEAR)
are set to their default routines.
The inks are set to their default colours (see Appendix V).
The ink flashing periods are set to their default values.
The screen is put into mode 1.
The screen base is set to put the screen memory at #C000.. #FFFF (under the
upper ROM).
The screen offset is set to 0.
The screen is cleared to ink 0.
The Graphics VDU write mode is set to FORCE mode.
The ink flashing frame flyback event is setup.

The initialization is performed in an order that attempts to avoid the previous


contents of the screen becoming visible (at EMS the contents will be random).

Related entries:
GRA INITIALISE
SCR RESET
TXT INITIALISE
86: SCR RESET #BC02

Reset the Screen Pack.

Action:
Reinitializes the Screen Pack indirections and the ink colours. Also reinitializes
the flash rate and Graphics VDU write mode.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The screen indirections (SCR READ, SCR WRITE and SCR MODE CLEAR)
are set to their default routines.
The inks are set to their default colours (see Appendix V).
The ink flashing periods are set to their default values.
The Graphics VDU write mode is set to FORCE mode.

The inks are not passed to the hardware. This will be done when the inks flash
next.

Related entries:
SCR INITIALISE
SCR SET ACCESS
SCR SET FLASHING
SCR SET INK
87: SCR SET OFFSET #BC05

Set the offset of the start of the screen.

Action:
Set the offset of the first character on the screen. By changing this offset the
screen can be rolled.

Entry conditions:
HL contains the required offset.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The offset passed is masked with #O7FE to make sure it is not too big and to
make sure that the offset is even. (The screen is only capable of rolling in two
byte increments).

The screen base and screen offset are combined into a single value and sent to
the hardware together.

The screen offset is used by SCR CHAR POSITION and SCR DOT
POSITION to calculate screen addresses. If the screen offset is changed merely
by calling the Machine Pack routine MC SCREEN OFFSET then the Text and
Graphics VDUs will use incorrect screen addresses.

The offset is set to zero when the screen mode is set or the screen is cleared by
calling SCR CLEAR.

Related entries:
MC SCREEN OFFSET
SCR GET LOCATION
SCR HW ROLL
SCR SET BASE
SCR SET POSITION
88: SCR SET BASE #BC08

Set the area of RAM to use for the screen memory.

Action:
Sets the base address of the screen memory. This can be used to move the
screen out from underneath the upper ROM or to display a prepared screen
instantly.

Entry conditions:
A contains the more significant byte of the base address.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The screen memory can only be located on a 16K boundary so the value passed
is masked with #C0. The default screen base, set at EMS, is #C0.

The screen offset is combined with the screen base into a single value which is
sent to the hardware.

The screen base address is used by SCR CHAR POSITION and SCR DOT
POSITION to calculate screen addresses. If the screen base is changed merely
by calling the Machine pack routine MC SCREEN OFFSET then the text and
graphics VDUs will use incorrect screen addresses.

The screen memory is not cleared when the screen base is set, use SCR
CLEAR to do this.

Related entries:
MC SCREEN OFFSET
SCR GET LOCATION
SCR SET OFFSET
SCR SET POSITION
89: SCR GET LOCATION #BC0B

Fetch current base and offset settings.

Action:
Ask where the screen memory is located and where the start of the screen is.

Entry conditions:
No conditions.

Exit conditions:
A contains the more significant byte of the base address.
HL contains the current offset.

Flags corrupt.
All other registers preserved.

Notes:
The base and offsets returned by this routine may not be the same as those set
using SCR SET BASE or SCR SET OFFSET. This is because the values are
masked to make them legal and the screen offset is also changed when the
hardware screen rolling routine, SCR HW ROLL, is used.

Related entries:
SCR SET BASE
SCR SET OFFSET
SCR SET POSITION
90: SCR SET MODE #BC0E

Set screen into a new mode.

Action:
Put the screen into a new mode and make sure that the Text and Graphics
VDUs are set up correctly.

Entry conditions:
A contains the required mode.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The mode requested is masked with #03. If the resulting value is 3 then no
action is taken. Otherwise one of the following screen modes is set up:

Mode 0: 160 x 200 pixels, 20 x 25 characters.


Mode 1: 320 x 200 pixels, 40 x 25 characters.
Mode 2: 640 x 200 pixels, 80 x 25 characters.

At an early stage the screen is cleared to avoid the old contents of the screen
being displayed in the wrong mode. The screen is cleared by calling the SCR
MODE CLEAR indirection.
All text and graphics windows are set to cover to whole screen and the graphics
user origin is set to the bottom left corner of the screen. The cursor blobs for all
text streams are turned off. Stream zero is selected.

The current text and graphics pen and paper inks are masked as appropriate for
the new mode (see TXT SET PEN et al). When changing mode to a mode that
allows fewer inks on the screen this may cause the pen or paper inks to change.

Related entries:
MC SET MODE
SCR GET MODE
91: SCR GET MODE #BC11

Ask the current screen mode.

Action:
Fetch and test the current screen mode.

Entry conditions:
No conditions.

Exit conditions:
If current mode is mode 0:
Carry true.
Zero false.
A contains 0.

If current mode is mode 1:


Carry false.
Zero true.
A contains 1.

If current mode is mode 2:


Carry false.
Zero false.
A contains 2.

Always:
Other flags corrupt.
All other registers preserved.

Notes:
The modes are:
Mode 0: 160 x 200 pixels, 20 x 25 characters.
Mode 1: 320 x 200 pixels, 40 x 25 characters.
Mode 2: 640 x 200 pixels, 80 x 25 characters.

Related entries:
SCR SET MODE
92: SCR CLEAR #BC14

Clear the screen (to ink zero).

Action:
Clear the whole of screen memory to zero.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
At an early stage the ink flashing is turned off and the inks are all set to the
same colour as ink 0. This makes the screen clearing appear instantaneous.
When all the screen memory has been set to 0 the ink flashing is turned back
on (an ink flashing event is added to the frame flyback queue) and all inks are
set to their proper colours.

If the text paper ink and the graphics paper ink are not set to ink 0 then this will
become apparent on the screen when characters are written or windows are
cleared.

The screen offset is set to zero.

Related entries:
GRA CLEAR WINDOW
SCR MODE CLEAR
TXT CLEAR WINDOW
93: SCR CHAR LIMITS #BC17

Ask the size of the screen in characters.

Action:
Get the last character row and column on the screen in the current mode.

Entry conditions:
No conditions.

Exit conditions:
B contains the physical last column on the screen.
C contains the physical last row on the screen.

AF corrupt.
All other registers preserved.

Notes:
The screen edges are given in physical coordinates. i.e. Row 0, column 0 is the
top left corner of the screen. This means that the last column on the screen is
19 in mode 0,39 in mode 1 and 79 in mode 2. The last row on the screen is 24
in all modes.

Related entries:
SCR GET MODE
94: SCR CHAR POSITION #BC1A

Convert physical coordinates to a screen position.

Action:
Calculate the screen address of the top left corner of a character position on the
screen. Also return the width of a character in the current mode.

Entry conditions:
H contains the physical character column.
L contains the physical character row.

Exit conditions:
HL contains the screen address of the top left corner of the character.
B contains the width in bytes of a character in screen memory.

AF corrupt.
All other registers preserved.

Notes:
The character position is given in physical coordinates. i.e. Row 0, column 0 is
the top left corner of the screen.

The character position given is not checked for being legal. An illegal position
(one outside the limits of the screen) will generate a meaningless screen
address.

The conversion to screen address uses the following formula:


Screen address = Screen base + (Block offset MOD #0800)
where:
Block offset = (Row * 80) + (Column * Width) + Screen offset
and:
Screen base is the address of the start of screen memory.
Width is the width of a character in bytes in the current mode (4
in mode 0, 2 in mode 1,1 in mode 2).
Screen offset is offset of the first byte to be displayed on the screen.

Related entries:
SCR DOT POSITION
SCR NEXT BYTE
8CR NEXT LINE
SCR PREY BYTE
SCR PREY LINE
95: SCR DOT POSITION #BC1D

Convert base coordinates to a screen position.

Action:
Calculate the screen address and mask for a pixel. Also return an indication of
the number of pixels in a screen byte in the current mode.

Entry conditions:
DE contains the base X coordinate of a pixel.
HL contains the base Y coordinate of a pixel.

Exit conditions:
HL contains the screen address of the pixel.
C contains the mask for the pixel.
B contains one less than the number of pixels in a byte.

AF and DE corrupt.
All other registers preserved.

Notes:
The pixel position is given in base coordinates. i.e. (0,0) is the pixel in the
bottom left corner of the screen and each coordinate position refers to a single
pixel.

The pixel position is not checked for being legal (within the limits of the
screen). If it is not then the screen address calculated is meaningless.

The conversion to screen address uses the following formula:

Screen address = Screen base + (Line in row * #0800) + (Row offset MOD
#0800)

where:
Screen base is the start address of screen memory.
Line in row = (199 - Y coordinate) MOD 8
Row offset = (Row number * 80) + Byte in row + Screen offset
and:
Row number = (199 - Y coordinate)/8
Byte in row = X coordinate/Byte width
Screen offset is offset of the first byte to be displayed on the screen.
Byte width is the number of pixels in a byte in the current mode (2 in
mode 0, 4 in mode 1, 8 in mode 2).

X coordinate MOD Byte width is used to calculate the mask for the appropriate
pixel.
Related entries:
GRA FROM USER
SCR CHAR POSITION
SCR NEXT BYTE
SCR NEXT LINE
SCR PREY BYTE
SCR PREY LINE
96: SCR NEXT BYTE #BC20

Step a screen address right one byte.

Action:
Calculate the screen address of the byte right of the supplied screen address.

Entry conditions:
HL contains a screen address.

Exit conditions:
HL contains the updated screen address.

AF corrupt.
All other registers preserved.

Notes:
Moving off the end of the screen line is not prevented. It will simply point the
screen address at the next byte in the screen block. Normally this will be the
first byte on a screen line 8 screen lines down from the old line (i.e. down one
character row). However, moving right off the end of the last screen line in a
block will point the screen address at the start of the 48 bytes in the block that
are not displayed on the screen.

This routine is intended to be used for moving the screen address when putting
characters or drawing lines on the screen.

Related entries:
SCR CHAR POSITION
SCR DOT POSITION
SCR NEXT LINE
5CR PREY BYTE
SCR PREY LINE
97: SCR PREV BYTE #BC23

Step a screen address left one byte.

Action:
Calculate the screen address of the byte left of the supplied screen address.

Entry conditions:
HL contains a screen address.

Exit conditions:
HL contains the updated screen address.

AF corrupt.
All other registers preserved.

Notes:
Moving off the start of the screen line is not prevented. It will simply point the
screen address at the previous byte in the screen block. Normally this will be
the last byte on a screen line 8 screen lines up from the old line (i.e. up one
character row). However, moving left off the start of the top screen line in a
block will point the screen address at the last of the 48 bytes in the block that
are not displayed on the screen.

This routine is intended to be used for moving the screen address when putting
characters or drawing lines on the screen.

Related entries:
SCR CHAR POSITION
SCR DOT POSITION
SCR NEXT BYTE
SCR NEXT LINE
SCR PREY LINE
98: SCR NEXT LINE #BC26

Step a screen address down one line.

Action:
Calculate the screen address of the byte below the supplied screen address.

Entry conditions:
HL contains a screen address.

Exit conditions:
HL contains the updated screen address.

AF corrupt.
All other registers preserved.

Notes:
Moving off the bottom of the screen is not prevented (and not recommended).
After moving off the bottom the screen address is not useful.

This routine is intended to be used for moving the screen address when putting
characters or drawing lines on the screen.

Related entries:
SCR CHAR POSITION
SCR DOT POSITION
SCR NEXT BYTE
SCR PREY BYTE
SCR PREY LINE
99: SCR PREV LINE #BC29

Step a screen address up one line.

Action:
Calculate the screen address of the byte above the supplied screen address.

Entry conditions:
HL contains a screen address.

Exit conditions:
HL contains the updated screen address.

AF corrupt.
All other registers preserved.

Notes:
Moving off the top of the screen is not prevented (and not recommended).
After moving off the top the screen address is not useful.

This routine is intended to be used for moving the screen address when putting
characters or drawing lines on the screen.

Related entries:
SCR CHAR POSITION
SCR DOT POSITION
SCR NEXT BYTE
SCR NEXT LINE
SCR PREY BYTE
100: SCR INK ENCODE #BC2C

Encode an ink to cover all pixels in a byte.

Action:
Convert an ink to the encoded form that will set all pixels in a byte to the ink.
This encoded ink can then be masked to generate the appropriate value to set a
single pixel to the ink.

Entry conditions:
A contains an ink number.

Exit conditions:
A contains the encoded ink.

Flags corrupt.
All other registers preserved.

Notes:
The encoding is not trivial as the pixels in a byte are interleaved and also the
bits in a pixel are not in the obvious order. The pixel bits are (most significant
to least significant):
Mode 0 Mode 1 Mode 2
Leftmost pixel: Bits 1,5,3,7 Bits 3,7 Bit 7
Bit 6
Bits 2,6 Bit 5
Bit 4
Bits 0,4,2,6 Bits l,5 Bit 3
Bit 2
Bits 0,4 Bit 1
Rightmost pixel: Bit 0

The Text and Graphic VDUs store their pen and paper inks in this encoded
form for ease of use internally. This saves time converting the ink for each
pixel plotted.

The encoding is different in different modes and so all inks have to be re-
encoded when the screen mode is changed. SCR SET MODE does this
automatically for the Text VDU and Graphics VDU pen and paper inks.

Related entries:
SCR INK DECODE
101: SCR INK DECODE #BC2F

Decode an encoded ink.

Action:
Convert an encoded ink to the appropriate ink number.

Entry conditions:
A contains an encoded ink.

Exit conditions:
A contains the ink number.

Flags corrupt.
All other registers preserved.

Notes:
The decoding is performed by decoding the ink of the leftmost pixel in the
encoded ink. The ink for this pixel is encoded in the following bits (most
significant to least significant) in the various screen modes:

Mode 0: Bits 1,5,3,7


Mode l: Bits 3,7
Mode 2: Bit 7

Related entries:
SCR INK ENCODE
102: SCR SET INK #BC32

Set the colours in which to display an ink.

Action:
Set which two colours will be used to display an ink. If the two colours are the
same then the ink will remain a steady colour. If the colours are different then
the ink will alternate between these two colours.

Entry conditions:
A contains an ink number.
B contains the first colour.
C contains the second colour.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The ink number is masked with #0F to make sure it is legal, and the colours are
masked with #1F. Colours 27. .31 are not intended for use; they are merely
duplicates of other colours available.

The new colours for an ink are not sent to the hardware immediately. They are
stored and will appear on the screen when the next frame flyback occurs.

The length of time for which each colour is displayed on the screen can be set
by calling SCR SET FLASHING.

The inks are set to their default colours at EMS and when SCR RESET is
called.

The various colours available and the default ink colours set are described in
Appendix V.

Related entries:
GRA SET PAPER
GRA SET PEN
SCR GET INK
SCR SET BORDER
SCR SET FLASHING
TXT SET PAPER
TXT SET PEN
103: SCR GET INK #BC35

Ask the colours an ink is currently displayed in.

Action:
Get the two colours that are used to display an ink on the screen.

Entry conditions:
A contains an ink number.

Exit conditions:
B contains the first colour.
C contains the second colour.

AF, DE and HL corrupt.


All other registers preserved.

Notes:
The ink number is masked with #0F to make sure it is legal. The colours
returned may not be the same as those supplied to the Screen Pack as the
colours are masked when they are set.

The new colours for an ink are not sent to the hardware immediately when they
are set. They are stored and appear on the screen when the next frame flyback
occurs. This means that the colours returned may not actually be visible to the
user yet.

The default settings for the inks and the various colours available are described
in Appendix V.

Related entries:
GRA GET PAPER
GRA GET PEN
SCR GET BORDER
SCR SET INK
TXT GET PAPER
TXT GET PEN
104: SCR SET BORDER #BC38

Set the colours in which to display the border.

Action:
Set which two colours will be used to display the border. If the two colours are
the same then the border will remain a steady colour. If the colours are
different then the border will alternate between these two colours.

Entry conditions:
B contains the first colour.
C contains the second colour.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The colours are masked with # 1F to ensure that they are legal. Colours 27..31
are not intended for use; they are merely duplicates of other colours available.

The new colours for the border are not sent to the hardware immediately. They
are stored and will appear on the screen when the next frame flyback occurs.

The length of time for which each colour is displayed on the screen can be set
by calling SCR SET FLASHING.

The border is set to its default colour at EMS and when SCR RESET is called.
The default colour and the colours available are described in Appendix V.

Related entries:
SCR GET BORDER
SCR SET FLASHING
SCR SET INK
105: SCR GET BORDER #BC3B

Ask the colours the border is currently displayed in.

Action:
Get the two colours used to display the border on the screen.

Entry conditions:
No conditions.

Exit conditions:
B contains the first colour.
C contains the second colour.

AF, DE and HL corrupt.


All other registers preserved.

Notes:
The colours returned may not be the same as those supplied to the Screen Pack
as they are masked when they are set.

The new colours for the border are not sent to the hardware immediately when
they are set. They are stored and appear on the screen when the next frame
flyback occurs. This means that the colours returned may not actually be
visible to the user yet. The default border colour and the colours available are
described in Appendix V.

Related entries:
SCR GET INK
SCR SET BORDER
106: SCR SET FLASHING #BC3E

Set the flash periods.

Action:
Set for how long each of the two colours for the inks and the border are to be
displayed on the screen. These settings apply to all inks and the border.

Entry conditions:
H contains the period for the first colour.
L contains the period for the second colour.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The flash periods are given in frame flybacks (1/50 or 1/60 of a second). A
period of 0 is taken to mean a period of 256.

The default setting for the flash periods is 10 frame flybacks (1/5 or 1/6 of a
second). This is set at EMS and when SCR RESET is called.

The new flash periods are not used immediately but when the inks next flash.

Related entries:
SCR GET FLASHING
SCR SET BORDER
SCR SET INK
107: SCR GET FLASHING #BC41

Ask the current flash periods.

Action:
Get the time for which each of the two colours associated with an ink or the
border is displayed.

Entry conditions:
No conditions.

Exit conditions:
H contains the period for the first colour.
L contains the period for the second colour.

AF corrupt.
All other registers preserved.

Notes:
The flash periods are given in frame flybacks (1/50 or 1/60 of a second).

A period of 0 means 256.

Related entries:
SCR SET FLASHING
108: SCR FILL BOX #BC44

Fill a character area of the screen with an ink.

Action:
Fill a rectangular area of the screen with an ink. The boundaries of this area are
given in character positions.

Entry conditions:
A contains the encoded ink to fill the area with.
H contains the physical left column of the area to fill.
D contains the physical right column of the area to fill.
L contains the physical top row of the area to fill.
E contains the physical bottom row of the area to fill.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The area boundaries are given in physical coordinates. i.e. Row 0, column 0 is
the top left corner of the screen. They are not checked for legality. If illegal
boundaries are passed (edges off the screen) then unpredictable effects may
occur.

The screen is written directly without using any other write routine. The
current Graphics VDU write mode is therefore ignored.

Related entries:
SCR CLEAR
SCR FLOOD BOX
TXT CLEAR WINDOW
109: SCR FLOOD BOX #BC47

Fill a byte area of the screen.

Action:
Fill a rectangular area of the screen with an ink. The boundaries of the area
must lie on byte boundaries. This routine will not fill an arbitrary area of the
screen to a pixel boundary.

Entry conditions:
C contains the encoded ink to fill the area with.
HL contains the screen address of the top left corner of the area to fill.
D contains the (unsigned) width of the area to fill in bytes.
E contains the (unsigned) height of the area to fill in screen lines.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The whole of the rectangle being cleared must lie on the screen. If any of it lies
off the screen then unpredictable effects may occur.

A height or width of 0 is taken to mean 256 (which is too large to fit on the
screen).

The screen is written directly without using any other write routine. The
current

Graphics VDU write mode is therefore ignored.

Related entries:
GRA CLEAR WINDOW
SCR CLEAR
SCR FILL BOX
110: SCR CHAR INVERT #BC4A

Invert a character position.

Action:
All pixels at a character position that are written in one ink are rewritten in a
second ink, and vice versa. This gives an inverse effect to the character
position. Inverting the character a second time will restore the original inks.
This effect is used to draw the Text VDU cursors.

Entry conditions:
B contains an encoded ink.
C contains another encoded ink.
H contains a physical character column.
L contains a physical character row.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The character position is given in physical coordinates. i.e. Row 0, column 0 is
the top left corner of the screen.

The character position given is not checked for being legal. An illegal position
(one outside the limits of the screen) will have unpredictable effects.

All pixels at the character position are exclusive-ored with the exclusive-or of
the two inks supplied. Pixels at the character position that are set to one of the
two inks supplied will therefore be set to the other supplied ink. Pixels set to
other inks will also be altered.

Related entries: -

TXT PLACE CURSOR


TXT REMOVE CURSOR
111: SCR HW ROLL #BC4D

Move the whole screen up or down eight pixel lines (one


character).
Action:
Roll the screen using the hardware. The new line appearing on the screen is
cleared.

Entry conditions:
If the screen is to roll down:
B must be zero.

If the screen is to roll up:


B must be non-zero.

Always:
A contains the encoded ink to clear the new line to.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The screen is rolled by changing the screen offset (see SCR SET OFFSET).
Rolling the screen upwards moves the screen contents up and clears the new
bottom line. The screen offset is therefore increased by 80 (MOD #0800).
Rolling the screen downwards moves the screen contents down and clears the
new top line. The screen offset is therefore decreased by 80 (MOD #0800).
The new line is cleared by writing to it directly thus the Graphics VDU write
mode is ignored.
The Text VDU roll count is not changed by this routine (see TXT GET
WINDOW).
Special precautions are taken to make sure that the screen is kept looking
presentable during the rolling and in particular during the clearing of the new
line. Principally this consists of clearing the new line in two parts. First the part
that is not visible on the screen (by virtue of the screen addressing) is cleared.
Then, after waiting for frame flyback and changing the screen offset, the
second half of the the line that was part of the line that just rolled off the screen
is cleared.

Related entries:
SCR SET OFFSET
SCR SW ROLL
112: SCR SW ROLL #BC50

Move an area of the screen up or down eight pixel lines


(one character).

Action:
Roll an area of the screen by copying. The area to be rolled is specified in
character positions.

Entry conditions:
If the screen is to roll down:
B must be zero.
If the screen is to roll up:
B must be non-zero.
Always:
A contains the encoded ink to clear the new line to.
H contains the physical left column of the area to roll.
D contains the physical right column of the area to roll.
L contains the physical top row of the area to roll.
E contains the physical bottom row of the area to roll.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The area boundaries are given in physical coordinates. i.e. Row 0, column 0 is
the top left corner of the screen. The boundaries are not checked for legality. If
illegal boundaries are passed (edges off the screen) then unpredictable effects
may occur.

Rolling the area upwards moves the area contents up and clears the new bottom
line. Rolling the area downwards moves the area contents down and clears the
new top line.

The line is cleared by writing to it directly; the Graphics VDU write mode is
ignored.

The Text VDU roll count is not changed by this routine (see TXT GET
WINDOW).

Special precautions are taken to make sure that the screen is kept looking
presentable during the rolling. Principally this consists of waiting for frame
flyback before performing the copy.

Related entries:
SCR HW ROLL
113: SCR UNPACK #BC53

Expand a character matrix for the current screen mode.

Action:
Convert a matrix from its standard form to a set of pixel masks as appropriate
for the current screen mode.

Entry conditions:
HL contains the address of a matrix.
DE contains the address of an area to unpack into.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The matrix is converted into a series of masks which cover all the screen bytes
in the character. This means that each byte of the matrix is converted to 4 bytes
in mode 0,2 bytes in mode 1 and 1 byte in mode 2. Thus the unpacking area
must be 32, 16 or 8 bytes long.

If a bit in the matrix is set then the appropriate pixel mask is included in the
unpacked version (the bits are set to one). Otherwise the pixel mask is not
included in the unpacked version (the bits are set to zero).

Related entries:
SCR REPACK
114: SCR REPACK #BC56

Compress a character matrix to the standard form.

Action:
A character on the screen is converted to a matrix by comparing each pixel
with an ink. If the pixel is set to that ink then the appropriate bit in the
character matrix is set, otherwise the bit is cleared.

Entry conditions:
A contains the encoded ink to match against.
H contains the physical character column to read from.
L contains the physical character row to read from.
DE contains the address of the area to construct the matrix in.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The character position is given in physical coordinates in which row 0, column
0 is the top left corner of the screen.

The character position given is not checked for legality. An illegal position
(one outside the limits of the screen) will have unpredictable effects.

The matrix produced has the norrflal layout. It is 8 bytes long, stored top line
first and bottom line last, the most significant bit of a byte refers to the leftmost
pixel of a line and the least significant bit to the rightmost pixel.

Because the pixels are tested for being set to only one inkthe matrix produced
is not an exact representation of what is on the screen. It may be necessary,
when trying to read characters from the screen, to repack using various
different inks.

Related entries:
SCR UNPACK
TXT RD CHAR
115: SCR ACCESS #BC59

Set the screen write mode for the Graphics VDU.

Action:
Set the Graphics VDU write mode so that the Graphics VDU plots pixels by
writing, anding, oring or exclusive-oring.

Entry conditions:
A contains the required write mode.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The write mode is masked with #03 to make it legal. The write modes are:

0: FORCE mode: NEW = INK


1: XOR mode: NEW = INK exclusive-or OLD
2: AND mode: NEW = INK and OLD
3: OR mode: NEW = INK or OLD

NEW is the final setting of the pixel.


OLD is the current setting of the pixel.
INK is the ink being plotted.
The default mode is FORCE mode (mode 0) and this is set at EMS and when
SCR RESET is called.

Setting the write mode affects how the indirection routine SCR WRITE sets
pixels. Graphics VDU plotting routines call this indirection to set pixels and so
the write mode affects the Graphics VDU. No Text VDU routines call this
indirection (they set pixels on the screen directly) and so the write mode does
not affect the Text VDU. The routines that clear areas of the screen (e.g. GRA
CLEAR WINDOW) act like the Text VDU and are unaffected by the write
mode.

Related entries:
GRA DEFAULT
SCR INITIALISE
SCR RESET
SCR WRITE
116: SCR PIXELS #BC5C

Write a pixel to the screen ignoring the Graphics VDU


write mode.

Action:
Write a pixel or pixels to the screen. The position to write at is given by a
screen address and pixel mask. The pixel is always set to the ink supplied
whatever mode of writing the Graphics VDU is using.

Entry conditions:
B contains the encoded ink to write.
C contains the mask for the pixel(s).
HL contains the screen address of the pixel(s).

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The screen address is not checked and so passing an invalid screen address will
have unpredictable results.

The pixel mask may be a combined mask for more than one pixel (thus
speeding up plotting in certain cases).

To plot a pixel using the Graphics VDU write mode SCR WRITE should be
called. SCR PIXELS is equivalent to calling SCR WRITE when the default
mode (FORCE mode) is selected. The Text VDU sets the pixels in characters
using FORCE mode.

Related entries:
SCR WRITE
117: SCR HORIZONTAL #BC5F

Plot a purely horizontal line.

Action:
Draw a line on the screen that runs horizontally. The pixels on the line are
plotted using the SCR WRITE indirection and thus use the current Graphics
VDU write mode.

Entry conditions:
A contains the encoded ink to draw in.
DE contains the base X coordinate of the start of the line.
BC contains the base X coordinate of the end of the line.
HL contains the base Y coordinate of the line.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The endpoints of the line are given in base coordinates. i.e. (0,0) is the pixel in
the bottom left corner of the screen and each coordinate position refers to a
single pixel.

The endpoints are not checked for being legal (within the limits of the screen).
If they are not legal then unpredictable effects may occur.

The start X coordinate must be less than or equal to the end X coordinate.

This routine may be used to duplicate the method that the Graphics VDU uses
for plotting lines - it splits a line that is more horizontal than vertical into a
number of segments that are purely horizontal and plots these separately.

Related entries:
GRA FROM USER
GRA LINE ABSOLUTE
GRA LINE RELATIVE
SCR VERTICAL
118: SCR VERTICAL #BC62

Plot a purely vertical line.

Action:
Draw a line on the screen that runs vertically. The SCR WRITE indirection is
used to plot pixels in the line thus the current Graphics VDU write mode is
used.

Entry conditions:
A contains the encoded ink to draw in.
DE contains the base X coordinate of the line.
HL contains the base Y coordinate of the start of the line.
BC contains the base Y coordinate of the end of the line.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The endpoints of the line are given in base coordinates. i.e. (0,0) is the pixel in
the bottom left corner of the screen and each coordinate position refers to a
single pixel.

The endpoints are not checked for being legal (within the limits of the screen).
If they are not legal then unpredictable effects may occur.

The start Y coordinate must be less than or equal to the end Y coordinate.

This routine may be used to duplicate the method that the Graphics VDU uses
for plotting lines - it splits a line that is more vertical than horizontal into a
number of segments that are purely vertical and plots these separately.

Related entries:
GRA FROM USER
GRA LINE ABSOLUTE
GRA LINE RELATIVE
SCR HORIZONTAL
119: CAS INITIALISE #BC65

Initialize the Cassette Manager.

Action:
Full initialization of the Cassette Manager (as used during EMS).

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
Operations carried out are:

All streams are marked closed.


The default write speed is set up.
The prompt messages are turned on.
The cassette motor is turned off (except on V1.0 firmware).

Related entries:
CAS IN ABANDON
CAS NOISY
CAS OUT ABANDON
CAS SET SPEED
CAS STOP MOTOR
120: CAS SET SPEED #BC68

Set the write speed.

Action:
Set the length to write bits and the amount of write precompensation to apply.

Entry conditions:
HL contains the length of haifa zero bit.
A contains the precompensation to apply.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The speed supplied is the length of half a zero bit in microseconds. A one bit is
written as twice the length of a zero bit. The speed supplied can be related to
the average baud rate (assuming equal numbers of ones and zeros) by the
following equation:

Average baud rate


= 1 000 000 / (3 * Half zero length)
= 333 333/ Half zero length
The half zero length must lie between 130 and 480 microseconds. Values
outside this range will cause read and write errors.

The precompensation supplied is the extra length, in microseconds, to add to


half a one bit and to subtract from half a zero bit under certain conditions. The
amount of precompensation required varies with the speed (more is required at
higher baud rates).

The precompensation may lie between 0 and 255 microseconds although the
higher settings are not useful as they will cause read and write errors.

The default half zero length and precompensation settings are 333
microseconds (1000 baud) and 25 microseconds respectively. The commonly
used faster setting is 167 microseconds (2000 baud) with 50 microseconds of
precompensation. These values have been determined after extensive testing
and the user is advised to stick to them.

Related entries:
CAS INITIALISE
121: CAS NOISY #BC6B

Enable or disable prompt messages.

Action:
Disabling messages will prevent the prompt and information messages from
being printed. It will not prevent error messages from being printed. Enabling
messages allows all messages to be printed.

Entry conditions:
If messages are to be enabled:
A must be zero.

If messages are to be disabled:


A must be non-zero.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The prompt and information messages which are turned off are:

Press PLAY then any key:


Press REC and PLAY then any key:
Found <FILENAME> block <N>
Loading <FILENAME> block <N>
Saving <FILENAME> block <N>

The error messages which are not turned off are:

Read error <x>


Write error a
Rewind tape

Related entries:
CAS INITIALISE
122: CAS START MOTOR #BC6E

Start the cassette motor.

Action:
Turn the cassette motor on and wait for it to pick up speed if it was previously
off.

Entry conditions:
No conditions.

Exit conditions:
If the motor turned on OK:
Carry true.

If the user hit escape:


Carry false.

Always:
A contains the previous motor state.
Other flags corrupt.
All other registers preserved.

Notes:
If the motor is not already on then the routine waits for approximately two
seconds to allow the tape to reach full speed.
The motor is always turned on by this routine. If the user hits the escape key
then the time spent waiting for the motor to pick up speed is truncated.
The previous motor state may be passed to CAS RESTORE MOTOR.

Related entries:
CAS RESTORE MOTOR
CAS STOP MOTOR
123: CAS STOP MOTOR #BC71

Stop the cassette motor.

Action:
Turn the cassette motor off and return its previous state.

Entry conditions:
No conditions.

Exit conditions:
If the motor was turned off OK:
Carry true.

If the user hit escape:


Carry false.

Always:
A contains the previous motor state.
Other flags corrupt.
All other registers preserved.

Notes:
The motor is always turned off by this routine. There is no delay to allow the
motor to slow down.
The previous motor state may be passed to CAS RESTORE MOTOR.

Related entries:
CAS RESTORE MOTOR
CAS START MOTOR
124: CAS RESTORE MOTOR #BC74

Restore previous state of cassette motor.

Action:
Turn the cassette motor on or off again. Wait for motor to pick up speed when
turning the motor on if it is currently off.

Entry conditions:
A contains the previous motor state.

Exit conditions:
If the motor was turned on or off OK:
Carry true.

If the user hit escape:


Carry false.

Always:
A and other flags corrupt.
All other registers preserved.

Notes:
This routine uses the previous motor state as returned by CAS START
MOTOR or CAS STOP MOTOR.

If calling this routine results in the motor being turned on when it is currently
off then the routine waits for approximately two seconds to allow the tape to
reach full speed.

The motor is always turned on or off (as appropriate) by this routine. If the user
hits the escape key then this merely truncates the time spent waiting for the
motor to pick up speed.

Related entries:
CAS START MOTOR
CAS STOP MOTOR
125: CAS IN OPEN #BC77

Open a file for input.

Action:
Set up the read stream for reading a file and read the first block.

Entry conditions:
B contains the length of the filename.
HL contains the address of the filename.
DE contains the address of a 2K buffer to use.

Exit conditions:
If the file was opened OK:

Carry true.
Zero false.
HL contains the address of a buffer containing the file header.
DE contains the data location (from the header).
BC contains the logical file length (from the header).
A contains the file type (from the header).

If the stream is in use:

Carry false.
Zero false.
In V1.1: A contains an error number (#0E).
In V1.0: A corrupt.
BC, DE and HL corrupt.

If the user hit escape:

Carry false.
Zero true.
In V1.1: A contains an error number(#00).
In V1.0: A corrupt
BC, DE and HL corrupt.

Always:

IX and other flags corrupt. All other registers preserved


Notes:
This routine can return two error numbers:

#00: The user hit escape.


#0E: The stream is already in use.

The 2K buffer (2048 bytes) supplied is used to store the contents of a block of
the file when it is read from tape. It will remain in use until the file is closed by
calling either CAS IN CLOSE or CAS IN ABANDON. The buffer may lie
anywhere in memory, even underneath a ROM.

The filename passed is copied into the read stream descriptor. If it is longer
than i6 characters then it is truncated to 16 characters. If it is shorter than 16
characters then it is padded with nulls (#00) to 16 characters. While the
filename may contain any character, it is best to avoid nulls. Lower case ASCII
letters (characters #61.. #7A) are converted to their upper case equivalents
(characters #41.. #5A). The filename may lie anywhere in RAM, even
underneath a ROM.

The filename is normally the name of the file that is to be read. However, a
zero length filename (or one starting with a null) is treated specially. It is taken
to mean read the next file on the tape.

When the file is opened for reading the first block of the file is read
immediately. The address of the area where the header from this block is stored
is passed back to the user so that information can be extracted from it. This
area will lie in the central 32K of RAM. The user is not allowed to write to the
header, only to read from it. The Cassette Manager uses some fields in the
header for its own purposes and so these may differ from those read from the
tape. The file type, logical length, entry point and all user fields will remain
unchanged. (See section 8 for a description of the header.)

Related entries:
CAS IN ABANDON
CASINCHAR
CAS IN CLOSE
CAS INDIRECT
CAS IN OPEN (DISC)
CAS OUT OPEN
125 CAS IN OPEN (DISC) #BC77

Open a file for input.

Action:
Set up the read stream for reading a file and read the header if there is one,
otherwise create a fake header in store.

Entry conditions:
B contains the length of the filename.
HL contains the address of the filename.
DE contains the address of a 2K buffer to use.

Exit conditions:
If the file was opened OK:

Carry true.
Zero false.
HL contains the address of a buffer containing the file header.
DE contains the data location (from the header).
BC contains the logical file length (from the header).
A contains the file type from the header).

If the stream is already open:

Carry false.
Zero false.
A contains an error number (#0E).
BC, DE and HL corrupt.

If the open failed for any other reason:

Carry false.
Zero true.
A contains an error number.
BC, DE and HL corrupt.

Always:

IX and other flags corrupt. All other registers preserved.


Notes:
The 2K buffer (2048 bytes) supplied is used to store the contents of the file
when it is read from disc. It will remain in use until the file is closed by calling
either CAS IN CLOSE or CAS IN ABANDON. The buffer may lie anywhere
in memory, even underneath a RUM.

The filename must conform to the AMSDOS conventions with no wild cards.
The filename may lie anywhere in RAM, even underneath a RUM.

If the type part of the filename is omitted AMSDOS will attempt to open, in
. . .
turn, a file with the following type parts ' ',‘ BAS’, ‘ BIN’, If none of
these exist then the open will fail.

When the file is opened the first record of the file is read immediately. If this
record contains a header then it is copied into store, otherwise a fake header is
constructed in store. The address of the area where the header is stored is
passed back to the user so that information can be extracted from it, This area
will lie in the central 32K of RAM. The user is not allowed to write to the
header, only to read from it. AMSDOS uses some fields in the header for its
own purposes and so these may differ from those read from the disc. The file
type, logical length, entry point and all user fields will remain unchanged.

Related entries:
CAS IN ABANDON (DISC)
CAS IN CHAR (DISC)
CAS IN CLOSE (DISC)
CAS IN DIRECT (DISC)
CAS IN OPEN
CAS OUT OPEN (DISC)
126: CAS IN CLOSE #BC7A

Close the input file properly.

Action:
Mark the read stream as closed.

Entry conditions:
No conditions.

Exit conditions:
If the stream was closed OK:

Carry true.
A corrupt.

If the stream was not open:

Carry false.
In V1.1: A containsaerrornumber(#0E).
In V1.0: A corrupt.

Always:

BC, DE, HL and other flags corrupt.


All other registers preserved.

Notes:
This routine can only return one error number:

#0E: The stream is not open.

This routine should be called to close a file after reading from it using either
CAS IN CHAR or CAS IN DIRECT.

The user may reclaim the buffer passed to CAS IN OPEN after calling this
routine.

Related entries:
CAS IN ABANDON
CAS IN CLOSE (DISC)
CAS IN OPEN
CAS OUT CLOSE
126 CAS IN CLOSE (DISC) #BC7A

Close the input file properly.

Action:
Mark the read stream as closed.

Entry conditions:
No conditions.

Exit conditions:
If the stream was closed OK:
Carry true.
Zero false.
A corrupt.

If the stream is not open:


Carry false.
Zero false.
A contains an error number(#0E). If the close failed for any other reason:
Carry false.
Zero true.
A contains an error number.

Always:
BC, DE, HL and other flags corrupt.
All other registers preserved.

Notes:
This routine should be called to close a file after reading from it using either
CAS IN CHAR or CAS IN DIRECT.

The user may reclaim the buffer passed to CAS IN OPEN after calling this
routine.

The drive motor is turned off immediately after the input file is closed. This is
done so that a loaded program which takes over the machine is not left with the
motor running indefinitely.

Related entries:
CAS IN ABANDON (DISC)
CAS IN CLOSE
CAS IN OPEN (DISC)
CAS OUT CLOSE (DISC)
127: CAS IN ABANDON #BC7D

Close the input file immediately.

Action:
Abandon reading from the read stream and close it.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
This routine is intended for use after an error or in similar circumstances.

The user may reclaim the buffer passed to CAS IN OPEN after calling this
routine.

Related entries:
CAS IN ABANDON (DISC)
CAS IN CLOSE
CAS IN OPEN
CAS OUT ABANDON
127 CAS IN ABANDON (DISC) #BC7D

Close the input file immediately.

Action:
Abandon reading from the read stream and close it.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
This routine is intended for use after an error or in similar circumstances.

The user may reclaim the buffer passed to CAS IN OPEN after calling this
routine.

Related entries:
CAS IN ABANDON
CAS IN CLOSE (DISC)
CAS IN OPEN (DISC)
CAS OUT ABANDON (DISC)
128: CAS IN CHAR #BC8O

Read a character from the input file.

Action:
Read a character from the input stream. Fetches blocks from tape as required.

Entry conditions:
No conditions.

Exit conditions:
If the character was read OK:
Carry true.
Zero false.
A contains the character read from the file.

If the end of the file was found:


Carry false.
Zero false.
In V1.1: A contains an error number(#0E or #0F).
In V1.0: A corrupt If the user hit escape:
Carry false.
Zero true.
In V1.1: A contains an error number(#00).
In V1.0: Acorrupt

Always:
IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can return three error numbers:

#00: The user hit escape.


#0E: The stream is not open for reading or the user hit escape previously.
#0F: Have reached the end of the file.

Once the first character has been read from a file it can only be used for
character by character access. It is not possible to switch to direct reading (by
CAS IN DIRECT).

Related entries:
CAS IN CHAR (DISC)
CAS IN CLOSE
CAS IN DIRECT
CAS IN OPEN
CAS OUT CHAR
CAS RETURN
CAS TEST EOF
128 CAS IN CHAR (DISC) #BC8O

Read a character from the input file.

Action:
Read a character from the input stream.

Entry conditions:
No conditions.

Exit conditions:
If the character was read OK:
Carry true.
Zero false.
A contains the character read from the file.

If the end of the file was found, or stream not open as expected:
Carry false.
Zero false.
A contains an error number(#0E, #0F or #1A).

If failed for any other reason:


Carry false.
Zero true.
A contains an error number.

Always:
IX and other flags corrupt.
All other registers preserved.

Notes:
Once the first character has been read from a file the rest of the file may only
be read character by character (using CAS IN CHAR), It is not possible to
switch to direct reading (by CAS IN DIRECT).

The CP/M end of file character (#1A) is treated as end of file (carry false, zero
false). However, it is possible to continue reading characters until the hard end
of file. The error number returned is set to #1A for soft (CP/M) end of file and
#0F for hard end of file. The action of spotting soft end of file is not performed
by the equivalent cassette version of the routine and it will never return #1A
when carry is false.

If a file containing binary data is read using this routine then it will be
necessary to spot soft EOF and ignore it.

Related entries
CAS IN CHAR
CAS IN CLOSE (DISC) CAS OUT CHAR (DISC)
CAS IN DIRECT (DISC) CAS RETURN (DISC)
CAS IN OPEN (DISC) CAS TEST EOF (DISC)
129: CAS IN DIRECT #BC83

Read the input file into store.

Action:
Read the input file directly into store in one go rather than one character at a
time.

Entry conditions:
HL contains the address to put the file (anywhere in RAM).

Exit conditions:
If the file was read OK:
Carry true.
Zero false.
HL contains the entry address (from the header).
A corrupt.
If the file was not open as expected:
Carry false.
Zero false.
In V1.1: A contains an errornumber(#OE).
In V1.0: Acorrupt.
HL corrupt.
If the user hit escape:
Carry false.
Zero true.
In V1.1: A contains an error number(#00).
In V1.0: A corrupt.
HL corrupt.
Always:
BC, DE, IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can return two error numbers:
#00: The user hit escape.
#0E: The stream is not open for reading directly or escape hit previously.

The read stream must be newly opened (by CAS IN OPEN). If the stream has
been used for character access (by calling CAS IN CHAR) then it is not
possible to directly read the file. Neither is it possible to directly read from the
file more than once. This will merely corrupt the copy of the file read.
The buffer of data read when the stream was opened is copied to its correct
position and the remainder of the file (if any) is also read into store.

Related entries:
CAS IN DIRECT (DISC)
CAS IN CHAR CAS IN OPEN
CAS IN CLOSE CAS OUT DIRECT
129 CAS IN DIRECT (DISC) #BC83

Read the input file into store.

Action:
Read the input file directly into store in one go rather than one character at a
time.

Entry conditions:
HL contains the address to put the file (anywhere in RAM).

Exit conditions:
If the file was read OK:

Carry true.
Zero false.
HL contains the entry address (from the header).
A corrupt.

If the stream is not open as expected:


Carry false.
Zero false.
A contains an error number (#OE).
HL corrupt.

If the read failed for any other reason:


Carry false.
Zero true.
A contains an error number.
HL corrupt.

Always:
BC, DE,IX and other flags corrupt.
All other registers preserved.

Notes:
The read stream must be newly opened (by CAS IN OPEN). If the stream has
been used for character access (by calling CAS IN CHAR or CAS TEST EOF)
then it is not possible to directly read the file. Neither is it possible to directly
read from the file more than once. Any attempt to do so will corrupt the copy
of the file read.)

If the file has a header then the number of bytes read is that recorded in the 24
bit file length field (bytes 64..66 of the disc file header. If there is no header the
file is read until hard end of file.

The CP/M end of file character, #1A, is not treated as end of file.

Related entries:
CAS IN CHAR (DISC)
CAS IN CLOSE (DISC) CAS IN OPEN (DISC)
CAS IN DIRECT CAS OUT DIRECT (DISC)
130: CAS RETURN #BC86

Put the last character read back.

Action:
Put the last character read by CAS IN CHAR back into the read buffer. The
character will here-read next time CAS IN CHAR is called.

Entry conditions:
No conditions.

Exit conditions:
All registers and flags preserved.

Notes:
It is only possible to use this routine to return the last character that has been
read by CAS IN CHAR. At least one character must have been read since:

the stream was opened


or the last character was returned
or the last test for the end of file was made.

Related entries:
CAS IN CHAR
CAS RETURN (DISC)
130 CAS RETURN (DISC) #BC86

Put the last character read back.

Action:
Put the last character read by CAS IN CHAR back into the read buffer. The
character will here-read next time CAS IN CHAR is called.

Entry conditions:
No conditions.

Exit conditions:
All registers and flags preserved.

Notes:
It is only possible to use this routine to return the last character that has been
read by CAS IN CHAR. At least one character must have been read since:

the stream was opened


or the last character was returned
or the last test for the end of file was made.

Related entries:
CAS IN CHAR (DISC)
CAS RETURN
131: CAS TEST EOF #BC89

Have we reached the end of the input file yet?

Action:
Test if the end of the input file has been reached.

Entry conditions:
No conditions.

Exit conditions:
If the end of the file was not found:
Carry true.
Zero false.
A corrupt.

If the end of the file was found:


Carry false.
Zero false.
In V1.1: A contains an error number(#0E or #0F).
In V1.0: A corrupt.

If the user hit escape:


Carry false.
Zero true.
In V1.1: A contains a error number(#00).
In V1.0: A corrupt.

Always:
IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can return three error numbers:
#00: The user hit escape.
#0E: The stream is not open for reading characters or the user hit escape
previously.
#0F: Have reached the end of the file.

Calling this routine puts the stream into character input mode. It is not possible
to use direct reading after calling this routine.
It is not possible to call CAS RETURN after this routine has been called. A
character must be read first.

Related entries:
CAS IN CHAR
CAS TEST EOF (DISC)
131: CAS TEST EOF (DISC) #BC89

Have we reached the end of the input file yet?

Action:
Test if the end of the input file has been reached.

Entry conditions:
No conditions.

Exit conditions:
If the end of the file was not found:
Carry true.
Zero false.
A corrupt.

If the end of the file was found or stream not open as expected:
Carry false.
Zero false.
A contains an error number (#0E, #0F or #1A).

If failed for any other reason:


Carry false.
Zero true.
A contains an error number.

Always:
IX and other flags corrupt. All other registers preserved.

Notes:
This routine will report end of file if either there are no more characters in the
file or if the next character to be read is the CP/M end of file character, #1A.

Calling this routine puts the stream into character input mode. It is not possible
to use direct reading after calling this routine.

It is not possible to call CAS RETURN after this routine has been called. A
character must be read first.

Related entries:
CAS IN CHAR (DISC)
CAS TEST EOF
132: CAS OUT OPEN #BC8C

Open a file for output.

Action:
Set up the write stream for output.

Entry conditions:
B contains the length of the filename.
HL contains the address of the filename.
DE contains the address of a 2K buffer to use.

Exit conditions:
If the user hit escape:
Carry false.
Zero true.
In V1.1: A contains an error number(#00).
In V1.0: Acorrupt.
HL corrupt.

If the stream is in use already:


Carry false.
Zero false.
In V1.i: A contains an error number(#OE),
InVi.0: Acorrupt.
HL corrupt.

If the file was opened OK:


Carry true.
Zero false.
A corrupt.
HL contains the address of a buffer containing the header that will be
written to each file block.

Always:
BC, DE, IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can only return two error numbers.
#00: The user hit escape.
#0E: The stream is already open.

When writing files character by character the 2K buffer (2048 bytes) supplied
is used to store the contents of a block of the file before it is written to tape. It
will remain in use until the file is closed by calling either CAS OUT CLOSE or
CAS OUT ABANDON. The buffer may reside anywhere in memory - even
underneath a ROM
When the stream is opened for writing, a header is set up which will be written
at the start of each block of the file. Many of the fields in the header are set by
the Cassette Manager but the remainder are available for use by the user. The
address of this header is passed to the user so that information can be stored in
it. The user may write to the file type, logical length, entry point and all user
fields. The user is not allowed to write to any other field in the header. The user
settable fields are all zeroized initially, with the exception of the file type
which is set to unprotected ASCII version 1. (See section 8.4 for a description
of the header.)

The filename passed is copied into the write stream descriptor. If it is longer
than 16 characters then it is truncated to 16 characters. If it is shorter than 16
characters then it is padded with nulls (#00) to 16 characters. While the
filename may contain any character, it is best to avoid nulls. Lower case ASCII
letters (characters #61..#7A) are converted to their upper case equivalents
(characters #41..#5A). The filename may lie anywhere in RAM, even
underneath a ROM.

Related entries:
CAS IN OPEN
CAS OUT ABANDON
CAS OUT CHAR
CAS OUT CLOSE
CAS OUT DIRECT
CAS OUT OPEN (DISC)
132 CAS OUT OPEN (DISC) #BC8C

Open a file for output.

Action:
Set up the write stream for output.

Entry conditions:
B contains the length of the filename.
HL contains the address of the filename.
DE contains the address of a 2K buffer to use.

Exit conditions:
If the file was opened OK:
Carry true.
Zero false.
HL contains the address of a buffer containing the header.
A corrupt.

If the stream is open already:


Carry false.
Zero false.
A contains an error number (#0E).
HL corrupt.

If the open failed for any other reason:


Carry false.
Zero true.
A contains an error number.
HL corrupt.

Always:
BC, DE, IX and other flags corrupt.
All other registers preserved.

Notes:
When characters are output to the file using CAS OUT CHAR the 2K buffer
supplied is used by AMSDOS to buffer the output. It will remain in use until
the file is closed by calling either CAS OUT CLOSE or CAS OUT
ABANDON. The buffer may reside anywhere in memory - even underneath a
ROM.
The filename passed must conform to AMSDOS conventions with no wild
cards. It is copied into the write stream header. The filename may lie anywhere
in RAM - even underneath a ROM.

.
The file is opened with a type part of ' $$$' regardless of the type part
.
supplied. Any existing file with the same name and a type part of ' $$$' is
deleted. The file is renamed to its supplied name when CAS OUT CLOSE is
called.

When the stream is opened a header is set up. Many of the fields in the header
are set by AMSDOS but the remainder are available for use by the user. The
address of this header is passed to the user so that information can be stored in
it. The user may write to the file type, logical length, entry point and all user
fields. The user is not allowed to write to any other field in the header. The user
settable fields are all zeroized initially, with the exception of the file type
which is set to unprotected ASCII version 1.

The header type field must be written to before CAS OUT CHAR or CAS
OUT DIRECT is called.The type field must not be altered after calling either of
these routines. If the file type is set to any type other than unprotected ASCII
then space will be reserved for the header which will be written when the file is
closed.

Related entries:
CAS IN OPEN (DISC)
CAS OUT ABANDON (DISC)
CAS OUT CHAR (DISC)
CAS OUT CLOSE (DISC)
CAS OUT DIRECT (DISC)
CAS OUT OPEN
133: CAS OUT CLOSE #BC8F

Close the output file properly.

Action:
Mark the write stream as closed and write the last buffer of data to tape.

Entry conditions:
No conditions.

Exit conditions:
If the stream was closed OK:
Carry true.
Zero false.
A corrupt.
If the stream was not open:
Carry false.
Zero false.
In V1.1: A contains an error number(#OE).
In Vl.0: Acorrupt. If the user hit escape:
Carry false.
Zero true.
In V1.1: A contains an errornumber(#00).
In V1.0: Acorrupt.
Always:
BC, DE, HL, IX and other flags corrupt.
All other registers preserved.
Notes:
This routine can return two error numbers:
#00: The user hit escape.
#0E: The stream is not open.
It is necessary to call this routine after using CAS OUT CHAR or CAS OUT
DIRECT to cause the last block of data to be written to the tape. If the block is
zero bytes long (nothing has been written to the file) then nothing is written to
tape.
If the writing is to be abandoned then CAS OUT ABANDON should be called
as this does not write the last block of data to the tape.
If the user hits escape during the writing of the last block then the file is left
open and is not closed.
The user may reclaim the buffer passed to CAS OUT OPEN after calling this
routine.

Related entries:
CAS IN CLOSE
CAS OUT ABANDON
CAS OUT CLOSE (DISC)
CAS OUT OPEN
133 CAS OUT CLOSE (DISC) #BC8F

Close the output file properly.

Action:
Mark the write stream as closed and give it its correct name.

Entry conditions:
No conditions.

Exit conditions:
If the stream was closed OK:

Carry true.
Zero false.
A corrupt.

If the stream is not open:

Carry false.
Zero false.
A contains an error number ( # OE).

If the close failed for any other reason:

Carry false.
Zero true.
A contains an error number.

Always:

BC, DE, HL, IX and other flags corrupt.


All other registers preserved.

Notes:
It is necessary to call this routine after using CAS OUT CHAR or CAS OUT
DIRECT to ensure that all the data is written to the disc, to write the header to
the start of the file and to give the file its true name.

If no data has been written to the file then it is abandoned and nothing is
written to disc. This is for compatability with cassette routines.
.
When the file was opened it was given the type part of ’ $$$’. This routine
will rename the file to its true name and rename any existing version to have a
.
‘ BAK’ type part. This ensures that any previous version of the file is
.
automatically kept as a backup. Any existing ‘ BAK’ version is deleted. If,
when the file was opened, the caller did not specify a type part then AMSDOS
. .
will use the type part ‘ BAS’ for BASIC files, ’ BIN’ for binary files and
.
‘ ‘for all other files, as specified by the file type field in the header.

If the actual length of the file is not a multiple of 128 bytes (a CP/M record)
then a CP/M end of file character, #1A, is added to the file. This additional
character is not recorded in the length of the file.

If writing is to be abandoned then CAS OUT ABANDON should be called as


this does not write any more data to disc.

The user may reclaim the buffer passed to CAS OUT OPEN after calling this
routine.

Related entries:
CAS IN CLOSE (DISC)
CAS OUT ABANDON (DISC)
CAS OUT CLOSE
CAS OUT OPEN (DISC)
134: CAS OUT ABANDON #BC92

Close the output file immediately.

Action:
Abandon the output file and mark the write stream closed. Any unwritten data
is discarded and not written to tape.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
This routine is intended for use after an error or in similar circumstances.

Related entries:
CAS IN ABANDON
CAS OUT ABANDON (DISC)
CAS OUT CLOSE
CAS OUT OPEN
134 CAS OUT ABANDON (DISC) #BC92

Close the output file immediately.

Action:
Abandon the output file and mark the write stream closed. Any unwritten data
is discarded and not written to disc.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.

All other registers preserved.

Notes:
This routine is intended for use after an error or in similar circumstances.

If more than one 16K physical extent has already been written to disc then the
.
file will appear in the disc directory with a type part of ' $$$'. Otherwise the
file will disappear. This is because each 16K of a file requires a directory entry,
A directory entry is not written to disc until the 16K has been written or the file
is closed (CAS OUT CLOSE).

Related entries:
CAS IN ABANDON (DISC)
CAS OUT ABANDON
CAS OUT CLOSE (DISC)
CAS OUT OPEN (DISC)
135: CAS OUT CHAR #BC95

Write a character to the output file.


Action:
Add a character to the buffer for the write stream. If the buffer is already full
then it is written to tape before the new character is inserted.

Entry conditions:
A contains the character to write.

Exit conditions:
If the character was written OK:
Carry true.
Zero false.
A corrupt.

If the file was not open as expected:


Carry false.
Zero false.
In V1.1: A contains an error number(#OE).
In V1.0: Acorrupt. If the user hit escape:
Carry false.
Zero true.
In V1.1: A contains an error number(#00).
In V1.0: Acorrupt.

Always:
A, IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can return two error numbers:
#00: The user hit escape.
#0E: The stream is not open for writing characters or the user hit escape
previously.
If this routine returns the file not open as expected condition then either the
user has hit escape previously or the file has been written using CAS OUT
DIRECT. In either case, or if escape is pressed, the character sent will be
discarded.
It is necessary to call CAS OUT CLOSE after sending all the characters to the
file to ensure that the last block of the file is written to the tape.
Once this routine has been called it is not possible to switch to directly writing
the file.
Related entries:
CAS IN CHAR
CAS OUT CHAR (DISC) CAS OUT DIRECT
CAS OUT CLOSE CAS OUT OPEN
135 CAS OUT CHAR (DISC) #BC95

Write a character to the output file.

Action:
Add a character to the buffer for the write stream. If the buffer is already full
then it is written to disc before the new character is inserted.

Entry conditions:
A contains the character to write.

Exit conditions:
If the character was written OK:
Carry true.
Zero false.
A corrupt.

If the stream is not open as expected:


Carry false.
Zero false.
A contains an error number (#0E).

If failed for any other reason:


Carry false.
Zero true.
A contains a error number.

Always:
IX and other flags corrupt.
All other registers preserved.

Notes:
It is necessary to call CAS OUT CLOSE after sending all the characters to the
file to ensure that the file is correctly written to disc.

Once this routine has been called it is not possible to switch to directly writing
the file (CAS OUT DIRECT).

Related entries:
CAS IN CHAR (DISC) CAS OUT DIRECT (DISC)
CAS OUT CHAR CAS OUT OPEN (DISC)
CAS OUT CLOSE
136: CAS OUT DIRECT #BC98

Write the output file directly from store.


Action:
Write the contents of store directly out to the output file.

Entry conditions:
HL contains the address of the data to write.
DE contains the length of the data to write.
BC contains the entry address (to go into the header).
A contains the file type (to go into the header).

Exit conditions:
If the file was written OK:
Carry true.
Zero false.
A corrupt.
If the file was not open as expected:
Carry false.
Zero false.
In V1.1: A contains in error number(#OE).
In V1.0: Acorrupt. If the user hit escape:
Carry false.
Zero true.
In V1.1: A contains a error number(#00).
In V1.0: Acorrupt.
Always:
BC, DE, HL, IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can return two error numbers:
#00: The user hit escape.
#0E: The stream is not newly opened.
After writing the file it must be closed using CAS OUT CLOSE to ensure that
the last block of the file is written to tape.
It is not possible to change the method for writing files from character output
(using CAS OUT CHAR) to direct output (using CAS OUT DIRECT) or vice
versa once the method has been chosen. Nor is it possible to directly write a
file in two or more parts by calling CAS OUT DIRECT more than once - this
will write corrupt data. Attempting to break these rules will result in a file not
open as expected error.

Related entries:
CAS IN DIRECT CAS OUT DIRECT (DISC)
CAS OUT CLOSE CAS OUT OPEN
136 CAS OUT DIRECT (DISC) #BC98

Write the output file directly from store.

Action:
Write the contents of store directly out to the output file.

Entry conditions:
HL contains the address of the data to write (to go into the header).
DE contains the length of the data to write (to go into the header).
BC contains the entry address (to go into the header).
A contains the file type (to go into the header).

Exit conditions:
If the file was written OK:
Carry true.
Zero false.
A corrupt.

If the stream is not open as expected:


Carry false.
Zero false.
A contans an error number (#0E).

If failed for any other reason:


Carry false.
Zero true.
A contains an error number.

Always:
BC, DE, HL, IX and other flags corrupt.
All other registers preserved.

Notes:
After writing the file it must be closed using CAS OUT CLOSE to ensure that
the file is written to disc.

It is not possible to change the method for writing files from character output
(using CAS OUT CHAR) to direct output (using CAS OUT DIRECT) or vice
versa once the method has been chosen. Nor is it possible to directly write a
file in two or more parts by calling CAS OUT DIRECT more than once - this
will write corrupt data.

Related entries:
CAS IN DIRECT (DISC)
CAS OUT CLOSE (DISC)
CAS OUT DIRECT
CAS OUT OPEN (DISC)
137: CAS CATALOG #BC9B

Generate a catalogue from the tape.

Action:
Read file blocks to check their validity and print information about them on the
screen.

Entry conditions:
DE contains the address of a 2K buffer to use.

Exit conditions:
If the cataloguing went OK:

Carry true.
Zero false.
A corrupt.

If the read stream was in use:

Carry false.
Zero false.
In V1.1: A contains an error number (#0E).
In V1.0: A corrupt.

Always:
BC ,DE, HL, IX and other flags corrupt.
All other registers preserved.

Notes:
This routine can only return one error number:

#0E: The stream is already in use.

This routine uses the read stream and so the stream must be closed when it is
called. The read stream remains closed when this routine exits. The write
stream is unaffected by this routine.
The prompt messages are turned on (see CAS NOISY) by this routine.

When cataloguing the Cassette Manager reads a header record, prints


information from it and then reads the data record. This cycle repeats until the
user hits the escape key. The information printed is as follows:

FILENAME block N T Ok

FILENAME is the name of the file on the tape, or ‘Unnamed file’ if the
filename starts with a null (character #00).

N is the number of the block. Block 1 is normally the first block in a file.

T is a representation of the file type of the file. It is formed by adding #24 (the
character ‘$‘) to the file type byte masked with #0F (to remove the version
number field). The standard file types are thus:

$ a BASIC program file


% a protected BASIC program file
* an ASCII text file (default file type)
& a binary file
' a protected binary file

Other file types are possible but will not have been written by the BASIC in the
on-board ROM. See section 8.4 for a description of the file type byte.

Ok is printed after the end of the data record. This shows that the data was read
without errors and also serves to indicate the end of the data on tape (to help
avoid over-recording a tape file).

Related entries:
CAS CATALOG (DISC)
CAS NOISY
137 CAS CATALOG (DISC) #BC9B

Display the disc directory.

Action:
Display the disc directory for the current drive and current user. The directory
is sorted into alphabetical order and displayed in as many columns as will fit in
the current text window (stream #0). The size in Kbytes is shown along side
each file. The total amount of free space on the disc is also shown.

Entry conditions:
DE contains the address of a 2K buffer to use.

Exit conditions:
If the cataloging went OK:

Carry true.
Zero false.
A corrupt.

If failed for any reason:

Carry false.
Zero true.
A contains an error number.
Always:

BC, DE, HL, IX and other flags corrupt.


All other registers preserved.

Notes:
Files marked SYS are not shown.

Files marked R/O are shown with a ‘*‘ after the file name.

Unlike the cassette version of this routine, the disc input stream is not required.
(Note: BASIC abandons both the input and output streams when generating the
catalogue.)

Related entries:
CAS CATALOG
| DIR
138: CAS WRITE #BC9E

Write a record to tape.

Action:
Write a record to the cassette. This routine is used by the higher level routines
(CAS OUT CHAR, CAS OUT DIRECT and CAS OUT CLOSE) to write the
header and data records that make up a tape file.

Entry conditions:
HL contains the address of the data to write.
DE contains the length of the data to write.
A contains the sync character to write at the end of the leader.

Exit conditions:
If the record was written OK:

Carry true.
A corrupt.

If an error occured or the user hit escape:

Carry false.
A contains an error code.

Always:

BC, DE, HL, IX corrupt.

All other registers preserved.

Notes:
A data length of 0 passed to this routine is taken to mean 65536 bytes and all of
memory will be written to tape. (This is unlikely to be useful).

The data to be written may lie anywhere in RAM, even underneath a ROM.

The sync character is used to distinguish header records (sync is #2C) from
data records (sync is #16). Other sync characters could be used but the
resulting record would require special action to be taken to read it.

The error codes returned by this routine are:

0 Break The user hit the escape key.


1 Overrun The Cassette Manager was unable to get back to writing a
bit fast enough.
Because reading and writing the tape requires stringent timing considerations
interrupts are disabled whilst the tape is being written (potentially a period of
over 5 minutes). It would be unpleasant to have the sound chip making a noise
for all this time so the Sound Manager is shut down (SOUND RESET). When
writing to the tape has finished interrupts are re-enabled.

The cassette motor is started by this routine (in case it is not already on) and
restored to its previous state when writing is completed.

Related entries:
CAS CHECK
CAS READ
139: CAS READ #BCA1

Read a record from tape.

Action:
Read a whole or part record from the cassette. This routine is used by the
higher level routines (CAS IN CHAR, CAS IN DIRECT and CAS CATALOG
amongst others) to read the header and data records that make up a file.

Entry conditions:
HL contains the address to put the data read.
DE contains the length of the data to read.
A contains the sync character expected at the end of the leader.

Exit conditions:
If record was read OK:

Carry true.
A corrupt.

If an error occured or the user hit escape:

Carry false.
A contains an error code.
Always:

BC, DE, HL, IX and other flags corrupt.


All other registers preserved.

Notes:
A data length of 0 passed to this routine is taken to mean 65536 bytes. (This is
not useful).

It is not necessary to read the whole of a record from tape. If the length passed
is less than the actual length of the record then only that number of bytes will
be read. Trying to read more bytes from a record than were written will
produce an error, usually an overflow error (see below).

The sync character is used to distinguish header records (sync is #2C) from
data records (sync is #16). Other sync characters could be used if the record
was written that way.
The error codes returned by this routine are:

0 Break The user hit the escape key.


1 Overflow The Cassette Manager found a bit that was too long to read.
2 CRC A CRC failure was detected.

The cassette motor is started by this routine (in case it is not already on) and
restored to its previous state when reading is completed.

Because reading the tape requires stringent timing considerations, interrupts are
disabled whilst the tape is being read (potentially a period of over 5 minutes). It
would be unpleasant to have the sound chip making a noise for all this time so
the Sound Manager is shut down (SOUND RESET). When reading from the
tape has finished interrupts are re-enabled.

Related entries:
CAS CHECK
CAS WRITE
140: CAS CHECK #BCA4

Compare a record on tape with the contents of store.

Action:
Check that a tape record contains a correct version of the data supplied. This
routine is intended to be used after writing records to check that they were
written correctly.

Entry conditions:
HL contains the address of the data to check.
DE contains the length of the data to check.
A contains the sync character expected at the end of the leader.

Exit conditions:
If the record checked OK:

Carry true.
A corrupt.

If an error occured or the user hit escape:

Carry false.
A contains an error code.

Always:

BC, DE, HL, IX and other flags corrupt.

All other registers preserved.

Notes:
A data length of 0 passed to this routine is taken to mean 65536 bytes. (This is
bound to produce a check failure).

It is not necessary to check the whole of a record on tape. If the length passed
is less than the actual length of the record then only that number of bytes will
be checked. Trying to check more bytes in a record than were written will
produce an error of some sort (see below).

The data to be checked may lie anywhere in RAM, even underneath a ROM.

The sync character is used to distinguish header records (sync is #2C) from
data records (sync is #16). Other sync characters could be used.
The error codes returned by this routine are:
0 Break The user hit the escape key.
1 Overrun The Cassette Manager found a bit that was too long to read.
2 CRC A CRC failure was detected.
3 Different The data read from tape did not agree with that in memory.

The cassette motor is started by this routine (in case it is not already on) and
restored to its previous state when checking is completed.

Because reading from the tape requires stringent timing considerations,


interrupts are disabled whilst the tape is being checked (potentially a period of
over 5 minutes). It would be unpleasant to have the sound chip making a noise
for all this time so the Sound Manager is shut down (SOUND RESET). When
checking has finished interrupts are re-enabled.

Related entries:
CAS READ
CAS WRITE
141: SOUND RESET #BCA7

Reset the Sound Manager.

Action:
Re-initialize the Sound Manager - shut the sound chip up and clear all queues.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The sound queues are cleared.
Any current sound is stopped.
The sound generator chip is silenced.

This routine enables interrupts.

Related entries:
SOUND HOLD
142: SOUND QUEUE #BCAA

Add a sound to a sound queue.

Action:
Try to add a sound to the sound queue of one or more channels. If the sound
queue of any of the channels is full then no sound will be issued to any
channel.

Entry conditions:
HL contains the address of a sound program which must lie in the central 32K
of RAM.

Exit conditions:
If the sound was added to the queue(s):

Carry true.
HL corrupt.

If at least one queue was full:

Carry false.
HL preserved.

Always:

A, BC, DE, IX and other flags corrupt.


All other registers preserved.

Notes:
The sound program is laid out as follows:

Byte 0: Channels to use and rendezvous requirements.


Byte 1: Amplitude envelope to use.
Byte 2: Tone envelope to use.
Bytes 3...4: Tone period.
Byte 5: Noise period.
Byte 6: Initial amplitude.
Bytes 7...8: Duration or envelope repeat count.

All values in the sound program are masked into the appropriate range before
being used.

The channels to issue the sound on are encoded into byte 0 as follows:

Bit 0: Issue on channel A.


Bit 1: Issue on channel B.
Bit 2: Issue on channel C
The rendezvous requirements are encoded into byte 0 as follows:

Bit 3: Rendezvous with channel A.


Bit 4: Rendezvous with channel B.
Bit 5: Rendezvous with channel C.
Bit 6: Hold until released.
Bit 7: Flush queue

A channel will ignore an order to rendezvous with itself. Sounds issued on


multiple channels implicitly rendezvous with each other. Sounds that are
ordered to rendezvous will be issued to the sound generator starting at the same
time.
Setting the hold bit prevents the sound from running until it is released by
calling SOUND RELEASE (or a routine having a similar effect). Setting the
flush bit will empty the queue and abandon any currently active sound thus
allowing the new sound to start immediately.
The amplitude envelope is in the range 0..15. Envelopes 1..15 are the
amplitude envelopes that can be set using SOUND AMPL ENVELOPE.
Envelope 0 means use no amplitude envelope, simply hold the initial amplitude
for 2 seconds or the duration specified.
The tone envelope is in the range 0..15. Envelopes 1..15 are the tone envelopes
that can be set using SOUND TONE ENVELOPE. Envelope 0 means use no
tone envelope, simply hold the initial tone.
A tone period of 0 means do not generate any tone. Tone periods in the range
1..4095 specify the period of the tone in 8 microsecond units.
The noise period is in the range 0..31. Noise periods 1.31 specify the period of
the noise component of a sound. A noise period of 0 means use no noise.
The initial amplitude is in the range 0..15. Amplitude 0 being no initial sound,
amplitude 15 being maximum volume.
Bytes 7 and 8 store the sound time. If this is zero then the amplitude envelope
is obeyed once. If the sound time is negative then the amplitude envelope is
obeyed minus the sound time number of times (i.e. 1…32768 times). If the
sound time is positive but not zero then it is taken to be the duration of the
sound in 1/l00s of a second.
If a duration is specified when an amplitude envelope is in use then the
duration given sets the length of the sound. If the duration is shorter than the
envelope then the envelope is truncated. If the duration is longer than the
envelope then the final amplitude of the envelope is sustained until the duration
expires. Tone envelopes are treated in much the same way as amplitude
envelopes except that they never specify the length of the sound.
The sound event that is run when a sound queue has a free slot is disarmed on
the channels specified in this command.
All sounds currently held by SOUND HOLD are automatically released when
this routine is called. Also, the sound queue event is disarmed (see SOUND
ARM EVENT). SOUND QUEUE may enable interrupts.

Related entries:
SOUND ARM EVENT
SOUND CHECK
143: SOUND CHECK #BCAD

Ask if there is space in a sound queue.

Action:
Ask the status of a sound channel. The status includes the number of free
spaces in the sound queue and whether the channel is held.

Entry conditions:
A contains the bit for the channel to test.

Exit conditions:
A contains the channel status.
BC, DE, HL and flags corrupt.
All other registers preserved.

Notes:
The channel to ask the status of is encoded as follows:

Bit 0: Ask about channel A.


Bit 1: Ask about channel B.
Bit 2: Ask about channel C.

If more than one bit is set then the status of only one channel is returned. The
channels are tested in the order given above.

The status returned is encoded as follows:

Bits 0..2: Contain the number of free slots in the channel’s sound queue.
Bit 3: The channel is awaiting a rendezvous with channel A.
Bit 4: The channel is awaiting a rendezvous with channel B.
Bit 5: The channel is awaiting a rendezvous with channel C.
Bit 6: The channel is held.
Bit 7: The channel is active (producing a sound).

Calling this routine disarms the sound queue event that occurs when the queue
has a free slot for the channel returned (see SOUND ARM EVENT).
This routine may enable interrupts.

Related entries:
SOUND ARM EVENT
SOUND QUEUE
144: SOUND ARM EVENT #BCB0

Set up an event to be run when a sound queue becomes empty.

Action:
Arm the sound event to be run when a free slot occurs in a channel’s sound
queue.

Entry conditions:
A contains the bit for the channel to arm.
HL contains the address of an event block.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The channel for which to arm the event is encoded as follows:

Bit 0: Arm channel A.


Bit 1: Arm channel B.
Bit 2: Arm channel C.

If more than one bit is set then only one channel is armed. The channels are
armed in the order given above.

The event block passed must be initialized (by KL INIT EVENT).

The event will be ‘kicked’ when a free slot occurs in the queue. If there is a
free slot in the queue when this routine is called then the event will be ‘kicked’
immediately.

The sound event is disarmed automatically when SOUND QUEUE or SOUND


CHECK is called. It is also disarmed when the event is run. Thus, the event
routine will need to rearm the sound event to keep it running continuously.

This routine may enable interrupts.

Related entries:
KL INIT EVENT
SOUND CHECK
SOUND QUEUE
145: SOUND RELEASE #BCB3

Allow sounds which are individually held to start.

Action:
Release held sounds on a number of channels. This allows sounds that were
marked with a hold bit when they were set up by SOUND QUEUE to start
(other factors willing).

Entry conditions:
A contains bits for the channels to release.

Exit conditions:
AF, BC, DE, HL and IX corrupt.
All other registers preserved.

Notes:
The channels to release are encoded as follows:

Bit 0: Release channel A.


Bit 1: Release channel B.
Bit 2: Release channel C.

All channels that are specified are released.

All sounds currently held by SOUND HOLD are automatically released.

This routine may enable interrupts.

Related entries:
SOUND QUEUE
146: SOUND HOLD #BCB6

Stop all sounds in midflight.

Action:
This stops all sounds immediately. The sounds can be started again by calling
SOUND CONTINUE.

Entry conditions:
No conditions.

Exit conditions:
If a sound was active:

Carry true.

If no sound was active:

Carry false.

Always:

A, BC, HL and other flags corrupt.


All other registers preserved.

Notes:
Sounds that are held by this routine are automatically restarted when SOUND
QUEUE or SOUND RELEASE are called as well as when SOUND
CONTINUE itself is called.

The sound is stopped by halting the execution of sound and tone envelopes and
setting the sound chip volume to zero for all channels. When the sound is
restarted it will continue from as near where it was stopped as is possible.

This routine enables interrupts.

Related entries:
SOUND CONTINUE
SOUND RESET
147: SOUND CONTINUE #BCB9

Restart sounds after they have all been held.

Action:
Allow sounds that have been held by calling SOUND HOLD to continue.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and IX corrupt.
All other registers preserved.

Notes:
If no sounds are held then no action is taken.

This routine may enable interrupts.

Related entries:
SOUND HOLD
SOUND RELEASE
148: SOUND AMPL ENVELOPE #BCBC

Set up an amplitude envelope.

Action:
Set up one of the 15 user programmable amplitude (volume) envelopes.

Entry conditions:
A contains an envelope number.
HL contains the address of an amplitude data block.

Exit conditions:
If envelope has been setup OK:

Carry true.
HL contains the address of the data block + 16.
A and BC corrupt.

If envelope number is invalid:

Carry false.
A, B, and HL preserved.

Always:

DE and other flags corrupt.


All other registers preserved.

Notes:
The envelope to set up is specified by a number in the range 1.. 15. No
envelope is set up if a number outside this range is passed.

The amplitude data block is copied into the amplitude envelope. The data block
may lie in ROM or in RAM. It may not lie in RAM hidden underneath a ROM.

The amplitude data block has the following layout:

Byte 0: Count of sections in the envelope.


Bytes 1. .3: First section of the envelope.
Bytes 4. .6: Second section of the envelope.
Bytes 7..9: Third section of the envelope.
Bytes 10.. 12: Fourth section of the envelope.
Bytes 13.. 15: Fifth section of the envelope.

The first byte of the amplitude data block specifies the number of sections used
in the envelope. Sections not used need not be set up. An envelope using no
sections has a special meaning - hold a constant volume lasting for 2 seconds.
The number of sections to use is not checked, if a number outside the range 0.
.5 is supplied then this will have unpredictable effects. This should be avoided.

Each section of the amplitude data block can specify either a hardware or a
software envelope. This is indicated by the first byte of the section.

A software envelope section is laid out as follows:

Byte 0: Step count.


Byte 1: Step size.
Byte 2: Pause time.

The fact that this is a software envelope section rather than a hardware
envelope section is indicated by byte 0 not having bit 7 set.

If the step count is in the range 1…127 then the step size is added to the
volume that number of times with a wait equal to the pause time in 1/l00s of a
second after each addition.

If the step count is 0 the the step size is taken to be an absolute volume setting.
A single wait of the pause time in 1/l00s of a second is made.

After calculating the new volume this is masked with #0F to make sure it is
legal. Thus, all arithmetic on the volume is carried out modulo 16.

A pause time of 0 is taken to mean 256 1/lOOs of a second.

A hardware envelope section is laid out as follows:

Byte 0: Envelope shape.


Byte 1..2: Envelope period.

The fact that this is a hardware envelope section rather than a software
envelope section is indicated by byte 0 having bit 7 set.

The envelope shape (masked with #7F) is sent to register 13 of the sound
generator. This sets the shape of the hardware envelope and whether it repeats
(see Appendix IX for details).

The envelope period is sent to registers 11 and 12 of the sound generator.


These set the the length of the hardware envelope (see Appendix IX for
details).

The section after a hardware section should be a pause long enough to allow
the hardware envelope to operate. A pause can be constructed using a software
envelope with a step size of 0 and with the repeat count and pause time juggled
to give the right total time.

There is no protection against changing an envelope whilst it is in use. This


could have unpredictable effects and should be avoided.
The length of the sound can either be determined by the duration supplied
when the sound is queued or by the envelope terminating (see SOUND
QUEUE). If a duration is set that is shorter than the envelope then the envelope
is truncated. If the duration is longer than the envelope then the final volume is
sustained until the duration expires.

Related entries:
SOUND A ADDRESS
SOUND TONE ENVELOPE
149: SOUND TONE ENVELOPE #BCBF

Set up a tone envelope.

Action:
Set up one of the 15 user programmable tone envelopes.

Entry conditions:
A contains an envelope number.
HL contains the address of a tone data block.

Exit conditions:
If the envelope has been set up OK:

Carry true.
HL contains the address of the data block + 16.
A and BC corrupt.

If the envelope number is invalid:

Carry false.
A, BC and HL preserved.

Always:

DE and other flags corrupt.


All other registers preserved.

Notes:
The envelope to set up is specified by a number in the range 1.15. No envelope
is set up if a number outside this range is passed.

The tone data block is copied into the tone envelope. The data block may lie in
ROM or in RAM. It may not lie in RAM hidden underneath a ROM.

The tone data block has the following layout:

Byte 0: Count of sections in the envelope.


Bytes 1..3: First section of the envelope.
Bytes 4..6: Second section of the envelope.
Bytes 7..9: Third section of the envelope.
Bytes 10.. 12: Fourth section of the envelope.
Bytes 13.. 15: Fifth section of the envelope.
The first byte of the tone data block (masked with #7F) specifies the number of
sections used in the envelope. Sections not used need not be set up. An
envelope using no sections will not alter the tone (i.e. no enveloping). The
number of sections to use is not checked, if a number outside the range 0.5 is
supplied then this will have unpredictable effects. This should be avoided.

The top bit, bit 7, of the count is used to indicate a repeating envelope. If this
bit is set then when the last section of the envelope finishes the first will be
used again.

Each section of the tone data block is laid out as follows:

Byte 0: Step count.


Byte 1: Step size.
Byte 2: Pause time.

If the step count lies in the range #00.. #EF then the section is a relative
section. The step size is sign extended (bit 7 is copied to bits 8.. 15) and is
added to the current tone period the number of times specified by the step
count. After each addition a wait of the pause time in 1/lOOs of a second is
made. The sound chip only uses the lower 12 bits of the tone period so all
arithmetic is carried out modulo #1000.

A step count of 0 is taken to mean 1 step whilst a pause time of 0 is taken to


mean 256 1/l00s of a second.

If the step count lies in the range #F0.. #FF then the section is an absolute
section. The least significant four bits of the step count are taken to be the most
significant byte of the tone period and the step size is taken to be the least
significant byte. This tone period is set immediately and is followed by a pause
whose length is set by the pause time in 1/l00s of a second.

There is no protection against changing an envelope whilst it is in use. This


could have unpredictable effects and should be avoided.
If the tone envelope finishes before the end of the sound (as set when the sound
was queued) then the final tone is held. i.e. The tone envelope does not affect
the length of the sound.

Related entries:
SOUND AMPL ENVELOPE
SOUND T ADDRESS
150: SOUND A ADDRESS #BCC2

Get the address of an amplitude envelope.

Action:
Ask where the data area for an amplitude envelope is stored.

Entry conditions:
A contains an envelope number.

Exit conditions:
If the envelope was found OK:

Carry true.
HL contains the address of the amplitude envelope.
BC contains the length of an envelope (16 bytes).

If the envelope number was invalid:

Carry false.
HL corrupt.
BC preserved.

Always:

A and other flags corrupt.

All other registers preserved.

Notes:
The envelope number must lie in the range 1.. 15.

The amplitude envelope is laid out as described in SOUND AMPL ENVELOPE.

Related entries:
SOUND AMPL ENVELOPE
SOUND T ADDRESS
151: SOUND T ADDRESS #BCC5

Get the address of a tone envelope.

Action:
Ask where the data area for a tone envelope is stored.

Entry conditions:
A contains an envelope number.

Exit conditions:
If the envelope was found OK:

Carry true.
HL contains the address of the tone envelope.
BC contains the length of an envelope (16 bytes).

If the envelope number was invalid:

Carry false.
HL corrupt.
BC preserved.

Always:

A and other flags corrupt.

All other registers preserved.


Notes:
The envelope number must lie in the range 1.. 15.

The tone envelope is laid out as described in SOUND TONE ENVELOPE.

Related entries:
SOUND A ADDRESS
SOUND TONE ENVELOPE
152: KL CHOKE OFF #BCC8

Reset the Kernel - clears all event queues etc.

Action:
This entry completely clears all event queues, the various timer and frame flyback
lists and so on. The effect is to dispose of any pending synchronous events and to
halt all timer related functions other than sound generation and keyboard
scanning.

Entry conditions:
No conditions.

Exit conditions:
B contains the ROM select address of the current foreground ROM (if any).
DE contains the address at which the current foreground ROM was entered.
C contains the ROM select address for a RAM foreground program.

AF and HL corrupt.

All other registers preserved.

Notes:
If the current foreground program is in RAM then the ROM select address and
entry point returned are both zero. i.e. The default ROM (ROM 0) at its entry
address.

KL CHOKE OFF forms part of the close down required before a new RAM
foreground program is loaded, as is required by MC BOOT PROGRAM.

The close down must ensure that there are no interrupt or other events active and
using memory which might be damaged by loading a new program into memory.
In the complete close down MC BOOT PROGRAM does:

SOUND RESET to kill off sound generation

an OUT to I/O port #F8FF to reset any external interrupt sources.

KL CHOKE OFF to kill off events etc.

KM RESET to reset any keyboard indirections and the break event.

TXT RESET to reset any Text VDU indirections.

SCR RESET to reset any screen indirections.


The values returned by KL CHOKE OFF are used by MC BOOT PROGRAM
if the program load fails.

This information is included for the reader’s interest. MC BOOT PROGRAM


is the recommended means of loading and entering a RAM foreground
program. MC START PROGRAM is the recommended means of entering a
ROM foreground program. or a RAM foreground program which has already
been loaded.

KL CHOKE OFF disables interrupts.

Related entries:
MC BOOT PROGRAM
MC START PROGRAM
153: KL ROM WALK #BCCB

Find and initialize all background ROMs.

Action:
Background ROMs provide support for expansion hardware or augment the
software facilities of the machine. If the facilities provided by the background
ROMs are to be available, the foreground program must initialize them. This
routine finds and initializes all background ROMs.

Entry conditions:
DE contains address of the first usable byte of memory (lowest address).
HL contains address of the last usable byte of memory (highest address).

Exit conditions:
DE contains the address of the new first usable byte of memory.
HL contains the address of the new last usable byte of memory.
AF and BC corrupt.
All other registers preserved

Notes:
When a foreground program is entered it is passed the addresses of the first and
last bytes in memory which it may use. The area of memory outside this is used
to store firmware variables, the stack, the jumpblocks and the screen memory.
From the area available for a foreground program to use, the areas for
background programs to use must be allocated.
The foreground program should initialize background ROMs at an early stage,
before it uses the memory it is given. It may choose whether to enable
background ROMs or not. KL INIT BACK may be used to initialize a
particular background ROM or this routine may be used to initialize all
available background ROMs.
KL ROM WALK inspects the ROMs at ROM select addresses in the range 1..7
in V1.0 firmware and 0..15 in V1.1 firmware. The power-up initialization entry
of each background ROM found is called (unless it is the current foreground
ROM in V1.1 firmware). This entry may allocate some memory for the
background ROM’s use by adjusting the values in DE and HL before returning.
Once the ROM has been initialized the Kernel adds it to the list of external
command servers, and notes the base of the area which the ROM has allocated
to itself at the top of memory (if any). Subsequent FAR CALLs to entries in the
ROM will automatically set the IY index register to point at the ROM’s upper
memory area.
See section 10.4 for a full description of background ROMs.

Related entries:
KL FIND COMMAND
KL INIT BACK
KL LOG EXT
154: KL INIT BACK #BCCE

Initialize a particular background ROM.

Action:
Background ROMs provide support for expansion hardware or augment the
software facilities of the machine. If the facilities provided by the background
ROMs are to be available the foreground program must initialize them. This
routine selects and initializes a particular background ROM.

Entry conditions:
C contains the ROM select address of the ROM to initialize.
DE contains address of the first usable byte of memory (lowest address).
HL contains address of the last usable byte of memory (highest address).

Exit conditions:
DE contains the address of the new first usable byte of memory.
HL contains the address of the new last usable byte of memory.
AF and B corrupt.
All other registers preserved.

Notes:
The ROM select address must be in the range 1..7 in V1.0 and 0...15 in V1.1
firmware and the ROM at this address must be a background ROM or the
request will be ignored. In V1.1 firmware the request will be ignored if the
ROM is the current foreground ROM.
When a foreground program is entered it is passed the addresses of the first and
last bytes in memory which it may use. The area of memory outside this is used
to store firmware variables, the stack, the jumpblocks and the screen memory.
From the area available for a foreground program to use, the areas for
background programs to use must be allocated.
The foreground program should initialize background ROMs at an early stage,
before it uses the memory it is given. It may choose whether to enable
background ROMs or not. KL ROM WALK maybe used to initialize all
available ROMs or this routine may be used to initialize particular ROMs.
This routine causes the background ROM’s power-up initialization entry to be
called. This entry may allocate some memory for the background ROM’s use
by adjusting the values in DE and HL before returning. Once the ROM has
been initialized the Kernel adds it to the list of external command servers, and
notes the base of the area which the ROM has allocated to itself at the top of
memory (if any). Subsequent FAR CALLs to entries in the ROM will
automatically set the IY index register to point at the ROM’s upper memory
area.
See section 10.4 for a full description of background ROMs.

Related entries:
KL FIND COMMAND
KL LOG EXT
KL ROM WALK
155: KL LOG EXT #BCD1

Introduce an RSX to the Firmware.

Action:
RSXs (Resident System Extensions) are similar to background ROMs, but are
loaded into RAM. This routine must be called to include the RSX on the
Kernel’s list of external command servers.

Entry conditions:
BC contains the address of the RSX’s command table.
HL contains the address of a 4 byte area of RAM for the Kernel’s use.

Exit conditions:
DE corrupt.
All other registers preserved.

Notes:
Both the RSX’s command table and the Kernel’s storage area must lie in the
central 32K of memory, i.e. not under a ROM.
The format of a command table is described in section 10.2 and RSXs are
discussed in section 10.5.

Related entries:
KL FIND COMMAND
KL INIT BACK
156: KL FIND COMMAND #BCD4
Search for an RSX, background ROM or foreground ROM
to process a command.

Action:
All expansion ROMs and RSXs have command tables of the same form. This
routine searches all RSXs and background ROMs on the Kernel’s list of
external command servers looking for a match for the given command name. If
the name is found, then
the ‘far address’ of the associated routine is returned. If the command is not a
background or RSX command then all the foreground ROMs that can be found
are searched for a foreground program with the given name. If a foreground
program is found then the system immediately enters it.

Entry conditions:
HL contains the address of the command name to search for.

Exit conditions:
If an RSX or background ROM command was found:

Carry true.
C contains the ROM select address.
HL contains the address of the routine.

If the command was not found:

Carry false.
C and HL corrupt.

Always

A, B and DE corrupt.

All other registers preserved.

Notes:
The command name passed must be in RAM but may lie underneath a ROM.
The name may be any number of characters long but only the first 16
characters are significant. All alphabetic characters in the name should be in
upper case and the last character of the name should have bit 7 set.

The ROM select and routine addresses returned are suitable for calling KL
FAR PCHL.
The list of external command servers is generated as background ROMs and
RSXs are initialized (see KL ROM WALK, KL INIT BACK and KL LOG
EXT). The command tables are scanned in the opposite order to that in which
the command servers were introduced. Thus, RSXs will tend to take
precedence over background ROMs, since RSX’s are, in general, initialized
after background ROMs. Background ROMs are normally initialized in reverse
order of ROM select address, so lower numbered ROMS will take precedence
over higher.

See section 10.2 for a full description of the format of expansion ROM
command tables.

The first entry in a background ROM’s command name table (the one
associated with the power-up entry) may be used as the ROM’s name. KL
FIND COMMAND may be used, therefore, to find out whether a particular
background ROM has been initialized.

When searching for a foreground program, ROMs are inspected starting with
ROM 0 and working upwards. The search ceases when the first unused ROM
address greater than 0 on V1.0 firmware and greater than 15 on V1. 1 firmware
is found.

The on-board BASIC may be entered by searching for and invoking the
command
‘BASIC’.

If a foreground ROM command is found the ROM is entered unconditionally


and this routine never returns.

Related entries:
KL INIT BACK
KL LOGEXT
KL ROM WALK
MC START PROGRAM
157: KL NEW FRAME FLY #BCD7

Initialize and put a block onto the frame flyback list.

Action:
The Kernel maintains a list of events to be kicked each time frame flyback
occurs. This routine initializes a block and adds it to the list.

Entry conditions:
HL contains the address of the frame flyback block.
B contains the event class.
C contains the ROM select address of the event routine.
DE contains the address of the event routine.

Exit conditions:
AF, DE and HL corrupt.
All other registers preserved.

Notes:
The frame flyback block is 9 bytes long and must lie in the central 32K of
RAM. The last 7 bytes of the frame flyback block are an event block which is
initialized to reflect the parameters passed in B, C and DE (see KL INIT
EVENT). The exact layout of a frame flyback block is described in Appendix
X.

The frame flyback block is appended to the frame flyback list if it is not
already on it. This routine enables interrupts.

Related entries:
KL ADD FRAME FLY
KL DEL FRAME FLY
KL INIT EVENT
158: KL ADD FRAME FLY #BCDA

Put a block onto the frame flyback list.

Action:
The Kernel maintains a list of events to be kicked each time frame flyback
occurs. This routine adds a block to the list.

Entry conditions:
HL contains the address of the frame flyback block.

Exit conditions:
AF, DE and HL corrupt.
All other registers preserved.

Notes:
The frame flyback block is 9 bytes long and it must lie in the central 32K of
RAM. The last 7 bytes of the frame flyback block are an event block which
must be initialized separately before calling this routine. The exact layout of a
frame flyback block is described in Appendix X.

The block is appended to the frame flyback list if it is not already on it. This
routine enables interrupts.

Related entries:
KL DEL FRAME FLY
KL INIT EVENT
KL NEW FRAME FLY
159: KL DEL FRAME FLY #BCDD
Remove a block from the frame flyback list.

Action:
The Kernel maintains a list of events to be kicked each time frame flyback
occurs. This routine removes a block from the list.

Entry conditions:
HL contains the address of the frame flyback block.

Exit conditions:
AF, DE and HL corrupt.
All other registers preserved.

Notes:
This routine does nothing if the block is not on the list.

Removing a block from the list only prevents the event being kicked again. It
does not affect any outstanding frame flyback events.

This routine enables interrupts.

Related entries:
KL ADD FRAME FLY
KL NEW FRAME FLY
160: KL NEW FAST TICKER #BCEO

Initialize and put a block onto the fast ticker list.

Action:
The Kernel maintains a list of events to be kicked each time the 1/300th of a
second timer interrupt occurs. This is known as the fast ticker list. This routine
initializes a block and adds it to the list.

Entry conditions:
HL contains the address of the fast ticker block.
B contains the event class.
C contains the ROM select address of the event routine.
DE contains the address of the event routine.

Exit conditions:
AF, DE and HL corrupt.

All other registers preserved.

Notes:
The fast ticker block is 9 bytes long and must lie in the central 32K of RAM.
The last 7 bytes of the fast ticker block are an event block which is initialized
to reflect the parameters passed in B, C and DE (see KL INIT EVENT). The
exact layout of a fast ticker block is described in Appendix X.

The fast ticker block is appended to the fast ticker list if it is not already on it.

The fast ticker facility is not intended for general use. However, it does allow
relatively short times to be measured giving greater resolution than the general
ticker facilities.

This routine enables interrupts.

Related entries:
KL ADD FAST TICKER
KL ADD TICKER
KL DEL FAST TICKER
KL INIT EVENT
KL TIME PLEASE
161: KL ADD FAST TICKER #BCE3

Put a block onto the fast ticker list.

Action:
The Kernel maintains a list of events to be kicked each time the 1/300th of a
second timer interrupt occurs. This is known as the fast ticker list. This routine
adds a block to the list.

Entry conditions:
HL contains the address of the fast ticker block.

Exit conditions:
AF, DE and HL corrupt.

All other registers preserved.

Notes:
The fast ticker block is 9 bytes long and must lie in the central 32K of RAM.
The last 7 bytes of the fast ticker block are an event block which must be
initialized before calling this routine. The exact layout of a fast ticker block is
described in Appendix X.

The fast ticker block is appended to the fast ticker list if it is not already on it.

The fast ticker facility is not intended for general use. However, it does allow
relatively short times to be measured giving greater resolution than the general
ticker facilities.

This routine enables interrupts.

Related entries:
KL ADD TICKER
KL DEL FAST TICKER
KL INIT EVENT
KL NEW FAST TICKER
KL TIME PLEASE
162: KL DEL FAST TICKER #BCE6

Remove a block from the fast ticker list.

Action:
The Kernel maintains a list of events to be kicked each time the 1/300th of a
second timer interrupt occurs. This is known as the fast ticker list. This routine
removes a block from the list.

Entry conditions:
HL contains the address of the fast ticker block.

Exit conditions:
AF, DE and ilL corrupt.
All other registers preserved.

Notes:
This routine does nothing if the block is not on the list.

Removing a block from the list only prevents the event from being kicked
again. It does not affect any outstanding fast ticker events.

This routine enables interrupts.

Related entries:
KL ADD FAST TICKER
KL DEL TICKER
KL NEW FAST TICKER
163: KL ADD TICKER #BCE9

Put a block onto the tick list.

Action:
The general purpose timing facility measures time in 1/50th of a second units.
The Kernel maintains a list of tick blocks each of which contains a count and a
recharge value. Every 1/50th of a second the Kernel processes all the tick
blocks, decrementing the count entry of each. If the count entry of a block
becomes zero the event contained in the block is ‘kicked’, and the count is set
to the recharge value.

Entry conditions:
HL contains the address of the tick block.
DE contains the initial value for the count entry.
BC contains the value for the recharge entry.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The tick block is 13 bytes long and must lie in the central 32K of memory. The
last 7 bytes of the tick block are an event block which must be initialized
before this routine is called. The exact layout of a tick block is described in
Appendix X.
The count and recharge entries in the block are set. The block is then appended
to the tick list if it is not already on the list. This routine may be used,
therefore, to change the count and recharge entries of an existing block.
Blocks with a count entry of zero are ignored when the list is processed.
Setting a recharge value of zero, therefore, sets up the block as a ‘one shot
timer’. Since it takes the Kernel time to ignore a tick block, any redundant
blocks should be removed from the list as soon as possible.
It is not possible to predict, particularly with synchronous events, how long it
will be after the ‘kick’ before the event routine is actually called.
Notwithstanding these delays, the ticker may be used to obtain an exact
number of ‘kicks’ in a given period since the recharge mechanism immediately
resets the count. The event counting mechanism will ensure that ‘kicks’ are not
missed, provided that there are never more than 127 outstanding at once.
This routine enables interrupts.

Related entries:
KL ADD FAST TICKER KL DEL TICKER
KLINITEVE
164: KL DEL TICKER #BCEC

Remove block from the tick list.

Action:
If the given block is on the tick list it is removed. The contents of the block are
not affected.

Entry conditions:
HL contains the address of the tick block.

Exit conditions:
If the tick block was found on the tick list:

Carry true.
DE contains the count remaining before the next event.

If the tick block was not found on the tick list:

Carry false.
DE corrupt.

Always:

A, HL and other flags corrupt.

All other registers preserved.

Notes:
The contents of the block are not affected by removing it from the list. In
particular the continued processing of outstanding events is not affected. The
block could be put back on the list at a later date and it could continue counting
where it left off.

This routine enables interrupts.

Related entries:
KL ADD TICKER
KL DEL FAST TICKER
165: KL INIT EVENT #BCEF

Initialize an event block.

Action:
Initialize all entries in an event block.

Entry conditions:
HL contains the address of the event block.
B contains the event class.
C contains the RUM select address of the event routine.
DE contains the address of the event routine

Exit conditions:
HL contains the address of the event block + 7
All other registers preserved.

Notes:
The event block is 7 bytes long and must lie in the central 32K of RAM. The
layout of an event block is described in Appendix X. See section 12 for a
general discussion of events.
The ROM select and address of the routine are the ‘far address’ of the event
routine (see section 2).

The event class is bit significant as follows:

Bit 0: Near address.


Bits 1..4: Synchronous event priority.
Bit5: Must be zero.
Bit 6: Express event.
Bit 7: Asynchronous event.

If the asynchronous bit is set then the event is an asynchronous event,


otherwise it is a synchronous event. Asynchronous events do not have priorities
and so the priority field is ignored.
If the express event bit is set then the event is an express event. The meaning of
this depends on whether the event is synchronous or asynchronous.
All express synchronous events have higher priorities than any normal
synchronous event. The priority of a synchronous event is encoded in bits 1.4
of the class, the higher the number the greater the priority. No event may have
priority
0. The processing of normal synchronous events may be disabled (by calling
KL EVENT DISABLE), while that of express synchronous events may not.
An express asynchronous event will have its event routine called directly from
the interrupt path. A normal asynchronous event is processed just before
returning from the interrupt (with interrupts enabled).
If the near address bit is set then the event routine is located either in the lower
ROM or in the central 32K of RAM. The ROM select address is ignored and
the routine is called directly, rather than through the FAR CALL mechanism,
thus reducing the event processing overhead. Where possible, asynchronous
events should be at ‘near addresses’. Express asynchronous events must always
be at ‘near addresses’.

Event blocks appear in various other blocks handled by the Kernel, including
frame flyback, fast ticker and tick blocks. This routine is used to initialize the
event block parts of these.
The bytes after the last byte of the event block, even where the block forms
part of another block, are not used by the Kernel. When the event routine is
called the address of the block is passed to it, so the user may append further
information about the event to the block. This allows several similar events to
share the same event routine, each event having its ‘own’ variables appended
to its event block.
The event routine has the following entry and exit conditions:

Entry:

If the event routine is at a ‘far address’:

HL contains the address of byte 5 of the event block


(so any appended data can start at address HL + 2).
If the event routine is at a ‘near address’:

DE contains the address of byte 6 of the event block


(so any appended data can start at address DE + 1)

Exit:

AF, BC, DE and HL corrupt.


All other registers preserved.

The event routine may use the IX and IY registers but must preserve them. It
may not use the second register set. Express asynchronous events may not
enable interrupts.

KL INIT EVENT enables interrupts.

Related entries:
KL DEL SYNCHRONOUS
KL DISARM EVENT
KL EVENT
KL NEW FAST TICKER
KL NEW FRAME FLY
KL NEW TICKER
KL SYNC RESET
166: KL EVENT #BCF2

‘Kick’ an event block.

Action:
The event mechanism arranges that an event routine be called in response to
each ‘kick’ of an event block. KL EVENT performs the ‘kick’.

Entry conditions:
HL contains the address of the event block.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
Unlike the vast majority of Kernel routines this routine may be called from the
interrupt path. Because the LOW JUMP instruction in the main
firmwarejumpblock enables interrupts the user must pick the address part of
the ‘low address’ out of the jumpblock and mask off the top two bits to extract
the address in the lower ROM of KL EVENT. The following code does this:

LD DE,(KL_EVENT+ 1) ;extract address part of LOW JUMP


RES 7,D ;remove upper ROM state from ‘low address’
RES 6,D ;remove lower ROM state from ‘low address’
CALL PCDE_INSTRUCTION ; CALL KL EVENT

(If the user is going to perform this operation repeatedly it is recommended that
the address should be extracted once and should be stored somewhere).

The effect of the ‘kick’ depends on the event count in the event block:

Count < 0: The event is disarmed, and kicking it has no effect.

Count> 0: There are other kicks outstanding and the event is being
processed. This kick simply increments the count (unless it has already reached
the maximum of 127). Once event processing has begun it continues until the
count becomes zero or the event is disarmed.

Count = 0: The event is armed but event processing is not active.


The count is incremented and event processing initiated.
How event processing is initiated depends on the event class.

Synchronous Events.

Synchronous events are added to the synchronous event queue in priority order.
It is the responsibility of the foreground program to process the synchronous
event queue regularly.

Synchronous event routines are called when the foreground program calls KL
DO SYNC, the event count is then dealt with when KL DONE SYNC is called.

Asynchronous Events.
a. Not in the Interrupt Path

The event routine is called immediately. When the routine returns, if the
event count greater than zero it is decremented. If the count is still greater
than zero then the procedure is repeated.

b. In the Interrupt Path - Normal Asynchronous Event

The event is placed on the interrupt event pending queue. On exit from the
interrupt path the Kernel processes all events on the interrupt pending
queue as described in (a) above. This means that normal asynchronous
event routines are called in an extension of normal (non-interrupt)
processing between interrupt return and the main program. The routine is,
therefore, not subject to the restrictions imposed on interrupt path routines.

c. In the Interrupt Path - Express Asynchronous Event

The event routine is called immediately, in the interrupt path. The routine
must be at a ‘near address’ (see KL INIT EVENT). Under no
circumstances may the routine enable interrupts.

KL EVENT enables interrupts unless it is called from the interrupt path.

Related entries:
KL INIT EVENT
KL NEXT SYNC
KL POLL SYNCHRONOUS
KL SYNC RESET
167: KL SYNC RESET #BCF5

Clear synchronous event queue.

Action:
The synchronous event queue is set empty - any outstanding events are simply
discarded. The current event priority, used by KL POLL SYNCHRONOUS
and KL NEXT SYNC to mask out lower priority events, is reset.

Entry conditions:
No conditions.

Exit conditions:
AF and HL corrupt.

All other registers preserved.

Notes:
It is the user’s responsibility to ensure that the discarded events and any
currently active events are reset. The event count of discarded events will be
greater than zero, so any further ‘kicks’ will simply increment the count, but
not add the event to the synchronous event queue - the events are, therefore,
effectively disarmed.

Related entries:
KL DEL SYNCHRONOUS
KL NEXT SYNC
KL POLL SYNCHRONOUS
168: KL DEL SYNCHRONOUS #BCF8

Remove a synchronous event from the event queue.

Action:
The event is disarmed. If it is on the synchronous event queue then it is
removed.

Entry conditions:
HL contains the address of the event block.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
Deleting an event from the queue prevents the outstanding ‘kicks’ from being
processed.

Before a synchronous event block is reset or reinitialized this routine should be


used to ensure that it is not currently pending.

This routine enables interrupts.

Related entries:
KL DISARM EVENT
KL INIT EVENT
KL SYNC RESET
169: KL NEXT SYNC #BCFB

Get next event from the queue.

Action:
If there is an event on the synchronous event queue whose priority is greater
than the current event priority (if any), then remove the event from the queue,
set the current event priority to that of the event removed and return the
previous event priority.

Entry conditions:
No conditions.

Exit conditions:
If there is an event to be processed:

Carry true.
HL contains the address of the event block.
A contains the previous event priority (if any). If there is no event to be
processed:
Carry false.
A and HL corrupt.
Always:
DE corrupt.
All other registers preserved.

Notes:
KL NEXT SYNC returns the address of the next event to be processed, if any,
which it has taken off the synchronous event queue and whose priority has now
been set as the event priority mask.
The foreground program should call KL POLL SYNCHRONOUS regularly to
check for outstanding events. KL POLL SYNCHRONOUS is a short routine in
RAM, so calling it imposes little overhead. If there is an event outstanding then
the above procedure should be invoked, and should be repeated until the event
queue is empty.
The current event priority mechanism allows event routines to poll for, and
process, events of higher priority. The priority returned by this routine must be
preserved until it is passed to KL DONE SYNC.
KL NEXT SYNC enables interrupts.
The procedure for processing synchronous events is as follows:

TRY.AGAIN:
CALL KL_NEXTSYNC ; return next event, if any
JR NC,?????? ; jump if no event to process
;
PUSH HL ; save address of event
PUSH AF ; save previous event priority
CALL KL DO_SYNC ; call the event routine
POP AF
POP HL
;
CALL KL_DONE_SYNC ; reset the event priority mask, deal with the
; event count and put the event back on the
; queue if the count is still greater
; than zero
JR TRYAGAIN ; see if any events are still awaiting
; processing

Related entries:
KL DONE SYNC
KLDO SYNC
KLEVENT
KL INIT EVENT
KL POLL SYNCHRONOUS
170: KL DO SYNC #BCFE
Perform an event routine.

Action:
Call the event routine for a given event.

Entry conditions:
HL contains the address of the event block.

Exit conditions:
AF, BC, DE and HL corrupt.

All other registers preserved.

Notes:
This routine is intended to be called to process an event after KL NEXT SYNC
has found it to be pending. Use of this entry at any other time is not
recommended.

See KL NEXT SYNC above for the general scheme for processing
synchronous events.

KL DO SYNC does not itself affect the event count.

Related entries:
KL DONE SYNC
KL NEXT SYNC
171: KL DONE SYNC #BDO1

Finish processing an event.

Action:
Once a synchronous event has been processed, by invoking its event routine
via KL DO SYNC, this entry must be called to restore the current event
priority and to deal with the event count. If the count remains greater than zero
the event block is placed back on the synchronous event queue.

Entry conditions:
A contains the previous event priority.
HL contains the address of the event block.

Exit conditions:
AF, BC, DE and HL corrupt
All other registers preserved.

Notes:
This routine is intended to be called after calling KL NEXT SYNC, to find a
pending event, and KL DO’ SYNC, to run the event routine. It uses the
previous event priority and the event block address returned by KL NEXT
SYNC. Other uses of this entry are not recommended.

See KL NEXT SYNC above for the general scheme for processing
synchronous events.

Restoring the current event priority is an essential step in maintaining the


synchronous event priority scheme.

If the event count is greater than zero then it is decremented. If the count is still
greater than zero then there are further events outstanding and the event is
placed back on the synchronous event queue. The event may be disarmed
between KL NEXT SYNC and KL DONE SYNC. Setting the event count to
one before calling KL DONE SYNC forces multiple events to be treated as a
single event.

KL DONE SYNC may enable interrupts.

Related entries:
KL DO SYNC
KL NEXT SYNC
172: KL EVENT DISABLE #BDO4

Disable normal synchronous events.

Action:
Prevent normal synchronous events from being processed but allow express
synchronous events to be processed. This is achieved by setting the current
event priority higher than any possible normal synchronous event priority.

Entry conditions:
No conditions.

Exit conditions:
HL corrupt.
All other registers preserved.

Notes:
KL EVENT DISABLE does not prevent events from being kicked. The effect
is to ‘mask off all pending normal synchronous events so that they are hidden
from the foreground program (when KL POLL SYNCHRONOUS or KL
NEXT SYNC are called) and hence are not processed.

KL EVENT ENABLE reverses the effect of KL EVENT DISABLE.

It is not possible to disable synchronous events permanently from inside a


synchronous event routine as the previous current event priority is restored
when the event routine returns.

Related entries:
KL DISARM EVENT
KL EVENT ENABLE
KL NEXT SYNC
KL POLL SYNCHRONOUS
173: KL EVENT ENABLE #BDO7

Enable normal synchronous events.

Action:
Allows normal and express synchronous events to be processed.

Entry conditions:
No conditions.

Exit conditions:
HL corrupt.
All other registers preserved.

Notes:
Events are enabled by default. KL EVENT ENABLE reverses the effect of KL
EVENT DISABLE.

It is not possible to enable synchronous events permanently from inside a


synchronous event routine as the current event priority which is used to disable
events is restored when the event routine returns.

Related entries:
KL EVENT DISABLE
KL NEXT SYNC
KL POLL SYNCHRONOUS
174: KL DISARM EVENT #BDOA

Prevent an event from occurring.

Action:
Disarms the event by setting the event count to a negative value. Any further
‘kicks’ (calls of KL EVENT) for the event will be ignored, any outstanding
events are discarded.

Entry conditions:
HL contains the address of the event block.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
KL DISARM EVENT should only be used with asynchronous events.
Synchronous events may be disarmed by calling KL DEL SYNCHRONOUS,
which also ensures that the event is not on the synchronous event queue.

The event may be rearmed by reinitializing it KL INIT EVENT) or by setting


the event count (byte 2) of the event block to zero.

Related entries:
KL DEL SYNCHRONOUS
KL INIT EVENT
175: KL TIME PLEASE #BDOD

Ask the elapsed time.

Action:
The Kernel maintains a count which it increments on each time interrupt. The
count, therefore, measures time in 1/300th of a second units. This routine
returns the current count.

Entry conditions:
No conditions.

Exit conditions:
DEHL contains the four byte count (D contains the most significant byte and L
the least significant byte).

All other registers preserved.

Notes:
The count is zeroized when the machine is turned on or reset. The count may
be set to another starting value by KL TIME SET.

The count is not kept up to date if interrupts are disabled for long periods, such
as while reading and writing the cassette.

The four byte count overflows after approximately:


14,316,558 Seconds
= 238,609 Minutes
= 3,977 Hours
= 166 Days

This routine enables interrupts.

Related entries:
KL TIME SET
176: KL TIME SET #BD1O

Set the elapsed time.

Action:
The Kernel maintains a count which it increments on each time interrupt. The
count, therefore, measures time in 1/300th of a second units. This routine sets
the count to a given value.

Entry conditions:
DEHL contains the four byte count to set (D contains the most significant byte
and L the least significant byte).

Exit conditions:
AF corrupt.

All other registers preserved.

Notes:
The four byte count overflows after approximately:
14,316,558 Seconds
238,609 Minutes
= 3,977 Hours
= 166 Days

KL TIME SET may be used to set the count to the actual time of day, so that
the Kernel then maintains a real clock rather than a simple measure of the time
elapsed since the last reset.

The count is not kept up to date if interrupts are disabled for long periods, such
as while reading and writing the cassette.

This routine enables interrupts.

Related entries:
KLTIME PLEASE
177: MC BOOT PROGRAM #BD13

Load and run a program.

Action:
Shut down as much of the system as possible then load a program into RAM
and run it. If the load fails then the previous foreground program is restarted.

Entry conditions:
HL contains the address of the routine to call to load the program.

Exit conditions:
Does not exit!

Notes:
The system is partially reset before attempting to load the program. External
interrupts are disabled, as are all timer, frame flyback and keyboard break
events. Sound generation is turned off, indirections are set to their default
routines and the stack is reset to the default system stack. This process ensures
that no memory outside the firmware variables area is in use when loading the
program. Overwriting an active event block or indirection routine could
otherwise have unfortunate consequences.

The partial system reset does not change the ROM state or ROM selection. The
routine run to load the program must be in aecessible RAM or an enabled
ROM. Note that the firmware jumpblock normally enables the lower ROM and
disables the upper ROM and so the routine must normally be in RAM above
#4000 or in the lower
ROM.
The routine run to load the program is free to use any store from #0040 up to
the base of the firmware variables area (#B100) and may alter indirections and
arm external device interrupts as required. It should obey the following exit
conditions:

If the program loaded successfully:


Carry true.
HL contains the program entry point.

If the program failed to load:


Carry false.
HL corrupt.

Always:
A, BC, DE, IX, IY and other flags corrupt.
After a successful load the firmware is completely initialized (as at EMS) and
the program is entered at the entry address returned by the load routine.
Returning from the program will reset the system (perform RST 0).

After an unsuccessful load an appropriate error message is printed and the


previous foreground program is restarted. If the previous foreground was itself
a RAM program then the default ROM is entered instead as the program may
have been corrupted during the failed loading.

Related entries:
CAS IN DIRECT
KL CHOKE OFF
MC START PROGRAM
178: MC START PROGRAM #BD16

Run a foreground program.

Action:
Fully initialize the system and enter a program.

Entry conditions:
HL contains the entry point address.
C contains the required ROM selection.

Exit conditions:
Never exits!

Notes:
HL and C comprise the ‘far address’ of the entry point of the foreground
program (see section 2).

When entering a foreground program in ROM the ROM selection should be


that required to select the appropriate ROM. When entering a foreground
program in RAM the ROM selection should be used to enable or disable
ROMs as the RAM program requires (ROM select addresses # FC.. # FF).

This routine carries out a full EMS initialization of the firmware before
entering the program. Returning from the program will reset the system
(perform RST 0). MC START PROGRAM is intended for running programs in
ROM or programs that have already been loaded into RAM. To load and run a
RAM program use MC BOOT PROGRAM.

Related entries:
MC BOOT PROGRAM
RESET ENTRY (RST0)
179: MC WAIT FLYBACK #BD19

Wait for frame flyback.

Action:
Wait until frame flyback occurs.

Entry conditions:
No conditions.

Exit conditions:
All registers and flags preserved.

Notes:
Frame flyback is a signal generated by the CRT controller to signal the start of
the vertical retrace period. During this period the screen is not being written
and so major operations can be performed on the screen without producing
unsightly effects. A prime example is rolling the screen.

The frame flyback signal only lasts for a couple of hundred microseconds but
the vertical retrace period is much longer than this. However, there will be a
ticker interrupt in the middle of frame flyback which may cause the foreground
processing to be suspended for a significant length of time. It is important,
therefore, to perform any critical processing as soon after frame flyback is
detected as is possible.

This routine returns immediately if frame flyback is ocduring when it is called.


It does not wait for the start of frame flyback use a frame flyback event to do
this).

Related entries:
KL ADD FRAME FLY
180: MC SET MODE #BD1C

Set the screen mode.

Action:
Load the hardware with the required screen mode.

Entry conditions:
A contains the required mode.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The required mode is checked and no action is taken if it is invalid. If it is valid
then the new value is sent to the hardware.

The screen modes are:.


0: 160 x 200 pixels, 20 x 25 characters.
1: 320 x 200 pixels, 40 x 25 characters.
2: 640 x 200 pixels, 80 x 25 characters.

Altering the screen mode without notifying the Screen Pack will produce
peculiar effects on the screen. In general SCR SET MODE should be called to
change screen mode. This, in its turn, sets the new mode into the hardware.

Related entries:
SCR SET MODE
181: MC SCREEN OFFSET #BD1F

Set the screen offset.

Action:
Load the hardware with the offset of the first byte on the screen inside a 2K
screen block and which 16K block the screen memory is located in.

Entry conditions:
A contains the new screen base.

HL contains the new screen offset.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The screen base address is masked with #C0 to make sure it refers to a valid
16K memory area. The default screen base is #C0 (the screen is underneath the
upper ROM).
The screen offset is masked with #07FE to make it legal. Note that bit 0 is
ignored as the hardware only uses even offsets.

If the screen base or offset is changed without notifying the Screen Pack then
unexpected effects may occur on the screen. In general SCR SET BASE or
SCR SET OFFSET should be called. These, in their turn, send the values to the
hardware.

Related entries:
SCR SET BASE
SCR SET OFFSET
182: MC CLEAR INKS #BD22

Set all inks to one colour.

Action:
Set the colour of the border and set the colour of all the inks. All the inks are
set to the same colour thus giving the impression that the screen has been
cleared instantly.

Entry conditions:
DE contains the address of an ink vector.

Exit conditions:
AF corrupt.

All other registers preserved.

Notes:
The ink vector has the form:

Byte 0: Colour for the border.


Byte 1: Colour for all inks.

The colours supplied are the numbers used by the hardware rather than the grey
scale numbers supplied to SCR SET INK (see Appendix V).

After the screen has been cleared (or whatever) the correct ink colours can be
set by calling MC SET INKS.

This routine sets the colours for all 16 inks whether they can be displayed on
the screen in the current mode or not.

This ink clearing technique is used by the Screen Pack when clearing the
screen or changing mode (by SCR CLEAR and SCR SET MODE)

Related entries:
MC SET INKS
183: MC SET INKS #BD25

Set colours of all the inks.

Action:
Set the colours of all the inks and the border.

Entry conditions:
DE contains the address of an ink vector.

Exit conditions:
AF corrupt.

All other registers preserved.

Notes:
The ink vector passed has the following layout:

Byte 0: Colour for the border.


Byte 1: Colour for ink 0.
Byte 2: Colour for ink 1.
…. ….
Byte 16: Colour for ink 15.

The colours supplied are the numbers required by the hardware rather than the
grey scale numbers supplied to SCR SET INK (see Appendix V).
This routine sets the colours for all inks including those that cannot be visible
in the current screen mode. However, it is only necessary to supply sensible
colours for the visible inks.
The Screen Pack sets the colours for all the inks each time the inks flash and
after an ink colour has been changed (by calling SCR SET INK or SCR SET
BORDER).

Related entries:
MC CLEAR INKS
SCR SET BORDER
SCR SET INK
184: MC RESET PRINTER #BD28

Reset the printer indirection.

Action:
Set the printer indirection, MC WAIT PRINTER, to its default routine and, in
V1.1 firmware, set up the default printer translation table.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.

All other registers preserved.

Notes:
The default printer translation table is described in Appendix XIV. This is
designed to drive the DMP-1 printer. It only translates the additional characters
in the character set (#A0.. #AF); it does not translate any of the standard ASCII
characters or the graphic characters.

Related entries:
MC WAIT PRINTER
MC PRINT CHAR
185: MC PRINT CHAR #BD2B

Try to send a character to the Centronics port.

Action:
Send a character to the printer (Centronics port( or time out if the printer is
busy for too long.

Entry conditions:
A contains the character to send (bit 7 ignored).

Exit conditions:
If the character was sent OK:

Carry true.

If the printer timed out:

Carry false.

Al ways:

A and other flags corrupt.

All other registers preserved.

Notes:
In V1.1 firmware. the character to he sent i~ translated u~in~ the printer translation
table as set by MC PRINT TRANSLATION. If the supplied character is not found in
the table then it is sent as supplied without translation. However, if the character is
found in the translation table then the corresponding translation is sent instead; unless
the translation is #FF in which case the character is ignored and nothing is sent.

This routine calls the Machine Pack indirection MC WAIT PRINTER to send the
character. The default indirection routine waits for the Centronics port to become non-
busy then sends the character. If the port remains busy for too long (approximately 0.4
seconds) then the routine times out and the character is not sent. This time out is
provided so that the caller can test for break whilst driving the printer.

Related entries:
MC PRINT TRANSLATION
MC RESET PRINTER
MC WAIT PRINTER
186: MC BUSY PRINTER #BD2E

Test if the Centronics port is busy.

Action:
Test if the printer (Centronics port) is busy.

Entry conditions:
No conditions.

Exit conditions:
If Centronics port is busy:

Carry true.

If Centronics port is idle:

Carry false.

Always:

Other flags corrupt.

All other registers preserved.

Notes:
This routine has no other effects.

Related entries:
MC SEND PRINTER
187: MC SEND PRINTER #BD31

Send a character to the Centronics port.

Action:
Send a character to the printer (Centronics port) which must not be busy.

Entry conditions:
A contains the character to send (bit 7 ignored).

Exit conditions:
Carry true.
A and other flags corrupt.
All other registers preserved.

Notes:
The printer must not be busy when a character is sent. The higher level routine
MC PRINT CHAR will automatically wait for the printer to become non-busy
and should be used in preference.

Related entries:
MC BUSY PRINTER
MC PRINT CHAR
188: MC SOUND REGISTER #BD34

Send data to a sound chip register.

Action:
Set a sound chip sound register. This is a rather convoluted action because of
the way the hardware has been designed.

Entry conditions:
A contains the sound chip register number.
C contains the data to send,

Exit conditions:
AF and BC corrupt.
All other registers preserved.

Notes:
This routine enables interrupts.

Related entries:
None!
189: JUMP RESTORE #BD37

Restore the standard jumpblock.

Action:
Set the main firmware jumpblock to its standard state as described in sections
14.1 and 15.

Entry conditions:
No conditions.

Exit conditions:
AF, BC. DE and HL corrupt.
All other registers preserved.

Notes:
This routine may be used to restore the jumpblock to its standard routines after
the user has changed entries in it. The whole of the jumpblock is set up so care
must be taken if other programs, such as AMSDOS, have patched it.

The indirections jumpblock is set up piecemeal by the various packs’


initialization and reset routines. JUMP RESTORE does not set up the
indirections.

Related entries:
GRA RESET
KM RESET
MC RESET PRINTER
SCR RESET
TXT RESET
190 KM SET LOCKS #BD3A

Set the shift and caps lock states.

Action:
Turn the shift and caps locks on or off.

Entry conditions:
H contains the required caps lock state.
L contains the required shift lock state.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

The lock states are:

#00 means that the lock is to be turned off.


#FF means that the lock is to be turned on.

The default lock states are off.

Related entries:
KM GET STATE
191 KM FLUSH #BD3D

Flush the keyboard buffers.

Action:
Discard all pending keys from the key buffer, the ‘put back’ character and any
current expansion string.

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

The next character that will be returned by KM READ CHAR (or a similar
routine) after KM FLUSH is called will be the first character that the user types
after the call of KM FLUSH since all the pending characters will have been
discarded.

On V1.0 firmware the effect of this routine can be simulated by repeatedly


calling KM READ CHAR until it comes back with carry false.

Related entries:
KM READ CHAR
KM READ KEY
192 TXT ASK STATE #BD40

Get the state of the Text VDU.

Action:
Return the VDU enable/disable state and the cursor on/off and cursor
enable/disable states oft he current selected stream.

Entry conditions:
No conditions.

Exit conditions:
A contains the stream state.

Flags corrupt.

All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

The stream state is returned as follows:


Bit 0 0 ⇒ cursor enabled. 1 ⇒ cursor disabled.
Bit 1 0 ⇒ cursor on, 1 ⇒ cursor off.
Bits 2..6 are undefined.
Bit 7 0 ⇒ VDU disabled, 1 ⇒ VDUenabled.

Related entries:
TXT CUR DISABLE
TXT CUR ENABLE
TXT CUR OFF
TXT CUR ON
TXT VDU DISABLE
TXT VDU ENABLE
193 GRA DEFAULT #BD43

Set default Graphics VDU modes.

Action:
Sets the graphics write mode, background mode, first pixel mode and line mask
to their default settings.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and ilL corrupt.
All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

This routine sets the following modes:

Graphics write mode is set to force.


Graphics background mode is set to opaque.
First point mode is set to plot the first pixel of lines.
Line mask is set to give continuous lines (mask of #FF).

Related entries:
GRA INITIALISE
GRA RESET
GRA SET BACK
GRA SET FIRST
GRA SET LINE MASK
SCR ACCESS
194 GRA SET BACK #BD46

Set whether background is to be written.

Action:
Set the graphics background write mode to opaque or transparent. This affects
how GRA LINE ABSOLUTE, GRA LINE RELATIVE and GRA WR CHAR
write ‘background’ pixels. In opaque mode the pixels are written in the current
paper ink using the current graphics write mode. In transparent mode these
pixels are not plotted at all.

Entry conditions:
If background is to be written (opaque mode):

A must be zero.

If background is not to be written (transparent mode):

A must be non-zero.

Exit conditions:
All registers and flags preserved.

Notes:
This routine is not available on V1 .0 firmware.

Transparent write mode is useful for annotating diagrams and for similar
applications.

The graphics background write mode is similar to but independent of the


character write mode of each stream of the Text VDU.

The default setting is opaque mode.

Related entries:
GRA DEFAULT
GRA LINE
GRA LINE ABSOLUTE
GRA LINE RELATIVE
GRA SET LINE MASK
GRA WR CHAR
TXT SETBACK
195 GRA SET FIRST #BD49

Set whether the first point of a line is to be plotted.

Action:
Turn plotting of the first pixel of lines on or off.

Entry conditions:
If the first pixel is not to be plotted:

A contains zero.

If the first pixel is to be plotted:

A contains non-zero.

Exit conditions:
All registers and flags preserved.

Notes:
This routine is not available on V1.0 firmware.

Turning off the plotting of the first pixel of a line is particularly useful when
drawing using XOR graphics write mode. For example, if a box is drawn in
XOR mode when the first pixels of lines are being plotted then the corner
pixels will be plotted twice and will therefore not be set. By not plotting the
first pixel of lines this effect is avoided.

The default setting for this mode is to plot the first pixel.

Related entries:
GRA DEFAULT
GRA LINE
GRA LINE ABSOLUTE
GRA LINE RELATIVE
196 GRA SET LINE MASK #BD4C

Set the line mask for plotting pixels of lines.

Action:
Set the line mask that specifies how pixels on lines are to be plotted. Where a
bit in the mask is set the pixel will be plotted in the foreground (in graphics pen
ink using the graphics write mode), Where a pixel in the mask is not set the
pixel will either be plotted in the graphics paper ink using the graphics write
mode or it will not be plotted at all depending on the graphics background
write mode.

Entry conditions:
A contains the line mask to use.

Exit conditions:
All registers and flags preserved.

Notes:
This routine is not available on V1.0 Firmware.

The line mask is used starting with bit 7 and running to bit 0 and then starting
with bit 7 again. Successive lines will use the mask as it was left when the
previous line finished, the mask is not reset between lines.

The line mask specifies how pixels are to be plotted. This means that the same
mask will give noticeably different effects in the various screen modes.

The mask is applied to the line running from left to right or from bottom to top,
depending of the angle of the line, irrespective of which way round the end
points of the line are specified.

If the first pixel of the line is not being plotted then the line mask is applied to
the second pixel of the line first. It is not stepped on foi’ the missing first pixel.

The default line mask is #FF which plots the whole line in the foreground.

Related entries:
GRA DEFAULT
GRA LINE
GRA LINE ABSOLUTE
GRA LINE RELATIVE
GRA SET BACK
197 GRA FROM USER #BD4F

Convert user coordinates to base coordinates.

Action:
Convert the coordinates of a point from user coordinates to base coordinates
rounding as appropriate.

Entry conditions:
DE contains the user X coordinate.
HL contains the user Y coordinate.

Exit conditions:
DE contains the base X coordinate.
HL contains the base Y coordinate.

AF corrupt.
All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

The following formulae are used to convert between the cordinate systems:

Base X = (Origin X + Rounded X) / Points per pixel


Rounded X = (UserX + Round factor) AND Round mask
Where:

Round factor Round mask Points per pixel

+ve userX -ve userX


Mode 0: 0 0 #FFFF 1
Mode 1: 0 1 #FFFE 2
Mode 2: 0 3 #FFFC 4

Base Y = (OriginY + Rounded Y) / Points per pixel


Rounded Y = (UserY + Round factor) AND Round mask

Where: Round factor = 0 for +ve user Y


= 1 for -ve user Y
Roundmask = #FFFE
Points per pixel = 2
This routine is particularly useful when calling Screen pack routines which

take the positions of points in base coordinates.

Related entries:
GRA SET ORIGIN
SCR DOT POSITION
198 GRA FILL #BD52

Fill an area of the screen.

Action:
Fill an area of the screen containing the current graphics position and bounded
by the edge of the window and pixels set to the pen ink.

Entry conditions:
A contains the (unencoded) ink to fill the area with
HL contains the address of a buffer.
DE contains the length of the buffer.

Exit conditions:
If the area was filled successfully:
Carry true.

If the area was not filled:


Carry false.

Always:
A, BC, DE, HL and other flags corrupt.
All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

The filling algorithm treat.s pixels set to the current pen ink and pixels set to
the ink that is being used for filling as delimiters of the edge of the area. The
fill ink and the pen ink maybe the same ink.

Pixels that are filled are set to the fill ink. The graphics write mode does not
affect the way that pixels are written when filling.

The filling algorithm only moves up, down, right or left. It does not move
diagonally and so the algorithm will not ‘escape’ through a gap between edge
pixels that are diagonally adjacent. This means that the edge can be delimited
using the normal lines drawn by the Graphics VDU.

The filling algorithm avoids recursing. Instead it stores ‘interesting points’,


places that the algorithm has chosen one route to fill but might have chosen
another route, in the buffer supplied by the user. The buffer may lie anywhere
in RAM. Each ‘interesting point’ stored uses 7 bytes of the buffer and there is
an overhead of 1 byte used to mark the end of the buffer. Thus a buffer 64
bytes long will allow 9 ‘interesting points’ to be stored which should be
sufficient for filling most simple areas.
The area to be filled may be as complicated as required but the more
complicated the shape the longer the ‘interesting point’ buffer needs to be.

The failure return from this routine can occur for three reasons. Firstly, the
current graphics position may be outside the window. Secondly, the pixel at
current graphics position may be edge (pen or fill ink), In these cases the
routine will return without filling anything. Thirdly the algorithm may exhaust
the ‘interesting point’ buffer in whjch case some portions of the area will not
be filled.

Related entries:
GRA SET PEN
199 SCR SET POSITION #BD55

Set the location of the screen memory.

Action:
Tell the Screen pack the screen base and offset without telling the hardware.

Entry conditions:
A contains the screen base.
HL contains the screen offset.

Exit conditions:
A contains the screen base masked as required.
HL contains the screen offset masked as required.

Flags corrupt.
All other registers preserved.

Notes:
This routine is not available on V1.0 firmware.

This routine changes the location of the screen without notifying the hardware
of the change. This effect may be used to construct a second screen of text or
graphics without clearing the previous screen. When the new screen has been
constructed the hardware may be notified and the picture will appear instantly.

In general the user is advised to set the base using SCR SET BASE and the
offset using SCR SET OFFSET.

The screen base is masked with #C0 and the screen offset with #07FE to make
the values legal.

Related entries:
SCR GET LOCATION
SCR SET BASE
SCR SET OFFSET
200 MC PRINT TRANSLATION #BD58

Set the printer translation table.

Action:
Set how characters are to be translated before being sent to the printer.

Entry conditions:
HL contains the address of the table.

Exit conditions:
If the table is too long (more than 20 entries):

Carry false.

If the table is OK:

Carry true.

Always:

A, BC, DE, HL and other flags corrupt.

All other registers preserved.

Notes:
This routine is not available on V1.0 Firmware.

The supplied translation table may lie anywhere in RAM, This routine copies
the table and so the memory may be re-used if required.

The format of the table is as follows:


Byte 0: Number of entries in the table (N).
Bytes l,2: Entry l
…. …..
Bytes 2N-1, 2N: Entry N

The format of each two byte entry is as follows:

Byte 0: Character to be translated.


Byte 1: Character to translate to.
If the character to translate to is #FF then the character is ignored and nothing
is sent to the printer.

Translation of characters by the printer driver occurs in MC PRINT CHAR.


The default translation table is set up when MC RESET PRINTER is called.
The default table is designed to drive the DMP-1 printer (see Appendix XIV).

Related entries:
MC PRINT CHAR
201: KL BANK SWITCH #BD5B

Select a memory organization.

Action:
Set which RAM banks are switched into the 64k of RAM in the memory map.

Entry conditions:
A contains new organization.

Exit conditions:
A contains old organization.

Flags corrupt.
All other registers preserved.

Notes:
This routine is only available on the CPC6128 (ie. V1.2 firmware). The
memory organizations and bank switching are discussed fully in section 2.5.

It is inadvisable to bank switch to a memory organization where the code that


is being executed, or stack are inaccessible!

Related entries:
KL L ROM DISABLE
KL L ROM ENABLE
KL ROM SELECT
KL U ROM DISABLE
KL U ROM ENABLE
16 The Firmware Indirections.

This section gives the detailed entry and exit conditions and effects of the
routines in the indirectionsjumpblock. See section 14.2 for a list of these
routines.

The firmware indirections are taken by the firmware at key points. They allow
the user to intercept and alter a number of firmware actions without having to
provide a complete new firmware package.

The descriptions given are for the default settings of the indirections.
Replacement routines need not perform all the actions that the default routine
performs although they are advised to do so.
IND: TXT DRAW CURSOR #BDCD

Place the cursor blob on the screen (if enabled).

Default action:
If the cursor is enabled and turned on then the cursor blob is drawn on the
screen. If not then no action is taken. The current text position is forced into the
window (see TXT VALIDATE) and the cursor blob is written at the resulting
position. The cursor blob is an inverse patch. This routine will only be called
twice if TXT UNDRAW CURSOR is called in between.

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
This indirection is provided to allow the user to change the form of the cursor
blob. See TXT PLACE CURSOR for a description of how the cursor blob is
normally written.

The Text VDU routines call this indirection whenever the cursor is placed on
the screen. All the Text VDU routines that read from the screen, write to the
screen or change the current position remove the cursor (using TXT
UNDRAW CURSOR) before performing their action and place it back on the
screen afterwards (using TXT DRAW CURSOR). An example of such a
routine is TXT WR CHAR that writes a character on the screen.

This indirection is set up when TXT INITIALISE or TXT RESET is called.

Related entries:
TXT PLACE CURSOR
TXT UND RAW CURSOR
IND: TXT UNDRAW CURSOR #BDD0

Remove the cursor blob from the screen (if enabled).

Default action:
If the cursor is enabled and turned on then the cursor blob is removed from the
screen. If not then no action is taken. The cursor blob is an inverse patch. This
routine will only be called after TXT DRAW CURSOR has been used to place
the cursor on the screen.

Entry conditions:
No conditions.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
This indirection is provided to allow the user to change the form of the cursor
blob. See TXT REMOVE CURSOR for a description of how the cursor blob is
normally removed.

The Text VDU routines call this indirection to remove the cursor from the
screen. All the Text VDU routines that read from the screen, write to the screen
or change the current position remove the cursor (using TXT UNDRAW
CURSOR) before performing their action and place it back on the screen
afterwards (using TXT DRAW CURSOR). An example of such a routine is
TXT WR CHAR that writes a character on the screen.

This indirection is set up when TXT INITIALISE or TXT RESET is called.

Related entries:
TXT DRAW CURSOR
TXT REMOVE CURSOR
IND: TXT WRITE CHAR #BDD3

Write a character onto the screen.

Default action:
Put a character on the screen at a character position.

Entry conditions:
A contains the character to write.
H contains the physical column to write at.
L contains the physical row to write at.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The character position to write at is given in physical coordinates. i.e. Row 0,
column 0 is the top left corner of the screen. The position is not checked for
legality.

TXT WRITE CHAR is called by TXT WR CHAR to print a character on the


screen. The removing of the cursor blob and the calculation of the new current
position are performed by TXT WR CHAR and not by TXT WRITE CHAR.

This indirection is set up when TXT INITIALISE or TXT RESET is called.

Related entries:
TXT OUTPUT
TXT UNWRITE
TXT WR CHAR
IND: TXT UNWRITE #BDD6

Read a character from the screen.

Default action:
Try to read a character from the screen at a character position.

Entry conditions:
H contains the physical column to read from.
L contains the physical row to read from.

Exit conditions:
If a readable character was found:
Carry true.
A contains the character read.

If no recognisable character was found:


Carry false.
A contains zero.

Always:
BC, DE, HL and other flags corrupt.

All other registers preserved.

Notes:
The character position to read from is given in physical coordinates. i.e. Row 0,
column 0 is the top left corner of the screen. The position is not checked for
legality.

This indirection is called by TXT RD CHAR to read a character from the


screen. TXT RD CHAR removes the cursor from the screen before calling this
indirection.

The read is performed by comparing the matrix found on the screen with the
matrices used to generate characters. As a result changing a character matrix,
changing the pen or paper inks or changing the screen (e.g. drawing a line
through a character) may make the character unreadable. In particular the
cursor blob will cause confusion and so it should not be
on the screen

Special precautions are taken against generating inverse space (character #8F).
Initially the character is read assuming that the background to the character was
written in the current paper ink. If this fails to generate a recognisable character
or it generates inverse space then another try is made by assuming that the
character was written in the current pen ink.
The characters are scanned starting with #00 and finishing with #FF. Thus, if
there are two possible character matrices that match the screen, the smaller of
the two character numbers will be returned.

This indirection is set up when TXT INITIALISE or TXT RESET is called.

Related entries:
TXT RD CHAR
TXT WRITE CHAR
IND: TXT OUT ACTION #BDD9

Output a character or control code.

Default action:
Print a character on the screen or obey a control code (characters #00..#1F).
Works on the currently selected stream (except as noted below).

Entry conditions:
A contains the character or code.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
This indirection is called by TXT OUTPUT to do the work of printing
characters or obeying the control codes. It is provided to allow the user to
change the method of dealing with characters and control codes or to allow the
user to redirect output (to the printer for example). TXT OUTPUT merely
preserves the registers around the call of TXT OUT ACTION.

Control codes may take up to 9 parameters. These are the characters sent
following the initial control code. The characters sent are stored in a buffer
until sufficient have been received to make up all the required parameters. The
control code buffer is only long enough to accept 9 parameter characters.

There is only one control code buffer which is shared between all the streams.
It is, therefore, possible to get unpredictable results if the output stream is
changed part of the way through sending a control code sequence.
If the VDU is disabled then no characters will be printed on the screen. In V1.1
firmware control codes that are specially marked in the control code table will
not be obeyed if the VDU is disabled. Other control codes and all control codes
in V1.0 firmware will be obeyed.
If the graphics character write mode is enabled then all characters and control
codes are printed using the Graphics VDU (see GRA WR CHAR) and are not
obeyed. Normally characters are written by the Text VDU (see TXT WR
CHAR).

This indirection is set up when TXT INITIALISE or TXT RESET is called.

Related entries:
TXT OUTPUT
TXT WR CHAR
IND: GRA PLOT #BDDC

Plot a point.
Default action:
Check if the point lies inside the current window and if so write it in the current
graphics pen ink and using the current graphics write mode. The current
graphics position is always moved to the specified point.

Entry conditions:
DE contains the user X coordinate of the point to plot.
HL contains the user Y coordinate of the point to plot.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The position of the point to plot is given in user coordinates, i.e. relative to the
user origin.

This indirection is called by GRA PLOT RELATIVE and GRA PLOT


ABSOLUTE to plot the point requested. It is provided to allow the user to
change the method for plotting (to output to an X-Y plotter for example). GRA
PLOT RELATIVE converts from relative to user coordinates and then calls
this indirection; GRA PLOT ABSOLUTE calls this indirection immediately.

To write the point on the screen the SCR WRITE indirection is used. Thus the
point is plotted using the current graphics write mode.

This indirection is set up when GRA INITIALISE or GRA RESET is called.

Related entries:
GRA PLOT ABSOLUTE
GRA PLOT RELATIVE
GRA TEST
SCR WRITE
IND: GRA TEST #BDDF

Test a point.

Default action:
Check if the point is inside the graphics window and return the ink it is
currently set to if so. Otherwise, return the current graphic paper ink. The
current graphics position is always moved to the specified point.

Entry conditions:
DE contains the user X coordinate of the point to test.
HL contains the user Y coordinate of the point to test.

Exit conditions:
A contains the decoded ink of the specified point.
BC, DE, HL and flags corrupt.
All other registers preserved.

Notes:
The position of the point to test is given in user coordinates, i.e. relative to the
user origin.

This indirection is used by GRA TEST RELATIVE and GRA TEST


ABSOLUTE to test the point requested. It is provided to allow the user to
change the method for testing (comparing with the current pen ink for
example). GRA TEST RELATIVE converts from relative to user coordinates
and then calls this indirection; GRA TEST ABSOLUTE calls this indirection
immediately.

To test the ink of a point inside the window the SCR READ indirection is used.
This indirection is set up when GRA INITIALISE or GRA RESET is called.

Related entries:
GRA PLOT
GRA TEST ABSOLUTE
GRA TEST RELATIVE
SCR READ
IND: GRA LINE #BDE2

Draw a line.

Default action:
Draw a line between the current graphics position and the given endpoint using
the current graphics write mode. Points on the line that lie outside the current
graphics window will not be plotted. The current graphics position is always
moved to the specified endpoint.

Entry conditions:
DE contains the user X coordinate of the endpoint.
HL contains the user Y coordinate of the endpoint.

Exit conditions:
AF, BC. DE and HL corrupt.
All other registers preserved.

Notes:
The position of the endpoint is given in user coordinates, i.e. relative to the
user origin.

This indirection is used by GRA LINE RELATIVE and GRA LINE


ABSOLUTE to draw the line requested. It is provided to allow the user to
change the method for line drawing (to output to an X-Y plotter for example).
GRA LINE RELATIVE converts from relative to user coordinates and then
calls the indirection; GRA LINE ABSOLUTE calls the indirection
immediately.

The line is split up into horizontal or vertical sections that are drawn separately
(see SCR HORIZONTAL and SCR VERTICAL. The SCR WRITE indirection
is called to write the points in these sections. This means that the line is plotted
using the current graphics write mode.

In V1.0 firmware the line is plotted in the current pen ink. But in V1.1
firmware the setting of the line mask determines how pixels on the line will be
plotted. The line mask is bit significant and is used repeatedly in the order bit
7, bit 6 down to bit 0 for each pixel in the line. If the bit is one then the pixel is
plotted in the graphics pen ink. If the bit is zero then the action taken depends
on the graphics background write mode. If the background mode is opaque
then the pixel is plotted in the graphics paper ink. If the background mode is
transparent then the pixel is not plotted.
In V1.1 firmware the first pixel of the line (that at the current graphics
position) is not plotted if the first point plotting mode is set false.

This indirection is set up when GRA INITIALISE or GRA RESET is called.

Related entries:
GRA LINE ABSOLUTE
GRA LINE RELATIVE
GRA SET BACK
GRA SET FIRST
GRA SET LINE MASK
SCR HORIZONTAL
SCR VERTICAL
IND: SCR READ #BDE5

Read a pixel from the screen.

Default action:
Read a pixel from the screen and decode its ink.

Entry conditions:
HL contains the screen address of the pixel.
C contains the mask for the pixel.

Exit conditions:
A contains the decoded ink that the pixel was set to.
Flags corrupt.

All other, registers preserved.

Notes:
The mask supplied must be a mask for a single pixel otherwise the decoding of
the ink read from the screen will not work correctly.

This indirection is set up when SCR INITIALISE or SCR RESET is called. It


is called by GRA TEST.

Related entries:
GRA TEST
SCR WRITE
IND: SCR WRITE #BDE8

Write pixel(s) using the current graphics write mode.

Default action:
Plot a pixel or pixels on the screen using the current graphics write mode.

Entry conditions:
HL contains the screen address of the pixel(s). C contains the mask for the
pixel(s).
B contains the encoded ink to plot with.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The pixel mask supplied can be for a single pixel or more than one pixel (or
even no
pixels). The ink supplied should be encoded to cover the whole of a byte (see
SCR INK ENCODE).
The pixel is plotted using the current Graphics VDU write mode. These modes
are:
FORCE Pixel is set to the new ink irrespective of the old ink.
XOR Pixel is set to the ink formed by exclusive-oring the new ink
for the pixel and its current setting.
AND Pixel is set to the ink formed by anding the new ink for the pixel
and its current setting.
OR pixel is set to the ink formed by oring the new ink for the pixel
and its current setting.
The write mode can be set by calling SCR ACCESS appropriately.
This indirection is called by all Graphics VDU write routines, in particular
GRA
PLOT RELATIVE, GRA PLOT ABSOLUTE, GRA LINE RELATIVE, GRA
LINE ABSOLUTE and GRA WR CHAR, to plot pixels on the screen. It is
provided to allow the user to intercept the lowest level of point plotting
(perhaps to add yet another plotting mode).
This indirection is set up when SCR INITIALISE or SCR RESET is called.

Related entries:
GRA PLOT
SCR ACCESS
SCR PIXELS
SCR READ
IND: SCR MODE CLEAR #BDEB

Clear the screen to ink 0.

Default action:
Clear the screen memory to zeros. This indirection is provided to allow the user
to prevent the screen being cleared after the mode is changed.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
Normally this indirection performs the actions described in SCR CLEAR.

In V1.0 firmware it is necessary for the user to set up the inks if this indirection
is intercepted (see Appendix XIII). In V1.1 firmware the screen pack sets up
the inks for the user after SCR MODE CLEAR has been called.

This indirection is set up when SCR INITIALISE or SCR RESET is called.


NB. When this indirection is called the text and graphics VDUs are in non-
standard states.

Related entries:
SCR CLEAR
SCR SET MODE
IND: KM TEST BREAK #BDEE

Test for break (or reset).

Default action:
Test if the escape key is pressed, if not then no action is taken. If escape, shift
and control are all pressed and no other keys then the system is reset.
Otherwise, a break event is reported (see KM BREAK EVENT).

Entry conditions:
Interrupts disabled.
C contains shift and control key states.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
This indirection is called by the firmware from the interrupt path. Thus
interrupts are disabled and they must remain disabled.

If bit 7 of C is set then the control key is pressed. If bit 5 of C is set then one of
the shift keys is pressed.

This indirection is called after the keys have been scanned and the escape key
was found to have been pressed. It is provided to allow the user to alter the
action of a break (particularly to prevent the system reset, see RESET
ENTRY).

This indirection is set up when KM INITIALISE or KM RESET is called.

Related entries:
KM BREAK EVENT
IND: MC WAIT PRINTER #BDF1

Print a character or time out.

Default action:
Wait for the Centronics port to become not busy and then send a character to it.
If the port remains busy for a long time the routine times out and the character
is not sent.

Entry conditions:
A contains the character to send.

Exit conditions:
If the character was sent OK:
Carry true.

If the Centronics port timed out:


Carry false.

Always:
A and BC corrupt.
All other registers preserved.

Notes:
This indirection is provided to allow the user to drive the printer in a different
way. For example, ‘escape sequences’ could be handled or the time out could
be changed.

This indirection is called by the routine MC PRINT CHAR. It tests whether the
printer is busy in the same way as MC BUSY PRINTER and sends the
character in the same way as MC SEND PRINTER.

This indirection is set up when MC RESET PRINTER is called.

Related entries:
MC BUSY PRINTER
MC PRINT CHAR
MC SEND PRINTER
IND KM SCAN KEYS #BDF4

Scan the keyboard.

Default action:
Scans the keyboard and updates the key state map. Newly pressed keys are
detected and appropriate markers are inserted into the key buffer.

Entry conditions:
No conditions except that interrupts must be disabled.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved and interrupts remain disabled.

Notes:
This indirection is called every fiftieth of a second during a ticker interrupt.
The repeat speeds and start-up delays of the keys are measured in scans of the
keyboard and hence fiftieths of a second.

If the escape key is pressed then the indirection KM TEST BREAK is called to
process the break.

Related entries:
KL SCAN NEEDED
KM READ KEY
KM TEST BREAK
KM TEST KEY
17 The High Kernel Jumpblock.

Separate from the main firmware jumpblock is a small jumpblock for Kernel
routines associated with ROM state and ROM selection. The routines accessed
through this jumpblock are all RAM resident, to avoid confusion while the
ROM state and ROM select are changed! The RAM area is copied out of ROM
during the power-up initialization. The jumpblock should not be altered by the
user.

The entry KL POLL SYNCHRONOUS is the ‘odd man out’ amongst the
routines in this jumpblock. Unlike the other synchronous event handling
routines, which are in the lower ROM, this routine is RAM resident. This
minimises the overhead involved in polling for synchronous events.

A brief listing of the entries in this jumpblock can be found in section 14.3. A
discussion of ROMs and the memory map can be found in section 2, further
discussion of ROMs can be found in section 10 and a discussion of events can
be found in section 12.
HI: KL U ROM ENABLE #B900

Enable the upper ROM.

Action:
Enables the currently selected upper ROM. Reading from addresses #C000 and
up will now return the contents of the ROM.

Entry conditions:
No conditions.

Exit conditions:
A contains the previous ROM state.
Flags corrupt.

All other registers preserved.

Notes:
The mechanisms provided for calling subroutines in the upper ROM and for
selecting upper ROMs automatically enable the ROM as required. This routine
is used by the firmware but is otherwise of little use.

The previous ROM state may be passed to KL ROM RESTORE to reset the
state to what it was before this routine was called.

This routine enables interrupts.

Related entries:
KL L ROM ENABLE
KL ROM RESTORE
KL ROM SELECT
KL U ROM DISABLE
HI: KL U ROM DISABLE #B903

Disable the upper ROM.

Action:
Disables the upper ROM. Reading from addresses #C000 and up will now
return the contents of the RAM.

Entry conditions:
No conditions.

Exit conditions:
A contains the previous ROM state.

Flags corrupt.

All other registers preserved.

Notes:
Disabling the upper ROM gives read access to the top 16K of RAM, which is
usually used as the screen memory. Note that the mapping of a location in
screen memory to pixels on the screen depends on the mode and on the screen
offset.

It is inadvisable to disable the upper ROM while executing instructions in it!

The previous ROM state may be passed to KL ROM RESTORE to reset the
state to what it was before this routine was called.

This routine enables interrupts.

Related entries:
KL L ROM DISABLE
KL ROM RESTORE
KL U ROM ENABLE
HI: KL L ROM ENABLE #B906

Enable the lower ROM.

Action:
Enables the lower ROM. Reading from addresses below #4000 will now return
the contents of the ROM.

Entry conditions:
No conditions.

Exit conditions:
A contains the previous ROM state.
Flags corrupt.
All other registers preserved.

Notes:
In general the lower ROM is disabled except when a firmware routine is called.
The firmware jumpblock arranges to enable the lower ROM automatically and
to disable it again when the routine returns. This routine is used by the
firmware but is otherwise of little use.

The previous ROM state may be passed to KL ROM RESTORE to reset the
state to what it was before this routine was called.
This routine enables interrupts.

Related entries:
KL L ROM DISABLE
KL ROM RESTORE.
KL U ROM ENABLE
HI: KL L ROM DISABLE #B909

Disable the lower ROM.

Action:
Disables the lower ROM. Reading from addresses below #4000 will now
return the contents of the RAM.

Entry conditions:
No conditions.

Exit conditions:
A contains the previous ROM state.
Flags corrupt.
All other registers preserved.

Notes:
In general the lower ROM is disabled except when a firmware routine is called.
The firmware jumpblock arranges to enable the lower ROM automatically and
to disable it again when the routine returns.

The previous ROM state may be passed to KL ROM RESTORE to reset the
state to what it was before this routine was called.

This routine enables interrupts.

Related entries:
KL L ROM ENABLE
KL ROM RESTORE
KL U ROM DISABLE
HI: KL ROM RESTORE #B9OC

Restore the previous ROM state.

Action:
The ROM state change routines all return a value giving the previous ROM
state. Given that value KL ROM RESTORE will reset the state to what it was
before the change.

Entry conditions:
A contains the previous ROM state.

Exit conditions:
AF corrupt.
All other registers preserved.

Notes:
The previous ROM state is the value returned by one of:

KL U ROM ENABLE
KL U ROM DISABLE
KL L ROM ENABLE
KL L ROM DISABLE
KL ROM SELECT

It is possible to use KL U ROM DISABLE to reverse the effect of a call of KL


U ROM ENABLE (amongst various other combinations). However, calling KL
ROM RESTORE is the prefered method since it restores the state to what it
was, which might have been enabled anyway.

This routine enables interrupts.

Related entries:
KL L ROM DISABLE
KL L ROM ENABLE
KL ROM SELECT
KL U ROM DISABLE
KL U ROM ENABLE
HI: KL ROM SELECT #B90F

Select a particular upper ROM.

Action:
Select a given upper ROM and enable the upper ROM.

Entry conditions:
C contains the ROM select address of the required ROM.

Exit conditions:
C contains the ROM select address of the previously selected ROM.
B contains the previous ROM state.

AF corrupt.
All other registers preserved.

Notes:
The previous state can be passed to KL ROM RESTORE to reset the ROM
enable to what it was. Both the previous state and the previous selection can be
passed to KL ROM DESELECT to restore the state to what it was and to select
the previously selected ROM again.

The mechanisms provided for calling routines in expansion ROMs


automatically perform ROM selection as required see section 21.

It is inadvisable to select another upper ROM whilst executing instructions in


the upper ROM.

This routine enables interrupts.

Related entries:
KL CURR SELECTION
KL PROBE ROM
KL ROM DESELECT
KL ROM RESTORE
HI: KL CURR SELECTION #B912

Ask which upper ROM is currently selected.

Action:
Returns the ROM select address of the currently selected upper ROM.

Entry conditions:
No conditions.

Exit conditions:
A contains the ROM select address of the currently selected ROM.

All other registers and flags preserved.

Notes:
It is not possible to predict the ROM select address at which any particular
expansion ROM will be fitted. The ‘far address’ used to reference subroutines
in expansion ROMs includes a ROM select byte which must be set up at run
time. This routine returns the ROM select address of the current ROM so that it
can set up suitable ‘far addresses’.

Related entries:
KL PROBE ROM
KL ROM SELECT
HI: KL PROBE ROM #B915

Ask class and version of a ROM.

Action:
The first few bytes of all upper ROMs contain information in a standard form
about the ROM. This routine extracts the class, mark number and version
number bytes from the ROM at the given ROM select address.

Entry conditions:
C contains the ROM select address of the ROM to probe.

Exit conditions:
A contains the ROM’s class.
L contains the ROM’s mark number.
H contains the ROM’s version number.

B and flags corrupt.


All other registers preserved.

Notes:
The ROM class returned may take any of the following values:

0: Foreground ROM.
1: Background ROM.
2: Extension foreground ROM.
#80: On board ROM (the built in BASIC foreground program).

Selecting a ROM address where no ROM is fitted implicitly selects the on-
board ROM and so it will return #80 as its class.

The meaning of the mark and version numbers depends on the ROM.

See section 10 for a description of expansion ROMs.

This routine enables interrupts.

Related entries:
KL ROM SELECT
KL CURR SELECTION
HI: KL ROM DESELECT #B918

Restore previous upper ROM selection.

Action:
Set the ROM state and upper ROM selection to what they were before KL
ROM SELECT was called.

Entry conditions:
C contains the ROM select address of the previously selected ROM.
B contains the previous ROM state.

Exit conditions:
C contains the ROM select address of the currently selected ROM.
B corrupt.
All other registers and flags preserved

Notes:
The previous ROM selection and state are the values returned by KL ROM
SELECT. The currently selected ROM returned by this routine is the ROM that
was selected by calling KL ROM SELECT (unless further selections have been
made).
The mechanisms provided for calling subroutines in expansion ROMs
automatically perform ROM selection as required.

It is inadvisable to select another upper ROM whilst executing instructions in


the upper ROM.

This routine enables interrupts.

Related entries:
KL CURR SELECTION
KL ROM RESTORE
KL ROM SELECT
HI: KL LDIR #B91B

Move store (LDIR) with ROMs turned off.

Action:
Performs an LDIR instruction (LoaD Increment and Repeat) with both upper
and lower ROMs disabled.

Entry conditions:
BC, DE, HL as required by the LDIR instruction.

Exit conditions:
F, BC, DE, HL as set by the LDIR instruction.
All other registers preserved.

Notes:
This routine may be used to move areas of RAM irrespective of the ROM state.

This routine enables interrupts.

Related entries:
KL LDDR
RAM LAM (RST4)
HI: KL LDDR #B91E

Move store (LDDR) with ROMs turned off.

Action:
Performs an LDDR instruction (LoaD Decrement and Repeat) with both upper
and lower ROMs disabled.

Entry conditions:
BC, DE, HL as required by LDDR instruction.

Exit conditions:
F, BC, DE, HL as set by LDDR instruction.
All other registers preserved.

Notes:
This routine may be used to move areas of RAM irrespective of the ROM state.

This routine enables interrupts.

Related entries:
KL LDIR
RAM LAM (RST4)
HI: KL POLL SYNCHRONOUS #B921

Check if an event with higher priority than the current


event is pending.

Action:
If the synchronous event queue is not empty then the priority of the highest
priority pending event is compared with the current event’s priority (if any).

Entry conditions:
No conditions.

Exit conditions:
If there is a higher priority event pending:
Carry true.

If there is no higher priority event pending:


Carry false.

Always:
A and other flags corrupt.
All other registers preserved.

Notes:
This routine is in the high jumpblock to minimise the overhead of polling for
synchronous events. If the synchronous event queue is empty then the routine
takes only a few instructions.

While a synchronous event is being processed the Kernel remembers its


priority. The synchronous event routine may itself poll the synchronous event
queue, but only events of a higher priority than itself are notified to it.

This routine may enable interrupts.

Related entries:
KL EVENT
KL DONE SYNC
KL DO SYNC
KL NEXT SYNC
HI: KL SCAN NEEDED #B92A

Ensure keyboard is scanned at next opportunity.

Action:
Force the Key Manager to scan the keyboard when the next ticker interrupt
occurs. This may be used to reduce the probability of key pressings being
missed while interrupts are disabled.

Entry conditions:
No conditions.

Exit conditions:
AF and HL corrupt.
All other registers preserved.

Notes:
The keyboard is normally scanned on every sixth ticker interrupt (every fiftieth
of a second). While interrupts are disabled the ticks are lost and the keyboard
will not be scanned. If interrupts are disabled for a significant period (more
than three ticks) then this routine should be called just before interrupts are re-
enabled. If interrupts are disabled for a long time more than twelve ticks) then
the user might consider calling this routine and re-enabling interrupts for a
short time every fiftieth of a second.

Related entries:
KM SCAN KEYS
18 The Low Kernel Jumpblock.

The bottom of memory, from #0000 to #003F inclusive, is occupied by the


code for the restart (RST) instructions and a number of Kernel entries. Most of
these entries are concerned with access to subroutines in ROM and RAM. The
RST’s are:
RST 0 performs a system reset.
RST instructions 1 to 5 inclusive have been used to extend the Z80
instruction set to provide extra CALL and JUMP instructions, which use
addresses extended to include ROM state and ROM select components.
RST 6 is available to the user.
RST 7 is used by interrupts.
Since all the entries supplied must be available whether the lower ROM is
enabled or not, the area is copied into RAM from the ROM during power-up
initialization.
The user is not intended to alter this jumpblock )except where noted in the
USER RESTART and EXT INTERRUPT areas). If the user does change the
area then it is the user’s responsibility to ensure that the changes do not affect
other programs. To some extent this can be achieved by ensuring that the lower
ROM is always enabled when other programs are running. However, since the
other programs may disable the lower ROM this is insufficient in most cases.
Ideally the original jumpblock contents should be restored where there is any
doubt.
Section 2 contains a discussion of ROMs and the memory map and section 10
contains a general discussion of external ROMs. A brief list of the routines in
this area can be found in section 14.4.
LOW: RESET ENTRY RST0 #0000

Completely reset the machine as if powered up.

Action:
When the machine is first turned on execution starts here. Calling or jumping
to #0000, or executing RST 0, resets the machine to its initial power-up state.

Entry conditions:
No conditions.

Exit conditions:
Does not return!

Notes:
All hardware is reset and the firmware is completely initialized. Once all tables
and jumpblocks have been set up, control is passed to the default entry in ROM
0 (see section 10).

Related Entries.
MC START PROGRAM
LOW: LOW JUMP RST 1 #0008

Jump to lower ROM or RAM, takes inline ‘low address’ to


jump to.

Action:
RST 1 is used to extend the instruction set. It is an expanded form of the jump
instruction. It should be followed by a 2 byte ‘low address’ which specifies the
location tojump to and the required ROM state.

Entry conditions:
All registers and flags are passed to the target routine untouched.

Exit conditions:
All registers and flags are as set by the target routine.

Notes:
The ‘low address’ following the restart instruction is laid out as follows:

Bit: 15 14 13 0

U L Address

If the ‘U’ bit is set then the upper ROM is disabled.


If the ‘L’ bit is set then the lower ROM is disabled.
‘Address’ is the actual address of the target routine to jump to once the
ROM state has been set.
When the target routine returns the ROM state is restored to what it was before
the jump. To accomplish this 4 bytes are pushed onto the stack and so care
should be taken when indexing up the stack (to find the address of inline
parameters, for example).
The LOW JUMP, RST 1, ‘instruction’ may replace the first byte of a JP (jump)
instruction. It is intended for use in jumpblocks. The main firmware jumpblock
is made up almost exclusively of LOW JUMP ‘instructions’.
It is assumed that the destination of the jump is a routine which will return in
the usual way. The restart instruction itself does not return. The value at the top
of the stack when a LOW JUMP is executed must, therefore, be a return
address.
Executing a LOW JUMP enables interrupts.
Related entries:
FAR CALL (RST3)
FIRM JUMP (RST5)
KL FAR ICALL
KL FAR PCHL
KL LOW PCHL
LOW: KL LOW PCHL #000B

Jump to lower ROM or RAM.


Register HL contains the ‘low address’ to jump to.

Action:
Takes a ‘low address’ as a parameter and jumps to it. The ‘low address’
specifies both the address to jump to and the ROM state required.

Entry conditions:
HL contains the ‘low address’ to jump to.
All registers and flags are passed to the target routine untouched.

Exit conditions:
All registers and flags are as set by the target routine.

Notes:
The ‘low address’ is laid out as follows:

Bit: 15 14 13 0

U L Address

If the ‘U’ bit is set then the upper ROM is disabled.


If the ‘L’ bit is set then the lower ROM is disabled.
‘Address’ is the actual address of the target routine to jump to once the
ROM state has been set.
When the target routine returns the ROM state is restored to what it was before
the jump. To accomplish this 4 bytes are pushed onto the stack and so care
should be taken when indexing up the stack (to find the address of inline
parameters, for example).
It is assumed that the destination of the jump is a routine which will return in
the usual way. The value at the top of the stack when a LOW PCHL is
executed must, therefore, be a return address.
Interrupts are enabled.

Related entries:
KL FAR ICALL
KL FAR PCHL
LOW JUMP (RST1)
PCHL INSTRUCTION
LOW: PCBC INSTRUCTION #000E

Jump to address in BC.

Action:
Equivalent to the JP (HL) instruction (or PCHL in some assembler dialects),
except that the destination is in BC not HL.

Entry conditions:
BC contains the address to jump to.
All registers and flags are passed to the target routine untouched.

Exit conditions:
All registers and flags are as set by the target routine.

Notes:
Calling PCBC INSTRUCTION is a useful way of invoking a routine whose
address has been picked out of a table or otherwise established at run time.

Related entries:
KLFAR PCHL
KL LOW PCHL
KL SIDE PCHL
PCDE INSTRUCTION
PCHL INSTRUCTION
LOW: SIDE CALL RST2 #0010
Call to a sideways ROM, takes inline ‘side address’ to call.

Action:
RST 2 is used to extend the instruction set. It is an expanded form of the CALL
instruction. It should be followed by a 2 byte ‘side address’ which specifies the
location to call and the required ROM selection.

Entry conditions:
All registers and flags are passed to the target routine untouched except for
IY (which is set to point at a background ROM’s upper data area).

Exit conditions:
IY corrupt.
All other registers and flags are as set by the target routine.

Notes:
The ‘side address’ following the restart instruction is laid out as follows:

Bit: 15 14 13 0

Off Address

‘Off’ gives a value in the range 0.3, which, when added to the ROM
select address of the main foreground ROM, gives the ROM select
address of the required ROM.
After #C000 has been added to it, ‘address’ is the address of the routine to
call.
The target routine returns to the instruction immediately following the inline
‘side address’. The ROM select and ROM state are restored to what they were
before the call. To accomplish this 6 bytes are pushed onto the stack and so
care should be taken when indexing up the stack (to find the address of inline
parameters, for example).
When the target routine is entered the lower ROM is disabled and the
appropriate upper ROM is selected and enabled.
SIDE CALLs are provided to support foreground programs split over a number
of ROMs (up to four). See section 9 on expansion ROMs.
Interrupts are enabled.

Related entries:
FAR CALL (RST3)
KL SIDE PCHL
LOW: KL SIDE PCHL #0013
Call to a sideways ROM, HL contains ‘side address’ to
call.

Action:
Takes a ‘side address’ and calls it. The ‘side address’ specifies the address of
the routine to call and which upper ROM to select.

Entry conditions:
HL contains the ‘side address’ to call.
All registers and flags are passed to the target routine untouched except for
IY (which is set to point at a background ROM’s upper data area).

Exit conditions:
IY corrupt:
All other registers and flags are as set by the target routine.

Notes:
The ‘side address’ is laid out as follows:
Bit: 15 14 13 0

Off Address

‘Off’ gives a value in the range 0.3, which, when added to the ROM
select address of the main foreground ROM, gives the ROM select
address of the required ROM.
After #C000 has been added to it, ‘address’ is the address of the routine to
call.
When the target routine is entered the lower ROM is disabled and the
appropriate upper ROM is selected and enabled.
When the target routine returns the ROM select and ROM state are restored to
what they were before the call. This is accomplished by pushing 6 bytes onto
the stack and so care should he taken when indexing up the stack (to find the
address of inline parameters, for example).
Side calls are provided to support foreground programs split over a number of
ROMs (up to four). See section 10 on external ROMs.
Interrupts are enabled.

Related entries:
FAR CALL (RST3)
KL FAR ICALL
KL FAR PCHL
LOW: PCDE INSTRUCTION #0016

Jump to address in DE.

Action:
Equivalent to the JP (HL) instruction (or PCHL in some assembler dialects),
except that the destination is in DE not HL.

Entry conditions:
DE contains the address to jump to.
All registers and flags are passed to the target routine untouched.

Exit conditions:
All registers and flags are as set by the target routine.

Notes:
Calling PCDE INSTRUCTION is a useful way of invoking a routine whose
address has been picked out of a table or otherwise established at run time.

Related entries:
KL FAR PCHL
KL LOW PCHL
KL SIDE PCHL
PCBC INSTRUCTION
PCHL INSTRUCTION
LOW: FAR CALL RST3 #0018
Call subroutine in RAM or any ROM, takes inline address
of ‘far address’.
Action:
RST 3 is used to extend the instruction set. It is an expanded form of the CALL
instruction that allows routines to be called anywhere in RAM or in any ROM.
The restart is followed by the address of a 3 byte ‘far address’ which specifies
the location to call and the required ROM state and ROM selection.

Entry conditions:
All registers and flags are passed to the target routine untouched except for IY
(which is set to point at a background ROM’s upper data area).

Exit conditions:
IY preserved.
All other registers and flags are as set by the target routine.

Notes:
The restart instruction takes a 2 byte inline parameter which is the address of a
‘far address’. The ‘far address’ is laid out as follows:

Byte: 0 1 2

Address ROM

Bytes 0…1 give the address of the routine to call.


Byte 2 is the ROM select byte which takes values as follows:
#00.. #FB: Select the given ROM, enable upper, disable lower.
#FC: No change of ROM selection. enable upper, enable lower.
#FD: No change of ROM selection, enable upper, disable lower.
#FE: No change of ROM selection, disable upper, enable lower.
#FF: No change of ROM selection, disable upper, disable lower.
The reason that the ‘far address’ is not contained in the FAR CALL instruction
directly is because the ROM select byte for routines in ROM will depend upon
the particular configuration of expansion ROMs on the machine and must
therefore be established and set at run time.
Registers are passed to the target routine untouched except for the IY register.
When entering a background ROM this is set to point at the base of the ROM’s
upper data area. (See section 10.4 and KL INIT BACK).
The target routine returns to the instruction immediately following the inline
parameter. The ROM select and ROM state are restored to what they were
before the call. This is accomplished by pushing values on the stack and so
care should be taken when indexing up the stack after a FAR CALL
instruction. (The stack usage is 4 bytes for ROM select bytes in the range #FC..
#FF and 6 bytes for ROM select bytes in the range #00..#FB.)
Interrupts are enabled.

Related entries:
KL FAR ICALL
KL FAR PCHL
LOW JUMP (RST1)
SIDE CALL (RST2)
LOW: KL FAR PCHL #001B

Call subroutine in RAM or any ROM.


C and HL contain the ‘far address’ to call.

Action:
The far call mechanism allows subroutines to be called anywhere in RAM or in
any ROM. This routine takes a ‘far address’ and calls the given routine setting
the requested ROM state and ROM selection.

Entry conditions:
HL contains the address of the routine to call.
C contains the ROM select byte.
All registers and flags are passed to the target routine untouched except for
IY (which is set to point at a background ROM’s upper data area).

Exit conditions:
IY preserved.
All other registers and flags are as set by the target routine.

Notes:
The ROM select byte takes values as follows:
#00.. #FB: Select the given ROM, enable upper, disable lower.
#FC: No change of ROM selection, enable upper, enable lower.
#FD: No change of ROM selection. enable upper, disable lower.
#FE: No change of ROM selection. disable upper, enable lower.
#FF: No change of ROM selection. disable upper, disable lower.
Registers are passed to the target routine untouched except for the IY index
register. When entering a background ROM this is set to point at the base of
the ROM’s upper data area. (See section 10.4 and KL INIT BACK).
When the target routine returns, the ROM select and ROM state are restored to
what they were before the call. This is accomplished by pushing values onto
the stack and so care should be taken when indexing up the stack after using
this routine. (The stack usage is 4 bytes for ROM select bytes in the range
#FC.. #FF and 6 bytes for ROM select bytes in the range #00.. # FB.
Interrupts are enabled.

Related entries:
FAR CALL (RST3)
KL FAR ICALL
KL LOW PCHL
KL SIDE PCHL
LOW: PCHL INSTRUCTION #001E

Jump to address in HL.

Action:
Entry comprises a JP (HL) instruction (or PCHL in some assembler dialects).

Entry conditions:
HL contains the address to jump to.
All registers and flags are passed to the target routine untouched.

Exit conditions:
All registers and flags are as set by the target routine.

Notes:
Calling PCHL INSTRUCTION is a useful way of invoking a routine whose
address has been picked out of a table or otherwise established at run time.

Related entries:
KL FAR PCHL
KL LOW PCHL
KL SIDE PCHL
PCBC INSTRUCTION
PCDE INSTRUCTION
LOW: RAM LAM RST4 #0020

LD A,(HL) with all ROMs disabled.

Action:
RST 4 is used to extend the instruction set. It is equivalent to a LD A, (HL)
instruction except that it always reads from RAM irrespective of whether the
ROMs are enabled or not.

Entry conditions:
HL contains the address of the location to read.

Exit conditions:
A contains the value read from the given location.
All other registers and flags preserved.

Notes:
Writing to a location always writes to RAM, even if the location is in one of
the ROM areas and the ROM is enabled. The RAM LAM, RST 4, ‘instruction’
is the read equivalent.
Interrupts are enabled.

Related entries:
KL LDDR
KL LDIR
LOW: KL FAR ICALL #0023

Call subroutine in RAM or any ROM, HL points at ‘far


address’.

Action:
The far call mechanism allows subroutines to be called anywhere in RAM or in
any ROM. This routine takes the address of a ‘far address’ and calls the given
routine setting the ROM state and ROM se1ection required.

Entry conditions:
HL contains the address of the ‘f’ar address’ to call.
All registers and flags are passed to the target routine untouched except for
IY (which is set to point at a background ROM’s upper data area).

Exit conditions:
IY preserved.
All other registers and flags are as set by the target routine.

Notes:
The parameter passed is the address of a 3 byte ‘far address’. This is laid out as
follows:
Byte: 0 1 2

Address ROM

Bytes 0…1 give the address of the routine to call.


Byte 2 is the ROM select byte which takes values as follows:
#00.. #FB: Select the given ROM, enable upper, disable lower.
#FC: No change of ROM selection. enable upper, enable lower.
#FD: No change of ROM selection, enable upper, disable lower.
#FE: No change of ROM selection, disable upper, enable lower.
#FF: No change of ROM selection, disable upper, disable lower.
Registers are passed to the target routine untouched except for the IY index
register. When entering a background ROM this is set to point at the base of
the ROM’s upper data area. (See section 10.4 and KL INIT BACK).
When the target routine returns, the ROM select and ROM state are restored to
what they were before the call. This involves pushing values onto the stack and
so care should be taken in indexing up the stack after calling this routine. (The
stack usage is 4 bytes for ROM select bytes in the range #FC.. #FF and 6 bytes
for ROM select bytes in the range #00..#FB.)
Interrupts are enabled.

Related entries:
KL FAR CALL
KL FAR PCHL
LOW: FIRM JUMP RST5 #0028

Jump to lower ROM, takes inline address to jump to.

Action:
RST 5 is used to extend the instruction set. It is an expanded form of the jump
instruction for jumping to routines in the lower ROM or into the central 32K of
RAM. The restart is followed by the address of the routine to jump to.

Entry conditions:
All registers and flags are passed to the target routine untouched.

Exit conditions:
All registers and flags are as set by the target routine.

Notes:
The lower ROM is enabled before the jump is taken and is disabled (rather than
restored) when the target routine returns. Neither the upper ROM state nor the
ROM selection are changed. Two bytes are pushed onto the stack and so care
should be taken when indexing up the stack (to find the address of inline
parameters, for example).
It is assumed that the destination of the jump is a routine which will return in
the usual way. The restart instruction itself does not return, The value at top of
stack when a FIRM JUMP is executed must, therefore, be a return address.
The FIRM JUMP, RST 5, ‘instruction’ may replace the first byte of a JP
(jump) instruction, particularly injumpblocks, much like a LOW JUMP. A
FIRM JUMP is slightly faster than a LOW JUMP but a LOW JUMP is more
flexible in dealing with ROM states.
Interrupts are enabled.

Related entries:
LOW JUMP (RST1)
LOW: USER RESTART RST6 #0030

Undedicated RST instruction.

Action:
The eight bytes from #0030 to #0037 inclusive may be patched as required.

Entry conditions:
Unknown.

Exit conditions:
Unknown.

Notes:
If the lower ROM is disabled when an RST 6 instruction is executed then the
instructions patched into locations #0030 to #0037 are executed in the normal
way.
If the lower ROM is enabled when the RST 6 instruction is executed then the
firmware disables the lower ROM and jumps to #0030 to execute the
instructions planted by the user.
Generally the lower ROM is disabled except while the firmware is active.
Since there are no RST 6s in the firmware there should be no problem about
the ROM state when a RST 6 is executed. However, to cope with all
eventualities, if the lower ROM is found to be enabled when the restart is
executed then the ROM state before the lower ROM is disabled is saved in
location #002B. If the lower ROM is found to be disabled then location #002B
is left untouched. The value stored is suitable to be passed to KL ROM
RESTORE to re-enable the ROM (although KL L ROM ENABLE will have
the same effect).
The user can detect whether the lower ROM was enabled when the restart was
executed if location #002B is set to zero when the RST 6 area is patched and
after processing each restart. If #002B is zero when the RST 6 code is entered
then the lower ROM was disabled, and if it is non-zero then the lower ROM
was enabled.
The default action for RST 6 as set at power-up is to perform a RST 0, i.e. a
system reset.

Related entries:
None.
LOW:INTERRUPT ENTRY RST 7 #0038

Hardware interrupt entry point.

Action:
The Z80 runs in interrupt mode 1, which treats normal interrupts as RST 7
instructions. The firmware interrupt handler looks after the built in regular time
interrupt. External interrupts, generated by expansion hardware, are passed on
to user supplied software.

Entry conditions:
No conditions.

Exit conditions:
All registers and flags preserved.

Notes:
The user must not use RST 7s as these are dedicated to the processing of
interrupts.
If the interrupt is from an external source then the user supplied interrupt
routine, EXT INTERRUPT, is called.
See section 10 for a fuller discussion of interrupts.
The user may patch this area (#0038.. #003A inclusive) to intercept interrupts
if it is absolutely necessary (see Appendix XI, particularly section c).

Related entries:
EXT INTERRUPT
LOW: EXT INTERRUPT #003B

External interrupt routine.

Action:
The five bytes from # 003B to # 003F inclusive must be patched by the user if
there are going to be any external interrupts. When an external interrupt is
detected by the firmware interrupt handler the lower ROM is disabled and the
code at #OO3B is called.

Entry conditions:
No conditions.

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
When the routine is called interrupts are disabled and they must remain
disabled. Under no circumstances may the user enable interrupts or use the
second register set. Before the routine returns it must clear the interrupt source.
See section 11.2 for a discussion of external interrupts.
When an interrupt routine is set up the current contents of #003B.. #003F
should be copied elsewhere before they are replaced. If, when the routine is
called, it discovers that its hardware is not responsible for the interrupt then it
should jump to the copy of the previous external interrupt routine (whose
hardware may be responsible).
The purpose of an interrupt routine is to clear the interrupt as quickly as
possible, and perhaps perform a minimum of processing. While in the interrupt
path no further interrupts are acknowledged. If the interrupt generates a
substantial work load, then it should be translated into an event, so that the
system is not delayed in the interrupt path for any longer than necessary (see
section 11.3).
The interrupt routine must be in RAM at addresses lower than #C000 (as the
ROM enable and disable routines cannot be called from the interrupt path).
The default external interrupt routine merely returns. This means that the
interrupt will not be cleared and so it will repeat as soon as interrupts are re-
enabled. This will cause the machine to ‘lock up’.

Related entries:
INTERRUPT ENTRY
KL EVENT
19 AMSDOS BIOS Facilities
AMSDOS uses the CP/M BIOS to access the disc. In order that a program
running under AMSDOS may access the disc directly nine of the BIOS
extended jumpblock routines are available.
The routines are accessed as external commands. To find the address of the
required routines use KL FIND COMMAND. The command names are single
control characters (Ctrl A...Ctrl I) as these cannot be typed in from BASIC. An
example of how to use these commands can be found in section 10.7.
N.B. The BIOS extended jumpblock itself is not available, indeed it does not exist in an
AMSDOS environment.

The BIOS routines available and their command names are as follows:
SET MESSAGE Ctrl A (#01)
SET UP DISC Ctrl B (#02)
SELECT FORMAT Ctrl C (#03)
READ SECTOR Ctrl D (#04)
WRITE SECTOR Ctrl E (#05)
FORMAT TRACK Ctrl F (#06)
MOVE TRACK Ctrl G (#07)
GET DR STATUS Ctrl H (#08)
SET RETRY COUNT Ctrl I (#09)
The word at #BE40 contains the address of the disc parameter header vector.
Disc parameter headers and extended disc parameter blocks may be patched as
required. For more details on this see section 9.9.
When one of these routines fails (carry false) it returns an error number in the
A register. This is referred to in the following pages as the ‘error status byte’. If
bit 7 of this byte is set then the error has already been reported to the user. Bit 6
is used to distinguish errors generated by the floppy disc controller from those
generated by AMSDOS.
If bit 6 is zero then the error numbers are as follows:
#0E the file is not open as expected.
#0F hard end of file.

#10 bad command, usually caused by an incorrect filename.


#11 file already exists.
#12 file doesn’t exist.
#13 directory is full.
#14 disc is full.
#15 disc has been changed with files open on it.
#16 file is read-only.

# 1A soft end of file (explained in Appendix XIII).

Also V1.1 machines have error #00


#00 user has hit escape.

If bit 6 is one then the error was detected by the floppy disc controller and the
other bits are returned as follows:

bit 5 data error - CRC error on data or ID field


bit 4 overrun error
bit 3 drive not ready - there is no disc in the drive
bit 2 no data - can’t find the sector
bit 1 not writable - disc is write protected
bit 0 address mark missing
In addition the routine may also return the address of the ‘error status buffer’.
The first byte of this is a count of the number of bytes received during the
results phase of the µPD765A disc controller, the following bytes are those
received. For information on the meaning of these bytes see the manufacturer’s
documentation.

On the following pages are the interfaces to the intercepted routines:


BIOS: SET MESSAGE (CTRL/A)

Enable or disable the disc error messages.

Action:
When disc error messages are enabled and an error occurs the BIOS will
display error messages on the screen and interact with the user. When disabled
no messages are displayed.

Entry conditions:
If messages are to be enabled:
A = #00
If messages are to be disabled:
A = #FF

Exit conditions:
A contains previous state.
HL and flags corrupt.
All other registers preserved.

Notes:
The default state is ENABLED.

Related entries:
SET RETRY COUNT
BIOS: SETUP DISC (CTRL/B)

Set disc parameters.

Action:
Sets the values for the motor on, motor off, write current off and head settle
times. Sends a SPECIFY command to the floppy disc controller.

Entry conditions:
HL contains address of parameter block
Format of the parameter block:
bytes 0, 1 motor on timeout in 20 millisecond units.
bytes 2, 3 motor off timeout in 20 millisecond units.
byte 4 write current off time in 10 microsecond units.
byte 5 head settle time in 1 millisecond units.
byte 6 step rate time in 1 millisecond units.
byte 7 head unload delay (as per µPD765A SPECIFY
command).
byte 8 bits 7…1: head load delay, bit 0: non-DMA mode (as
per µPD765A SPECIFY command).

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
The values given are used for both drives. When using two differing drives use
the slower of the two times.
The default values are:
motor on timeout 50
motor off timeout 250
write current off time 175
head settle time 15
step rate time 12
head loadtime 1
head unload time 1
non-DMA mode 1
A motor on time of zero will lock the system up. A motor off time of zero will
never turn the motor off.
The standard boot program calls this routine to reset some of the disc
parameters as specified in the configuration sector, that is, motor on and off
timeouts and the step rate.

Related entries
SELECT FORMAT
SET RETRY COUNT
BIOS: SELECT FORMAT (CTRL/C)

Select a disc format.

Action:
This routine initializes the extended disc parameter block for the given format.
Normally the BIOS automatically detects the format of a disc when SELDSK
is called by looking at the sector numbers, but for programs such as formatters
it is necessary to pre-set the format.

Entry conditions:
A contains first sector number of required format
#41 ⇒ system format
#C1 ⇒ data only format
#01 ⇒ IBM format
E contains drive number:
#00 ⇒ A:
#01 ⇒ B:

Exit conditions:
AF, BC, DE and HL corrupt.
All other registers preserved.

Notes:
Bytes 0...21 of the extended disc parameter block are completely reset, all
previous values are lost. Bytes 22...24 (track, align flag, auto-select flag) are
not affected. See chapter 2.15.
To set a non-standard format the user may patch the extended disc parameter
block directly.
BIOS: READ SECTOR (CTRL/D)

Read a sector from disc.

Action:
Read the specified sector into store.

Entry conditions:
HL contains address of sector buffer
E contains drive number
#00 ⇒ A:
#01 ⇒ B:
D contains track number
C contains sector number

Exit conditions:
If sector read OK:

Carry true.
A contains 0
HL preserved

If failed to read sector correctly:

Carry false.
A contains error status byte (as defined above).
HL contains address of error status buffer.

Always:

Other flags corrupt.


All other registers preserved.

Notes:
The sector buffer may lie anywhere in RAM, even under a ROM.

Related entries:
WRITE SECTOR
BIOS: WRITE SECTOR (CTRL/E)

Write a sector to disc.

Action:
Write the required sector from store.

Entry conditions:
HL contains address of sector buffer
E contains drive number
#00 ⇒ A:
#01 ⇒ B:
D contains track number
C contains sector number

Exit conditions:
If sector written OK:
Carry true.
A contains 0.
HL preserved.
If failed to write sector correctly:
Carry false.
A contains error status byte as defined above.
HL contains address of error status buffer.
Always:
Other flags corrupt.
All other registers preserved.

Notes:
The sector buffer maybe anywhere in RAM, even underneath a ROM.

Related entries:
READ SECTOR
BIOS: FORMAT TRACK (CTRL/F)

Format an entire track.

Action:
Format a track.

Entry conditions:
HL contains address of header information buffer
E contains drive number
#00 ⇒ A:
#0l ⇒ B:
D contains track number
Format of header information:
sector entry for first sector
sector entry for second sector

sector entry for last sector

sector entry format:


byte 0: track number
byte 1: head number
byte 2 : sector number
byte 3 : log 2 (sector size) - 7

Exit conditions:
If track formatted OK:
Carry true.
A contains 0.
HL preserved.
If failed to format track correctly:
Carry false.
A contains error status byte as defined above.
HL contains address of error status buffer.
Always:
Other flags corrupt.
All other registers preserved.
Notes:
The extended DPB must be preset for the required format (see SELECT
FORMAT).

Related entries:
SELECT FORMAT
BIOS: MOVE TRACK (CTRL/G)

Move to specified track.

Action:
Move head to specified track without verifying the move.

Entry conditions:
E contains drive number
#00 ⇒ A:
#01 ⇒ B:
D contains track number

Exit conditions:
If moved to the track OK:
Carry true.
A contains 0.
HL preserved.
If failed to move to the track:
Carry false.
A contains error status byte as defined above
HL contains address of error status buffer
Always
Other flags corrupt.
All other registers preserved.

Notes:
This routine is intended as a diagnostic aid and need not normally be used
because the read/write/format routines all seek to the correct track
automatically.

Related entries:
None.
BIOS: GET DR STATUS (CTRL/H)

Return status for specified drive.

Action:
This routine returns status register 3 of the floppy disc controller as defined
below for the specified drive.
bit 7 undefined
bit 6 write protect - The write protect line is true.
bit 5 drive ready - The ready line is true.
bit 4 track zero - The track zero line is true.
bit 3 undefined
bit 2 head address - always zero.
bit 1 unit select 1 - unit select 1, always zero.
bit 0 unit select 0 - currently selected drive.

Entry conditions:
A contains drive number
#00 ⇒ A:
#01 ⇒ B:

Exit conditions:
If carry true
A contains Drive status byte as defined above
HL preserved
If carry false
HL contains address of error status buffer, second byte = Drive status byte
as defined above
A corrupt
Always
Other flags corrupt
All other registers preserved

Notes
This routine returns carry to indicate which set of exit conditions have
occurred. No other meaning should be attached to the state of carry.

Related entries:
SELECT FORMAT
READ SECTOR
WRITE SECTOR
FORMAT TRACK
MOVE TRACK
BIOS: SET RETRY COUNT (CTRL/I)

Set the number of retries for reading/writing/formatting.

Action:
Sets the number of times an operation is retried in the event of an error.

Entry conditions:
A contains new value for retry count

Exit conditions:
A contains old value of retry count.
HL and flags corrupt.
All other registers preserved.

Notes:
The pattern of retries is as follows. Each ‘Try’ counts one. The retry pattern is
repeated until either the operation succeeds or the number of tries has reached
the retry count:
Try
Try
Move in one track and back again
Try
Move out one track and back again
Try
Move to inner track and back again
Try
Try
Move in one track and back again
Try
Move out one track and back again
Try
Move to outer track and back again
Repeat
The default value is 16, i.e. twice around the above loop.

Related entries:
READ SECTOR
WRITE SECTOR
FORMAT TRACK
Appendix I
Key Numbering.
The various tables in the Key Manager, such as the translation tables or the
repeating key table, are all accessed by key number. The numbering of the keys
(and joysticks) is given in the following diagrams:
Note that the physical layout of the 6128 keyboard differs from the 464 and 664
keyboards but that the keys with the same key numbers have the same symbols
on the keytops and generate the same values. The keys that have moved are
marked with an asterisk.

464/664 Main Keyboard

6128 Main Keyboard/Function/Numeric Keypad


464/664 Function/Numeric Keypad 4641664 Cursor Keys

464/664/6128 Joysticks

Note that joystick 1 overlays keys 48..53 on the main keyboard and is
indistinguishable from them.
The following table translates key numbers in the opposite direction, from the
key number to the inscription on the keytop. Where there is a symbol on the
keytop an appropriate word is used, RIGHT for the right cursor key for
example. Brackets around the inscription are used to distinguish the various
areas of the keyboard as
follows:
{..} Function key (numeric keypad)
(..) Joystick 0.
[..] Joystick 1.

0 1 2 3 4 5 6 7

0 UP RIGHT DOWN {9} {6} {3} {ENTER} {.}

8 LEFT COPY {7} {8} {5} {1} {2} {0}

16 CLR [ ENTER ] {4} SHIFT \ CTRL

24 ↑ - @ P ; : / .

32 0 9 O I L K M ,

40 8 7 U Y H J N SPACE

48 6 5 R T G F B V

[UP] [DOWN] [LEFT] [RIGHT] [FIRE2] [FIRE1] [SPARE]

56 4 3 E W S D C X

64 1 2 ESC Q TAB A CAPS Z

72 (UP) (DOWN) (LEFT) (RIGHT) (FIRE2) (FIRE1) (SPARE) DEL


Appendix II
Key Translation Tables.

See section 3, and section 3.2 in particular, for a description of key translation.
Also, Appendix I, which gives the key numbering scheme, maybe of interest.
The diagrams given in this Appendix are for the 464 and 664 keyboards. The
6128 keyboard is similar but some keys have been moved.The new location of
the keys can be deduced by inspecting Appendix I.
There are three keyboard translation tables used. These convert a key into its
associated character or token. One table is used to translate keys when the
control key is pressed, one is used to translate keys when the shift key is
pressed or the shift lock is on but the control key is not pressed, the last is used
to translate keys when neither shift nor control is pressed.
The diagrams following describe the default translation tables. Where possible
the correct character has been placed on the key. The actual value for each of
these characters can be found in Appendix VI on the character set. In the cases
where the key produces a value which is not a printable ASCII character the
abbreviations in the following table will be used. The default settings of the
expansion tokens are given in Appendix IV.

Characters and Codes.

NUL #00 ASCII control code.


SOH #01 ASCII control code.
STX #02 ASCII control code.
ETX #03 ASCII control code.
EOT #04 ASCII control code.
ENQ #05 ASCII control code.
ACK #06 ASCII control code.
BEL #07 ASCII control code.
BS #08 ASCII control code.
HT #09 ASCII control code.
LF #0A ASCII control code.
VT #0B ASCII control code.
FF #0C ASCII control code.
CR #0D ASCII control code.
SO #0E ASCII control code.
SI #0F ASCII control code.
DLE #10 ASCII control code.
DC1 #11 ASCII control code.
DC2 #12 ASCII control code.
DC3 #13 ASCII control code.
DC4 #14 ASCII control code.
NAK #15 ASCII control code.
SYN #16 ASCII control code.
ETB #17 ASCII control code.
CAN #18 ASCII control code.
EM #19 ASCII control code.
SUB #1A ASCII control code.
ESC #1B ASCII control code.
FS #1C ASCII control code.
GS #1D ASCII control code.
RS #1E ASCII control code.
US #1F ASCII control code.

SPACE #20 ASCII space character.


UP #5E Up arrow.

DEL #7F ASCII code.

LB #A3 Pound character.

Expansion Tokens.
FO #80 Function key 0.
Fl #81 Function key l.
F2 #82 Function key 2.
F3 #83 Function key 3.
F4 #84 Function key 4.
F5 #85 Function key 5.
F6 #86 Function key 6.
F7 #87 Function key 7.
F8 #88 Function key 8.
F9 #89 Function key 9.
F. #8A Function key full stop.
FEN #8B Function key enter without control pressed.
FRUN #8C Function key enter with control pressed.

Edit and Cursor Codes.

COPY #E0 Copy key.


INS #El Insert/overwrite toggle key.

WUP #F0 Write cursor up.


WDN #Fl Write cursor down.
WLT #F2 Write cursor left.
WRT #F3 Write cursor right.

RUP #F4 Read cursor up.


RDN #F5 Read cursor down.
RLT #F6 Read cursor left.
RRT #F7 Read cursor right.

BEG #F8 Write cursor to start of text.


END #F9 Write cursor to end of text.
STA #FA Write cursor to start of line.
FIN #FB Write cursor to end of line.

System Tokens.

BRK #FC Breakkeytoken.


CAPS #FD Capslocktoggletoken.
SHIFT #FE Shiftlocktoggletoken.
#FF Ignore.

Keys that are not marked in the diagrams following generate the system ignore
token, if #FF.
Normal Translation Table.
The following diagram describes the translation when neither shift nor control
is pressed.

Main Keyboard

Function/Numeric Keypad
Cursor Keys
Shift Translation Table.
The following diagram describes the translation when either shift key is
pressed, or the shift lock is on, but the control key is not pressed.

Main Keyboard

Function/Numeric Keypad Cursor Keys

JOYSTICK 0 JOYSTICK 1
Control Translation Table.
The following diagram describes the translation when the control key is
pressed.

Main Keyboard

Function/Numeric Keypad Cuxsor Keys

JOYSTICK 0 JOYSTICK 1
Appendix III
Repeating Keys.
Which keys are allowed to repeat may be set by the user. See section 3 (and
section 3.5 in particular) for a full description of repeating keys. Also, see
Appendix I which gives the key numbering scheme and indicates which keys
have moved on the 6128 keyboard.
The default repeating key table is described in the following diagrams. Keys
which are not allowed to repeat are marked with an asterisk.

Main Keyboard

Function/Numeric Keypad Cursor Keys

JOYSTICK 0 JOYSTICK 1
Appendix IV
Function Keys and Expansion
Strings.
Function keys are more fully explained in section 3, and in section 3.7 in
particular. The following table specifies the default string for each expansion
token and which key the token is associated with by default.

Token Value Default String Default Key

0 #80 0 Function Key 0.


1 #81 1 Function Key 1.
2 #82 2 Function Key 2.
3 #83 3 Function Key 3.
4 #84 4 Function Key 4.
5 #85 5 Function Key 5.
6 #86 6 Function Key 6.
7 #87 7 Function Key 7.
8 #88 8 Function Key 8.
9 #89 9 Function Key 9.
10 #8A . Function Key full stop.
11 #8B ↵ Function Key enter.
12 #8C RUN ” ↵ Function Key enter with control.
13..31 #8D..#9F None.

Tokens 13..31 are all set to empty strings and none of them are defaulted to
associate with a key.
↵ stands for carriage return (Character #0D)
Appendix V
Inks and Colours.

A full discussion of inks and colours can be found in section 6.2. This appendix
lists the colours that are available and the default settings for the inks.

There are 27 colours available. The Screen Pack refers to these colours by a
grey scale number so that colour 0 is the darkest and colour 26 is the brightest.
The hardware requires these grey scales to be translated into the hardware code
for the colour. It is unlikely that the user will ever need to deal with the
hardware numbers, they are merely given for information.

Grey Scale Colour HW Number

0 Black 20
1 Blue 4
2 Bright blue 21
3 Red 28
4 Magenta 24
5 Mauve 29
6 Bright red 12
7 Purple 5
8 Bright magenta 13
9 Green 22
10 Cyan 6
11 Skyblue 23
12 Yellow 30
13 White 0
14 Pastel blue 31
15 Orange 14
16 Pink 7
17 Pastel magenta 15
18 Bright green 18
19 Sea green 2
20 Bright cyan 19
21 Lime 26
22 Pastel green 25
23 Pastel cyan 27
24 Bright yellow 10
25 Pastel yellow 3
26 Bright white 11
The user can set the colours in which the 16 inks and the border are displayed.
The following table gives the default settings:

Ink Colour Colour Numbers

Border Blue 1/1


0 Blue 1/1
1 Bright yellow 24/24
2 Bright cyan 20/20
3 Bright red 6/6
4 Bright white 26/26
5 Black 0/0
6 Bright blue 2/2
7 Bright magenta 8/8
8 Cyan 10/10
9 Yellow 12/12
10 Pastel blue 14/14
11 Pink 16/16
12 Bright green 18/18
13 Pastel green 22/22
14 Flashing blue / bright yellow 1/24
15 Flashing sky blue / pink 11/16
Appendix VI
Displayed Character Set.

There are 256 symbols in the displayed character set. All of these can be
printed, although it requires special effort to print characters 0. .31 which are
often interpreted as control codes. The user can set the matrix for any or all
characters (see section 4.6). The following lists describe the default character
set.

The character set is split into a number ofareas for ease of description:

0..31 (#00.. # 1F) ASCII control codes.


32..127 (#20.. #7F) ASCII characters.
128..143 (#80.. #8F) Block graphics.
144..159 (#90..#9F) Line graphics.
160..191 (#A0.. #BF) Further characters.
192..255 (#C0.. #FF) Miscellaneous graphic symbols.

a. ASCII Control Codes.

0 #00 NUL Square.


1 #01 SOH Upside down L.
2 #02 STX Upside down T.
3 #03 ETX BackwardsL.
4 #04 EOT Lightning flash.
5 #05 ENQ Square with a diagonal cross.
6 #06 ACK Tick.
7 #07 BEL Bell (semi-circle with feet).
8 #08 BS Left pointing arrow.
9 #09 HT Rightpointing arrow.
10 #0A LF Downpointingarrow.
11 #0B VT Uppointingarrow.
12 #0C FF Christmas tree (down pointing arrow with a tail).
13 #0D CR Bentleftpointingarrow.
14 #0E SO Circle with a diagonal cross.
15 #0F SI Circle with a central dot.
16 #10 DLE Square with a horizontal bar.
17 #11 DC1 Circle with three o’clock.
18 #12 DC2 Circle with half past three.
19 #13 DC3 Circle with half past nine.
20 #14 DC4 Circle with nine o’clock.
21 #15 NAK Crossed out tick.
22 #16 SYN Square wave.
23 #17 ETB Sideways T.
24 #18 CAN Hourglass.
25 #19 EM Vertical bar with a central blob.
26 #1A SUB Backwards question mark.
27 #1B ESC Circle with a horizontal bar.
28 #1C FS Square with nine o’clock.
29 #1D GS Square with half past nine.
30 #1E RS Square with half past three.
31 #1F US Square with three o’clock.

b. ASCII Characters.

Characters 32.127 ( #20.. #7F are listed in the following table. They make up the
standard ASCII character set.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 2 3 4 5 6 7 8 9 A B C D E F

32 #20 ! " # $ % & ‘ ( ) * + , - . /

48 #30 0 1 2 3 4 5 6 7 8 9 : ; < = > ?

64 #40 @ A B C D E F G H I J K L M N O

80 #50 P Q R S T U V W X Y Z [ \ ] ↑ -

96 #60 a b c d e f g h I j k l m n o

112 #70 p q r s t u v w x y z { | } ~ ¦
c. Block Graphics.

Characters 128..143 (#80..#8F) are a set of block graphics. Each character is


divided into four cells. Bits 0..3 of the character number determine which cells
are filled. If the appropriate bit is set then the cell is filled in, otherwise it is left
blank. The cells are:

Bit 0 Bit 1

Bit 2 Bit 3

In the following list cells that are filled are marked with an cells that are
blank are marked with an open square.

128 #80 Block graphic

129 #81 Block graphic

130 #82 Block graphic

131 #83 Block graphic

132 #84 Block graphic

133 #85 Block graphic

134 #86 Block graphic

135 #87 Block graphic

136 #88 Block graphic

137 #89 Block graphic

138 #8A Block graphic

139 #8B Block graphic

140 #8C Block graphic

141 #8D Block graphic

142 #8E Block graphic

143 #8F Block graphic


d. Line Graphics

Characters 144..159 (#90..#9F) are a set of line graphics. The lines join the
centre of the character to the centre of an edge. Each of the lines is associated
with a bit of the character number. If the bit is set then the line is present, if the
bit is not set then the line is not present. The central block of the character is
always set.

The lines are associated with bits as follows:

144 #90 Line graphic


145 #91 Line graphic
146 #92 Line graphic
147 #93 Line graphic
148 #94 Line graphic
149 #95 Line graphic
150 #96 Line graphic
151 #97 Line graphic
152 #98 Line graphic
153 #99 Line graphic
154 #9A Line graphic
155 #9B Line graphic
156 #9C Line graphic
157 #9D Line graphic
158 #9E Line graphic
159 #9F Line graphic
e. Further Characters.
160 #A0 Circumflex

161 #A1 Acute accent

162 #A2 Umlaut

163 #A3 Pound

164 #A4 Copyright

165 #A5 Pilcrow

166 #A6 Section

167 #A7 Open single quote (pairs with character 39)

168 #A8 One quarter

169 #A9 One half

170 #AA Three quarters

171 #AB Plus or minus

172 #AC Division

173 #AD Not

174 #AE Inverted question mark

175 #AF Inverted exclamation mark

176 #B0 Lower case alpha

177 #B1 Lower case beta

178 #B2 Lower case gamma

179 #B3 Lower case delta


180 #B4 Lower case epsilon

181 #B5 Lower case theta

182 #B6 Lower case lambda

183 #B7 Lower case mu

184 #B8 Lower case pi

185 #B9 Lower case sigma

186 #BA Lower case phi

187 #BB Lower case psi

188 #BC Lower case chi

189 #BD Lower case omega

190 #BE Upper case sigma

191 #BF Upper case omega

f. Miscellaneous Graphics Symbols.

192 #C0 Diagonal line joining top to left.

193 #C 1 Diagonal line joining top to right.

194 #C2 Diagonal line joining bottom to right.

195 #C3 Diagonal line joining bottom to left.

196 #C4 Diagonal lines joining top to left and right.

197 #C5 Diagonal lines joining right to top and bottom.

198 #C6 Diagonal lines joining bottom to right and left.

199 #C7 Diagonal lines joining left to top and bottom.

200 #C8 Diagonal lines joining top to left and bottom to right.

201 # C9 Diagonal lines joining top to right and bottom to left.

202 # CA Diamond joining all edges.


203 #CB Both major diagonals (Large X)

204 #CC Forwards major diagonal (Large slash)

205 #CD Backwards major diagonal (large backslash)

206 #CE Chequered pattern

207 #CF Shading

208 #DO Line along top edge

209 #D1 Line along right edge

210 #D2 Line along bottom edge

211 #D3 Line along left edge

212 #D4 Triangle filling top left corner

213 #D5 Triangle filling top right corner

214 #D6 Triangle filling bottom right corner

215 #D7 Triangle filling bottom left corner

216 #D8 Top half shaded

217 #D9 Right half shaded

218 #DA Bottom half shaded

219 #DB Left half shaded

220 #DC Shaded triangle filling top left corner

221 #DD Shaded triangle filling top right corner

222 #DE Shaded triangle filling bottom right corner

223 #DF Shaded triangle filling bottom left corner

224 #E0 Happy face

225 #E1 Sad face

226 #E2 Club


227 #E3 Diamond

228 #E4 Heart

229 #E5 Spade

230 #E6 Empty circle

231 #E7 Filled circle

232 #E8 Empty square

233 #E9 Filled square

234 #EA Male (Mars).

235 #EB Female (Venus).

236 #EC Crochet

237 #ED Quaver

238 #EE Star

239 #EF Rocket

240 #F0 Up pointing arrow head

241 #F1 Down pointing arrow head

242 #F2 Left pointing arrow head

243 #F3 Right pointing arrow head

244 #F4 Up pointing triangle

245 #F5 Down pointing triangle

246 #F6 Right pointing triangle

247 #F7 Left pointing triangle

248 #F8 Dancing person standing

249 #F9 Dancing person doing splits

250 #FA Dancing person with left leg out


251 #FB Dancing person with right leg out
252 #FC Bomb

253 #FD Mushroom cloud

254 #FE Up and down arrow

255 #FF Right and left arrow


Appendix VIII
Notes and Tone Periods.

The tables which follow give the recommended tone period settings for notes in
the even tempered scale for the full eight octave range. The period is calculated
from the note frequency as follows (since the period is given in 8 microsecond
units):

Period = 125000/Frequency
The frequency for each note is calculated from International A as follows:

Frequency = 440 * (2 ^ (Octave + (N - 10) / 12))


where:

Octave is the octave number. 0 is the octave including International A


(and middle C), -1 is the octave below, + 1 is the octave above
etc.
N is the note number. 1 is C, 2 isC#, 3 is D etc.
The period is an integer value and so the frequency of the note produced is not
exactly the required frequency. The relative error is given in the tables below.
This is calculated as follows:

Error = (Required frequency - Actual frequency) / Required frequency

Note Frequency Period Error Octave -3

C 32.703 3822 #0EEE -0.007%


C# 34.648 3608 #0E18 +0.007%
D 36.708 3405 #0D4D -0.007%
D# 38.891 3214 #0C8E -0.004%
E 41.203 3034 #0BDA +0.009%
F 43.654 2863 #0B2F -0.016%
F# 46.249 2703 #0A8F +0.009%
G 48.999 2551 #09F7 -0.002%
G# 51.913 2408 #0968 +0.005%
A 55.000 2273 #08E1 +0.012%
A# 58.270 2145 #0861 -0.008%
B 61.735 2025 #07E9 +0.011%
Note Frequency Period Error Octave -2

C 65.406 1911 #0777 -0.007%


C# 69.296 1804 #070C +0.007%
D 73.416 1703 #06A7 +0.022%
D# 77.782 1607 #0647 -0.004%
E 82.407 1517 #05ED +0.009%
F 87.307 1432 #0598 +0.019%
F# 92.499 1351 #0547 -0.028%
G 97.999 1276 #04FC +0.037%
G# 103.826 1204 #04D4 +0.005%
A 110.000 1136 #0470 -0.032%
A# 116.541 1073 #0431 +0.039%
B 123.471 1012 #03F4 -0.038%

Note Frequency Period Error Octave -1

C 130.813 956 #O3DC +0.046%


C# 138.591 902 #0386 +0.007%
D 146.832 851 #0353 -0.037%
D# 155.564 804 #0324 +0.058%
E 164.814 758 #02F6 -0.057%
F 174.614 716 #02CC +0.019%
F# 184.997 676 #02A4 +0.046%
G 195.998 638 #027E +Ø.Ø37%
G# 207.652 602 #025A +0.005%
A 220.000 568 #0238 -0.032%
A# 233.082 536 #0218 -0.055%
B 246.942 506 #O1FA -0.038%
Note Frequency Period Error Octave 0

C 261.626 478 #01DE +0.046% Middle C


C# 277.183 451 #01C3 +0.007%
D 293.665 426 #01AA +0.081%
D# 311.127 402 #0192 +0.058%
E 329.628 379 #017B -0.057%
F 349.228 358 #0166 +0.019%
F# 369.994 338 #0152 +0.046%
G 391.995 319 #013F +0.037%
G# 415.305 301 #012D +0.005%
A 440.000 284 #011C -0.032% International A
A# 466.164 268 #010C -0.055%
B 493.883 253 #00FD -0.038%

Note Frequency Period Error Octave 1

C 523.251 239 #00EF +0.046%


C# 554.365 225 #0E1 -0.215%
D 587.330 213 #00D5 +0.081%
D# 622.254 201 #00C9 +0.058%
E 659.255 190 #0BE +0.206%
F 698.457 179 #00B3 +0.019%
F# 739.989 169 #00A9 +0.046%
G 783.991 159 #009F -0.277%
G# 830.609 150 #0096 -0.328%
A 880.000 142 #008E -0.032%
A# 932.328 134 #0086 -0.055%
B 987.767 127 #007F +0.356%
Note Frequency Period Error Octave 2

C 1046.502 119 #0077 -0.374%


C# 1108.731 113 #0071 +0.229%
D 1174.659 106 #006A -0.390%
D# 1244.508 100 #0064 -0.441%
E 1318.510 95 #005F +0.206%
F 1396.913 89 #0059 -0.543%
F# 1479.978 84 #0054 -0.548%
G 1567.982 80 #0050 +0.350%
G# 1661.219 75 #004B -0.328%
A 1760.000 71 #0047 -0.032%
A# 1864.655 67 #0043 -0.055%
B 1975.533 63 #003F -0.435%

Note Frequency Period Error Octave 3

C 2093.004 60 #003C +0.462%


C# 2217.461 56 #0038 -0.662%
D 2349.318 53 #0035 -0.390%
D# 2489.016 50 #0032 -0.441%
E 2637.021 47 #002F -0.855%
F 2793.826 45 #002D +0.574%
F# 2959.955 42 #002A -0.548%
G 3135.963 40 #0028 +0.350%
G# 3322.438 38 #0026 +0.992%
A 3520.000 36 #2924 +1.357%
A# 3729.310 34 #0022 +1.417%
B 3951.066 32 #0020 +1.134%
Note Frequency Period Error Octave 4

C 4186.009 30 #001E +0.462%


C# 4434.922 28 #001C -0.662%
D 4698.636 27 #001B +1.469%
D# 4978.032 25 #0019 +1.441%
E 5274.041 24 #0018 +1.246%
F 5587.652 22 #0016 -1.685%
F# 5919.911 21 #0015 -0.548%
G 6271.927 20 #0014 +0.350%
G# 6644.875 19 #0013 +0.992%
A 7040.000 18 #0012 +1.357%
A# 7458.621 17 #0011 +1.417%
B 7902.133 16 #0010 +1.134%

The notes in the scale of C major are given in a slightly more digestible form
below.
Appendix IX
The Programmable Sound
Generator.

The programmable sound generator (PSG) is an AY-3-8912 chip. This is


briefly described in section 7.1. The PSG has a number of registers which are
described below. This information is provided for the interest of the user,
particularly if hardware enveloping is to be used (in which case section (e) will
be of special interest). However, the software enveloping provided by the
Sound Manager can achieve all that the sound chip is capable of unless very
short attacks or decays are required.
If the user is intending to drive the sound chip directly rather than by using the
Sound Manager then the information presented is not complete and the user
should consult the manufacturer’s data sheet. The user is advised to call the
routine MC SOUND REGISTER to write data to a sound chip register as this
obeys the timing constraints on access to the sound chip.
The following diagram indicates the interactions between the various sections
of the sound chip:

Envelope Tone I/O


Generator Generators Enables Port
(R11..R13) (R0..R5) (R7) (R14)

Amplitude Digital to Noise


Controls Analogue Generator
(R8..R10) Converters (R6)

Outputs
The sound chip data registers are as follows:

Register 0: Channel A tone period fine tune.


Register 1: Channel A tone period coarse tune.
Register 2: Channel B tone period fine tune.
Register 3: Channel B tone period coarse tune.
Register 4: Channel C tone period fine tune.
Register 5: Channel C tone period coarse tune.
Register 6: Noise period.
Register 7: Enables and I/O direction.
Register 8: Channel A amplitude and envelope enable.
Register 9: Channel B amplitude and envelope enable.
Register 10: Channel C amplitude and envelope enable.
Register 11: Envelope period fine tune.
Register 12: Envelope period coarse tune.
Register 13: Envelope shape.
Register 14: Input from or output to port A.
Register 15: Not used.

a. Tone Generators (Registers O..5)


Each channel has two tone period registers associated with it. These set the
period of the sound to be generated (in units of 8 microseconds) by that
channel. The fine tune register stores the least significant 8 bits of the period;
the coarse tune register stores the most significant 4 bits of the period. To
include the tone in the output of a channel the appropriate bit in the enables
register must be cleared.

b. Noise Generator (Register 6).

There is a single pseudo-random noise source. The output from this can be
included in the output of any of the three channels (as specified by the enables
register). The period of the noise generator is set by bits 0..4 of the noise period
register. The period specifies the middle frequency of the noise produced in 8
microsecond units.

c. Enables (Register 7).


The enables register specifies whether tone or noise is to be included in the
output from each channel. It also specifies whether the I/O port is to act in
input or in output mode. The bits are allocated as follows:

Bit 0: Channel A tone disable.


Bit 1: Channel B tone disable.
Bit 2: Channel C tone disable.
Bit 3: Channel A noise disable.
Bit 4: Channel B noise disable.
Bit 5: Channel C noise disable.
Bit 6: Port A output mode.
Bit 7: Not used.
Note that port A is connected to the keyboard and joystick and so the port must
always be in input mode. The user must ensure that bit 6 of the enables register
is always set to zero.

d. Amplitude Controls (Registers 8.. 10).


Each channel has an amplitude control register associated with it. Bit 4 of this
register specifies whether hardware enveloping is to be used for the channel. If
the bit is set then the channel amplitude (volume) is under the control of the
hardware envelope generator. If the bit is clear then the amplitude is set by bits
0. .3 of the register - a value of 0 means no sound and a value of 15 means
maximum volume.

e. Envelope generator (Registers 1 1..13).

The sound chip has a single hardware envelope generator which can be used to
control any combination of the three sound channels as specified by the
channel’s amplitude register (see (d) above). Bits 0 to 3 of register 13 control
the shape of the envelope in a rather unobvious manner. The following table
gives values required to generate each of the 8 hardware envelopes that are
possible. Other values (0. .7) duplicate envelopes 9 and 15.

8: Repeated jump up and ramp down.

9: Jump up and ramp down once then hold at minimum


volume (zero).

10: Jump up then repeatedly ramp down and up again.

11: Jump up and ramp down then jump up and hold at


maximum volume (fifteen).

12: Repeatedly ramp up and drop down.


13: Ramp up then hold at maximum volume (fifteen)

14: Repeatedly ramp up and down again.

15: Ramp up and drop down once then hold at


minimum volume (zero).

The length of each of the ramps, upwards or downwards, is set by the envelope
period. The envelope period is a full 16 bit value whose less significant byte is
stored in register 11 and whose more significant byte is stored in register 12.
The period is given in 128 microsecond units and is the time between steps in
the ramp. Since the ramp has 16 steps (corresponding to the 16 volume
settings) the total time taken for the ramp is the envelope period times 1024
microseconds (i.e. the envelope period approximately sets the total time for the
ramp in milliseconds).

f. I/O Port (Register 14).

The mode of operation of the PSG port is set by a bit in the enables register
(see section (c) above). However, since port A is dedicated to reading the
keyboard and joysticks it should always be operated in input mode. The port
may be read by reading the contents of register 14. However, scanning the
keyboard is a complex action and is best left to the Key Manager which
provides ample facilities for access to the keys.
References to port B in the manufacturer’s data sheet should be ignored as the
AY-3-8912 is a version of the chip that does not have port B.
Appendix X
Kernel Block Layouts.
The user provides a number of blocks to the Kernel for various puposes. The
layouts of these blocks are described below, mainly for the interest of the user.
There are very few occasions when the user is allowed to write to one of these
blocks. Routines are provided to perform most actions that the user could wish
to perform (see KL INIT EVENT, KL ADD TICKER, KL NEW FRAME
FLY, KL NEW FAST TICKER and KL DISARM EVENT). These routines set
values into the block from registers. The user should not write to the blocks,
except as noted below.

All the following blocks must lie in the central 32K of RAM (otherwise the
Kernel will be unable to access them).

On the CPC6128 the user is advised to keep these blocks in RAM block 2 if
any bank switching is being performed (see section 2.5).

a. Event Blocks.
See section 12 for a general discussion of events and event blocks. An event
block is laid out as follows:

0,1: Chain

2: Count

3: Class

4,5: Routine address

6: ROM

7+: User fields

Chain is a system pointer which must never be written to by the user. It is used
to store events on the various event queues.

Class records the type of the event. It should not be written to by the user.

Bit 0: 1 = Near address, 0 = Far address.


Bits 1..4: Synchronous event priority.
Bit5: Must be zero.
Bit 6: 1 = Express event, 0 = Normal event.
Bit 7: 1 = Asynchronous event, 0 = Synchronous event.
Note that many system queues are kept in priority order and so the block must
be requeued if the priority is changed, it is not sufficient merely to change the
priority in the event block.

Count is the event count - a record of how many kicks are waiting to be
processed or whether the event is disabled. See section 12.2 for a full
discussion of the use of the event count.

Routine address and ROM make up the far address of the event routine. If the
near address bit in the event class is true then the event routine is at a near
address - the ROM select byte (byte 6) is ignored and the event routine is
called directly. If the near address bit is false then the event routine is at far
address - bytes 4,5 and 6 make up the far address to call to run the event
routine. The user may write to the routine address and ROM fields (and to the
near address bit in the class byte as well) provided that the operation is
performed indivisibly (i.e. interrupts should be disabled).

The user fields are optional. They may be used to provide a data area specific
to the event block so that a single event routine may be shared between a
number of different event blocks (the event routine is passed the address of the
user fields).

b. Ticker Queue Blocks.

See section 11 for a general discussion of ticker interrupts and the ticker queue.
A ticker queue block is laid out as follows:

0,1: Tick chain

2,3: Tick count

4,5: Recharge count

6+: Event block

Tick chain is a system pointer which must never be written to by the user. It is
used to store the block on the ticker queue.

Tick count is a count of the number of ticks before the next kick occurs. A tick
count of zero means that the tick block is dormant and will not generate any
kicks. (Ideally a dormant block should be removed from the ticker queue to
avoid wasting time). The user may write to this field if required providing this
is done indivisibly.

Recharge count is the value that the tick count is set to after each kick. If the
recharge count is zero then the ticker block will become dormant after
generating one kick. The user may write to this field if required providing this
is done indivisibly.

Event block is a standard event block as described in section (a) above.


c. Frame Flyback Queue Blocks.

See section 11 for a general discussion of frame flyback interrupts and the
frame flyback queue. A frame flyback queue block is laid out as follows:

0,1: Frame chain

2+: Event block

Frame chain is a system pointer which must never be written to by the user. It is used
to store the block on the frame flyback queue.

Event block is a standard event block as described in section (a) above.

d. Fast Ticker Queue Blocks.

See section 11 for a general discussion of fast ticker interrupts and the fast
ticker queue. A fast ticker queue block is laid out as follows:

0,1: Fast chain

2+: Event block

Fast chain is a system pointer which must never be written to by the user. It is
used to store the block on the fast ticker queue.

Event block is a standard event block as described in section (a) above.


Appendix XI
The Alternate Register Set.
The Z80 microprocessor has two sets of registers - the normal set (AF, BC, DE
and HL) and the alternate set (AF’, BC’, DE’ and HL’). Unless the techniques
outlined in this appendix are implemented the user is prohibited from using the
alternate register set. This is because the alternate register set is used by the
firmware (the Kernel in particular) for storing certain system values and flags.
Providing that the user never enters the firmware then the alternate register set
may be used without restriction. Of course this would mean that the user would
be unable to use any facilities provided by the firmware. Furthermore, the user
would also have to disable interrupts as interrupts cause firmware routines to be
executed.

In the sections below a number of different methods are described that allow
the user to overcome these restrictions. The method chosen will depend on
what use is to be made of the alternate register set.

a. The firmware’s use of the alternate register set.


The Kernel stores a couple of system variables in the alternate register set. This
allows the Kernel to access these variables easily and thus speeds up a number
of operations (particularly entry to and exit from firmware routines). Only BC’
and the alternate carry flag (carry’) are used to store values, however, routines
do make use of the other alternate registers and so firmware routines may
corrupt them.

B’ is used to store the I/O address of the gate array (# 7F). C’ is used to store
the value required to set the current ROM state and screen mode:

Bits 0..1: Set the screen mode.


Bit 2: Disables the lower ROM.
Bit 3: Disables the upper ROM.
Bits 4. .7: System value to select gate array function.
By changing the ROM state bits and performing an OUT (C),C instruction the
user can enable or disable ROMs. (N.B. The Z80 OUT (C),r and IN (C),r
instructions use B as the top 8 bits of the I/O address. The hardware uses these
top bits for decoding the I/O address, it ignores the bottom 8 bits!) OUT (C),C
may be used to change the ROM state during the interrupt path when the
normal Kernel entries (e.g. KL U ROM ENABLE) may not be called because
they enable interrupts.

Carry’ is normally false. When carry’ is true this indicates that the firmware is
in the interrupt path. The firmware occasionaHy uses this flag to allow it to
take a different action when it is in the interrupt path to the action it takes when
it is not in the interrupt path (usually avoiding enabling interrupts).
b. Simple use of the alternate register set.
The technique described in this section allows use of the alternate register set
providing that no firmware routines are called and that interrupts are disabled.

After disabling interrupts registers A’, DE’ and HL’ may be used as required. If
registers BC’ or F’ (in particular carry’) are used then their original contents
must be restored before interrupts are re-enabled. The user may alter bits in C’
(as described in (a) above) and need not restore the original value provided that
an OUT (C),C is performed to keep the hardware abreast of the current state.
The machine will not function correctly if the hardware and the value in C’ are
out of step when interrupts are enabled.

This technique requires interrupts to be disabled for the duration of the operation
being performed. This is acceptable if the operation is short but not if the
operation is lengthy. Disabling interrupts for a lengthy period will stop many
firmware functions such as timers (and hence ink flashing, sound generation and
keyboard scanning). If the operation to be performed is lengthy then it might be
better to consider the use of one of the techniques described in sections (c) or (d)
instead.

Example.

The user might want to provide a routine that performs an LD A,(BC) from
RAM (similar to the RAM LAM pseudo-instruction provided by the
firmware).

The code for this routine could be written as follows:

A_FROM_BC:
PUSH BC
DI ; * * About to use alternate registers
EXX
POP HL ;Transfer BC to HL’
LD A,C
SET 2, A ;Set the disable lower ROM bit
SET 3, A ;Set the disable upper ROM bit
OUT (C), A ;Tell the hardware
LD A, (HL) ;Read the value from RAM
OUT (C),C ;RestoretheoldROMstate

EXX
El ; * * End of use of alternate registers
RET

N.B. This routine must be RAM resident or disabling the ROMs will have
an unfortunate effect!
c. Use of the alternate register set with interrupts enabled.

The technique described in this section allows the alternate register set to be
used and interrupts to be enabled. It does not allow firmware routines to be
called.

The simplistic use of the alternate register set by disabling interrupts as


described above is unsatisfactory if this results in interrupts being disabled for
an extended period of time. By patching INTERRUPT ENTRY in the low
Kernel jumpblock interrupts can be trapped and appropriate action to restore
the firmware registers can be taken. The actions that must be performed are as
follows:

Before starting to use the alternate register set the firmware’s BC’ is
saved and INTERRUPT ENTRY is patched so that the user’s interrupt
routine is used.

When the user has finished with the alternate register set the firmware’s
BC’ and carry’ are restored and INTERRUPT ENTRY is patched back to
the firmware’s interrupt routine.

When an interrupt occurs the user’s alternate registers are saved, the
firmware’s BC’ and carry’ are restored and INTERRUPT ENTRY is
patched back to the firmware’s interrupt routine. The latter is done in case
a second interrupt occurs whilst processing the events kicked from the
interrupt path of the first interrupt (remember that the event processing is
performed with interupts enabled).

After interrupt processing has finished the firmware’s BC’ is saved, the
user’s alternate registers are restored and INTERRUPT ENTRY is
patched back to the user’s interrupt routine again.

Note that when INTERRUPT ENTRY is patched it is vital to ensure that the
lower ROM is disabled and remains disabled. It is impossible to patch the
ROM version of INTERRUPT ENTRY! If an interrupt occured whilst the
lower ROM was enabled then the firmware would jump straight into its
interrupt routine without restoring its alternate registers first.

Example.

The following routines implement the scheme described above:

;
; The following storage locations are used
;
FIRM_BC: DEFS 2 ;Two bytes to store the firmware’s BC’
FIRM_INT: DEFS 2 ;Two bytes to store the address of the
;firmware’s interrupt routine
USER_AF: DEFS 2 ;Two bytes to store the user’s AF’
USER_BC: DEFS 2 ;Two bytes to store the user’s BC’
USER_DE: DEFS 2 ;Two bytes to store the user’s DE’
USER_HL: DEFS 2 ;Two bytes to store the user’s HL’
;
; This routine sets up the environment so that the
; user may make use of the alternate register set.
; N.B. Interrupts are enabled.
;
USER_ALTERNATE:
DI ;An interrupt would be disastrous
EX AF,AF’
EXX ;Swap to the alternate register set
;
LD (FIRM_BC), BC ;Save the firmware’s BC’
;
LD HL,(INTERUPT_ENTRY+1)
LD (FIRM_INT), HL ;Save the firmware’s interrupt routine
;
LD HL, USER_INTERRUPT ;Use the replacement interrupt routine
LD (INTERRUPT_ENTRY+1), HL
;
LD HL, (USER_AF)
PUSH HL
POP AF ;Restore user’s AF’
LD BC, (USER_BC) ;Restore user’s BC’
LD DE, (USER_DE) ;Restore user’s DE’
LD HL, (USER_HL) ;Restore user’s HL’
;
EXX ;Swap back to the standard register set
EX AF, AF’
El ;We have finished with the alternate regs
RET
;
; This routine restores the environment for the firmware to use the alternate
; register set. N.B. Interrupts are disabled and not re-enabled.
;
FIRM_ALTERNATE:
DI ;An interrupt would be disastrous
EX AF,AF’
EXX ;Swap to the alternate register set
;
LD (USER_HL),HL ;Save user’s HL’
LD (USER_DE), DE ;Save user’s DE’
LD (USER_BC), BC ;Save user’s BC’
PUSH AF
POP HL
LD (USER_AF), HL ;Save user’s AF’
;
LD HL, (FIRM_INT) ;Restore the firmware’s interrupt routine
LD (INTERRUPT_ENTRY+1), HL

LD BC, (FIRM_BC) ;Restore the firmware’s BC’


OR A, A ;Set the firmware’s carry’ to be false

EXX ;Swap back to the standard register set


EX AF,AF’
RET ;N.B. May be about to enter the interrupt
;path so no El.
;
;
; This routine replaces the firmware’s interrupt routine
; when the user is using the alternate register set
;
;
USER_INTERRUPT:
CALL FIRM_ALTERNATE ;Switch the environment to the firmware
CALL INTERRUPT_ENTRY ;Run the normal interrupt routine
JP USER_ALTERNATE ;Switch the environment back to the user

To start using the alternate register set the user obeys the instruction:

CALL USER_ALTERNATE

To finish using the alternate register set the user obeys the instructions:

CALL FIRM_ALTERNATE
EI

d. Calling firmware routines whilst using the alternate register set.

The technique described in this section extends the technique described in


section (c) to allow the user to call firmware routines whilst using the alternate
register set.

To call a firmware routine requires exactly the same action as is required for the
interrupt routine:

Before calling a firmware routine the user’s alternate registers are saved,
the firmware’s BC’ and carry’ are restored and INTERRUPT ENTRY is
patched back to the firmware’s interrupt routine. The latter is done in case
an interrupt occurs whilst executing the firmware routine.

After running the firmware routine the firmware’s BC’ is saved, the user’s
alternate registers are restored and INTERRUPT ENTRY is patched back
to the user’s interrupt routine again.

As indicated in section (c) it is vital to ensure that the lower ROM remains
disabled while the alternate register set is in use since INTERRUPT ENTRY in
the ROM is not patchable and jumps straight to the firmware’s interrupt routine.
Using the routines defined in section (c) a firmware routine may be called by
using the following sequence:
..
CALL FIRM_ALTERNATE ;Switch the environment to the firmware
El ;FIRM ALTERNATE disables interrupts
CALL firmware ;Run the firmware routine
CALL USER..ALTERNATE ;Switch the environment back to the user

The above code is rather long if a lot of firmware calls are to be made (10 bytes
per call). The following routine takes the address of a firmware routine to call to
as an inline parameter (and only uses 5 bytes per call).
;
; This routine saves the user’s alternate registers, calls a
; firmware routine whose address is passed inline and then restores the user’s
; alternate register set afterwards.
;
FIRM_ROUTINE:
CALL FIRM_ALTERNATE ;Switch to the firmware environment
EXX ;N.B. Interrupts are disabled
POP HL ;Recover address of routine to call, uses
LD E,(HL) ;firmware’s DE’ and HL’ which may be
INC HL ;corrupted
LD D,(HL) ;Get routine to call into DE’
INC HL
PUSH HL ;Put the real return address back
;
LD HL,USER_ALTERNATE ;Restore the user environment when
;the firmware returns by putting a
PUSH HL ;fake return address on the stack
;
PUSH DE ;Save the routine to call
EXX
El
RET ;Jump to the routine to call
To call a firmware routine using the above routine the following sequence
should be used:
..
CALL FIRM_ROUTINE
firmware ;Address of routine to call
.. ;FIRM ROUTINE returns here
Appendix XII
The Hardware and Hardware Variants

A. Processor.
The processor is a Z80A_running at a clock frequency of 4.00 MHz (±0.1%).
There is logic that stretches MREQ and IORQ using the CPU WAIT facility so
that the processor can only make one access to memory each microsecond.
The processor NMI pin is pulled up and made available on the expansion bus.
However, a non-maskable interrupt may cause the firmware to violate various
timing constraints and so its use is not recommended.
The processor interrupt pin is driven by a flip-flop in the video gate array. This
flip-flop is set during every vertical flyback and every 52 scan lines thereafter
until the next vertical flyback. The interrupt is arranged to occur approximately
2 scans (125 microseconds) into the 8 scan (500 microsecond) vertical flyback
signal. The interrupt latch is cleared by the processor acknowledging the
interrupt, or explicitly, using a software command. The top bit of the divide by
52 scan counter is also cleared when the processor acknowledges an interrupt
occurring after this counter has overflowed. This allows the interrupt system to
be expanded.

B. Memory.

ROM
A single 32K byte ROM is present on the processor board, but is mapped onto
two blocks of 16K in processor address space. The lower half of the ROM
occupies addresses #0000 to #3FFF and the upper half occupies addresses
#C000 to #FFFF. These two halves of the ROM can be separately enabled and
disabled by two control latches in the video gate array. On power-up or other
system reset both halves of the ROM are enabled.
An expansion port signal can be used to disable this internal ROM and allow
external ROM(s) to be accessed instead. These are selected by output
instructions and replace the upper half of the on-board 32K byte ROM when
selected.
RAM
On the CPC464 and CPC664 64k bytes of dynamic RAM are fitted to the
processor board at addresses #0000 to #FFFF. On the CPC6128 128k bytes are
fitted and this can be bank switched to be accessed at addresses #0000 to
#FFFF (see section 2.5). The lowest 16K and the top 16K are overlayed when
ROM is enabled. Whether the ROM is enabled or not affects where data is read
from, it has no effect on write operations which will be correctly performed
‘through’ the enabled ROM to the underlying RAM.
VDU SCREEN MEMORY

The display uses 16k of the processor RAM memory as screen refresh
memory. On the 464 and 664 the 16k used can be switched between the blocks
starting at #0000, #4000, #8000 and at #C000 by the top two bits (bits 12 and
13) programmed into the HD6845S start address register. On the 6128 the top
two bits select RAM banks 0, 1,2 or 3 to be used (see section 6.4 for further
details).
The arrangement of data in the VDU screen memory is dependent on the VDU
mode currently selected. In all modes the memory can be considered as
consisting of 8K 16 bit words. Each word contains either 4,8 or 16 pixels
(P0..Pn) of 1,2 or 4 bits (B0..Bm) depending on the mode as follows:

A0 Bit Mode 0 Mode 1 Mode 2

0 D7 P0 B0 P0 B0 P0 B0
0 D6 P1 B0 P1 B0 P1 B0
0 D5 P0 B2 P2 B0 P2 B0
0 D4 P1 B2 P3 B0 P3 B0
0 D3 P0 B1 P0 B1 P4 B0
0 D2 P1 B1 P1 B1 PS B0
0 D1 P0 B3 P2 B1 P6 B0
0 D0 P1 B3 P3 B1 P7 B0
1 D7 P2 B0 P4 B0 P8 B0
1 D6 P3 B0 P5 B0 P9 B0
1 D5 P2 B2 P6 B0 P10B0
1 D4 P3 B2 P7 B0 P11B0
1 D3 P2 B1 P4 B1 P12B0
1 D2 P3 B1 P5 B1 P13B0
1 Dl P2 B3 P6 B1 P14B0
1 D0 P3 B3 P7 B1 P15B0

Data for lines 0,8,16,24.. on the display are packed into the first 2K byte block
of the memory, lines 1,9,17,25.. are packed into the corresponding places of
the next 2K byte block of memory, with lines 7,15,23,31.. occupying the top
2Kbyte block of the 16k memory area.
The bottom 10 bits of the HD6845SP start address register define where within
these 2K blocks the screen starts. The offset from the start of the 2K byte block
is always even and is calculated as twice the register contents modulo 2K
bytes. When data has to be displayed from beyond the end of a 2K byte block
wrap around occurs to the begining of the same 2Kbyte block. See section 6.4
for a fuller description.
C. AY3-8912 Programmable Sound Generator.

The PSG is accessed using ports A and C of the µPD8255 device. Note that
when writing or loading address to the AY-3-8912 the maximum duration of
the write or load address command with BDIR high is 10 microseconds. The
clock input to the sound generator is exactly 1.00 MHz. The BC2 signal is tied
permanently high. On power-up the I/O port should be programmed to input
mode.
The user is advised to use the firmware routine MC SOUND REGISTER to
write to the PSG.

D. HD6845S CRT Controller (HD6845S CRTC).


The character clock to the CRTC occurs for every two bytes fetched from
memory, i.e. every 1 .0 microseconds. The first byte ofa pair has an even
address, the second has an odd address. In normal operation the internal
registers are set up as follows:

Register Function PAL SECAM NTSC

0 Horizontal Total 63 63 63
1 Horizontal Displayed 40 40 40
2 Horizontal Sync. Posn. 46 46 46
3 Vsync., Hsync. widths #8E #8E #8E
4 Vertical Total 38 38 31
5 Vertical Total Adjust 0 0 6
6 Vertical Displayed 25 25 25
7 Vertical Sync. Posn. 30 30 27
8 Interlace and Skew 0 0 0
9 Max. Raster Address 7 7 7
10 Cursor Start Raster X X X
11 Cursor End Raster X X X
12 Start Address (H) X X X
13 StartAddress(L) X X X
14 Cursor(H) X X X
15 Cursor(L) X X X

In the above table the numbers for PAL and SECAM standards are identical.

For information on the NTSC Register 5 see Appendix XIII.

Note that X indicates that software may vary these numbers during device
operation. The firmware only makes use of the start address register which is
used to set the screen base and offset.
E. Video Gate Array.

The software must access this device in order to control the enabling and
disabling of ROMs, the mode of operation of the VDU and also to load colour
information for ‘inks’ into the palette memory. One I/O channel is used for all
commands, the top two bits of data specifying the command type as follows:

Bit 7 Bit 6 Use

0 0 Load palette pointer register.


0 1 Load palette memory.
1 0 Load mode and ROM enable register.
1 1 Bank Switching Register on CPC6128.

MODE AND ROM ENABLE REGISTER

This write-only register controls the VDU mode and ROM enabling as follows:

Bit 7: 1
Bit 6: 0
Bit 5: ** Reserved ** (send 0)
Bit 4: Clear raster 52 divider.
Bit 3: Upper half ROM disable.
Bit 2: Lower half ROM disable.
Bit 1: VDU Mode control MC1.
Bit 0: VDU Mode control MC0.

Writing a 1 to bit 4 clears the top bit of the divide by 52 counter used for
generating periodic interrupts.
Modes are defined by the mode control pins as follows:

MC1 MC0 Mode

0 0 Mode 0, 160 x 200 pixels in 16 colours


0 1 Mode 1, 320 x 200 pixels in 4 colours.
1 0 Mode 2, 640 x 200 pixels in 2 colours.
1 1 **Do not use**
The gate array hardware synchronises mode changing to the next horizontal
flyback in order to aid software that requires different parts ofthe screen to be
handled in different modes.
On power-up and other system resets, the mode and ROM enable register is set
to zero, enabling both halves of the ROM.
PALETTE POINTER REGISTER
This write-only register controls the loading ofthe VDU colour palette as
follows:

Bit 7: 0
Bit 6: 0
Bit 5: ** Reserved ** (send 0)
Bit 4: Palette pointer bit PR4.
Bit 3: Palette pointer bit PR3.
Bit 2: Palette pointer bit PR2.
Bit 1 : Palette pointer bit PR1.
Bit 0: Palette pointer bit PR0.

Bits PRO to PR3 select which ink is to have its colour loaded, providing bit
PR4 is low. If bit PR4 is high then bits PR0 to PR3 are ignored and the border
ink colour is loaded.

PALETTE MEMORY

This write-only memory controls the VDU colour palette as follows:

Bit 7: 0
Bit 6: 1
Bit 5: **Reserved ** (send 0)
Bit 4: Colour data bit CD4.
Bit 3: Colour data bit CD3.
Bit 2: Colour data bit CD2.
Bit 1: Colour data bit CD1.
Bit 0: Colour data bit CD0.

The ink entry pointed at by the palette pointer register is loaded with the colour
sent on this channel. The number of colours that need to be loaded ranges from
2 colours in mode 2 to 16 colours in mode 0. In addition to loading the colours
an extra colour data byte must be sent to this channel to define the border
colour. On power-up and other system resets the contents ofthe palette are
undefined, but the border colour is set to BLACK, to avoid unsightly effects on
power-up.
The 32 colour codes are decoded to drive the RGB signals, producing 27
different colours. The hardware colours are listed in Appendix V.
BANK SWITCHING REGISTER (CPC6128 only)

This write-only register controls the layout of the bank switchable RAM as
follows:

Bit 7: 1
Bit 6: 1
Bit 5: **Reserved ** (send 0)
Bit 4: 0
Bit 3: 0
Bit 2: x
Bit 1: x
Bit 0: x

The xxx appearing on Bits 0, 1, and 2 is the code for the selected bank layout,
detailed as follows:

Code 0 1 2 3 4 5 6 7
Address
#C000: 3 7 7 7 3 3 3 3
#8000: 2 2 6 2 2 2 2 2
#4000: 1 1 5 3 4 5 6 7
#0000: 0 0 4 0 0 0 0 0

Selecting Code 0 (the number sent to the Bank Switch Register would be #C0)
will switch to the normal default bank layout, i.e. Banks 0..3.
The other 64k can be accessed by selecting codes 4..7. These switch one ofthe
other 16k blocks into area #4000. See section 2.5 for more details.
F. µPD8255 Parallel Peripheral Interface.

The PPI as well as the 8 port pins on the PSG are used to interface to the
keyboard and to control and sense miscellaneous signals on the processor
board. Port A must be programmed either to input or to output in mode 0 since
this port is used for reading and writing to the PSG. Port B must be
programmed to input in mode 0. Port C must be programmed to output in mode
0 on both halves.
Circuitry is provided around the PPI to reset it during system reset. For details
of the operation ofthe µPD8255 see the NEC product specification.

CHANNEL A (Input or Output)

Bit 7: Data/Address DA7 connected to AY-3-8912.


Bit 6: Data/Address DA6 connected to AY-3-8912.
Bit 5: Data/Address DA5 connected to AY-3-8912.
Bit 4: Data/Address DA4 connected to AY-3-8912.
Bit 3: Data/Address DA3 connected to AY-3-8912.
Bit 2: Data/Address DA2 connected to AY-3-8912.
Bit 1: Data/Address DA1 connected to AY-3-8912.
Bit 0: Data/Address DA0 connected to AY-3-8912.

CHANNEL B (Input Only)

Bit 7: Datacorder cassette read data.


Bit 6: Centronics busy signal.
Bit 5: Not expansion port active signal.
Bit 4: Not option link LK4.
Bit 3: Not option link LK3.
Bit 2: Not option link LK2.
Bit 1: Not option link LK1.
Bit 0: Frame flyback pulse.
The option links, LK1...LK4 are factory set. LK4 is fitted for 60 Hz TV.
standards and omitted for 50 Hz standards.

CHANNEL C (Output Only)

Bit 7: AY-3-89i2 BDIR signal.


Bit 6: AY-3-89i2 BC1 signal.
Bit 5: Datacorder cassette write data
Bit 4: Datacorder cassette motor on.
Bit 3: Keyboard row select KR3.
Bit 2: Keyboard row select KR2.
Bit 1 : Keyboard row select KR1.
Bit 0: Keyboard row select KR0.
G. Centronics Port Latch.

This latch is loaded with data by output commands to the correct I/O channel.
It cannot be read. Note that the timing requirements on Centronics interfaces
generally specify that the data must be present on the seven data lines at least 1
microsecond before the strobe is made active and must remain valid for at least
1 microsecond after the strobe returns inactive. The duration of the strobe must
be between 1 and 500 microseconds. The busy signal can be inspected as soon
as the strobe is inactive in order to determine when more data can be sent.

Bit 7: Centronics strobe signal (1 = active).


Bit 6: Data 7 to Centronics port.
Bit 5: Data 6 to Centronics port.
Bit 4: Data 5 to Centronics port.
Bit 3: Data 4 to Centronics port.
Bit 2: Data 3 to Centronics port.
Bit 1: Data 2 to Centronics port.
Bit 0: Data 1 to Centronics port.

On power-up and other system resets the outputs ofthis latch are all cleared.

H. Keyboard and Joysticks.


The keyboard andjoystick switches are sensed by selecting one of ten rows
using the four control bits on channel C of the PPI and reading the data from
the PSG parallel port using port A of the PPI.
The keyboard and joystick switches are arranged in a 10 by 8 matrix. One of
ten rows is selected using the code on KR0...KR3 and the eight bits of data are
then read in parallel on a parallel port as described above. A switch is active
(closed) if the corresponding data bit is a logic 0.
The key number associated with each key ( see Appendix I) is constructed as
follows:

Bit: 7 6 5 4 3 2 1 0

0 Row number Bit number

Thus the key that is associated with bit 5 in row 4 has key number 37(4*8+5).
I. Disc Interface

Floppy Disc Controller


The controller uses an NEC type µPD765A Floppy Disc Controller IC to
connect to the disc drives. Only two disc drives are supported, since the US1
line from the µPD765A is ignored. This results in the two disc drives being
accessed as drives 0 (zero) and 1 (one) and again as drives 2 and 3. The
controller supports both single and double sided and single and double density
mini-floppy disc drives. Note that the clock frequency supplied to the
µPD765A CLK pin is 4.00 MHz rather than the 8.00 MHz used with larger
disc drives.
The full facilities described in the NEC data sheet for the µPD765A are
available with the exception of interrupts and DMA which are not supported.

Expansion ROM
The disc ROM is normally number #07, but may be set to #00 by cutting
option trace LK1 in the case of the DDI-1, LK7 in the case of the 664, LK201
in the case of the 6128.

The EXP signal (pin 48), of the 50 way expansion connector, is grounded when
the disc ROM number is #07 in order that this address can be avoided by other
expansion peripherals. A 200 nanosecond 27128 type EPROM or ROM is
normally used, and may be fitted in a DIL socket in some machines.
Option traces LK2 and LK3 are manufacturing options for write pre-
compensation. They should not need alteration by the user.

Motor Control

Writing to channel #FA7E starts and stops the disc drive motors. Writing #00
will stop the motors, #01 will start the motors. On power-up and other system
resets the motors are not stopped.

Electrical Levels
All electrical levels on the controller are TTL compatible. Signals originating
in the drives are terminated by 680O resistors to +5v at the controller and
received with gates with input hysteresis. The maximum permissible cable
length is .075 metre.
Using Other Disc Drives

It is possible to use other disc drives with the CPC range ofcomputers (or the
DDI-1), in particular 5¼" drives. Some hardware knowledge will be required.
The following gives some advice and information which should assist in using
a different drive.
If Drive A: the 5V power should be supplied to pins 2,4,6 and 14 of the
5¼" drive after ensuring that any existing connections to the drive
circuitry have been removed.
If Drive B: no terminating resistor should be installed.
The drive MUST have a ‘READY’ signal on pin 34.
The drive will require its own power supply.
The extra cabling should be as short as possible and should consist of a
cable-mounting male connector (to mate with the female socket connector
on the cable from the interface), all 34 conductors and, normally, a 34
way double-sided card edge connector (to mate with the 5¼" drive).
The step rate, motor on and off timeout may have to be changed, see, in
the case of CP/M 2.2, the SETUP utility.
A drive such as the Shugart 201 is not suitable since it does not have a ready
signal, but one such as the Chinon F 051-MD is suitable.

Pin Arrangement

All odd numbered pins are pulled to ground (GND). All signals are active low.

PIN No. SIGNAL

2 +5V
4 +5V
6 +5V
8 INDEX
10 Drive select 0
12 Drive select 1
14 +5V
16 Motor On
18 Direction Select
20 Step
22 Write Data
24 Write Gate
26 Track 0
28 Write Protect
30 Read Data
32 Side 1 Select
34 Ready
J. Serial Interface

The BIOS supports a two channel asynchronous serial interface. The interface
is an optional extra for the CPC 464/664/6128 computers. This section
describes the recommended hardware configuration for the serial interface such
that, if fitted, it can be driven by the BIOS.
The interface consists of a Zilog Z80A SIO/0 or Z80A DART together with an
Intel 8253 programmable interval timer. The 8253 is used as a Baud rate
generator as follows:

Timer 0 generates the transmit clock for channel A of the 510.


Timer 1 generates the receive clock for channel B of the 510.
Timer 2 generates both transmit and receive clocks for channel B of the 510.

It is assumed that the CLK inputs to all three channels of this device are driven
by a 2.0(0.1%)MHz clock signal derived from the 4.0 MHz CPU clock. The
GATE inputs to all three channels are tied permanently high.

NOTE: This is an optional extra for all machines.


K. I/O ports

The following is a detailed list ofthe Z80 I/O used by the CPC range of
computers.

PORT OUPUT INPUT

#7Fxx Video Gate Array **Do not use**


#BCxx HD6845 CRTC address **Do not use**
#BDxx HD6845 CRTC data **Do not use**
#BExx **Do not use** Reserved for CRTC status
#BFxx **Do not use** HD6845 CRTC data
#DFxx Expansion ROM select **Not used**
#EFxx Centronics latch **Do not use**
#F4xx µPD8255 port A data µPD8255 port A data
#F5xx µPD8255 port B data µPD8255 port B data
#F6xx µPD8255 port C data µPD8255 port C data
#F7xx µPD8255 control **Undefined **
#F8xx Expansion bus Expansion bus
#F9xx Expansion bus Expansion bus
#FAxx Expansion bus Expansion bus
#FBxx Expansion bus Expansion bus
#FFxx **Not used** **‘Not used**

Disc Interface

#FA7E Motor Control **not used**


#FB7E **not used ** µPD765A Status Register
#FB7F µPD765A Data Register µPD765A Data Register

Serial Interface

#FADC 510 Channel A Data 510 Channel A Data


#FADD 510 Channel A Control 510 Channel A Control
#FADE 510 Channel B Data 510 Channel B Data
#FADF 510 Channel B Control 510 Channel B Control
#FBDC 8253 Load Counter 0 8253 Read Counter 0
#FBDD 8253 Load Counter 1 8253 Read Counter 1
#FBDE 8253 Load Counter 2 8253 Read Counter 2
#FBDF 8253 Write Mode Word **not used**
Expansion bus I/O channels in the address range #F800 to #FBFF are reserved
as follows:

ADDRESS (AO..A7) USE

#00...#7B ** Do not use **


#7C...#7F Reserved for Disc Interface
#80...#BB ** Do not use **
#BC...#BF Reserved for future use.
#C0...#DB ** Do not use **
#DC...#DF Reserved for communications interfaces.
#E0...#FE Available for user peripherals.
#FF Reset peripherals.

L. Hardware Variants

There have been slight differences with the circuitry concerning the ULA in
some of the CPC range of computers, but as long as legal values are used when
accessing them, there should be no noticeable difference.
The firmware has been altered for a few foreign computers. The major changes
have been to the character set (to provide a few new national characters) and to
the characters available on the keyboard (to allow new characters to be
entered), also some messages and version numbers have been changed. These
foreign changes are detailed below.

Spanish System
Character Set

#A1 matrix is set to Ñ


#AB matrix is set to ñ
#A3 matrix is set to Pt

Keyboard

* now generates Ñ
: now generates ñ
+ now generates :
{ now generates *
} now generates +
£ now generates Pt

( with control now generates {


) with control now generates }
! with control now generates ¡
? with control now generates ¿
Start Up Message
The V1 or V3 message at start-up has been changed to S1 or S3.
Identification
The ROM modification byte (at location #C003 in the on-board ROM) is
now 1, not 0.
Printer

Certain Codes have been changed for the printer translations. CPC6128
printer codes are unchanged

CPC464 translations changed are : #A1 - > #5C


#AB - > #7C
#AE - > #5D
#AF - > #5B

Danish System
Character Set
#30 matrix is now 0 (i.e. slash removed from zero)
#5B matrixis now Æ
#5C matrix is now Ø (i.e. letter O with slash through it)
#5D matrix is now ? (i.e. letter A with ° accent)
#7B matrix is now æ (i.e. lower case of #5B above)
#7C matrix is now ø (i.e. lower case of #5C above)
#7D matrix is now å (i.e. lower case of #5D above)
Keyboard

| now generates ?
@ now generates å
{ now generates
[ now generates @
* now generates Æ
: now generates æ
+ now generates Ø
; now generates ø
} now generates *
] now generates :
now generates +
\ now generates ;

Control versions have moved with keys/chars (as expected).


Start Up Messages
The V1 or V3 message at start-up has been changed to d1 or d3.
Identification
The ROM modification byte (at location #C003 in the on-board ROM) is
now 2 and not 0.
French System
Character Set
#40 matrix is now (i.e. a grave)
#5C matrix is now (i.e. c cedilla)
#5E matrix is now (i.e. circumflex)
#7B matrix is now (i.e. e grave)
#7C matrix is now (i.e. u grave)
#7D matrix is now (i.e. e acute)
#A2 matrix is now (i.e. degrees sign)
Keyboard
So many characters have been moved around that it is easiest to show the
changes with the following diagram. The control versions have moved
with the keys/chars (as expected).

Start Up Message

The V1 or V3 message at start-up has been changed to f1 or f3.

Identification
The ROM modification byte (at location #C003 in the on-board ROM) is
now 3, not 0.
Appendix XIII -
Hints, Tips, and Workarounds

Following are a number of ‘WORKAROUNDS’ for the 464 machine, that is,
routines which allow the 464 to act as specified in the ‘464 FIRMWARE
SPECIFICATION’.

Soft End Of File

Reading characters from the disc using CAS IN CHAR when it is redirected to
the AMSDOS routine can run into problems caused by the routine returning an
error when it reads the end of file character #1A. This can be avoided by
patching the jumpblock so that the end of file error is detected and ignored. The
following program does this.

SAVE_ENTRY: DEFS 3 ;Space to save jumpblock entry


;
INSTALL:
LD A, (CAS_IN_CHAR +0)
LD HL, (CAS_IN_CHAR +1)
LD (SAVE_ENTRY + 0), A
LD (SAVE_ENTRY + 1), HL ;Save original contents
;
INTERCEPT:
LD A,#C3
LD HL, NEW_CAS_IN_CHAR
JR PATCH ;A/HL = jump to new routine
;
RESTORE
LD A, (SAVE_ENTRY +0)
LD HL, (SAVE_ENTRY + 1) ;A/HL = jump to original routine
;
PATCH
LD (CAS_IN_CHAR + 0), A
LD (CAS_IN_CHAR + 1), HL
RET

;
NEW_CAS_IN_CHAR
PUSH HL
;
CALL RESTORE ;Put original jump back because
;AMSDOS requires it to be executed
;in its original position!
CALL CAS_IN_CHAR ;Read the character
PUSH AF
CALL INTERCEPT ;Continue intercepting jumpblock
POP AF
;
POP HL
RET C ;Quit if OK
RET Z ;Quit if ESC
CP #1A
SCF
CCF
RET NZ ;Quit if a real error
OR A

SCF
RET ;Pretend OK if soft EOF
Before reading from the file the user should call INSTALL and from then on
CAS IN CHAR will return character #1A just like any other character. Note
that INSTALL must only be called once, otherwise the original contents of the
jumpblock entry will be lost! The patch will be lost if the external commands
TAPE, TAPE.IN, DISC or DISC.IN are executed.

MODE switching on V1.0 firmware

Some programs, such as SORCERY+, run with different parts of the screen in
different modes. It is possible to do this using the firmware but it is necessary
to intercept the SCR MODE CLEAR indirection so that the screen is not
cleared each time the mode is changed. On V1.1 firmware all that is necessary
is to patch a RET instruction into the first byte of the SCR MODE CLEAR
indirection. On V1.0 firmware this would result in all the inks being set to the
background colour! This can be overcome by using the following routine to
install the users own ink refresh routine.

LD HL,SCR_MODE_CLEAR
LD (HL),#C9

LD HL,EVENT_BLOCK ; Points to 9 byte block


LD DE,INK_ROUTINE ; points to Interrupt routine
LD B,#81
CALL KL_NEW_FRAME_FLY ; Add Frame Flyback Interrupt
RET
INK_ROUTINE: LD DE,INK_VECTOR ; Points to INK settings
JP MC_SET_INKS

EVENT_BLOCK: DEFS 9

INK_VECTOR: DEFB 4,4,10,19,12,11,20,21,13,6,30,31,7,18,25,26,5

Detecting the DDI-1 on a 464

If you are writing a program which needs to detect whether a DDI-1 interface is
connected to the computer or not, then the way to accomplish this is to issue a
DISC command, if this is not found then the DDI-1 is not connected.
The following program shows how to do this under machine code.
FIND_DISC: LD HL,DISC_COMMAND
CALL KL_FIND_COMMAND
SBC A,A
RET

DISC_COMMAND: DEFM ‘DIS’ ,‘C’ +#80

Calling FIND DISC will return A = #FF if a DDI-1 is connected or A = 0 if a


DDI-1 is not connected).

Express Asynchronous Events

A problem was discovered with Express Asynchronous Events, in that, the


COUNT byte should always be reset (to 0) upon termination of the Event,
otherwise the event will not be kicked again. This can be done simply by
adding the following program to the event routine:

LD HL,EVENT_BLOCK+2
LD (HL),#00
RET
Printing characters above 127 and suppressing the
double line feed

The following patches are to enable characters greater than 127 to be printed,
and that the line feed character automatically sent after a carriage return can be
suppressed and so stop the infamous double line feed problem on printers.
First the main patch code which is used in both programs should be set up as
follows:
INITIALISE: LD A,(MC_WAIT_PRINT)
LD HL,(MC_WAIT_PRINT+1)
LD (NEW_PRINT),A
LD (NEW_PRINT+1),HL ; patch the jumpblock to end of new code

LD A,#C3
LD HL,PRINT._PATCH
LD (MC_WAIT_PRINT),A
LD (MC_WAIT_PRINT+1),HL ; redirect the jumpblock to the new code

RET

Then the PRINT PATCH code for printing characters above ASCII 127 is as
follows:
PRINT_PATCH: CP 128
JR C,NEW_PRINT ; character below 128 then print it
AND # 7F ; mask off bit 7
LD (CHAR),A ; store away the character
PUSH HL ; HL is preserved on exit
LD HL,ESCAPE ; point HL at escape sequence
LD B,5
PRINT_LOOP: PUSH BC
LD A,HL ; get character from sequence
CALL NEW_PRINT ; send character to printer
INC HL ; bump HL to next character
POP BC
DJNZ PRINT_LOOP ; do this 5 times
POP HL ; restoreHL
RET ; return to calling program
NEW_PRINT: DEFS 3 ; Storage foF MC_WAIT_PRINTER
; jumpblock

ESCAPE DEFM 27,”>” ; Sets the printer to alternate character set

CHAR DEFB 0 ; storage for original character being sent

DEFM 27,” =“ ; Sets the printer into normal character set

NOTE the escape sequences ( ESC= and ESC> ) are used with the AMSTRAD
DMP2000 printer and may have to be changed for other printers, (e.g. a number
of printers use ESC4 and ESC5 instead). Check with your printer user manual.
The PRINT PATCH code to suppress the line feed after a carriage return
appears below:
PRINT_PATCH: CP 10
JR NZ,NOT_LF ; jump if character not a line feed
LD A,(CHAR) ; restore last character printed
CP 13 ; test if last char was a l3(CR)
LD A,0
LD (CHAR),A ; zeroise the last char. printed store
SCF ; set carry flag, char. printed OK
RET Z ; Return to calling program if last char.
; printed was a 13 (CR)
LD A,10 ; If last char. was not a 13 (CR) then print
; 10 (Line Feed)
NOT_LF: LD (CHAR),A ; store character
NEW_PRINT: DEFS 3 ; Execute printing of character
; and return to calling program
CHAR: DEFB 0 ; storage for last characterprinted

So to use either the LF suppressor or the printing characters above 127 routines,
the code INITIALISE and the re’evant PRINT PATCH should be tied together
and then assembled at a convenient location in RAM. Once initialized they will
work until a call to MC RESET PRINTER which re-initializes the original
indirection jumpblock at MC WAIT PRINTER.
American CPC6 128: Frame Flybacks and Interrupts

This technical note discusses the relationship between frame flybacks and
interrupts on the NTSC version of the CPC464/664/6128. Currently the only
production model affected is the American version of the CPC6128 - all other
markets use PAL/SECAM models and this note does not apply to them.
There was an error in the original hardware specification for the CPC464/664/6
128 in that the value to be loaded into the Vertical Total Adjust register in the
HD6845 (register 5) was incorrectly given as 6 for the NTSC version whereas
it should have been 4. Thus the various ROMs produced for the
CPC464/664/6128, when used with an NTSC system, load an incorrect value
into the 6845 whenever a full reset occurs; for example when the machine is
first powered on, or the RESET_ENTRY firmware call is made.
PAL/SECAM systems work correctly and, fortunately, the only effect of the
incorrect value on NTSC systems is to cause the interrupt associated with frame
flyback to occur at exactly the same time as the frame flyback pulse becomes
true. With the correct NTSC value the interrupt will occur 125 microseconds
after frame flyback becomes true -corresponding to PAL/SECAM systems and
the description given in Section 1.
What this means in practice is that on an American CPC6 128 a program which
tests the PPI Frame Flyback signal (for example by calling
MC_WAIT_FLYBACK) will not see frame flyback become true before the
interrupt occurs, but must rely upon frame flyback still being true when the
processing associated with the interrupt is complete. If the interrupt processing
takes too long, the program will appear to ‘Lock Up’ because it never sees
frame flyback set true.
In order to minimise the possibility of ‘Lock Ups’ occuring Amstrad have
ensured that all American CPC6 128 machines are fitted with the type of 6845
which does not have a programmable frame flyback pulse length. Therefore the
frame flyback will last for a fixed 1000 microseconds rather than the
programmed time of 500 microseconds. The 500 microseconds period is in fact
quite sufficient for the system routines invoked by the frame flyback interrupt;
1000 microseconds will allow a number of user routines to also occur at that
time without any difficulty.
Clearly though, software for American CPC6128s which has much to do at
frame flyback time, or which wishes to avoid flickering effects on the top few
lines of the screen, must arrange to place the correct NTSC value into register 5
of the 6845 using code equivalent to the following:
SET_NTSC LD B,#F5
IN A,(C) ; Read PPl port B
AND #10 ; Inspect LK4
RET NZ ; Return if not YTSC No action required
DI ; Need exclusive access to CRTC
LD BC.#BC05
OUT (C).C ; Set CRTC address to register 5
LD BC.#BD04
OUT (C).C ; Set Vertical Total Adjust to 4
El ; End of exclusive access
RET
Using Interrupts with Z80 Peripherals

Z80 support chips such as PlO, SIO, DART, DMA, and CTC have an elaborate
interrupt priority system involving the connection of the lEO output of one chip
to the IEI input of the next in a daisy-chain.
When a chip wishes to interrupt it inspects its IEI input. If this is ‘1’ then no
higher priority device is interrupting and the chip may pull on the interrupt
request signal. It will also set lEO to ‘0’ so that lower priority devices are aware
of its request. If IEI into a chip goes to ‘0’ then the chip will not interrupt until
the higher priority devices have been serviced.
When the CPU is actually interrupted an interrupt acknowledge bus cycle
occurs and the highest priority interrupting device (the one with IEI = 1 and a
reason to interrupt) assumes that it is being serviced and disables its interrupt.
This means that interrupt service routines have the option to issue an El
instruction to allow immediate response to higher priority interrupts.
When interrupt servicing is complete a RETI instruction must be issued. This
causes a support chip with an interrupt under service to redetermine its interrupt
status and the state of IEI and to set lEO accordingly.
Section 11.2 clearly describes the scheme used for external interrupting
devices. This relies upon the external device continuing to interrupt during the
service routine so that it can be distinguished from the internal ticker interrupt
which is automatically disabled as soon as the interrupt acknowledge bus cycle
occurs. From the above description it will be clear that Z80 support chips do
not meet this condition and thus their interrupts cannot be used. Hardware
designers should also note that interrupts should be disarmed by an OUT to the
RESET PERIPHERALS channel (#F8FF).
The code given below does two things, it arranges for a RETI instruction to be
issued after every interrupt to ensure that all chips which assumed that they
were being serviced will reassert their interrupt request. This is important
where several Z80 support chips are involved because there is no provision for
IEO-IEI connections between add-on devices. Secondly, a RETI is issued
immediately before deciding whether an interrupt is internal or external which
will mean that Z80 support chips will renew their interrupt request and the
firmware will correctly determine that the interrupt is external.
Set up an external device service routine by intercepting the indirection at
#003B. Remember to make this interception code relocatable.
Add the following Z80 support chip code only if a mark 1 ROM versions 0, 1
or 2 is fitted (This means all existing CPC464/664/6128 machines - see KL
PROBE ROM.)
#0038 (ROM or RAM) originally contains:
JP ADDRESS_X
ADDRESS_X + 5 will be in RAM, not under a ROM, and originally contains:
LD A,C
SCF
El
EX AF,AF’
DI
replace the five bytes at ADDRESS_.X + 5 by:

CALL NEW_CODE
RETI

replace NEW CODE et seq (which must not be under a ROM) by:
LD A,C
SCF
EX AF,AF’
CALL LABEL_1
DI
JP ADDRESS_X +10
LABEL_1:

El
RETI

Note that there is no suitable indirection or jumpblock into which the new code
can be added, so that it is necessarily somewhat more contorted than the usual
sort of code which one adds. Note also that this code is only for use with
existing ROMs such as are fitted to the CPC464/664/6 128. Any future
compatible machines will not support it - so it is most important that the
program to install the code checks the ROM version number before proceeding.
Steps will be taken to ensure newer ROM versions will not need alteration in
this way.

Note that the old interrupt code and the indirection at #003B will be replaced
when KL CHOKE OFF, MC BOOT PROGRAM or MC START PROGRAM
are run (viz when a new foreground or background program is executed).
Fortunately these are also the routines which issue RESET PERIPHERALS
request.
Appendix XlV
Printer Translation Table

A facility is provided whereby special characters which may appear on the


screen and which are supported by the AMSTRAD DMP-1, will be printed
even though the character codes for the screen and printer may be different.
The majority of these symbols will only be available when the printer is
switched to one of its foreign language modes.
For example, if a circumflex is to be printed then the character code for the
screen would be &A0 but on the printer it is &5E, if an &A0 was sent to the
printer it would be translated into a &5E thus printing a circumflex
The following table shows all the default translation codes:

The default translation table only translates the additional characters in the. character
set (#A0..#AF). It does not translate any ofthe standard ASCII characters or the
graphics characters.

You might also like