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

ZXSpectrum+2aManual

The document is a manual for the Sinclair ZX Spectrum +2A, detailing its features, setup, and operation. It covers software compatibility, the BASIC programming language, and various chapters on loading software, using peripherals, and programming concepts. The manual emphasizes the importance of following safety precautions and provides a structured reading guide for users to effectively utilize the computer system.

Uploaded by

salva
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

ZXSpectrum+2aManual

The document is a manual for the Sinclair ZX Spectrum +2A, detailing its features, setup, and operation. It covers software compatibility, the BASIC programming language, and various chapters on loading software, using peripherals, and programming concepts. The manual emphasizes the importance of following safety precautions and provides a structured reading guide for users to effectively utilize the computer system.

Uploaded by

salva
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 364

Contents

Introduction 5
Software compatibility
The BASIC
How to read this book
Precautions!

Chapter 1 12
Open the box
Unpacking
Fitting a mains plug
Setting up

Chapter 2 15
Operating your +2A
Switching on
Tuning-in your TV
Using the +2A
The opening menu

Chapter 3 22
How to load disk software
Disks and drives for the +2A
Loading disk software
Abandoning loading

Chapter 4 24
How to load tape software
The datacorder
Loading Spectrum +3, +2(+2A) and Spectrum 128 software
Loading Spectrum 48 software
Abandoning loading

Chapter 5 28
Using a disk drive
Disks and drives for the +2A
Insertion
Write protection
Read/write indicator lamp
Eject button

Chapter 6 32
Introducing +3 BASIC
The editor
The edit menu
Renumbering a BASIC program
Swapping screens
Listing to the printer
Typing in a program
Moving the cursor
Running a program
Commands and instructions
Saving to tape
Verifying the tape
Loading from tape
Formatting a disk
Saving to disk
Filenames
Disk catalog
Loading from disk
Error reports

Chapter 7 48
Using 48 BASIC
Using the +2A as a 48K Spectrum
Entering 48 BASIC mode
The keyboard under 48 BASIC
Program entry
Editing the current line

Chapters 8 54
The +3 BASIC programmer's guide
Part 1 – Introduction 54
Part 2 - Simple programming concepts 58
Part 3 – Decisions 66
Part 4 – Looping 68
Part 5 – Subroutines 73
Part 6 - Data in programs 75
Part 7 – Expressions 78
Part 8 – Strings 82
Part 9 – Functions 85
Part 10 - Mathematical functions 92
Part 11 - Random numbers 98
Part 12 – Arrays 101
Part 13 – Conditions 105
Part 14 - The character set 109
Part 15 - More about PRINT and INPUT 118
Part 16 – Colours 125
Part 17 – Graphics 132
Part 18 – Timing 138
Part 19 – Sound l42
Part 20 - File operations 151
Part 21 - Printer operations 181
Part 22 – Streams 188
Part 23 - IN and OUT 191
Part 24 - The memory 195
Part 25 - The system variables 205
Part 26 - Using machine code 214
Part 27 - Guide to +3DOS 229
Part 28 - Spectrum character set 283
Part 29 – Reports 291
Part 30 - Reference information 302
Part 31 - The BASIC 305
Part 32 - Binary and hexadecimal 331
Part 33 - Example programs 335

Chapter 9 344
Using the calculator
Selecting the calculator
Entering numbers
Running total
Using built-in mathematical functions
Editing the screen
Assigning variables
User defined functions
Exit-ing from the calculator

Chapter 10 347
Peripherals for your +2A
Printer
Joystick(s)
VDU Monitor
Amplifier
Serial devices
MIDI device
Auxiliary interface
Expansion devices
Disk drive(s)

Index 356
Introduction

Sinclair ZX Spectrum +2A


128K Integrated Microcomputer
The Sinclair ZX Spectrum +2A is an enhanced version of the
Spectrum +2. The +2A has been designed to incorporate the more
advanced features of the Spectrum +3. These include a built-in
RAMdisk and disk operating system (which will also support
external floppy disk drives), a parallel interface (so that you
can connect a (Centronics) standard printer), and an additional
auxiliary interface (so that you can connect other external add-
ons such as robot devices). All this is allied to a powerful 128K
microcomputer that boasts support for joystick(s), sound, MIDI and
serial (RS232) interfaces, together with a comprehensive I/O
expansion bus and integrated cassette datacorder.

The whole is a truly complete system which combines established


Sinclair technology with AMSTRAD's expertise in integration and
engineering reliability. The +2A encapsulates all the computing
power and 'expandability' that you will probably ever need in a
simple to set up, simple to use, all-in-one package.

Software compatibility
The +2A may be used with software written for the earlier models
in the ZX Spectrum range. This means that a vast quantity of
software already exists for the +2A. There are literally thousands
of titles available covering every conceivable application: games,
utilities, music, scientific, educational and many many more.

The BASIC
The +2A uses a computer language called BASIC (Beginners' All-
purpose Symbolic Instruction Code). The version of BASIC provided
with the +2A is the same as that used by the +3. Known as +3
BASIC, it has been designed to be particularly easy to learn and
use.

The disk operating system


Like the BASIC, the +2A's disk operating system is the same as
that used by the +3. It is called +3DOS. The provision of +3DOS
means that you can connect an external floppy disk drive (or
drives) to the +2A via a suitable interface (see chapter 10 for
further details). The +2A also incorporates a RAMdisk (which
operates under +3DOS). The RAMdisk is the +2A's own internal
(volatile) disk drive on which you can save and load programs and
data at very high speed.

If you have connected an external floppy disk drive, then the +2A
will be, to all intents and purposes, a +3. This will be indicated
by the opening message on the screen (which displays the model
number +3 (at the top of the menu box)).

How to read this book


In order to get the best out of your +2A, it is vital that you
read all the relevant information provided in this manual. If you
skip various sections, it is likely that you will come to a
grinding halt later on!

Therefore, you should adopt the following reading programme...

Chapter 1 - This chapter shows you how to connect up your +2A


system. Note especially the safety warnings regarding the wiring-
up of the mains plug.

Chapter 2 - This chapter describes the switching on of the +2A and


shows you how to tune-in your TV to display the computer's signal.
You are then shown how to select an option from the 'opening menu'
- and if you don't know how to do that, you'll not be able to use
the +2A at all! If, however, you do know how to tune-in your TV
and select menu options (perhaps by having previously used a
Spectrum 128, +2 or +3), then you may skip this chapter.

Chapter 3 - This chapter shows you how to load commercially


available disk software. If you have not connected an external
disk drive to the +2A, or never intend to use such software, then
you may skip this chapter.

Chapter 4 - This chapter shows you how to load commercially


available pre-recorded tape software. If you never intend to use
such software, then you may skip this chapter.

Chapter 5 - This chapter covers the use of an external disk drive.


You may skip this chapter if you never intend to connect a disk
drive to the system. Note that if you have connected a second
external disk drive, then throughout this manual you should take
any general references to the 'disk drive' as meaning both drives.

Chapter 6 - This chapter introduces you to +3 BASIC. In


particular, it describes the editor and certain aspects of BASIC
programming that differ from those of other computers. Therefore,
even if you are an experienced BASIC programmer on another
computer, you should still read this chapter. Note that if you
have connected an external disk drive to the +2A, you'll require a
blank CF-2 floppy disk as you work through this chapter. If,
however, you never intend to program in BASIC and have purchased
the +2A solely to load and run commercially available software
(eg. games), then you may skip this chapter.

Chapter 7 - This is a chapter that you may freely skip. It


describes the 48 BASIC mode (in which the +2A operates exactly
like the 'old-style' Spectrum - even in the editing and
programming aspects). This mode is not recommended for anything
other than a history lesson for the curious, or for loading old
(Spectrum 48 only) tape software. You should certainly not use
this mode for BASIC programming; indeed you cannot access many of
the advanced features of the +2A (including support for disk
drive(s), extra memory, RS232/MIDI/AUX interfaces or RAMdisk) from
48 BASIC. Notwithstanding the above, we have provided the relevant
information in this chapter for your reference.

Chapter 8 - This chapter forms the very heart of the manual. It is


a complete guide to BASIC programming on the +2A. If you have
programmed in BASIC before, then you may wish to use this chapter
merely as a reference guide, searching the main index to find the
information you need from one of the subsections. If, on the other
hand, you are new to BASIC, you may wish to work through the
chapter, one subsection at a time, developing your programming
skills as you go. Once you are able to type in and run a program,
and have grasped a few of the fundamentals of BASIC, then you may
feel confident about skipping ahead to later subsections. If,
however, you never intend to program in BASIC and have purchased
the +2A solely to load and run commercially available software
(eg. games), then you may skip this chapter.

Chapter 9 - This chapter shows you how to use the +2A as a


calculator only. You may skip this chapter if you wish.

Chapter 10 - This chapter illustrates how add-ons (peripherals)


are connected to the +2A. Peripherals include such devices as disk
drives, printers, joysticks, etc. So if you're thinking of linking
up any device at all to the +2A, check this chapter to make sure
that you've got the right connections. If, on the other hand, you
intend to use just the standard +2A set up (ie. computer and TV
only), then you may skip this chapter.
© Copyright 1987 - AMSTRAD Plc.
Neither the whole nor any part of the information contained
herein, nor the product described in this manual, may be adapted
or reproduced in any material form except with the prior written
approval of AMSTRAD Plc. ('AMSTRAD').

The product described in this manual, and products for use with it
are subject to continuous development and improvement. All
information of a technical nature and particulars of the product
and its use (including the information and particulars in this
manual) are given by AMSTRAD in good faith.

All maintenance and service on the product must be carried out by


Sinclair authorised dealers. AMSTRAD cannot accept any liability
whatsoever for any loss or damage caused by service or maintenance
by unauthorised personnel. This guide is intended only to assist
the reader in the use of the product, and therefore, AMSTRAD shall
not be liable for any loss or damage whatsoever arising from the
use of any information or particulars in, or any error or omission
in, this guide or any incorrect use of the product.

We ask that all users take care to submit their user


registration/guarantee cards.

All correspondence relating to the product or to this manual


should be addressed to:

Sinclair Computers Division


AMSTRAD Plc
Brentwood House
169 Kings Road
BRENTWOOD
Essex CM14 4EF

First Published 1987

Written by Ivor Spital


Contributions by Cliff Lawson and Rupert Goodwins
Produced by Des Rackliff

Extracts from the book 'ZX Spectrum BASIC programming'


written by Steven Vickers and Robin Bradbeer

Published by AMSTRAD

+3DOS written by Locomotive Software Ltd.


CP/M is the trademark of Digital Research Inc.
LocoScript is the trademark of Locomotive Software Ltd.
Acknowledgements to Centronics and Epson Corps.

The following are registered trademarks of AMSTRAD Plc.:


Sinclair ZX Spectrum, +2A, +2, +3, +3DOS
AMSTRAD, AMSDOS, PCW8256, PCW8512,
CPC464, CPC664, CPC6128
DMP2000, DMP3000, DMP3160, DMP4000, FD-1, SI-1
AMSOFT, CF-2, PL-1

Unauthorised use the above trademarks, or of the word AMSTRAD, is


strictly forbidden.
Precautions!
You must read this....
(Don't worry if you are a little baffled by some of the technical
jargon on this page; the importance of these warnings will become
clearer as you work through this manual.)

1. Always connect the mains lead of the power supply unit (PSU)
to a 3-pin plug following the instructions given in chapter
1.

2. Do not attempt to connect the PSU to any mains supply other


than 220-240V AC50Hz.

3. After you have finished using the +2A, always disconnect the
PSU from the mains supply socket.

4. There are no user serviceable parts inside the equipment - DO


NOT ATTEMPT TO GAIN ACCESS INSIDE THE PSU - THERE ARE HIGH
VOLTAGES INSIDE. Refer all servicing to qualified service
personnel.

5. Do not block or cover the ventilation slots in the equipment.

6. Do not use or store the equipment in excessively hot, cold,


damp, or dusty areas.

7. Never plug in (or unplug) any device from any of the rear
sockets while the +2A is switched on - doing so will probably
damage both the +2A and the device.

8. If you have connected an external disk drive (and interface)


to the +2A, keep the ribbon cable away from mains leads.

9. After you have switched off your TV (or VDU monitor), do not
immediately disconnect the +2A - wait a few seconds or so.

10. Do not switch off the +2A (or switch on or off any peripheral
devices connected to the +2A) while there is a program or
data in the memory that you wish to keep - doing so may make
the +2A 'crash', losing the program or data.

11. (If you are using disks), always keep the disk drive and any
disks away from magnetic fields. For maximum data
reliability, do not position the disk drive close to your TV
or monitor, or close to any source of electrical
interference.

12. (If you are using disks), never switch the system on or off
while a disk is inserted in the disk drive. Doing so may
corrupt your disk, losing valuable programs or data.
13. (If you are using disks), whenever possible, make back-up
(duplicate) copies of disks which contain valuable programs.
Otherwise, should you accidentally lose or corrupt the disk
replacing it may prove very expensive.

14. (If you are using disks), never touch the floppy disk surface
itself, inside its protective casing.

15. (If you are using disks), do not eject a disk while it is
being read from or written to.

16. (If you are using disks), always remember that formatting a
disk will erase its previous contents.
Chapter 1
Open the box

Subjects covered...

Unpacking
Fitting a mains plug
Setting up

Unpacking
Inside the carton, you'll find the following...

The Spectrum +2A computer


The power supply unit (PSU)
The aerial lead
This manual (together with your user registration/guarantee card)
Fitting a mains plug
The power supply unit for the Spectrum +2A operates from a 220-240
Volt AC 50Hz mains supply.

Fit a proper mains plug to the mains lead of the power supply
unit. If a 13 Amp (BS1363) plug is used, a 3 Amp fuse must be
fitted. The 13 Amp fuse supplied in a new plug must NOT be used.
If any other type of plug is used, a 5 Amp fuse must be fitted
either in the plug or adaptor or at the distributor board.

IMPORTANT - The wires in this mains lead are coloured in


accordance with the following code...

Blue : Neutral

Brown : Live

As the colours of the wires in the mains lead of this apparatus


may not correspond with the coloured markings identifying the
terminals in your plug, proceed as follows...

The wire which is coloured BLUE must be connected to the terminal


which is marked with the letter N or coloured black.

The wire which is coloured BROWN must be connected to the terminal


which is marked with the letter L or coloured red.

Disconnect the mains plug from the supply socket when not in use.

Do not attempt to remove any screws, nor open the casing of the
power supply unit. Always obey the warning on the rating label of
the power supply unit...

WARNING: LIVE PARTS INSIDE - DO NOT REMOVE ANY SCREWS

Setting up
We will now set up the standard +2A system. All you need (other
than the items you unpacked) is a standard TV set (UHF). You can
use a colour or black-and-white TV, but of course, with the latter
you will not be able to enjoy the full colour capabilities of your
+2A.

Note that if you wish to attach one or more add-ons, or


peripherals, (eg. printer, joystick(s), disk drive(s), monitor,
audio amplifier, MIDI device, modem or other serial/expansion
device) to your +2A system, you should turn to chapter 10
(Peripherals for your +2A).

Place the +2A computer on a suitable flat surface, ready to be


connected to your TV. Next, remove any plug which is already
connected to the aerial socket at the back of the TV. Using the
aerial lead provided with your +2A, insert the larger plug into
the TV's aerial socket, and insert the smaller plug into the
socket marked TV at the back of the +2A.

Finally, insert the 6-pin DIN plug coming from the power supply
unit into the socket marked PSU at the back of the +2A.

The +2A system is now ready to be switched on.

The standard +2A system set up


Chapter 2
Operating your +2A

Subjects covered...

Switching on
Tuning-in your TV
Using the +2A
The opening menu

Switching on
Connect the mains plug of the power supply unit to the mains
supply socket, and switch on the socket-switch (if necessary). The
power indicator lamp on the top panel of the +2A should
illuminate.

Now switch on your TV. On the screen you will probably see either
a faint TV picture or just random 'white noise' and hear a loud
'hissing' sound from the TV's speaker. Adjust the TV's volume
control until the sound is at a comfortable listening level. The
next thing to do is set up the +2A ready for tuning-in.

Preparing to tune-in your TV


The +2A is capable of generating its own test signal, enabling you
to tune-in the TV accurately. The test signal consists of sixteen
vertical colour bars (overprinted with text characters) which
appear on the TV screen, and a repeating tone which is reproduced
through the TV's speaker. (If you are using a black-and-white TV,
then the colour bars appear as varying shades of grey.) You will
see and hear the test signal when you have completed the tuning-in
of your TV (described ahead).
Switch on the test signal by holding down the BREAK key (at the
top right of the keyboard) and while it is held down, press and
release the RESET button (at the left hand side of the +2A). Keep
the BREAK key held down for a few seconds longer, then release it.
The test signal will now be generated by the +2A, and you should
proceed to tune-in your TV as now described.

Push-button TV channel selectors


If your TV doesn't have push-button channel selectors, then skip
to the section ahead entitled 'Manual tuning'.

If your TV does have push-button channel selectors, then press one


of them to select a spare channel (ie. one not normally used for
receiving TV or video programmes). Note that if your TV is
equipped with an AFC (or AFT) switch, then this should be set to
the off position.

Using the tuning control that corresponds to the selected channel,


tune-in to the test signal (shown on the previous page). Make sure
that both picture and sound are tuned-in for the best possible
results.

When you are satisfied with the tuning, then you may (if your TV
is so equipped) set the AFC (or AFT) switch to the on position.

Finally, adjust the TV's brightness, contrast and colour controls


for the clearest display of the text characters within the colour
bars.

Now that you have tuned-in one of the TV's push-button channel
selectors specifically for the +2A, you may thereafter select that
particular channel whenever you wish to use the +2A with your TV.

You may now skip to the section ahead entitled 'Using the +2A'.

Manual tuning
If your TV isn't equipped with push-button channel selectors, then
you will have to use the TV's manual tuning knob to tune-in to
your +2A.

Having connected and switched on the +2A and TV, switch on the
+2A's test signal as described in the previous section entitled
'Preparing to tune-in your TV'.

Tune-in the TV's manual tuning knob until the test signal is
received. Make sure that both picture and sound are tuned-in for
the best possible results.
Finally, adjust the TV's brightness, contrast and colour controls
for the clearest display of the text characters within the colour
bars.

Each time that you wish to set up and use the +2A with your TV,
you should follow the above manual tuning procedure.

You may now skip to the section ahead entitled 'Using the +2A'.

Having problems?
If you have tuned-in your TV satisfactorily, you may now skip to
the section ahead entitled 'Using the +2A'.

If, however, you are unable to tune-in your TV, the following
check list may help you to ascertain where the problem lies, and
what remedial action you can take.

1. Problem...

The power indicator lamp (on the top panel of the +2A) is not
illuminated.

Action...

● Check 6-pin DIN plug from power supply unit is plugged into PSU
socket on computer.
● Check mains plug of PSU is plugged into mains supply socket.
● (If mains supply socket is switched) - Check supply socket
switch is on.
● Check connections and fuse in mains plug of PSU.

2. Problem...

The power indicator lamp is illuminated, but no signal whatsoever


can be tuned-in on the TV.

Action...

● Check TV is set up and working correctly.


● Check TV is standard UHF type (colour or black-and-white).
● Check aerial lead (supplied) is connected from computer to TV
aerial socket.
● (If you have push-button channel selectors) - Check you are
tuning-in the channel you selected.

3. Problem...

Only a poor signal from the computer can be tuned-in on the TV.
Action...

● Check TV is set up and working correctly.


● Check aerial lead (supplied) is fully plugged into computer and
TV aerial socket.
● (If TV is so equipped) - Check AFC (or AFT) switch is set to off
position.
● Check tuning-in has been carried out as accurately as possible.

4. Problem...

A signal from the computer is being tuned-in, but it's not the
test signal described above.

Action...

● Check computer's test signal has been switched on (as described


in the previous section entitled 'Preparing to tune-in your
TV').

5. Problem...

The test signal colour bars appear, but no sound (repeating tone)
is audible from the TV's speaker.

Action...

● Check TV's volume control is not at minimum.


● Check tuning-in has been carried out as accurately as possible.

6. Problem...

The test signal sound (repeating tone) can be heard, but no colour
bars can be seen on the TV.

Action...

● Check TV's brightness, contrast and colour controls are not at


minimum.
● Check tuning-in has been carried out as accurately as possible.

7. Problem...

The test signal colour bars and sound are tuned-in, but none of
the text characters can be read.

Action...

● Check tuning-in has been carried out as accurately as possible.


● Check TV's brightness, contrast and colour controls are adjusted
for best results.
If you cannot identify the cause of your problem, try carrying out
the entire procedure (from the beginning of this chapter) again.
If the problem still persists, contact your Sinclair dealer.

Using the +2A


The +2A system should now be fully set up, with the test signal
colour bars on the screen, and the repeating tone coming from the
TV's speaker.

We will now switch off the test signal and start using the +2A.
Press and release the RESET button (at the left hand side of the
+2A). The test signal will disappear from the screen, and in its
place will be the opening menu.

The opening menu

The opening menu will appear whenever you first plug in and switch
on the +2A, or whenever you press and release the RESET button.

If you have connected an external floppy disk drive (or drives),


then the +2A will be, to all intents and purposes, a +3. This will
be indicated by the opening menu which displays the model number
+3 (at the top of the menu box).

As its name suggests, the menu offers you a selection of options.


You can choose from one of the four options which appear within
the central box on the screen. These are...

Loader - Choose this option if you wish to load Spectrum


+3, +2 (+2A) or Spectrum 128 software.

+3 BASIC - Choose this option if you wish to use the +2A


for BASIC programming.

Calculator - Choose this option if you wish to use the +2A as


a calculator only.

48 BASIC - Choose this option if you wish to load Spectrum


48 software from tape (or wish to use the +2A as a
48K Spectrum).
How to choose an option
Notice that the menu option Loader appears to be highlighted by a
'bar'. This means that the Loader option is ready to be selected -
(the selection hasn't been confirmed yet). For the purpose of this
example, let's assume that you don't want to select Loader, but
that instead, you want to select +3 BASIC. This means that you
need to move the highlight bar to the option +3 BASIC. To do this,
use the cursor keys (shown below) until the highlight bar moves to
the desired position.

Cursor Keys

When the highlight bar is on +3 BASIC, confirm this choice by


pressing the ENTER key.

The computer then switches to the +3 BASIC mode. You will see a
black horizontal bar (containing the words +3 BASIC) towards the
bottom of the screen, and a flashing blue and white blob (called
the cursor) at the top left-hand corner.

Don't worry if you know nothing about BASIC - we're not going to
do any programming just yet - we'll simply return to the opening
menu again. To do this, we use a different menu - this one's
called the edit menu. Call up the edit menu by pressing the EDIT
key.

Again, using the cursor keys and ENTER, select the option Exit to
return to the opening menu.
You may now select whichever opening menu option you require.
Depending upon your selection, refer to the following chapters for
further information...

Loader - Refer to chapters 3 and 4.

+3 BASIC - Refer to chapters 6 and 8.

Calculator - Refer to chapter 9.

48 BASIC - Refer to chapters 4 and 7.

IMPORTANT - Whenever you have finished using the +2A, always


disconnect the power supply unit from the mains supply socket.
Chapter 3
How to load disk software

Subjects covered...

Disks and drives for the +2A


Loading disk software
Abandoning loading

If you do not intend to connect an external disk drive to the +2A,


then you may skip this chapter (which describes the loading of
commercially available disk software).

(For a description of the loading, saving, formatting, etc.,


procedures that you would use during BASIC programming, see
chapter 6 and chapter 8 part 20.)

Note that Spectrum 48 software is not available on disk.

Disks and drives for the +2A


If you wish to connect an external disk drive to the +2A, you
should use the model AMSTRAD FD-1 together with a suitable
interface (the AMSTRAD SI-1 when available, or other
manufacturer's equivalent). See chapter 10 (Peripherals for your
+2A) for further details.

The AMSTRAD FD-1 uses 3 inch compact floppy disks. We strongly


recommend that for reliable data-to-disk transfer, you use AMSOFT
CF-2 compact floppy disks. Disks made by other leading
manufacturers, however, may also be used.

Each side of a disk may be used independently. A disk should be


inserted with its label facing outward from the drive, and with
the side that you wish to use face up...
Loading disk software
To load software (a game, an utility program, etc.) from disk,
carry out the following instructions...

1. Set up the +2A and FD-1 together. First switch on the FD-1
(using the POWER ON/OFF switch at the back of the disk
drive), then switch on the +2A. The opening menu will appear
on the screen...

(As you have connected an external disk drive, the +2A is, to all
intents and purposes, a +3. This will be indicated by the opening
message on the screen (which displays the model number +3 (at the
top of the menu box)).

2. Insert your software disk into the disk drive.

3. Press the ENTER key to select the option Loader from the
opening menu. (If you don't know about selecting menu
options, refer back to chapter 2).

The software will start to load from disk. On the disk drive, you
will see the read/write indicator lamp start to flash on and off
(indicating that the disk is being read from). After a few
seconds, the screen display will change and the software will be
loaded, ready to use.

When you have finished using the software and wish to use the +2A
for something else, press and release the RESET button (at the
left-hand side of the +2A). Always remember that whenever the
RESET button is pressed, everything in the computer's memory (RAM)
is cleared. You should therefore always make sure that you have
completely finished with any program in the +2A's memory, before
you press the button.

If you are going to switch off the +2A completely, remember to


remove any disk from the disk drive first.

Abandoning loading
If you wish to abandon a loading operation, simply press and
release the RESET button. The +2A will return to the opening menu.
Chapter 4
How to load tape software

Subjects covered...

The datacorder
Loading Spectrum +3, +2 (+2A)
and Spectrum 128 software
Loading Spectrum 48 software
Abandoning loading

This chapter describes the loading of commercially available pre-


recorded tape software.

(For a description of the loading, saving, formatting, etc.,


procedures that you would use during BASIC programming, see
chapter 6 and chapter 8 part 20.)

The datacorder
Familiarise yourself with the keys on the datacorder...

Spectrum +3, +2 (+2A) and


Spectrum 128 software
To load Spectrum +3, +2 (+2A) and Spectrum 128 software (a game,
an utility program, etc.) from tape, carry out the following
instructions...
1. Switch on the system so that the opening menu appears on the
screen...

2. If you have connected an external disk drive to the +2A, make


sure that a disk is not inserted.

3. Press the ENTER key to select the option Loader from the
opening menu. (If you don't know about selecting menu
options, refer back to chapter 2.)

Now skip to the section ahead entitled 'Loading from tape'.

(If you have connected an external disk drive to the +2A, note
that when you select the Loader option from the opening menu, the
+2A knows that you wish to load from tape (instead of disk) by
automatically detecting the absence of a disk in the disk drive.
If a disk is inserted, the tape will be ignored.)

Spectrum 48 software
To load Spectrum 48 software (a game, an utility program, etc.)
from tape, carry out the following instructions...

1. Switch on the system so that the opening menu appears on the


screen...

2. Select the option 48 BASIC from the opening menu. (If you
don't know how to select a menu option, refer back to chapter
2.) The opening menu will disappear and the following message
will be displayed at the bottom of the screen...
3. Now press the J key once, followed by the " (double quotes)
key twice. The screen should look like this...

When you see this message, press ENTER.

Now skip to the section ahead entitled 'Loading from tape'.

(If the screen does not correspond to the above picture, then you
may have selected the wrong menu option or pressed the wrong key.
In this case, press and release the RESET button (at the left-hand
side of the +2A) and carry out steps 2 and 3 again.)

Loading from tape


1. Insert the software tape into the datacorder and make sure
that it is rewound to the beginning.

2. Play the cassette. As loading commences, the border colour


will flash and appear striped, indicating that the program is
being 'read' from the tape. If your TV's volume control is
turned up, you will also hear a varying high-pitched tone.
Again, this is an indication that the program is being read.

Most commercially available software cassettes take a few minutes


to load. Initially, the program name may appear (toward the top
left-hand corner of the screen) possibly followed by various other
displays or messages (these will differ from program to program).

When the program has loaded, stop the cassette. The software is
then ready to use.
When you have finished using the software and wish to use the +2A
for something else, press and release the RESET button (at the
left-hand side of the +2A). Always remember that whenever the
RESET button is pressed, everything in the computer's memory (RAM)
is cleared. You should therefore always make sure that you have
completely finished with any program in the +2A's memory, before
you press the button.

Abandoning loading
If, while loading software from tape, you wish to abandon the
loading operation, then simply press and release the RESET button.
The +2A will return to the opening menu.

NOTE - Holding the BREAK key down while loading Spectrum +3, +2
(+2A) or Spectrum 128 software will return the +2A to the opening
menu; holding the key down while loading Spectrum 48 software will
return the +2A to the 48 BASIC mode.
Chapter 5
Using a disk drive

Subjects covered...

Disks and drives for the +2A


Insertion
Write protection
Read/write indicator lamp
Eject button

Disks and drives for the +2A


If you wish to connect an external disk drive to the +2A, you
should use the model AMSTRAD FD-1 together with a suitable
interface (the AMSTRAD SI-1 when available, or other
manufacturer's equivalent). See chapter 10 (Peripherals for your
+2A) for further details.

The AMSTRAD FD-1 uses 3 inch compact floppy disks. We strongly


recommend that for reliable data-to-disk transfer, you use AMSOFT
CF-2 compact floppy disks. Disks made by other leading
manufacturers, however, may also be used.

If you have connected a single disk drive to the +2A, then note
that the drive is known as drive A:. If you have connected two
disk drives to the +2A, then note that the first drive is known as
drive A: and the second drive is known as drive B:.

Insertion
Each side of a disk may be used separately. A disk should be
inserted with its label facing outward from the drive, and with
the side that you wish to use face up...
Write protection
In the left-hand corner of each side of a blank disk, you will see
an arrow pointing to a small shuttered hole. This is called the
write protect hole, and allows you to protect the contents of the
disk from erasure or 'overwriting'...

When the hole is closed, data can be 'written' onto the disk by
the computer. When the hole is open, however, the disk will not
allow data to be written onto it, thus enabling you to avoid the
accidental erasure of valuable programs.

Various disk manufacturers employ differing mechanisms for opening


and closing the write protect hole. The operation may be carried
out on the AMSOFT CF-2 compact floppy disk as follows:

To open the write protect hole, slide back the small shutter
located at the left-hand corner of the disk and the hole will be
opened...

Once the hole is open, write protection is ON.

To close the write protect hole, simply slide the shutter to its
closed position. Write protection is then OFF.
Other manufacturers' disks employ a small lever located in a slot
at the left-hand corner...

To open the write protect hole on this type of disk, slide the
lever towards the middle of the disk (using the tip of a ball-
point pen or similar object)...

Note that regardless of the method employed to open and close the
write protect hole, opening the hole in all cases facilitates
protection against overwriting.

When your disk is in


At the front of the disk drive, you will see a push button (for
ejecting the disk), and a red lamp (called the read/write
indicator lamp)...
Read/write indicator lamp
This lamp indicates that data is being read from or written to the
disk. Note, however, that if two disk drives are connected, the
read/write indicator lamp on drive B: will be constantly on
(except when drive A: is reading or writing to disk).

Eject button
Pressing in the eject button allows you to remove your disk from
the disk drive.

Do not press the eject button while the disk is being read from or
written to.

Always eject your disk from the disk drive before switching the
system off.
Chapter 6
Introducing +3 BASIC

Subjects covered...

The editor
The edit menu
Renumbering a BASIC program
Swapping screens
Listing to the printer
Typing in a program
Moving the cursor
Running a program
Commands and instructions
Saving to tape
Verifying the tape
Loading from tape
Formatting a disk
Saving to disk
Filenames
Disk catalog
Loading from disk
Error reports

The +2A has an advanced editor to create, modify and run BASIC
programs. To enter the editor, select the option +3 BASIC from the
opening menu, using the cursor keys and ENTER. (If you don't know
how to select a menu option, refer back to chapter 2.)

The screen should now look like this...


There are three things to notice about this screen.

Firstly, there is a flashing blue and white blob in the top left-
hand corner. This is called the cursor, and if you type any
letters at the keyboard, then they will appear on the screen at
the position of the cursor.

Secondly, there's a black bar towards the bottom of the screen.


This is called the footer bar, and tells you which part of the
+2A's built-in software you're using. At the moment, it says +3
BASIC because that's the name of the editor (if you read the
introduction to this manual, you will remember that the +2A uses
the same BASIC as provided with the +3).

The last item of note at the moment is the small screen. This fits
between the footer bar and the bottom of the screen, and is
currently blank. It only has room for two lines of text, and is
most often used by the +2A when it detects an error and needs to
print a report to say so. It does have other uses, however, and
these will be described later.

Now press the EDIT key. You will notice two things happen - the
cursor vanishes, and a new menu appears. This is called the edit
menu...

The edit menu's options are selected in the same way as for the
opening menu (by using the cursor keys and ENTER).

Taking the options in turn...

+3 BASIC - This option simply cancels the edit menu and restores
the cursor. On the face of it - not very useful; however, if EDIT
is pressed accidentally, then this option allows you to return to
your program with no damage done.

Renumber - BASIC programs use line numbers to determine the order


of the instructions to be carried out. You enter these numbers
(which can be any whole-number from 1 to 9999) at the beginning of
each program line you type in. Selecting the Renumber option
causes the BASIC program's line numbers to start at line 10 and go
up in steps of 10. BASIC commands which include references to line
numbers (such as GO TO, GO SUB, LINE, RESTORE, RUN and LIST) also
have these references renumbered accordingly.
If for any reason it's not possible to renumber, perhaps because
there's no program in the +2A, or because Renumber would generate
line numbers greater than 9999, then the +2A makes a low-pitched
bleep and the menu goes away.

A useful aid to this renumbering facility can be found in chapter


8 part 33.

Screen - This option moves the cursor into the smaller (bottom)
part of the screen, and allows BASIC to be entered and edited
there. This is most useful for working with graphics, as any
editing in the bottom screen does not disturb the top screen. To
switch back to the top screen (which you can do at any time whilst
editing), select the edit menu option Screen again.

Print - If a printer is connected, this option will print-out a


listing of the current program to it. When the listing has
finished, the menu will go away and the cursor will come back. If
for some reason the computer cannot print (eg. the printer is not
connected or is off-line), then pressing the BREAK key twice will
return you to the editor.

Exit - This option returns you to the opening menu - the +2A
retains any program that you were working on in the memory. If you
wish to go back to the program again, select the option +3 BASIC
from the opening menu.

If you select the opening menu option 48 BASIC (or if you switch
off or reset the +2A), then any program in the memory will be
lost. (You may, however, use the opening menu option Calculator
without losing a program in the memory.)

Reset the computer and select +3 BASIC. Now type in the line
below. As you type it in, the characters will appear on the screen
(a character is a letter, number, space, etc.). Note that to type
in the equals sign = you should hold down the SYMB SHIFT key, then
press the L key once. Try typing in the line now...

10 for f=1 to 100 step 10

...then press ENTER. Providing you have spelt everything


correctly, the +2A should have reprinted the line with the words
FOR, TO and STEP in capital letters, like this...

10 FOR f=1 TO 100 STEP 10

The +2A should have also emitted a short high-pitched bleep, and
moved the cursor to the start of the next line.

If the line remains in small letters and you hear a low-pitched


bleep, then this indicates that you have typed in something wrong.
Note also that the colour of the cursor changes to red when a
mistake is detected, and you must correct the line before it will
be accepted by the +2A. To do this, use the cursor keys to move to
the part of the line that you wish to correct, then type in any
characters you wish to insert (or use the DELETE key to remove any
characters you wish to get rid of). When you have finally
corrected the line, press ENTER.

Now type in the line below...

(The colon : is obtained by SYMB SHIFT and Z, and the minus sign -
is obtained by SYMB SHIFT and J.)

20 plot 0,0:draw f,175:plot 255,0:draw -f,175

...then press ENTER. On the screen you will see...

10 FOR f=1 TO 100 STEP 10


20 PLOT 0,0: DRAW f,175: PLOT
255,0: DRAW -f,175

Don't worry about line 20 'spilling over' onto the next line of
the screen - the computer will take care of this and align the
text so that it is easier to read. Unlike a typewriter, there's no
need for you to do anything when you approach the end of a screen
line because the +2A detects this automatically and moves the
cursor to the beginning of a new line.

The final line of this program to type in is...

30 next f

...again, press ENTER.

The numbers at the beginning of each line are called line numbers
and are used to identify each line. The line you just typed in is
line 30, and the cursor should be positioned just below it. As an
exercise, we will now edit line 10 (to change the number 100 to
255). Press the cursor up ↑ key (four times) until the cursor has
moved up to line 10. Now press the cursor right → key until the
cursor has moved to the right of 100. Press DELETE three times and
you will see the 100 disappear. Now type in 255 and press ENTER.
Line 10 of the program has now been edited...

10 FOR f=1 TO 255 STEP 10

The computer has opened up a new line in preparation for some new
text. Type...

run

Press ENTER and watch what happens. Firstly, the footer bar and
the program lines are cleared off the screen as the +3 BASIC
editor prepares to hand over control to the program you've just
typed in. Then the program starts, draws a pattern, and stops with
the report...

0 OK, 30:1

Don't worry about what this report means.

Press ENTER. The screen will clear and the footer bar will come
back, as will the program listing. This takes about a second or
so, during which time the +2A won't be taking input from the
keyboard, so don't try to type anything while it's all happening.

You've just done most of the major operations necessary to program


and use a computer! First, you've given the +2A a list of
instructions. Instructions tell the +2A what to do (like the
instruction 30 NEXT f). Instructions have a line number and are
'stored away' rather than used immediately you type them in. Then
you gave the +2A the command RUN to execute the stored program.

Commands are just like instructions, only they don't have line
numbers and the +2A carries them out immediately (as soon as ENTER
is pressed). In general, any instruction can be used as a command,
and vice versa - it all depends on the circumstances. Every
instruction or command must have at least one keyword. Keywords
make up the vocabulary of the computer, and many of them require
parameters. In the command DRAW 40,200 for example, DRAW is the
keyword, while 40 and 200 are the parameters (telling the computer
exactly where to do the drawing). Everything the computer does in
BASIC will follow these rules.

Now press EDIT and select the Screen option. The editor moves the
program down into the bottom screen, and gets rid of the footer
bar. You can only see line 10 of the program as the rest is
'hiding' off-screen (you can prove this by moving the cursor up
and down).

Press ENTER then type...

run

Press ENTER again, and the program will run exactly the same as
before. But this time, if you press ENTER afterwards, the screen
doesn't clear, and you can move up and down the program listing
(using the cursor keys) without disturbing the top screen. If you
press EDIT to get the edit menu, you might think that this would
mess up the top screen. However, the +2A remembers whatever's
behind the edit menu and restores it when the menu is removed.

To prove that the editor really is working in the bottom screen,


press ENTER and change line 10 to...

10 FOR f=1 TO 255 STEP 7


...by moving the cursor to the end of line 10 (just to the right
of STEP 10), then pressing DELETE twice, and typing 7 (press
ENTER).

Now type...

go to 10

(Press ENTER.) The keywords GO TO tell the +2A not to clear the
screen before starting the program. The modified program draws a
slightly different pattern on top of the old one. You may continue
editing the program to add further patterns, if you wish.

A word of warning - while editing in the bottom screen, don't try


to edit instructions which are more than two screen lines long.
Otherwise, when the editor comes across an instruction which has
its beginning or its end off-screen, it may become 'confused'.
(The same is true of the top screen, but of course, this is
unlikely to cause any problems as the top screen is so much
larger.)

One thing you may notice while you're typing away is that CAPS
SHIFT and the number keys used together do strange things: CAPS
SHIFT with 5, 6, 7 and 8 move the cursor about, CAPS SHIFT with 1
calls up the edit menu, CAPS SHIFT with 0 deletes a character,
CAPS SHIFT with 2 is equivalent to CAPS LOCK, and finally CAPS
SHIFT with 9 selects graphics mode. All of these functions are
available using the dedicated keys on the +2A, and so there is no
reason why you should ever want to use the above CAPS SHIFT and
number key alternatives.

Saving and loading


You have now seen how to place a program into the computer's
memory by typing it in. This is all very well the first time you
write a particular program, but what about if you switch off the
computer and want to use the same program the next day? Surely you
don't have to type it all in again from scratch - the answer, of
course, is no - the datacorder section of the +2A allows you to
save a program from the computer's memory onto tape, and to load a
program from tape into the computer's memory. This means that you
can type in a program, save it to tape, then happily switch off
the +2A knowing that next time you switch it on, you'll be able to
load that same program back into the memory.

The final part of this chapter, therefore, deals with saving and
loading to and from tape using the +2A's built-in datacorder. If
you have connected a disk drive to the +2A, then the section ahead
entitled 'Simple disk operations' will show you how to save and
load to and from disk.
We will now save the program below...

10 FOR f=1 TO 255 STEP 7


20 PLOT 0,0: DRAW f,175: PLOT
255,0: DRAW -f,175
30 NEXT f

...which should still be in the memory from the previous exercise


(check that the above program is currently in the memory by
pressing ENTER then typing...

list

(Press ENTER again.) If the program isn't in the memory (or you
have since switched off the +2A), then switch it on, select +3
BASIC and type in the above program).

This is the program that you are going to save onto tape. Any
standard tape cassette should work, although low noise cassettes
may be better.

Saving to tape
If you have connected a disk drive to the +2A, then the system
assumes that you will want to save programs to disk. If, instead,
you wish to save programs to tape, you must first type in the
command...

save "t:"

...and press ENTER. (If you have not connected a disk drive to the
+2A, there is no need to issue this command.)

In order that each program file on tape can be identified, you


must give the program a filename when you save it. For example, as
the program that you are about to save draws a pattern, save the
program using the name 'my pattern', ie. type in...

save "my pattern"

...and press ENTER.

Although we chose the filename 'my pattern', you can choose any
filename you like for the program to be saved under. (You are
allowed up to ten characters in a tape filename.)

The +2A will display the message...

Press REC & PLAY, then any key.

We shall first go through a 'dry run' so that you can see what
will happen when we actually do save the program later. This time,
therefore, don't press the record and play keys on the datacorder
- just press a key on the keyboard (for example ENTER) and watch
the border of the TV screen. You will see patterns of coloured
horizontal stripes as follows:

Five seconds of red and cyan stripes moving slowly upwards,


followed by a very short burst of blue and yellow stripes.

A short pause.

Two seconds of the red and cyan stripes again, followed by another
short burst of blue and yellow stripes.

While the stripes appear on the screen, you can also hear the
'sound' of the data through your TV's speaker.

Keep trying out the above SAVE command (without actually operating
the datacorder) until you can recognise these patterns. What's
actually happening is that the information is being saved in two
blocks and both blocks have a 'lead-in' (which corresponds to the
red and cyan stripes) followed by the information itself (which
corresponds to the blue and yellow stripes). The first block is a
preliminary one containing the name and various other bits of
information about the program, and the second is the program
itself together with any variables present. The pause between them
is just a gap.

Now let's actually save the program onto tape:

1. Wind the tape to an area that is either blank, or that you


are prepared to overwrite.

2. Type...

save "my pattern"

..and press ENTER.

3. Follow the instructions on the screen, ie...

Press REC & PLAY, then any key.


4. Watch the screen as before. When the +2A has finished (with
the report 0 OK), stop the tape.

Verifying the tape


When you have successfully saved a program, you can happily switch
off or reset the computer, knowing that you could always load in
the saved program if you needed it. However, before clearing the
saved program from the computer's memory, you should always make
sure that the save worked correctly - you can check the signal on
the tape against the program in the memory using the VERIFY
command:

1. If you have connected a disk drive to the +2A and wish to


verify a tape, then you must first type in the command...

load "t:"

...and press ENTER. (If you have not connected a disk drive to the
+2A, there is no need to issue this command.)

2. Rewind the tape to just before the point at which you saved
the program.

3. Type...

verify "my pattern"

...press ENTER and play the tape. The border will alternate
between red and cyan until the +2A finds the program you
specified. Again, you will see the stripes appearing on the border
(as you did when you saved the program) and you will hear the
'sound' of the data through your TV's speaker. During the pause
between the blocks, the message Program: my pattern will be
displayed on the screen. (When the +2A is searching for something
on tape, it displays the name of everything it comes across.) If,
after the program name appears, the computer displays the report 0
OK, then your program is safely stored and you may stop the tape
and skip to the section ahead entitled 'Loading from tape'. If
not, something has gone wrong - take the following steps to find
out what.

If the program name has not been displayed, then either the
program was not saved properly in the first place, or it was
saved, but was not 'read back' properly. You need to find out
which. To see if it was saved properly, rewind the tape to just
before the point at which you saved the program, then play it back
while listening to the TV's speaker. The (red and cyan) lead-in
should produce a clear, steady high pitched note, while the (blue
and yellow) information part gives a much harsher screech.
If you do not hear these noises, then the program was probably not
saved. Check that you were not trying to save the program onto the
plastic 'leader' at the beginning of the tape. When you have
checked this, try saving again.

If you can hear the sounds as described, then SAVE was probably
alright and your problem is with reading back.

It could be that you mistyped the program name when you saved it
(in which case, when the +2A finds the program, it will display
the mistyped name on the screen). On the other hand, perhaps you
mistyped the program name when you verified it, in which case the
computer will ignore the correctly saved program and carry on
looking for the wrong name, flashing red and cyan as it goes.

If there is a genuine mistake on the tape, then the +2A will


display the message R Tape loading error which, in this case,
means that it failed to verify the program. Note that a slight
fault on the tape itself (which might be inaudible with music) can
wreak havoc with a computer program. Try saving the program again,
perhaps on a different part of the tape (or a different tape
altogether).

Loading from tape


Assuming that you've saved the program and successfully verified
it, reset the computer and load the program back into the memory
as follows:

1. Press the RESET button and select the option +3 BASIC from
the opening menu.

2. If you have connected a disk drive to the +2A, type in the


command...

load "t:"

...(press ENTER) so that any program subsequently loaded is from


tape instead of disk. (If you have not connected a disk drive to
the +2A, there is no need to issue this command.)

3. Rewind the tape to just before the point at which you saved
the program.

4. Type in...

load "my pattern"

Press ENTER and play the tape.

(Since the program verified properly, you should have no problem


loading it.)
LOAD deletes the old program (and variables) in the memory when it
loads in the new one from tape.

Once a program has been loaded, the report 0 OK will appear, and
you may stop the tape. If you then press ENTER, the program will
be listed on the screen. To start the program, simply type...

run

As mentioned in chapter 4, it is possible to buy pre-recorded


programs (software) on tape. They must be specially written for
the ZX Spectrum range (ie. the Spectrum, the Spectrum +, the
Spectrum 128 or the Spectrum +2 (+2A) or +3. Other different makes
and models of computer have different ways of storing programs, so
they cannot use each other's tapes.

If your tape has more than one program stored on the same side,
then each program will have a name. You can choose the program you
wish to load using the LOAD command - for instance, if the program
you wanted to load was called 'helicopter', you would enter the
command...

load "helicopter"

If you enter the command...

load ""

...then the +2A will load the first program it finds on tape. This
can be useful if you wish to load a program whose name you can't
remember.

The option Loader from the opening menu has the same action as
LOAD "" and is much quicker to use - simply switch on the +2A and
press ENTER. If you have connected a disk drive to the +2A, make
sure that no disk is inserted.

(Note that you cannot use the Loader option to load Spectrum 48
software.)

Simple disk operations


If you have connected an external disk drive to the +2A, then this
section will show you how to save and load programs to and from
disk instead of tape.

If you have not connected an external disk drive to the +2A, then
you may skip the rest of this chapter.

You will need to have a brand new blank disk to hand as you work
through this section. Whatever you do - don't use a disk with any
valuable software, games, etc. on it.
Disks and tapes
Even if you are familiar with tape saving and loading, it is worth
pointing out two important points which must be remembered when
using disks:

Firstly, a brand new blank disk cannot be simply taken out of its
wrapper and recorded onto (as is the case with a tape) - instead,
each side of a disk must be formatted first. Note that the
formatting process completely erases that side of the disk and
prepares it for future use.

Secondly, it is important that disk files are correctly 'named'.


Filenames on tape may vary greatly in length and may at times be
omitted. Not so with disks - disk filenames must conform to very
strict standards (and you will read about these shortly in the
section ahead entitled 'Filenames').

Formatting a disk
Formatting can be likened to building a series of shelves and
pigeonholes on a disk prior to the storage of information on those
shelves. In other words, formatting lays down an organised
framework around which data can be put in or taken out.

The formatting process divides the disk into 360 distinctly


separate areas...

There are 40 concentric tracks from the outside of the disk (track
0) to the inside (track 39), and each track is divided into 9
sectors.
Each portion of track in a sector can store up to 512 bytes of
data; hence the total available space on each side of a disk is
180 kilobytes (180K). Note that 7K of the 180K is reserved for the
computer's own use; this leaves 173K per side for your programs.

We will now format a new blank disk, and save the program below...

10 FOR f=1 TO 255 STEP 7


20 PLOT 0,0: DRAW f,175: PLOT
255,0: DRAW -f,175
30 NEXT f

...which may still be in the memory from the previous exercise


(check that the above program is currently in the memory by
pressing ENTER then typing...

list

...and pressing ENTER again. If the program isn't in the memory


(or you have since switched off the +2A), then switch it on,
select +3 BASIC and type in the above program).

Insert side 1 of a new blank disk into the disk drive. (If you
have connected two disk drives to the +2A, use the first drive
(drive A:) for all operations shown in this section.)

Type...

format "a:"

(Press ENTER.) The read/write indicator lamp on the disk drive


will start to flash on and off. About 30 seconds later, you will
see the report...

0 OK, 0:1

You have now formatted side 1 of the disk. Once you have done
this, you should not need to format side 1 of that disk ever
again.

(If you don't receive the above report (and some other message
appears instead), check the section entitled 'Error reports' at
the end of this chapter.)

Saving to disk
Having formatted side 1, it is now ready for saving programs onto.

In order that each program file on a disk can be identified, you


must give the program a filename when you save it. For example, as
the program that you are about to save draws a pattern, save the
program using the name 'my.pat', ie. type in...
save "my.pat"

(Press ENTER.) After a few seconds, you will see the report...

0 OK, 0:1

The program is now saved onto disk.

(If you don't receive the above report (and some other message
appears instead), check the section entitled 'Error reports' at
the end of this chapter.)

Filenames
Note that a filename on disk consists of two parts (fields). The
first field is obligatory and can contain up to 8 characters
(letters and numbers may be used but no spaces or punctuation
marks). In the above example filename, 'my' is the first field.

The second field is optional. You can use up to 3 characters (but


again no spaces or punctuation). In the above example filename,
'pat' is the second field.

If you use two fields in a filename, they must be separated by a


dot (eg. 'my.pat').

Disk catalog
A catalog of the disk (in alphabetical order) can be displayed by
typing in...

cat

(Press ENTER.) The filenames of all the programs on that side of


the disk will be displayed, together with each file's length (to
the nearest higher kilobyte). The amount of free space will also
be indicated...

MY .PAT 1K

172K free

Loading from disk


Imagine that you had switched off the +2A and had later wanted to
load the program just saved. Do this now by resetting the +2A
(using the RESET button) and selecting the option +3 BASIC from
the opening menu. Type in...

load "my.pat"

(Press ENTER.) After a few seconds, you will see the report...
0 OK, 0:1

The program is now loaded from disk. Press ENTER and you will see
the program listing displayed.

(If you don't receive the above report (and some other message
appears instead), check the next section entitled 'Error
reports'.)

Once loaded, you may start the program by typing...

run

...and pressing ENTER, as before.

Error reports
If you don't correctly carry out the instructions in this section,
you may receive various error reports. If so, identify the report
(from those shown below), read the explanation given, and then
take the necessary corrective action.

Drive not ready

The above report means that you have probably forgotten to insert
a disk into the disk drive. If there is a disk inserted in the
disk drive, then eject it, re-insert it and try again.

Disk is write protected

The above report means that you are trying to format, or save a
program to, a disk which has its write protect hole open. Eject
the disk, close its write protect hole, re-insert the disk and try
again.

File not found

The above report means that you are trying to load a program which
doesn't exist on that side of the disk. Eject the disk, make sure
that the correct disk is inserted (the right way up) and try
again. Take care to ensure that you accurately type in the
filename to load.

Bad filename

...or...

Invalid filename

The above reports mean that you are trying to load or save a
program using an illegal filename (or no filename at all). Read
the section entitled 'Filenames' earlier in this chapter, and try
again.
Disk is already formatted
A to abandon, other key continue

The above report means that you are trying to format a disk that
has already been formatted. In general, a disk should need
formatting only once (at the beginning of its life). In rare
cases, a disk may become corrupted and there will be no
alternative other than to format it again. However, unless this is
the case, you should always type A (to abandon) when you see the
above report.

NOTE - If you don't type A, then the formatting process will go


ahead and completely erase that side of the disk (as soon as you
press a key).

If you find that one particular disk (or side of a disk) keeps
requiring formatting, then it is likely that the disk itself is
damaged and you should avoid using it in future.

Some commands that fail will produce reports that offer you the
options...

- Retry, Ignore or Cancel?

If you receive the above options, then:

...typing R (after taking the necessary corrective action) makes


the computer retry the command;

...typing I makes the computer ignore the reason that the command
failed in the first place and continue regardlessly (typing I is
therefore not recommended unless you know exactly what you're
doing);

...typing C abandons the command (this may be followed by the


appearance of another report).

Further information
Further information on tape and disk operations (together with
details of how to use the +2A's RAMdisk) can be found in chapter 8
part 20. A guide to +3DOS (the disk operating system provided with
the +2A) will be found in chapter 8 part 27.
Chapter 7
Using 48 BASIC

Subjects covered...

Using the +2A as a 48K Spectrum


Entering 48 BASIC mode
The keyboard under 48 BASIC
Program entry
Editing the current line

The +2A has the ability to act exactly like a 48K Spectrum (or
Spectrum +). This is achieved by selecting the option 48 BASIC
from the opening menu. In 48 BASIC mode, many of the enhanced
features of the +2A (such as facilities for disk drive(s), extra
memory, full screen editor, multi-channel sound, RS232/MIDI/AUX
interfaces and RAMdisk) cannot be used. The JOYSTICK 1 and
JOYSTICK 2 sockets will still operate, however.

The 48 BASIC mode is included for compatibility reasons only -


there is no advantage in using 48 BASIC mode (instead of +3 BASIC
mode) to write programs, and it is not recommended. The following
information is included for reference only, or for anybody who is
used to the old 48K Spectrum and wants to use the machine
immediately without having to learn about the +3 BASIC editor.

There are, in fact, two methods of entering the 48 BASIC mode: the
first is by selecting the 48 BASIC option from the opening menu
(if you don't know how to select a menu option, refer back to
chapter 2). When 48 BASIC starts up, you will see the following on
the screen...

The second method allows you to enter the 48 BASIC mode while
editing a +3 BASIC program. To do this (while in +3 BASIC mode),
type...
spectrum

...and press ENTER. The +2A will respond with an OK message and
will have changed to 48 BASIC mode, retaining any program that you
had in memory. Once in 48 BASIC mode, there is no way back to +3
BASIC mode apart from resetting the +2A (or switching off, then on
again).

One major difference between 48 BASIC and +3 BASIC is in the


entering and editing of programs. (Note also that in 48 BASIC the
tokens SPECTRUM and PLAY have replaced the user defined graphics
characters for the keys T and U under +3 BASIC (values 163 and
164).)

Once in 48 BASIC mode, the keyboard performs as follows:

All the BASIC commands, functions and operators are available


directly from the keyboard rather than needing to be spelled out.
In order to accommodate all these functions and commands, some
keys have five or more distinct meanings, obtained partly by
'shifting' the keys (ie. pressing either CAPS SHIFT or SYMB SHIFT
together with the required key); and partly by having the machine
in different modes. The flashing cursor contains a letter (K, L,
C, E or G) to indicate which mode you are operating in.

K (for Keywords) mode automatically replaces L (for Letters) mode


when the machine is expecting a command or program line (rather
than input data), and from its position on the line the +2A knows
that it should expect either a line number or a keyword. K mode
occurs at the beginning of a line, or after a colon : (except in a
string), or after the keyword THEN. Whenever the K cursor appears,
the next key pressed will be interpreted as either a keyword or a
line number, as follows...

The keyboard in K mode

L (for Letters) mode normally occurs at all times (other than K


mode, described above). Whenever the L cursor appears, the next
key pressed will be interpreted as per the legends on the key-tops
themselves, ie...
The keyboard in L mode

In both K and L modes, pressing SYMB SHIFT together with a key


will be interpreted as follows...

The keyboard using SYMB SHIFT in K or L mode

Using CAPS SHIFT in L mode simply converts small letters to


capitals. In K mode, however, CAPS SHIFT does not affect the
keywords.

C (for Capitals) mode is a variant of L mode whereby all letters


appear as capitals. The CAPS LOCK key is used to change from L
mode to C mode, and back again.

E (for Extended) mode is used to obtain further characters, mostly


tokens. It is entered by pressing the EXTEND MODE key, and lasts
for only one character (or key depression) thereafter. Whenever
the E cursor appears, the next key pressed will be interpreted as
follows...
The keyboard in E mode

Applying CAPS SHIFT while in E mode, the next key pressed will be
interpreted as follows...

The keyboard using CAPS SHIFT in E mode

Applying SYMB SHIFT while in E mode, the next key pressed will be
interpreted as follows...

The keyboard using SYMB SHIFT in E mode

G (for Graphics) mode occurs when GRAPH is pressed, and lasts


until it is pressed again (or 9 is pressed on its own). A number
key will give a mosaic graphic, and each of the letter keys (apart
from V, W, X, Y and Z) will give a user-defined graphic which,
until it is defined, will look identical to a capital letter.
Whenever the G cursor appears, the next key pressed will be
interpreted as follows...

The keyboard in G mode

Applying CAPS SHIFT while in G mode inverts the mosaic graphics


(ie. the ink colour becomes the paper colour, and the paper
becomes the ink colour). Hence, the next key pressed will be
interpreted as follows...

The keyboard using CAPS SHIFT in G mode

General keyboard notes


If any key is held down for more than 2 or 3 seconds, it will
start repeating. Keyboard input appears in the bottom half of the
screen as it is typed, each character (single symbol or compound
token) being inserted just before the cursor. The cursor can be
moved left and right using the cursor control keys ← → (to the
left of the space bar). The character to the left of the cursor
can be removed using DELETE.

When ENTER is pressed, the line is either executed, entered into


the program, or used as input data. If the line contains a syntax
error, however, a flashing question mark ? appears next to the
error.
As program lines are entered, a listing is displayed in the top
half of the screen. The last line entered is called the current
line and is indicated by the symbol > after the line number. Any
line in the program may be selected as the current line (for
editing purposes) by using the up and down cursor keys ↑ ↓ (to the
right of the space bar). To then edit the selected current line,
press the EDIT key. (Editing takes place at the bottom of the
screen.)

When a command is executed or a program is run, output is


displayed in the top half of the screen and remains there until
either ENTER or the cursor up or down key ↑ ↓ is pressed. At the
bottom of the screen appears a report giving a code (digit or
letter) referred to in part 29 of chapter 8. This report remains
on the screen until a key is pressed and the +2A returns to K
mode.
Chapter 8
The +3 BASIC programmer's guide

Part 1
Introduction
Whether you read chapter 6 first, or came straight here, you
should be aware that...

Commands are obeyed straight away.

Instructions begin with a line number and are stored away for
later use.

This guide to BASIC starts by repeating some of the information


given in chapter 6 (Introducing +3 BASIC), but in greater detail.
You may also find exercises at the end of some sections - don't
ignore these, as many of them illustrate points that are hinted at
in the text. Look through them, and do any that interest you or
that seem to cover ground that you don't understand properly.

The Keyboard

The characters used on the +2A comprise not only single symbols
(letters, digits, etc.) but also compound tokens (keywords,
function names, etc.). Everything must be typed in full, and in
most cases it doesn't matter whether capital letters (known as
UPPER CASE) or small letters (lower case) are used. There are
three sorts of keys on the keyboard: letter and number keys
(called alphanumeric keys); symbol keys (punctuation marks); and
control keys (things like CAPS SHIFT, DELETE and so on).

The most commonly used keys for BASIC are the alphanumeric keys.
When a letter key is pressed, a lower case letter will appear on
the screen together with a flashing blue and white blob called the
cursor. To get an upper case letter, the CAPS SHIFT key should be
held down while the letter is typed.

If you wish to continuously type upper case letters, then pressing


the CAPS LOCK key once will make all subsequent letters typed
upper case. To return to lower case letters, simply press CAPS
LOCK again.

To type the symbols which appear on the alphanumeric keys on the


keyboard, ie...

! @ # $ % & ' ( ) _ < > ↑ - + = : £ ? / *

...simply hold down the SYMB SHIFT key while the alphanumeric key
with the required symbol on it is pressed (see the following
diagram)...

Symbols available using SYMB SHIFT

Additionally, the symbols...

[ ] © ~ | \ { }

...can be obtained by first pressing the EXTEND MODE key once,


then holding down SYMB SHIFT while pressing the appropriate
alphanumeric key (see the following diagram)...

Symbols available using SYMB SHIFT in EXTEND MODE


To enter graphics mode, the GRAPH key is pressed once. Mosaic
graphics (see the following diagram) can then be produced by
pressing the number keys (except 9 and 0). Pressing the letter
keys (except T, U, V, W, X, Y and Z) produce user-defined graphics
(if set up).

Mosaic graphics available using GRAPH

To obtain inverted mosaic graphics, press the above number keys


while holding down CAPS SHIFT.

General keyboard notes


If any key is held down for more than 2 or 3 seconds, it will
start repeating. As keys are pressed, a line will be built up on
the screen. A line, by the way, means a line of BASIC, and may
easily be several lines long on the screen. The cursor keys ← → ↑
↓ can be used to move about the line, and if the part of the line
that the cursor is moved to is off screen, then the text on screen
will scroll up or down to display it. Any characters typed will be
inserted at the cursor, and pressing DELETE causes the character
to the left of the cursor to be removed. As soon as ENTER is
pressed or any attempt is made to move the cursor off the line,
the +2A checks to see if the line makes sense. If it does, then
there is a high-pitched bleep, and the line is either acted upon
immediately or stored away as part of a program. If the line
contains an error, then the +2A generates a low-pitched bleep and
moves the cursor to the area where it thinks the error is (the
colour of the cursor also changes to red to indicate the error).
It is impossible to move off a line which contains an error - the
+2A will always move the cursor back.

The monitor screen


This has 24 lines (each being 32 characters long) and is divided
into two parts. The larger (top) part of the screen is at most 22
lines and displays either a listing or program output. It is the
one used most often for editing. When printing in the top part has
reached its bottom limit, the contents scroll up by one line. If,
however, scrolling would mean losing a line that you haven't yet
had a chance to see, then the +2A stops with the message...

scroll?

Pressing any key (except N, BREAK or the space bar) will let
scrolling continue.

Pressing one of the keys N, BREAK or the space bar will make the
program stop with the report...

D BREAK - CONT repeats

The smaller (bottom) part of the screen is used for editing short
programs, entering input data, entering direct commands (where the
main screen must not be used, eg. graphics programs), and also for
displaying reports.

Program entry
If the program being entered gets bigger than the screen size,
then the +2A attempts to display the area of most interest
(usually the last line entered together with its surrounding
lines). You may, however, specify a different area of the program
to be displayed using the command...

LIST xxx

... where 'xxx' is a line number, telling the +2A to bring a


specified area of the program into view.

When a command is executed or a program is run, output is


displayed in the top part of the screen and remains there when the
program finishes (until a key is pressed). If the program is being
edited in the bottom part of the screen, then any output in the
top screen will stay there until it is either overwritten,
scrolled off, or a CLS command is issued. The bottom screen may
display a report giving a code (digit or letter) referred to in
part 29 of this chapter. This report remains in the bottom screen
until a key is pressed.

While the +2A is running a BASIC program, the BREAK key is checked
every so often. This happens at the end of a statement, during use
of the datacorder or printer (if connected), or while music is
being played. If the +2A finds that the BREAK key is pressed, then
program execution stops and displays a report. The program may
then be edited.
Part 2
Simple programming concepts
Subjects covered...

Programs
Line numbers
Editing programs using ← → ↑ ↓
RUN, LIST
GO TO, CONTINUE, INPUT, NEW, REM
PRINT
Stopping a program

Type in the following first two lines of a program (which will


eventually print the sum of two numbers). Don't forget to press
ENTER after you type each line...

20 print a
10 let a=10

Note that the screen looks like this...

10 LET a=10

20 PRINT a

As we have already discussed - because these lines began with


numbers, they were not obeyed immediately but were stored away as
program lines. You will have also noticed here that the line
numbers govern the order in which the program lines are to be
executed, and as you can see on the screen, the +2A sorts all the
lines into order whenever a new line is entered.

Note also that although we typed each line in lower case letters,
the keywords (ie. PRINT and LET) were converted to upper case as
soon as the line was entered and accepted by the +2A. From now on,
we will show keywords to be typed in upper case letters; however,
you may continue to type in lower case letters.

(By the way, if you don't know what a keyword is, you should have
studied chapter 6 before reading this chapter.)

So far you have only entered one number, so type...

15 LET b=15

...and press ENTER. Now you need to change line 20 to...


20 PRINT a+b

You could type out the replacement line in full, but it is far
easier to move the cursor (using the cursor keys) to just after
the a, and then type...

+b (don't press ENTER yet)

Check that the line then reads...

20 PRINT a+b

...then press ENTER. The cursor will move to the line below, and
the screen should look like this...

10 LET a=10
15 LET b=15
20 PRINT a+b

What you have done in this program is to have assigned the value
10 to the variable called a, and the value 15 to the variable
called b. You have then instructed the computer to print the sum
of these two values by simply adding the two variables.

Run this program by typing...

RUN

...and pressing ENTER. The sum of the two numbers will be


displayed...

25

Run the program again and then afterwards, press ENTER and type...

PRINT a,b

Now press ENTER again and notice how the values of the variables a
and b are still in the +2A's memory, even though the program has
finished...

10 15

Mistakes
If you enter a line by mistake, say...

12 LET b=8

...and you wish to delete the line, then simply type...

12
...and press ENTER. Line 12 will vanish, and the cursor will
reappear where line 12 used to be.

Now type...

30

...and press ENTER. The +2A will search for line 30, and since
there isn't one, it will 'fall off' the end of the program. The
cursor will be positioned just after the last line. If you enter
any non-existent line number (such as 30), then the +2A will place
the cursor where it thinks the line would have been if it really
existed. This can be a useful way of moving about large programs,
but beware - it can also be very dangerous because if the line
really did exist before you entered the line number - it certainly
wouldn't exist afterwards!

To list a program on the screen, type...

LIST

...and press ENTER. You may (particularly when working with more
lengthy programs) wish to list from a certain point onwards. This
can be achieved by typing an appropriate line number after the
LIST command.

Type...

LIST 15

...and press ENTER, to see this illustrated.

When we were developing the above program, note how we were able
to insert line 15 between the other two lines - this would have
been impossible if they had been numbered 1 and 2 instead of 10
and 20. It is always good practice, therefore, to leave gaps
between line numbers.

(Note that line numbers must be entered as whole numbers between 1


and 9999.)

If, at some time, you find that you haven't left enough space
between line numbers, then you may use the edit menu to renumber a
program. To do this, press the EDIT key then select the Renumber
option from the menu that appears; this sets the gap between each
line number to 10. Try this out and see how the line numbers
change.

We are now going to use the BASIC command NEW. This erases any
existing programs and variables in the +2A's memory. The command
should be used whenever you are about to start afresh, so type...

NEW
...and press ENTER. From now on, we won't mention 'press ENTER'
every time - we'll assume that you'll remember.

With the opening menu on the screen, start up BASIC by selecting


the option +3 BASIC.

Now carefully type in this program, which converts Fahrenheit


temperatures to Celsius (centigrade)...

10 REM temperature conversion


20 PRINT "deg F","deg C"
30 PRINT
40 INPUT "Enter deg F",f
50 PRINT f,
60 PRINT (f-32)*5/9
70 GO TO 40

Although you can type in all of line 10 in lower case, only the
REM will be converted to upper case on entry as it's the only
keyword that the +2A recognises. Also, although the words GO TO
will appear with a space between them, they may be typed in as one
word (GOTO) if you prefer.

Now run the program. The instructions will start being carried out
in the order determined by the line numbers. First of all, you'll
see the headings deg F and deg C printed on the screen (as
instructed by line 20), but what has line 10 done? It looks like
the +2A has completely ignored it - in fact, it has! The REM in
line 10 stands for remark, so line 10 is solely to remind you of
what the program does. A REM command consists of REM followed by
anything you like - the +2A will ignore everything after the REM,
right up to the end of the line.

After line 20, the +2A carries out line 30 which simply prints a
blank line. When the +2A gets to the INPUT command in line 40 it
waits for you to type in a value for the variable f - you can tell
this because at the bottom of the screen is a flashing cursor.

Type in a number (then press ENTER). The +2A displays the result
and then waits for you to enter another number. This is because
the instruction in line 70 says GO TO 40 - in other words,
'instead of running out of program and stopping, jump back to line
40 and continue running from there'.

So, enter another temperature, then another...

After a few more of these you might be wondering if the computer


will ever get bored with this - it won't! Next time it asks for
another number, hold down SYMB SHIFT and type A. The word STOP
will appear, and when you press ENTER the +2A comes back with the
report...

H STOP in INPUT in line 40:1


...which tells you why it stopped, and where (in line 40). (The :1
after the line number in the report tells you that the 1st
instruction in line 40 is being reported upon.)

If you wish to continue the program, type...

CONTINUE

...and the +2A will ask you for another number.

When CONTINUE is used, the +2A remembers the line number in the
last report that it sent you (as long as the report was not 0 OK)
and jumps back to that line, which in this case is line 40 (the
INPUT command).

Stop the program again and replace line 70 by...

70 GO TO 31

There will be no perceptible difference to the running of the


program because if the line number in a GO TO command refers to a
non-existent line, then the jump is to the next line after the
given number. The same goes for RUN (in fact, RUN on its own
actually means RUN 0).

Keep entering numbers until the screen starts getting full. When
it is full, the +2A will move the whole of the top half of the
screen up one line to make room, losing the heading off the top -
this is called scrolling.

When you are tired of entering numbers, stop the program as before
and enter the editor by pressing ENTER.

Look at the PRINT statement in line 50. The , comma in this line
is very important.

Commas are used to make the printing start either at the left-hand
margin, or in the middle of the screen (depending upon which comes
next). Thus in line 50, the comma causes the Celsius temperature
to be printed in the middle of the line.

A semicolon ; on the other hand, is used to make the next number


(or characters) be printed immediately after the preceding one(s).

Another punctuation mark you can use like this in PRINT commands
is the ' apostrophe. This makes whatever is printed next appear at
the beginning of the next line on the screen. This also happens by
default at the end of each PRINT command.

If you wish to inhibit this (so that whatever follows to be


printed continues on the same line) you can put a comma or
semicolon at the end of the PRINT statement. To see how this
works, replace line 50 in turn by each of these...
50 PRINT f,
50 PRINT f;
50 PRINT f

...and run the program each time to see the difference.

The line with the comma (you typed in originally) prints


everything in two columns; the line with the semicolon crams
everything together, and the line without either, prints each
number on a new line (you could have also used PRINT f' to do
this).

Always remember the difference between commas and semicolons in


PRINT commands, and do not confuse them with : colons which are
used as separators between commands on a single line, for
example...

PRINT f: GO TO 40

Now type in these extra lines...

100 REM greeting program


110 INPUT "Enter your name",n$
120 PRINT "Hello ";n$;"!"
130 GO TO 110

This is a separate program from the last one, but you may keep
them both in the +2A at the same time. To run the new one, type...

RUN 100

Because this program expects you to input a string (a character or


group of characters) instead of a number, it prints out two string
quotes "" as a reminder. So type in a name and press ENTER.

Next time round, you will get two string quotes again, but you
don't have to use them if you don't want to. Try this, for
example: rub out the quotes by pressing cursor right → then DELETE
twice, and type...

n$

Since there are no string quotes, the +2A knows that it has to do
some calculation - the calculation in this case is to find the
value of the string variable called n$ (which is whatever name you
happen to have typed in last time round). In this way, the INPUT
statement acts like LET n$=n$, so the value of n$ is unchanged.

If you wish to stop the program, delete the quotes then hold down
SYMB SHIFT and type A, then ENTER.

Now look back at that RUN 100 instruction which jumps to line 100
and runs the program from there. You may be asking, 'What's the
difference between RUN 100 and GO TO 100?' Well, RUN 100 first of
all clears all the variables and the screen, and after that works
just like GO TO 100. On the other hand, GO TO 100 doesn't clear
anything, and there may well be occasions where you wish to run a
program without clearing any variables; here GO TO would be
necessary and RUN could be disastrous, so it is better not to get
into the habit of automatically typing RUN to start a program.

Another difference of course is that you may type RUN without a


line number, and it starts off at the first line in the program;
GO TO must always be followed by a line number.

Both this program and the 'temperature conversion' program stopped


because you pressed SYMB SHIFT and typed A in the input line.
Sometimes, you may write a program that you can't stop and that
won't stop itself. Type...

200 GO TO 200
RUN 200

Although the screen is blank, the program is running - executing


line 200 over and over again. This looks all set to go on forever
unless you pull the plug out or reset the computer! However, there
is a less drastic remedy - press the BREAK key. The program will
stop with the report...

L BREAK into program

At the end of every statement, the program looks to see if this


key is pressed, and if it is, then the program stops. The BREAK
key can also be used when you are in the middle of using the
datacorder, a printer or various other add-ons that you can attach
to the +2A.

In these cases there is a different report...

D BREAK - CONT repeats

The instruction CONTINUE in this case (and in most other cases


too) repeats the statement when the program was stopped and
carries straight on with the next statement (after allowing for
any jumps to be made).

Run the 'name' program again and when it asks you for input,
type...

n$ (after removing the quotes)

Because n$ is an undefined variable, you will get the error


report...

2 Variable not found


If you now type...

LET n$="Fremsley"

(which produces the report 0 OK,0:1), and then type...

CONTINUE

...you will find that you can use n$ as input data without any
trouble.

In this case CONTINUE does a jump to the INPUT command in line


110. It disregards the report from the LET statement because that
said OK and jumps to the command referred to in the previous
report, ie. line 110. This feature can be extremely useful as it
allows you to 'fix' a program that has stopped due to errors, and
then CONTINUE from that point.

As we said before, the report L BREAK into program is special


because after it, CONTINUE does not repeat the command where the
program stopped.

You have now seen the statements, PRINT, LET, INPUT, RUN, LIST, GO
TO, CONTINUE, NEW and REM, and they can all be used either as
direct commands or in program lines - this is true of almost all
commands in +3 BASIC, however, RUN, LIST, CONTINUE and NEW are not
usually of much use in a program.

Exercises...

1. Put a LIST statement in a program, so that when you run it,


it lists itself afterwards.

2. Write a program to input prices and print out the tax due (at
15 percent). Put in PRINT statements so that the +2A
announces what it is going to do, and asks for the input
price with extravagant politeness. Modify the program so that
you can also input the tax rate (to allow for zero ratings
or future changes).

3. Write a program to print a running total of numbers you input


(like an adding machine).

4. What would CONTINUE and NEW do in a program? Can you think of


any uses at all for this?
Part 3
Decisions
Subjects covered...

CLS, IF, STOP


=, <, >, <=, >=, <>

All the programs we have seen so far have been pretty predictable
- they went straight through the instructions, and then went back
to the beginning again. This is not very useful, as in practice,
we would want the +2A to make decisions and act accordingly. The
instruction to do this in BASIC takes the form...

IF something is true (or not true) THEN do something

Let's look at an example of this. Use NEW to clear the previous


program from the +2A, select +3 BASIC, then type in and run this
program. (This is clearly meant for two people to play!)...

10 REM Guess the number


20 INPUT "Enter a secret numbe
r",a: CLS
30 INPUT "Guess the number",b
40 IF b=a THEN PRINT "That is
correct": STOP
50 IF b<a THEN PRINT "That is
too small, try again"
60 IF b>a THEN PRINT "That is
too big, try again"
70 GO TO 30

Note that the CLS command (at the end of line 20) means 'clear the
screen'. We have used it in this program to stop the other person
seeing the secret number after it is entered.

You can see that the IF statement takes the form...

IF condition THEN xxx

...where 'xxx' stands for a command (or a sequence of commands


separated by colons). The condition is something that is going to
be worked out as either true or false - if it comes out as true
then the statements in the rest of the line (after THEN) are
executed; otherwise they are skipped over, and the program
executes the next instruction.

The simplest conditions compare two numbers or two strings; they


can test whether two numbers are equal or whether one is bigger
than the other. They can also test whether two strings are equal,
or whether one comes before the other in alphanumerical order.
They use the symbols =, <, >, <=, >=, and <> (these are known as
relational operators).

= means is equal to.


< means is less than.
> means is greater than.
<= means is less than or equal to.
>= means is greater than or equal to.
<> means is not equal to.

(If you keep getting mixed up about the meanings of < and >, it
may help you to remember that the thin end of the symbol points to
the number which is supposed to be smaller.)

In the program we have just typed in, line 40 compares a and b. If


they are equal, then the program is halted by the STOP command.
The report at the bottom of the screen...

9 STOP statement, 40:3

...shows that the 3rd statement (ie. the STOP command) in line 40
caused the program to halt.

Line 50 determines whether b is less than a, and line 60 whether b


is greater than a. If one of these conditions is true then the
appropriate comment is printed, and the program works its way down
to line 70 which jumps back to line 30 and starts all over again.

Finally, note that in some versions of BASIC (not +3 BASIC) the IF


statement can have the form...

IF condition THEN line number

This means the same as...

IF condition THEN GO TO line number

...in +3 BASIC.

Exercise...

1. Try this program...

10 LET a=1
20 LET b=1
30 IF a>b THEN PRINT a;" is higher"
40 IF a<b THEN PRINT b;" is higher"

Before you run it, try to work out what will be printed on the
screen.
Part 4
Looping
Subjects covered...

FOR, NEXT
TO, STEP

Suppose you wish to input five numbers and add them together.

One way (don't type this in unless you are feeling dutiful) is as
follows...

10 LET total=0
20 INPUT a
30 LET total=total+a
40 INPUT a
50 LET total=total+a
60 INPUT a
70 LET total=total+a
80 INPUT a
90 LET total=total+a
100 INPUT a
110 LET total=total+a
120 PRINT total

This method is not good programming practice. It may be just about


controllable for five numbers, but you can imagine how tedious a
program like this to add twenty numbers would be, and to add a
hundred or more would be out of the question.

Much better is to set up a variable to count up to 5 and then stop


the program, like this (which you should type in)...

10 LET total=0
20 LET count=1
30 INPUT a
40 REM count is number of time
s that a has been input so
far
50 LET total=total+a
60 LET count=count+1
70 IF count <= 5 THEN GO TO 30
80 PRINT total

Notice how easy it would be to change line 70 so that this program


adds ten numbers, or even a hundred.
This sort of thing is so useful that there are two special
commands to make it easier - the FOR command and the NEXT command.
They are always used together. Using these, the program you have
just typed in does exactly the same as...

10 LET total=0
20 FOR c=1 TO 5
30 INPUT a
40 REM c is number of times th
at a has been input so far
50 LET total=total+a
60 NEXT c
80 PRINT total

(To get this program from the previous one, you just have to edit
lines 20, 40 and 60, then delete line 70.)

Note that we have changed count to c. This is because the control


variable of a FOR...NEXT loop must have a single letter as its
name.

The effect of this program is that c runs through the values 1


(the initial value), 2, 3, 4 and 5 (the limit), and each time,
lines 30, 40 and 50 are executed. Then, when c has finished its
five values, line 80 is executed.

At this point, attempt exercise 2 (which refers to the above


program), at the end of this section.

An extra subtlety to the FOR...NEXT structure is that the control


variable does not have to go up by 1 each time - you can change
this 1 to anything you like by using a STEP part in the FOR
command. The most general form of a FOR command is...

FOR control variable = initial value TO limit STEP step

...where the control variable is a single letter, and where the


initial value, the limit and the step are all things that the +2A
can calculate as numbers - like the actual numbers themselves, or
sums, or the names of numeric variables. So, if you replace line
20 in the program by...

20 FOR c=1 TO 5 STEP 3/2

...this will step the control variable by the amount 3/2 each time
the FOR loop is executed. Note that we could have simply said STEP
1.5, or we could have assigned the step value to a variable, say
s, and then said STEP s.

With the above modification, c will run through the values 1, 2.5
and 4. Notice that you don't have to restrict yourself to whole
numbers, and also that the control value does not have to hit the
limit exactly; it carries on looping as long as it is less than or
equal to the limit.

At this point, attempt exercise 3 at the end of this section


(which refers to the above program).

Step values can be negative instead of positive. Try this program


which prints out the numbers from 1 to 10 in reverse order.
(Remember, use the command NEW before typing in a new program).

10 FOR n=10 TO 1 STEP -1


20 PRINT n
30 NEXT n

We said before that the program carries on looping as long as the


control variable is less than or equal to the limit. If you
consider what that would mean in this case, you'll see that it now
doesn't hold true. Hence, the rule has to be modified to say that
when the step is negative, the program carries on looping as long
as the control variable is greater than or equal to the limit.

At this point, attempt exercises 4 and 5 at the end of this


section (which refer to the above program).

You must be careful if you are running two FOR...NEXT loops


together, one inside the other. Try this program, which prints out
the numbers for a complete set of six dot dominoes.

10 FOR m=0 TO 6
20 FOR n=0 TO m
30 PRINT m;":";n;" "; n loop m loop
40 NEXT n
50 PRINT
60 NEXT m

You can see that the n loop is entirely inside the m loop. This
means that they are properly nested.

However, what must be avoided is having two FOR...NEXT loops that


overlap without either being entirely inside the other, like
this...

5 REM this program is wrong


10 FOR m=0 TO 6
20 FOR n=0 TO m
30 PRINT m;":";n;" "; m loop
40 NEXT m n loop
50 PRINT
60 NEXT n

Two FOR...NEXT loops must either be one inside the other, or


completely separate.
Another thing to avoid is jumping into the middle of a FOR...NEXT
loop from the outside. The control variable is only set up
properly when its FOR statement is executed, and if you miss this
out, then the NEXT statement will confuse the +2A. You will
probably get an error report saying NEXT without FOR or Variable
not found.

There is nothing to stop you using a FOR...NEXT loop in a direct


command. For example, try...

FOR m=0 TO 10: PRINT m: NEXT m

You can sometimes use this as a (somewhat artificial) way of


getting around the restriction that you cannot GO TO anywhere
inside a command - because a command has no line number. For
instance...

FOR m=0 TO 1 STEP 0: INPUT a: PRINT a: NEXT m

The step size of zero here makes the command repeat itself
forever.

This sort of thing is not really recommended, because if an error


crops up then you have lost the command and will have to type it
in again; moreover, CONTINUE will not work.

Exercises...

1. Make sure that you understand that a control variable not


only has a name and a value (like an ordinary variable), but
also a limit, a step, and a reference to the statement after
the corresponding FOR statement. Ensure that when the FOR
statement is executed all this information is available
(using the initial value as the first value the variable
takes), and also that this information is enough for the NEXT
statement to know by how much to increase the value, whether
to jump back, and if so where to jump back to.

2. Run the third program in this section, then type...

PRINT c

Why is the answer 6, and not 5?

(Answer: The NEXT command in line 60 is executed five times, each


time 1 being added to c. On the last time, c becomes 6 so the NEXT
command decides not to loop back but to carry on, c now being past
its limit).

3. What happens if you put STEP 2 at the end of line 20 of the


third program? Try STEP 10.
Now change the third program so that instead of automatically
adding five numbers, it asks you to input the amount of
numbers you wish to add. When you run this program, what
happens if you input 0 (meaning that you don't wish to add
any numbers)? Why might you expect this to cause problems for
the +2A, even though it is clear what you mean?

4. In line 10 of the fourth program in this section, change 10


to 100 and run the program. It will print the numbers from
100 down to 79 on the screen, and then say scroll? at the
bottom. This is to give you a chance to see the numbers that
are about to be scrolled off the top. If you press N, BREAK
or the space bar, the program will stop with the report D
BREAK - CONT repeats. If you press any other key, then it
will print another 22 lines and ask you again if you wish to
scroll.

5. Delete line 30 from the fourth program. When you run the new
curtailed program, it will print the first number and stop
with the message 0 OK. If you then type...

NEXT n

...the program will go once round the loop, printing out the next
number.
Part 5
Subroutines
Subjects covered...

GO SUB, RETURN

Sometimes, different parts of the program will have rather similar


jobs to do, and you will find yourself typing in the same lines
two or more times; however, this is not necessary. Instead, you
need only type in the lines once (in what's called a subroutine)
and then call the subroutine into action whenever you need it in
the program.

To do this, you use the statements GO SUB (go to subroutine) and


RETURN. This takes the form...

GO SUB xxx

...where 'xxx' is the line number of the first line in the


subroutine. It is just like GO TO xxx except that the +2A
remembers where the GO SUB statement was, so that it can come back
again after carrying out the subroutine.

(In case you are interested, the +2A does this by remembering at
which point in the program the GO SUB command was issued (in other
words where it should continue from afterwards) and storing this
return address on top of a pile called the GO SUB stack.)

When the command...

RETURN

...is met (at the end of the subroutine itself), the +2A takes the
top return address off the GO SUB stack, and continues from the
next statement.

As an example, let's look at the number guessing program again.


Retype it as follows...

10 REM "A rearranged guessing


game"
20 INPUT "Enter a secret numbe
r",a: CLS
30 INPUT "Guess the number",b
40 IF b=a THEN PRINT "Correct"
: STOP
50 IF b<a THEN GO SUB 100
60 IF b>a THEN GO SUB 100
70 GO TO 30
100 PRINT "Try again"
110 RETURN

The GO TO 30 statement in line 70 (and the STOP statement in line


60 of the next program) are very important because otherwise the
programs will run on into their subroutines and cause an error (7
RETURN without GO SUB) when the RETURN statement is reached.

The following program uses a subroutine (from line 100 to 150)


which prints a 'times table' corresponding to the value of
parameter n. The command GO SUB 100 may be issued from any point
in the program to call the subroutine. When the RETURN command in
line 150 of the subroutine is reached, control returns to the main
program, which continues running from the statement after the GO
SUB call. Like GO TO, GO SUB may be typed in as GOSUB.

10 REM times tables for 2, 5,


10 and 11
20 LET n=2: GO SUB 100
30 LET n=5: GO SUB 100
40 LET n=10: GO SUB 100
50 LET n=11: GO SUB 100
60 STOP
70 REM end of main program, st
art of subroutine
100 PRINT n;" times table"
110 FOR t=1 TO 9
120 PRINT t;" x ";n;" = ";t*n
130 NEXT t
140 PRINT
150 RETURN

One subroutine can happily call another, or even itself (a


subroutine that calls itself is known as recursive).
Part 6
Data in programs
Subjects covered...

READ, DATA, RESTORE

In some of the previous programs we saw that information, or data,


can be entered directly into the +2A using the INPUT statement.
Sometimes this can be very tedious, especially if a lot of the
data is repeated every time the program is run. You can save a lot
of time by using the READ, DATA and RESTORE commands. For
example...

10 READ a,b,c
20 PRINT a,b,c
30 DATA 1,2,3

A READ statement consists of READ followed by a list of the names


of variables, separated by commas. It works rather like an INPUT
statement, except that instead of getting you to type in the
values to give to the variables, the +2A looks up the values in
the DATA statement.

Each DATA statement is a list of expressions - numeric or string


expressions - separated by commas. You can put them anywhere you
like in a program, because the +2A ignores them except when it is
doing a READ. You must imagine the expressions from all the DATA
statements in the program as being put together to form one long
list of expressions - the DATA list. The first time the +2A goes
to READ a value, it reads the first expression from the DATA list;
the next time, it reads the second; and thus as it meets
successive READ statements, it works its way through the DATA
list. (If it tries to read past the end of the DATA list, then it
reports an error.)

Note that it's a waste of time putting DATA statements in a direct


command, because READ will not find them. DATA statements must go
in a program.

Let's see how all this works in the program you've just typed in.
Line 10 tells the +2A to read three pieces of data and assign them
to the variables a, b and c. Line 20 then says PRINT these
variables. The DATA statement in line 30 provides the values of a,
b and c for line 10 to read.

The information in DATA can be part of a FOR...NEXT loop. Type


in...
10 DATA 2,4,6,8,10,12
20 FOR n=1 TO 6
30 READ d
40 PRINT d
50 NEXT n

Note from the above two programs that a DATA statement can appear
anywhere - before or after the READ statement.

When the above program is run, the READ statement moves through
the DATA list with each pass of the FOR...NEXT loop.

DATA statements may also contain string variables. For example...

10 FOR a=1 TO 7
20 READ n$
30 PRINT n$
40 DATA "Bob","Edith","Carole"
,"Jacquie","Gavin","Charles
","Holly"
50 NEXT a

The +2A doesn't have to READ the DATA statements in order - it can
be made to 'jump about' between DATA statements by using the
RESTORE command. The form of the command is...

RESTORE xxx

...where 'xxx' is the line number of the DATA statement to be READ


from. If you use the command RESTORE on its own (without a line
number) the +2A will jump to the first DATA statement in the
program.

Type in and run the following program...

10 DATA 1,2,3,4,5
20 DATA 6,7,8,9
30 GO SUB 110
40 GO SUB 110
50 GO SUB 110
60 RESTORE 20
70 GO SUB 110
80 RESTORE
90 GO SUB 110
100 STOP
110 READ a,b,c
120 PRINT a'b'c
130 PRINT
140 RETURN
The command GO SUB 110 calls a subroutine which READs the next
three items of DATA and then PRINTs them. Notice how the RESTORE
command affects which items are read.

Delete line 60 and run this program again to see what happens.
Part 7
Expressions
Subjects covered...

Operations: +, -, *, /
Expressions, scientific notation,
variable names

You have already seen some of the ways in which the +2A can
calculate with numbers. It can perform the four arithmetic
operations +, -, * and / (remember that * is used for
multiplication, and / is used for division), and it can find the
value of a variable, given its name.

The example...

LET tax=sum*15/100

...illustrates that calculations can be combined. Such a


combination, like sum*15/100, is called an expression - so an
expression is just a short-hand way of telling the +2A to do
several calculations, one after the other. In our example, the
expression sum*15/100 means 'look up the value of the variable
called sum, multiply it by 15, and divide by 100'.

In expressions containing *, /, +, -, multiplication and division


are carried out first - they have a higher priority than addition
and subtraction. Multiplication and division have the same
priority as each other, which means that they are carried out in
whichever order they appear in the expression (from left to
right). The next operations to be carried out are addition and
subtraction - these again have the same priority as each other and
so, again, are carried out in order from left to right.

Hence in the expression 8-12/4+2*2, the first operation to be


carried out is the division 12/4 which equals 3, so we can then
represent the expression as 8-3+2*2.

The next operation to be carried out is the multiplication 2*2


which equals 4, so the expression then becomes 8-3+4.

Next to be carried out is the subtraction 8-3 which equals 5, so


the expression becomes 5+4. Finally, the addition is carried out
leaving the result 9.
Try this out for yourself. Type in...

PRINT 8-12/4+2*2

A full list of the priorities of mathematical (and logical)


operations will be found in part 31 of this chapter.

You may, however, change the priority of calculations within an


expression by the use of brackets. Calculations within brackets
are carried out first, so if in the above expression, you required
the addition 4+2 to be carried out first, you would enclose it in
brackets. To see this, type in...

PRINT 8-12/(4+2)*2

...and the result this time is 4 instead of 9.

Expressions are useful because, whenever the +2A is expecting a


number from you, you can give it an expression instead and it will
work out the answer.

You can also add together strings (or string variables) in a


single expression. For example...

10 LET a$="large "


20 LET b$="and puffy"
30 LET c$=a$+b$
40 PRINT c$

We really ought to tell you what you can and cannot use as the
names of variables. As we have already said, the name of a string
variable has to be a single letter followed by $, and the name of
the control variable in a FOR...NEXT loop must be a single letter;
however, the names of ordinary numeric variables are less
restricted - they can use any letters or digits as long as the
first one is a letter. You can put spaces in as well to make it
easier to read, but they won't count as part of the name. Also, it
doesn't make any difference to the name whether you type it in
upper or lower case letters. There are some restrictions about
variable names which are the same as commands, however. In
general, if the variable contains a BASIC keyword in it (with
spaces around it) then it won't be accepted.

Here are some examples of the names of variables that are


allowed...

x
any old thing
t42
this name is impractical because it is too long
tobeornottobe
mixed cases spaces
MixEdCAsEsSpAcES
(Note that these last two names (mixed cases spaces and
MixEdCAsEsSpAcES) are considered the same, and refer to the same
variable).

The following are not allowed as the names of variables...

pi (PI is a keyword)
any new thing (contains the separated keyword NEW)
42t (begins with a digit)
2001 (contains digits only)
to be or not to be (contains TO, OR and NOT, which are
all separated keywords)
3 bears (begins with a digit)
M*A*S*H (* is not a letter or a digit)
Lloyd-Webber (- is not a letter or a digit)

Numerical expressions can be represented by a number and exponent.


Try the following to prove the point...

PRINT 2.34e0
PRINT 2.34e1
PRINT 2.34e2

...and so on upto...

PRINT 2.34e15

PRINT gives only eight significant digits of a number. Try...

PRINT 4294967295, 4294967295-429e7

This proves that the computer can hold the digits of 4294967295,
even though it is not prepared to display them all at once.

The +2A uses floating point arithmetic, which means that it keeps
separate the digits of a number (its mantissa) and the position of
the point (the exponent). This is not always exact, even for whole
numbers. Type...

PRINT 1e10+1-1e10,1e10-1e10+1

Numbers are held to about nine and a half digits accuracy, so 1e10
is too big to be held exactly right. The inaccuracy (actually
about 2) is more than 1, so the numbers 1e10 and 1e10+1 appear to
the computer to be equal.

For an even more peculiar example, type...

PRINT 5e9+1-5e9

Here the inaccuracy in 5e9 is only about 1, and the 1 to be added


on in fact gets rounded up to 2. The numbers 5e9+1 and 5e9+2
appear to the computer to be equal. The largest integer (whole
number) that can be held completely accurately is 4,294,967,294.

The string "" with no character at all is called the empty or null
string. Remember that spaces are significant and an empty string
is not the same as one containing nothing but spaces.

Try...

PRINT "Did you read "The Times" yesterday?"

When you press ENTER you will get the flashing red cursor that
shows there is a mistake somewhere in the line. When the +2A finds
the double quotes at the beginning of "The Times" it imagines that
these mark the end of the string "Did you read ", and it then
can't work out what The Times means.

There is a special device to get over this - whenever you wish to


write a string quote symbol in the middle of a string, you must
write it twice, like this...

PRINT "Did you read ""The Times"" yesterday?"

As you can see from what is printed on the screen, each double
quote is only really there once - you just have to type it twice
to get it recognised.
Part 8
Strings
Subjects covered...

Slicing, using TO

Given a string, a substring of it consists of some consecutive


characters from it, taken in sequence. Thus "cut" is a substring
of "cutlery", but "cute" and "cruelty" are not substrings.

There is a notation called slicing for describing substrings, and


this can be applied to arbitrary string expressions. The general
form is...

string expression (start TO finish)

...so that, for instance...

"abcdef"(2 TO 5)

...is equal to bcde.

If you omit the start, then 1 is assumed; if you omit the finish,
then the length of the string is assumed. Thus...

"abcdef"( TO 5) is equal to abcde


"abcdef"(2 TO ) is equal to bcdef
"abcdef"( TO ) is equal to abcdef

You can also write this last one as "abcdef"().

A slightly different form misses out the TO and just has one
number.

"abcdef"(3) is equal to "abcdef"(3 TO 3) is equal to c

Although normally both start and finish must refer to existing


parts of the string, this rule is overridden by another one: if
the start is more than the finish, then the result is the empty
string. So...

"abcdef"(5 TO 7)

...gives the error 3 Subscript wrong because the string only


contains 6 characters and 7 is too many, but...

"abcdef"(8 TO 7)
...and...

"abcdef"(1 TO 0)

...are both equal to the empty string "" and are therefore
permitted.

The start and finish must not be negative, or you get the error B
integer out of range. This next program is a simple one
illustrating some of these rules...

10 LET a$="abcdef"
20 FOR n=1 TO 6
30 PRINT a$(n TO 6)
40 NEXT n

Type NEW when this program has been run and enter the next
program.

10 LET a$="1234567890"
20 FOR n=1 TO 10
30 PRINT a$(n TO 10),a$((11-n)
TO 10)
40 NEXT n

For string variables, we can not only extract substrings, but also
assign to them. For instance, type...

LET a$="Velvet Donkey"

...and then...

LET a$(8 TO 13)="Lips******"

...and...

PRINT a$

Since the substring a$(8 TO 13) is only 6 characters long, only


its first 6 characters (Lips**) are used; the remaining 4
characters (****) are discarded. This is a characteristic of
assigning to substrings: the substring has to be exactly the same
length afterwards as it was before. To make sure this happens, the
string that is being assigned to it is cut off on the right if it
is too long, or filled out with spaces if it is too short - this
is called 'Procrustean assignment' after the inn-keeper Procrustes
who used to make sure that his guests fitted their beds by either
stretching them out on a rack or cutting their feet off!
Complicated string expressions will need brackets around them
before they can be sliced. For example...

"abc"+"def"(1 TO 2) is equal to "abcde"


("abc"+"def")(1 TO 2) is equal to "ab"

Exercise...

1. Try writing a program to print the day of the week using


string slicing. (Hint - Let the string be
SunMonTuesWednesThursFriSatur).
Part 9
Functions
Subjects covered...

LEN, STR$, VAL, SGN, ABS, INT, SQR


DEF FN

Consider the sausage machine. You put a lump of meat in at one


end, turn a handle and out comes a sausage at the other end. A
lump of pork gives a pork sausage, a lump of fish gives a fish
sausage, and a lump of beef a beef sausage.

Functions are practically indistinguishable from sausage machines


but there is a difference; they work on numbers and strings
instead of meat. You supply one value (called the argument), mince
it up by doing some calculations on it, and eventually get another
value - the result...

Meat in → Sausage Machine → Sausage out


Argument in → Function → Result out

Different arguments give different results, and if the argument is


completely inappropriate the function will stop and give an error
report.

Just as you can have different machines to make different products


- one for sausages, another for combs, a third for dish cloths,
and so on, different functions will do different calculations.
Each will have its own value to distinguish it from the others.

You use a function in expressions by typing its name followed by


the argument, and when the expression is evaluated the result of
the function will be worked out.

As an example, there is a function called LEN, which works out the


length of a string. Its argument is the string whose length you
wish to find, and its result is the length, so that if you type...

PRINT LEN "Jammy Smears"

the +2A will write the answer 12, ie. the number of characters
(including spaces) in the string Jammy Smears.

If you mix functions and operations in a single expression, then


the functions will be worked out before the operations. Again,
however, you can circumvent this rule by using brackets. For
instance, here are two expressions which differ only in the
brackets, and yet calculations are performed in an entirely
different order in each case (although, as it happens, the end
results are the same).

LEN "Fred" + LEN "Bloggs"

4+LEN "Bloggs"

4+6

10

...and...

LEN ("Fred" + "Bloggs")

LEN ("FredBloggs")

LEN "FredBloggs"

10

Here are some more functions...

STR$ converts numbers into strings: its argument is a number, and


its result is the string that would appear on the screen if the
number were displayed by a PRINT statement. Note how its name ends
in a $ sign to show that its result is a string. For example, you
could say...

LET a$= STR$ 1e2

...which would have exactly the same effect as typing...

LET a$="100"

Or you could say...

PRINT LEN STR$ 100.0000

...and get the answer 3, because STR$ 100.0000 is equal to 100,


the length of which is 3 characters.

VAL is like STR$ in reverse - it converts strings into numbers.


For instance...

VAL "3.5"

...is equal to the number 3.5.

VAL is the reverse of STR$ because if you take any number, apply
STR$ to it, and then apply VAL to it, you get back to the number
you first thought of.
However, if you take a string, apply VAL to it, and then apply
STR$ to it, you do not always get back to your original string.

VAL is an extremely powerful function, because the string which is


its argument is not restricted to looking like a plain number - it
can be any numeric expression. Thus, for instance...

VAL "2*3"

...is equal to 6. Even...

VAL ("2"+"*3")

...is equal to 6. There are two processes at work here. In the


first, the argument of VAL is evaluated as a string - the string
expression "2"+"*3" is evaluated to give the string "2*3". Then,
the string has its double quotes stripped off, and what is left is
evaluated as a number: so 2*3 is evaluated to give the number 6.

There is another function, rather similar to VAL, though probably


less useful, called VAL$. Its argument is still a string, but its
result is also a string. To see how this works, recall how VAL
goes in two steps: first its argument is evaluated as a string,
then the string quotes are stripped off this, and whatever is left
is evaluated as a number. With VAL$, the first step is the same,
but after the string quotes have been stripped off in the second
step, whatever is left is evaluated as another string. Thus...

VAL$ """Ursula""" is equal to "Ursula"

(Notice how the string quotes proliferate again.) Try...

LET a$="99"

...and print all of the following: VAL a$, VAL "a$", VAL """a$""",
VAL$ a$, VAL$ "a$" and VAL$ """a$""". Some of these will work, and
some of them won't - try to explain all the answers.

SGN is the sign function (sometimes called signum). It is the


first function you have seen that has nothing to do with strings,
because both its argument and its result are numbers. The result
is +1 if the argument is positive, 0 if the argument is zero, and
-1 if the argument is negative.

ABS is another function whose argument and result are both


numbers. It converts the argument into a positive number (which is
the result) by forgetting the sign, so that for instance...

ABS -3.2

...is equal to

ABS 3.2
...which is simply equal to 3.2.

INT stands for integer part - an integer is a whole number,


possibly negative. This function converts a fractional number into
an integer by 'throwing away' the fractional part, so that for
instance...

INT 3.9

...is equal to 3.

Be careful when you are applying it to negative numbers, because


it always rounds down. Thus for instance...

INT -3.1

...is equal to -4.

SQR calculates the square root of a number, ie. the result that,
when multiplied by itself, gives the argument, for instance...

SQR 4

...is equal to 2 because 2x2 is equal to 4.

SQR 0.25

...is equal to 0.5 because 0.5x0.5 is equal to 0.25.

SQR 2

...is equal to 1.4142136 (approx) because 1.4142136x1.4142136 is


equal to 2 (almost).

If you multiply any number (even a negative one) by itself, the


answer is always positive. This means that negative numbers do not
have square roots, so if you apply SQR to a negative argument you
get the error report A Invalid Argument.

You can also define functions of your own. Possible names for
these are FN followed by a letter (if the result is a number) or
FN followed by a letter followed by $ (if the result is a string).
These functions are much stricter about brackets - the argument
must be enclosed in brackets.

You define a function by putting a DEF statement somewhere in the


program. For instance, here is the definition of a function FN s
whose result is the square of the argument...

10 DEF FN s(x)=x*x: REM the sq


uare of x
The s following the DEF FN is the name of the function. The x in
brackets is a name by which you wish to refer to the argument of
the function. You can use any single letter you like for this (or,
if the argument is a string, a single letter followed by $).

After the = sign comes the actual definition of the function. This
can be any expression, and it can also refer to the argument using
the name you've given it (in this case, x) as though it were an
ordinary variable.

When you have entered this line, you can invoke the function just
like one of the +2A's own functions by typing its name, FN s,
followed by the argument. Remember that when you have defined a
function yourself, the argument must be enclosed in brackets. Try
it out a few times...

PRINT FN s(2)
PRINT FN s(3+4)
PRINT 1+ INT FN s ( LEN "chicken"/2+3)

Once you have put the corresponding DEF statement into the
program, you can use your own functions in expressions just as
freely as you can use the computer's.

INT always rounds down. To round to the nearest integer, add 0.5
first - you could write your own function to do this...

20 DEF FN r(x)= INT (x+0.5): R


EM gives x rounded to the n
earest integer.

You will then get, for instance...

FN r(2.9) is equal to 3
FN r(2.4) is equal to 2
FN r(-2.9) is equal to -3
FN r(-2.4) is equal to -2

Compare these with the answers you will get when you use INT
instead of FN r. Type in and run the following...

10 LET x=0: LET y=0: LET a=10


20 DEF FN p(x,y)=a+x*y
30 DEF FN q()=a+x*y
40 PRINT FN p(2,3), FN q()

There are a lot of subtle points in this program. Firstly, a


function is not restricted to just one argument: it can have more,
or even none at all - but you must still always keep the brackets.

Secondly, it doesn't matter whereabouts in the program you put the


DEF statements. After the +2A has executed line 10, it simply
skips over lines 20 and 30 to get to line 40. They do, however,
have to be somewhere in the program - they can't be in a command.

Thirdly, x and y are both the names of variables in the program as


a whole, and the names of arguments for the function FN p. FN p
temporarily forgets about the variables called x and y, but since
it has no argument called a, it still remembers the variable a.
Thus when FN p(2,3) is being evaluated, a has the value 10 because
it is the variable, x has the value 2 because it is the first
argument, and y has the value 3 because it is the second argument.
The result is then, 10+2*3 which is equal to 16. When FN q () is
being evaluated, on the other hand, there are no arguments, so a,
x and y all still refer to the variables and so have the values
10, 0 and 0 respectively. The answer in this case is 10+0*0 which
is equal to 10.

Now change line 20 to...

20 DEF FN p(x,y)= FN q()

This time, FN p(2,3) will have the value 10 because FN q will


still go back to the variables x and y rather than using the
arguments of FN p.

Some BASICs (not +3 BASIC) have functions called LEFT$, RIGHT$,


MID$ and TL$.

LEFT$(a$,n) gives the substring of a$ consisting of the first n


characters.

RIGHT$(a$,n) gives the substring of a$ consisting of the


characters from nth on.

MID$(a$,n1,n2) gives the substring of a$ consisting of n2


characters, starting at the n1th.

TL$(a$) gives the substring of a$ consisting of all its characters


except the first.

You can write some user-defined functions to do the same...

10 DEF FN t$(a$)=a$(2 TO ): RE
M TL$
20 DEF FN l$(a$,n)=a$( TO n):
REM LEFT$

Check that these work with strings of length 0 or 1. Note that our
FN l$ has two arguments, one a number and the other a string. A
function can have up to 26 numeric arguments (why 26?) and at the
same time up to 26 string arguments.
Exercise...

Use the function FN s(x)=x*x to test SQR. You should find that...

FN s( SQR x)

...equals x if you substitute any positive number for x, and...

SQR FN s(x)

...equals ABS x whether x is positive or negative (Why is the ABS


there?).
Part 10
Mathematical functions
Subjects covered...


PI, EXP, LN, SIN, COS, TAN, ASN, ACS, ATN

This section deals with the mathematics that the +2A can handle.
Quite possibly you will never have to use any of this at all, so
if you find it too heavy going, don't be afraid of skipping it. It
covers the operation ↑ (raising to a power), the functions EXP and
LN, and the trigonometrical functions SIN, COS, TAN and their
inverses ASN, ACS, and ATN.

↑ and EXP
You can raise one number to the power of another. This means
'multiply the first number by itself the second number of times'.
This is normally shown by writing the second number just above and
to the right of the first number; but obviously this would be
difficult on a computer so we use the symbol ↑ instead. For
example, the powers of 2 are...

2 ↑ 1 equals 2
2 ↑ 2 equals 2x2 equals 4 (2 squared, normally written 22)
2 ↑ 3 equals 2x2x2 equals 8 (2 cubed, normally written 23)
2 ↑ 4 equals 2x2x2x2 equals 16 (2 to the power of four, normally
written 24)

...and so on.

Thus, at its most elementary level, a↑b means 'a multiplied by


itself b times', but obviously this only makes sense if b is a
positive whole number. To find a definition that works for other
values of b, we consider the rule...

a↑(b+c) equals a↑bxa↑c

(Notice that we give ↑ a higher priority than multiplication and


division so that when there are several operations in one
expression, ↑ is evaluated before * and /). You should not need
much convincing that this works when b and c are both positive
whole numbers; but if we decide that we want it to work even when
they are not, then we find ourselves compelled to accept that...

a↑0 equals 1
a↑(-b) equals 1/a↑b
a↑(1/b) equals the bth root of a, which is to say, the number that
you have to multiply by itself b times to get a

...and...

a↑(bxc) equals (a↑b)↑c

If you have never seen any of this before then don't try to
remember it straight away, just remember that...

a↑(-1) equals 1/a

...and...

a↑(1/2) equals SQR a

...and maybe when you are familiar with these, the rest will begin
to make sense.

Experiment with all this by trying this program...

10 INPUT a,b,c
20 PRINT a*(b+c),a↑b*a↑c
30 GO TO 10

Of course, if the rule we gave earlier is true, then each time


round, the two numbers that the +2A prints out will be equal.
(Note - because of the way the computer works out ↑, the number on
the left, a in this case, must never be negative.)

A rather typical example of what this function can be used for is


that of compound interest. Suppose you keep some of your money in
a building society and they give 15% interest per year. Then after
one year you will have not just the 100% that you had anyway, but
also the 15% interest that the building society has given you,
making altogether 115% of what you had originally. To put it
another way, you have multiplied your sum of money by 1.15, and
this is true however much you had there in the first place. After
another year, the same will have happened again, so that you will
then have 1.15x1.15, or in other words, 1.15↑2, or in other words,
1.3225 times your original sum of money. In general then, after y
years, you will have 1.15↑y times what you started out with.

If you try this command...

FOR y=0 TO 100: PRINT y,10*1.15↑y: NEXT y

...you will see that even starting off from just £10, it all
mounts up quite quickly, and what's more, it gets faster and
faster as time goes on (though you might still find that it
doesn't keep up with inflation).
This sort of behaviour, where after a fixed interval of time some
quantity multiplies itself by a fixed proportion, is called
exponential growth, and it is calculated by raising a fixed number
to the power of the time.

Suppose you did this...

10 DEF FN a(x)=a↑x

Here, a is more or less fixed, by LET statements - its value will


correspond to the interest rate, which changes only every so
often.

There is a certain value for a that makes the function FN a look


especially pretty to the trained eye of a mathematician; and this
value is called e. The +2A has a function called EXP defined by...

EXP x is equal to e↑x

Unfortunately, e itself is not an especially pretty number; it is


an infinite non-recurring decimal. You can see its first few
decimal places by typing...

PRINT EXP 1

...because EXP 1 is equal to e↑1 which is equal to e. Of course,


this is just an approximation. You can never write down e exactly.

LN
The inverse of an exponential function is a logarithmic function -
the logarithm (to base a) of a number x is the power to which
you'd have to raise a to get the number x, and this is written
logax. Thus by definition, a↑logax is equal to x; and it is also
true that log (a↑x) is equal to x.

You may well already know how to use base 10 logarithms for doing
multiplications; these are called common logarithms. The +2A has a
function LN which calculates logarithms to the base e; these are
called natural logarithms. To calculate logarithms to any other
base, you must divide the natural logarithm by the natural
logarithm of the base, ie. logax is equal to LN x/LN a.

PI
Given any circle, you can find its perimeter (the distance round
its edge - often called its circumference) by multiplying its
diameter (width) by a number called π. π (pronounced pi) is the
Greek equivalent of the English letter p, and it is used because
it stands for perimeter.
Like e, π is an infinite non-recurring decimal - it starts off as
3.1415927. The word PI on the +2A is taken as standing for this
number. Try...

PRINT PI

SIN COS and TAN, ASN ACS and ATN


These trigonometrical functions measure what happens when a point
moves round a circle. Here is a circle of radius 1 ('1 what?' you
may ask - it doesn't matter, as long as we keep to the same unit
all the way through) and a point moving round it. The point
started at the '3 o'clock' position, and then moved round in an
anti-clockwise direction.

We have also drawn in two lines called axes through the centre of
the circle. The one through 3 o'clock is called the x-axis, and
the one through 12 o'clock is called the y-axis.
To specify where the point is, you say how far it has moved round
the circle from its 3 o'clock starting position: let us call this
distance a. We know that the circumference of the circle is 2π
(because its radius is 1 and its diameter is thus 2); so when it
has moved a quarter of the way round the circle, a is equal to
π/2; when it has moved halfway round, a is equal to π, and when it
has moved the whole way round, a is equal to 2π.

Given the curved distance round the edge - a, two other distances
you might like to know are how far the point is to the right of
the y-axis, and how far it is above the x-axis. These are called,
respectively, the cosine and sine of a. The functions COS and SIN
on the +2A will calculate these.

Note that if the point goes to the left of the y-axis, then the
cosine becomes negative, and if the point goes below the x-axis,
the sine becomes negative.
Another property is that once a has got up to 2π, the point is
back where it started and the sine and cosine start taking the
same values all over again, ie. SIN (a+2*PI) equals SIN a, and COS
(a+2*PI) equals COS a.

The tangent of a is defined as being the sine divided by the


cosine; the corresponding function on the +2A is called TAN.

Sometimes we need to work these functions out in reverse, finding


the value of a that has given sine, cosine or tangent. The
functions to do this are called arcsine (ASN on the +2A),
arccosine (ACS) and arctangent (ATN).

In the diagram of the point moving round the circle, look at the
radius joining the centre to the point. You should be able to see
that the distance we have called a (the distance that the point
has moved round the edge of the circle) is a way of measuring the
angle through which the radius has moved away from the x-axis.
When a is equal to π/2, the angle is 90 degrees; when a is equal
to π the angle is 180 degrees, and so on, round to when a is equal
to 2π, and the angle is 360 degrees. You might just as well forget
about degrees, and measure the angle in terms of a alone; we say
then that we are measuring the angle in radians. Thus π/2 radians
is equal to 90 degrees and so on.

You must always remember that on the +2A, the functions SIN, COS,
etc. use radians and not degrees. To convert degrees to radians,
divide by 180 and multiply by π; to convert back from radians to
degrees, you divide by π and multiply by 180.
Part 11
Random Numbers
Subjects covered...

RANDOMIZE
RND

This section deals with the keywords RND and RANDOMIZE.

In some ways RND is like a function - it does calculations and


produces a result. It is unusual in that it does not need an
argument.

Each time you use it, its result is a new random number between 0
and 1. (Sometimes it can take the value 0, but never 1.)

Try...

10 PRINT RND
20 GO TO 10

...to see how the answer varies. Can you detect any pattern? You
shouldn't be able to - 'random' means that there is no pattern.

Actually, RND is not truly random, because it follows a fixed


sequence of 65536 numbers. However, these are so thoroughly
jumbled up that there are at least no obvious patterns, and we say
that RND is pseudo-random.

RND gives a random number between 0 and 1, but you can easily get
random numbers in other ranges. For instance, 5*RND is between 0
and 5, and 1.3+0.7*RND is between 1.3 and 2. To get whole numbers,
use INT (remembering that INT always rounds down) as in
1+INT(RND*6), which we shall use in a program to simulate dice.
RND*6 is in the range 0 to 6, but since it never actually reaches
6, INT(RND*6) is 0, 1, 2, 3, 4 or 5.

Here is the program...

10 REM dice throwing program


20 CLS
30 FOR n=1 TO 2
40 PRINT 1+ INT ( RND *6);" ";
50 NEXT n
60 INPUT a$: GO TO 20

Press ENTER each time you wish to 'throw' the dice.


The RANDOMIZE statement may be used to make RND start off at a
definite place in its sequence of numbers, as you can see with
this program...

10 RANDOMIZE 1
20 FOR n=1 TO 5: PRINT RND ,:
NEXT n
30 PRINT : GO TO 10

After each execution of RANDOMIZE 1, the RND sequence starts off


again with 0.0022735596. You can use other numbers between 1 and
65535 in the RANDOMIZE statement to start the RND sequence off at
different places.

If you had a program with RND in it and it also had some mistakes
that you had not found, then it would help to use RANDOMIZE like
this so that the program behaved the same way each time you ran
it.

RANDOMIZE used on its own (or RANDOMIZE 0) have a different effect


- they really do randomise RND - you can see this in the next
program...

10 RANDOMIZE
20 PRINT RND : GO TO 10

The sequence you get here is not very random, because RANDOMIZE
uses the time since the +2A was switched on. As this has gone up
by the same amount each time that RANDOMIZE is executed, the next
RND does more or less the same. You would get better 'randomness'
by replacing GO TO 10 by GO TO 20.

Here is a program to toss coins and count the numbers of heads and
tails...

10 LET heads=0: LET tails=0


20 LET coin= INT ( RND *2)
30 IF coin=0 THEN LET heads=he
ads+1
40 IF coin=1 THEN LET tails=ta
ils+1
50 PRINT heads;",";tails,
60 IF tails <> 0 THEN PRINT he
ads/tails;
70 PRINT: GO TO 20

The ratio of heads to tails should become approximately 1 if you


go on long enough, because in the long run you expect
approximately equal numbers of heads and tails.
Exercise...

1. Choose a number between 1 and 872 and type...

RANDOMIZE your number

Note that the next value of RND will be...

(75*(your number+1)-1)/65536

Try this out for yourself.


Part 12
Arrays
Subjects covered...

Arrays
DIM

Suppose that you have a list of numbers - for instance, the marks
of ten people in a class. To store them in the +2A you could use
the variables m1, m2, m3...and so on up to m10, but the program to
set up these ten variables would be rather long and tedious to
type in, ie...

10 LET m1=75
20 LET m2=44
30 LET m3=90
40 LET m4=38
50 LET m5=55
60 LET m6=64
70 LET m7=70
80 LET m8=12
90 LET m9=75
100 LET m10=60

Instead, there is a mechanism, known as an array whereby you may


specify a variable which (instead of containing a single value as
variables normally do) may contain a number of separate elements,
each of which may contain different values. Each element is
referenced by an index number (the subscript) written in brackets
after the variable name. For the above example, the array
variable's name could be m - (the name of an array variable must
be a single letter), and the ten variables would then be m(1),
m(2), m(3)...and so on up to m(10).

The elements of an array are called subscripted variables, as


opposed to the simple variables that you are already familiar
with.

Before you can use an array, you must reserve some space for it in
the +2A's memory, and you do this by using the keyword DIM (for
dimension). The statement...

DIM m(10)

...sets up an array called m whose dimensions are 10 (ie. there


are 10 subscripted variables). The DIM statement initialises each
element in the array to zero. It also deletes any array called m
that existed previously - (however, it doesn't delete any simple
variable called m. An array variable can coexist alongside a
simple numerical variable of the same name because the array can
always be distinguished by its subscript).

The array elements' subscripts may be represented by any numerical


expression yielding a valid subscript number. This means that an
array can be processed using a FOR...NEXT loop. Thus, instead of
the above long-winded program, we can now set up the variables
m(1)...m(10) using...

10 DIM m(10)
20 FOR n=1 TO 10
30 READ m(n)
40 NEXT n
50 DATA 75,44,90,38,55,64,70,1
2,75,60

...to READ in the elements' values from a DATA list, or...

10 DIM m(10)
20 FOR n=1 TO 10
30 INPUT m(n)
40 NEXT n

...to INPUT the elements' values by hand.

Note that the DIM statement must come before any attempt to access
the array in a program.

If you wish, you may examine the contents of the array using...

10 FOR n=1 TO 10
20 PRINT m(n)
30 NEXT n

...or individually using...

PRINT m(1)
PRINT m(2)
PRINT m(3)

...etc...

You can also set up arrays with more than one dimension. In a two
dimensional array you need two numbers to specify an element -
rather like the line and column numbers that specify a character
position on the screen. If you imagine the line and column numbers
(two dimensions) as referring to a printed page, you could then,
for example, have an extra dimension to represent the page
numbers. Think of the elements of a three dimensional array v as
being specified by v (page number,line number,column number).
For example, to set up a two-dimensional array c with dimensions 3
and 6, you use the DIM statement...

DIM c(3,6)

This then gives you 3x6=18 subscripted variables...

c(1,1), c(1,2)...to c(1,6)


c(2,1), c(2,2)...to c(2,6)
c(3,1), c(3,2)...to c(3,6)

The same principle works for any number of dimensions.

Although you can have a number and an array with the same name,
you cannot have two arrays with the same name, even if they have a
different number of dimensions.

There are also string arrays. The strings in an array differ from
simple strings in that they are of fixed length and assignment to
them is always Procrustean (ie. chopped off or padded with
spaces).

The name of a string array is a single letter followed by $.


Unlike numeric arrays, a string array and a simple string variable
cannot have the same name.

Suppose then, that you want an array a$ of five strings. You must
decide how long these strings are to be - let us suppose that 10
characters for each element is long enough. You then say...

DIM a$(5,10) (type this in)

This sets up a 5x10 array of characters, but you can also think of
each row as being a string...

a$(1) equals a$(1,1) a$(1,2)...to a$(1,10)


a$(2) equals a$(2,1) a$(2,2)...to a$(2,10)
a$(3) equals a$(3,1) a$(3,2)...to a$(3,10)
a$(4) equals a$(4,1) a$(4,2)...to a$(4,10)
a$(5) equals a$(5,1) a$(5,2)...to a$(5,10)

If you give the same number of subscripts (two in this case) as


there were dimensions in the DIM statement, then you get a single
character; but if you miss the last one out, then you get a fixed
length string. So, for instance, a$(2,7) is the 7th character in
the string a$(2). Using the slicing notation, we could also write
this as a$(2)(7). Now type...

LET a$(2)="1234567890"

...and...

PRINT a$(2), a$(2,7)


You get...

1234567890 7

For the last subscript (the one you can miss out), you can also
have a slicer, so that for instance...

a$(2,4 TO 8) is equal to a$(2)(4 TO 8) is equal to


"45678"

Remember - In a string array, all the strings have the same fixed
length.

The DIM statement has an extra number (the last one) to specify
this length. When you write down a subscripted variable for a
string array, you can put in an extra number (a slicer) to
correspond with the extra number in the DIM statement.

You can have string arrays with no extra dimensions. Type...

DIM a$(10)

...and you will find that a$ behaves just like a string variable,
except that it always has length 10, and assignment to it is
always Procrustean.

Exercise...

1. Use READ and DATA statements to set up an array m$ of twelve


strings in which m$(n) is the name of the nth month. (Hint -
The DIM statement will be DIM m$(12,9). Test it by printing
out all the values of m$(n) (use a loop).)
Part 13
Conditions
Subjects covered...

AND, OR
NOT

We saw in part 3 of this chapter how an IF statement takes the


form...

IF condition THEN...

The conditions there were the relations =, <, >, <=, >= and <>
which compare two numbers or two strings. You can also combine
several of these, using the logical operations: AND, OR and NOT.

One relation AND another relation is true whenever both relations


are true, so you could have a line like...

IF a$="yes" AND x>0 THEN PRINT "result"

...in which result gets printed only if a$ is equal to yes and x


is greater than zero. The BASIC here is so close to English that
it hardly seems worth spelling out the details. As in English, you
can join lots of relations together with AND, and then the whole
lot is true if all the individual relations are.

One relation OR another is true whenever at least one of the two


relations is true. (Remember that it is still true if both the
relations are true - this is something that English doesn't always
imply.)

The NOT relationship turns things upside down. The NOT relation is
true whenever the relation is false, and false whenever it is
true.

Logical expressions may use combinations of AND, OR and NOT, just


as numerical expressions may use combinations of +, -, * and so
on. You can even put them in brackets if necessary. Logical
operations have priorities in the same way as +, -, *, / and ↑ do.
NOT has the highest priority, then AND, then OR.

NOT is really a function, with an argument and a result, but its


priority is much lower than that of other functions. Therefore,
its argument does not need brackets unless it contains AND or OR
(or both). NOT a=b means the same as NOT (a=b) (and the same as
a<>b of course).
<> is the negation of = in the sense that it is true only if = is
false. In other words...

a<>b is the same as NOT a=b

...and also...

NOT a<>b is the same as a=b

Convince yourself that >= and <= are the negations of < and >
respectively. Thus you can always get rid of NOT from in front of
a relation by changing the relation.

Also...

NOT(a first logical expression AND a second)

...is the same as...

NOT(the first)OR NOT(the second)

...and...

NOT(a first logical expression OR a second)

...is the same as...

NOT(the first)AND NOT(the second)

Using this, you can work NOTs through brackets until eventually
they are all applied to relations, and then you can get rid of
them. Logically speaking, NOT is unnecessary, although you might
still find that using it makes a program clearer.

The following section is quite complicated, and can be skipped by


the faint-hearted!

Try...

PRINT 1=2,1 <> 2

...which you might expect to give a syntax error. In fact, as far


as the computer is concerned, there is no such thing as a logical
value - instead it uses ordinary numbers, subject to a few
rules...

(i) =, <, >, <=, >= and <> all give the numeric results: 1 for
true, and 0 for false. Thus, the PRINT command above printed
0 for 1=2, which is false, and 1 for 1<>2, which is true.

(ii) In the statement...

IF condition THEN...
...the condition can be actually any numeric expression. If its
value is 0, then it counts as false, and any other value
(including the value of 1 that a true relation gives) counts as
true. Thus the IF statement means exactly the same as...

IF condition <>0 THEN...

(iii)AND, OR and NOT are also number-valued operations...

x, if y is true (non-zero)
x AND y has the value
0 (false), if y is false (zero)

1 (true), if y is true (non-zero)


x OR y has the value
x, if y is false (zero)

0 (false), if x is true (non-zero)


NOT x has the value
1 (true), if x is false (zero)

(Notice that 'true' means non-zero when we're checking a given


value, but it means 1 when we're producing a new one.)

Now try this program...

10 INPUT a
20 INPUT b
30 PRINT (a AND a >= b)+(b AND
a< b)
40 GO TO 10

Each time it prints the larger of the two numbers a and b.

Convince yourself that you can think of...

x AND y

...as meaning...

x if y (else the result is 0)

...and of...

x OR y

...as meaning...

x unless y (in which case the result is 1)


An expression using AND or OR like this is called a conditional
expression. An example using OR could be...

LET total=price less tax*(1.15 OR v$="zero rated")

Notice how AND tends to go with addition (because its default


value is 0), and OR tends to go with multiplication (because its
default value is 1).

You can also make string valued conditional expressions, but only
using AND.

x$ if y is non-zero
x$ AND y has the value
"" if y is zero

...so it means x$ if y (else the empty string).

Try this program, which inputs two strings and puts them in
alphabetical order.

10 INPUT "type in two strings"


'a$,b$
20 IF a$> b$ THEN LET c$=a$: L
ET a$=b$: LET b$=c$
30 PRINT a$;" ";("<" AND a$< b
$)+("=" AND a$=b$);" ";b$
40 GO TO 10
Part 14
The Character Set
Subjects covered...

CODE, CHR$
POKE, PEEK
USR
BIN

The letters, digits, spaces, punctuation marks and so on that can


appear in strings are called characters, and they make up the
character set that the +2A uses. Most of these characters are
single symbols, but there are some more, called tokens, that
represent whole words, such as PRINT, STOP, <> and so on.

There are 256 characters, and each one has a code between 0 and
255 (there is a complete list of them in part 28 of this chapter).
To convert between codes and characters, there are two functions,
CODE and CHR$.

CODE is applied to a string, and gives the code of the first


character in the string (or 0 if the string is empty).

CHR$ is applied to a number, and gives the single character string


whose code is that number.

This program prints out the entire character set...

10 FOR a=32 TO 255: PRINT CHR$


a;: NEXT a

On the screen will appear the following...

The character set


As you can see, the character set consists of a space, 15 symbols
and punctuation marks, the ten digits, seven more symbols, the
capital letters, six more symbols, the lower case letters and five
more symbols. These are all (except £ and ©) taken from a widely-
used set of characters known as ASCII (American Standard Codes for
Information Interchange). ASCII also assigns numeric codes to
these characters, and these are the codes that the +2A uses.

The rest of the characters are not part of ASCII, but are
dedicated to the ZX Spectrum range of computers. First amongst
them are a space and 15 patterns of black and white blobs. These
are called the graphics symbols and can be used for drawing
pictures. You can enter these from the keyboard, using what's
known as graphics mode. Pressing the GRAPH key switches on
graphics mode, after which the keys 1, 2, 3, 4, 5, 6, 7 and 8 will
produce the graphics symbols...

While in graphics mode, pressing CAPS SHIFT together with one of


the keys 1 to 8 produces 'inverted' versions of the same symbols,
ie. black becomes white and white becomes black...

The cursor keys won't work properly while all this is going on as
the +2A interprets them as shifted number keys, and prints
graphics characters accordingly.

Pressing the 9 key turns everything back to normal (as does


pressing GRAPH again). The 0 key deletes the character to the left
of the cursor.
Here are the sixteen graphics symbols...

Symbol Code Symbol Code

128 143

129 142

130 141

131 140

132 139

133 138

134 137

135 136

After the graphics symbols in the character set, you will see what
appears to be another copy of the alphabet from A to S. These are
characters that you can redefine yourself (though when the machine
is first switched on they are set as letters) - they are called
user-defined graphics. You can type these in from the keyboard by
going into graphics mode, and then using the letter keys A to S.

To define a new character for yourself, follow this recipe - it


defines a character to show π.

(i) Work out what the character looks like. Each character has an
8 x 8 grid of dots, each of which can appear to be either on
or off. You'd draw a diagram something like this (with black
squares representing the dots which are on)...
When a dot is on, the +2A prints the ink colour; when a dot is
off, the +2A prints the paper colour. (The terms ink and paper are
explained in part 16 of this chapter.)

We've left a one-square border around the edge of the character


because all the other letters also have one (except for lower case
letters with tails, where the tail goes right down to the bottom).

(ii) Work out which user-defined graphic you wish to display π -


let's say the one corresponding to P, so that if you press P
(after pressing GRAPH) you get π.

(iii)Store the new pattern. Each user-defined graphic has its


pattern stored as eight numbers, one for each row. You can
write each of these numbers in a program as BIN followed by
eight 0's or 1's - 0 for paper, 1 for ink - so the eight
numbers for our π character are...

BIN 00000000 - top row


BIN 00000000 - second row down
BIN 00000010 - third row down
BIN 00111100 - fourth row down
BIN 01010100 - fifth row down
BIN 00010100 - sixth row down
BIN 00010100 - seventh row down
BIN 00000000 - bottom row

(If you know about binary numbers, then it should help you to know
that BIN is used to write a number in binary instead of the usual
decimal.) Look at the pattern of binary numbers through half-
closed eyes - you may even be able to see the π character!

These eight numbers are stored in eight locations (bytes) in


memory. Each of these locations has an address. The address of the
first byte (or group of eight digits) is USR "P" (we chose P in
(ii) above). The address of the second byte is USR "P"+1, and so
on up to the eighth byte, which has the address USR "P"+7.

USR here is a function to convert a string argument into the


address of the first byte in memory for the corresponding user-
defined graphic. The string argument must be a single character
which can be either the user-defined graphic itself or the
corresponding letter (in upper or lower case). There is another
use for USR, when its argument is a number, which will be dealt
with later.

Even if you don't understand this, the following program will


define the character for you...

10 FOR n=0 TO 7
20 READ row : POKE USR "P"+n, r
ow
30 NEXT n
40 DATA BIN 00000000
50 DATA BIN 00000000
60 DATA BIN 00000010
70 DATA BIN 00111100
80 DATA BIN 01010100
90 DATA BIN 00010100
100 DATA BIN 00010100
110 DATA BIN 00000000

The POKE statement stores a number directly in a memory location,


bypassing the mechanisms normally used by the BASIC. The opposite
of POKE is PEEK, and this allows us to look at the contents of a
memory location although it does not actually alter the contents
themselves. PEEK and POKE are described more fully in part 24 of
this chapter.

After the user-defined graphics in the character set come the


tokens.

You will have noticed that we have not printed out the first 32
characters (codes 0 to 31) - these are control characters. They
don't produce anything printable, but instead are used to control
the screen display or some other function of the +2A.

(If you try to print control characters, the +2A displays ? to


show that it doesn't understand them. Control characters are
described more fully in part 28 of this chapter.)

The three control characters that the screen display uses are 6, 8
and 13 (these will now be explained). On the whole, CHR$ 8 is the
only one you are likely to find useful.

CHR$ 6 prints spaces in exactly the same way as a comma does in a


PRINT statement, for instance...

PRINT 1; CHR$ 6;2

...does the same as...

PRINT 1,2

Obviously this is not a very clear way of using it. A more subtle
way is to say...

LET a$="1"+ CHR$ 6+"2"


PRINT a$

CHR$ 8 is 'backspace' - it moves the print position back one


place. Try...

PRINT "1234"; CHR$ 8;"5"

...which prints out...


1235

CHR$ 13 is 'newline' - it moves the print position to the


beginning of the next line.

The screen display also uses control codes 16 to 23 - these are


explained in parts 15 and 16 of this chapter (all the codes are
listed in part 28).

Using the codes for the characters we can extend the concept of
'alphanumerical ordering' to cover strings containing any
characters, not just letters. If instead of thinking in terms of
the usual alphabet of 26 letters we use the extended alphabet of
256 characters, in the same order as their codes, then the
principle is exactly the same. For instance, the following strings
are in their 'Spectrum' ASCII alphabetical order. (Notice the
rather odd feature that lower case letters come after all the
capitals; so a comes after Z. Notice also that spaces are
significant.)

CHR$ 3+"ZOOLOGICAL GARDENS"


CHR$ 8+"AARDVARK HUNTING"
" AAAARGH!"
"(Parenthetical remark)"
"100"
"129.95 inc. VAT"
"AASVOGEL"
"Aardvark"
"Elgar, the Regal Lager"
"PRINT"
"Zoo"
"[interpolation]"
"aardvark"
"aasvogel"
"derby"
"zoo"
"zoology"

Here is the rule for finding out in which order two strings come.
Start by comparing the first two characters. If they are
different, then one of them has its code less than the other, and
the string it comes from is the earlier (lesser) of the two
strings. If they are the same, then go on to compare the next two
characters. If in this process one of the strings runs out before
the other, then that string is the earlier; otherwise they must be
equal.

The relations =, <, >, <=, >=, and <> are used for strings as well
as for numbers: < means 'comes before' and > means 'comes after',
so that...

"AA man"<"AARDVARK"
"AARDVARK">"AA man"
...are both true.

<= and >= work the same way as they do for numbers, so that...

"The same string" <= "The same string"

...is true, but...

"The same string" < "The same string"

...is false.

Experiment on all this using the program here, which inputs two
strings and puts them in order.

10 INPUT "Type in two strings:


",a$,b$
20 IF a$> b$ THEN LET c$=a$: L
ET a$=b$: LET b$=c$
30 PRINT a$;" ";
40 IF a$< b$ THEN PRINT "<";:
GO TO 60
50 PRINT "=";
60 PRINT " ";b$
70 GO TO 10

Note (in the above program and also in the program at the end of
part 13) how we have to introduce c$ in line 20 when we swap over
a$ and b$. Can you see why simply using...

LET a$=b$: LET b$=a$

...would not have the desired effect?

The next program sets up user defined graphics for the following
keys to display chess pieces...

B for bishop
K for king
R for rook
Q for queen
P for pawn
N for knight

Chess pieces...

5 LET b=BIN 01111100: LET c=B


IN 00111000: LET d=BIN 0001
0000
10 FOR n=1 TO 6: READ p$: REM
6 pieces
20 FOR f=0 TO 7: REM read piec
es into 8 bytes
30 READ a: POKE USR p$+f, a
40 NEXT f
50 NEXT n
100 REM bishop
110 DATA "b", 0, d, BIN 0010100
0, BIN 01000100
120 DATA BIN 01101100, c, b, 0
130 REM king
140 DATA "k", 0, d, c, d
150 DATA c, BIN 01000100, c, 0
160 REM rook
170 DATA "r", 0, BIN 01010100,
b, c
180 DATA c, b, b, 0
190 REM queen
200 DATA "q", 0, BIN 01010100,
BIN 00101000, d
210 DATA BIN 01101100, b, b, 0
220 REM pawn
230 DATA "p", 0, 0, d, c
240 DATA c, d, b, 0
250 REM knight
260 DATA "n", 0, d, c, BIN 0111
1000
270 DATA BIN 00011000, c, b, 0

Note that in the above DATA statements, we have simply used 0


instead of BIN 00000000.

When you have run this program, you may look at the pieces by
pressing GRAPH followed by any of the keys: B, K, R, Q, P or N.

Exercises...

1. Imagine the space for one symbol divided up into four


quarters like a Battenberg cake. Then if each quarter can be
either black or white, there are 24=16 possibilities. Find
them all in the character set.

2. Run this program...

10 INPUT c
20 PRINT CHR$ c;
30 GO TO 10

If you experiment with it, you'll find that CHR$ c is rounded to


the nearest whole number; and if c is not in the range 0 to 255,
then the program stops with the error report B integer out of
range.
3. Which of these is the lesser?

"EVIL"
"evil"
Part 15
More about PRINT and INPUT
Subjects covered...

CLS
PRINT items
Expressions (numeric or string type)
TAB numeric expression
AT numeric expression
PRINT separators, ; '
INPUT items
Variables (numeric or string type)
LINE string variable
Scrolling
SCREEN$

You have already seen PRINT used quite a lot, so you will have a
rough idea of how it is used. Expressions whose values are printed
are called PRINT items. They may be separated by commas,
semicolons or apostrophes, which are called PRINT separators. A
PRINT item can also be nothing at all, which is a way of
explaining what happens when you use PRINT on its own.

There are two more kinds of PRINT items, which are used to tell
the +2A not what, but where to print. For example, the
instruction...

10 PRINT AT 11,16;"*"

...prints an asterix * in the centre of the screen. This is


because...

AT line,column

...moves the PRINT position (the place where the next item is to
be printed) to the line and column specified. Lines are numbered
from 0 (at the top) to 21; columns are numbered from 0 (on the
left) to 31.

SCREEN$ is the reverse function to PRINT AT, and will (within


limits) 'read' the character which is located at a particular
position on the screen. It uses line and column numbers in the
same way as PRINT AT, but enclosed in brackets. For example, the
instruction...

20 PRINT AT 0,0; SCREEN$ (11,16)

...will read the asterix printed in the centre of the screen, then
print it at location 0,0 (the top left-hand corner).

Characters from tokens are read normally (as single characters),


and spaces are read as spaces. However, attempting to read user-
defined characters, graphics characters, or lines drawn by PLOT,
DRAW and CIRCLE, result in a null (empty) string being returned.
The same applies if OVER has been used to create a composite
character. (The keywords PLOT, DRAW, CIRCLE and OVER are described
in parts 16 and 17 of this chapter.)

The function...

TAB column
...prints enough spaces to move the PRINT position to the column
specified. It stays on the same line, or, if this would involve
backspacing, moves to the next line. Note that the +2A reduces the
column number 'modulo 32' (ie. it divides by 32 and takes the
remainder) - so TAB 33 means the same as TAB 1.

As an example...

PRINT TAB 30;1; TAB 12;"Contents


"; AT 3,1;"Chapter"; TAB 24;"Pag
e"

...is how you might want to print out the heading on the contents
page (page 1) of a book.

Try running this...

10 FOR n=0 TO 20
20 PRINT TAB 8*n;n;
30 NEXT n

This shows what is meant by the TAB numbers being reduced modulo
32.

For a more elegant example, change the 8 in line 20 to a 6.

Note the following points...

(i) TABs and print items are best terminated with semicolons, as
we have done above. You can use commas (or nothing, at the
end of the statement), but this means that after having
carefully set up the PRINT position, you immediately move it
on again - not terribly useful!

(ii) You cannot print on the bottom two lines (22 and 23) on the
screen because they are reserved for commands, INPUT data,
reports, error messages and so on. References to the 'bottom
line' usually mean line 21.

(iii)You can use AT to locate the PRINT position even where there
is already something printed - the new print item will simply
overwrite the old.

Another statement connected with PRINT is CLS. This clears the


whole screen.

When printing reaches the bottom of the screen, it starts to


scroll upwards rather like a typewriter. You can see this if you
go into the small screen using the edit menu option Screen
(described in chapter 6), and then type...

CLS: FOR n=1 TO 30: PRINT n: NEXT n


When it has printed a screen full, the +2A will stop with the
message scroll? at the bottom of the screen. You can now inspect
the first 22 numbers at your leisure. When you have finished with
them, press Y (for yes) and the +2A will give you the next screen
full of numbers. Actually, any key will make the +2A carry on
except N (for no), the BREAK key or the space bar. These will make
the +2A stop running the program with the report D BREAK - CONT
repeats.

The INPUT statement can do much more than we have told you so far.
You have already seen INPUT statements like...

INPUT "How old are you?", age

...in which the +2A prints the caption How old are you? at the
bottom of the screen, and then you have to type in your age. In
fact though, an INPUT statement can be made up of items and
separators in exactly the same way as a PRINT statement, so How
old are you? and age are both INPUT items. INPUT items are
generally the same as PRINT items, however, there are some very
important differences:

First, an obvious extra INPUT item is the variable whose value you
require to be typed in - age in our example above. The rule is
that if an INPUT item begins with a letter, then it must be a
variable whose value is to be input.

This would seem to mean that you can't print out the values of
variables as part of a caption. However, you can get round this by
putting brackets around the variable. Any expression that starts
with a letter must be enclosed in brackets if it is to be printed
as part of a caption.

Any kind of PRINT item that is not affected by these rules is also
an INPUT item. Here is an example to illustrate what's going on...

LET my age = INT ( RND * 100): I


NPUT ("I am ";my age;".");" How
old are you?", your age

my age is contained in brackets, so its value gets printed out.


your age is not contained in brackets, so you have to type its
value in.

Everything that an INPUT statement writes goes to the bottom part


of the screen, which acts somewhat independently of the top part.
In particular, its lines are numbered relative to the top line of
the bottom half, even if this has moved up the actual TV screen
(which it does if you type lots of INPUT data). Whatever the small
screen does during INPUT, however, it will always revert to being
two lines in size when the program stops, and you start editing.
To see how AT works in INPUT statements, try this...

10 INPUT "This is line 1.",a$;


AT 0,0;"This is line 0.",a
$; AT 2,0;"This is line 2."
,a$; AT 1,0;"This is still
line 1.",a$

Run the program (just press ENTER each time it stops). When This
is Line 2, is printed, the lower part of the screen moves up to
make room for it; but the numbering moves up as well, so that the
lines of text keep their same numbers.

Now try this...

10 FOR n=0 TO 19: PRINT AT n, 0


;n;: NEXT n
20 INPUT AT 0, 0;a$; AT 1, 0;a$
; AT 2, 0;a$; AT 3, 0;a$; AT
4, 0;a$; AT 5, 0;a$;

As the lower part of the screen goes up and up, the upper part
remains undisturbed until the lower part threatens to write on the
same line as the PRINT position. Then the upper part starts
scrolling up to avoid this.

Another refinement to the INPUT statement that we haven't seen yet


is called LINE input and is a different way of inputting string
variables. If you use LINE before the name of a string variable to
be input, as in...

INPUT LINE a$

...then the +2A will not give you the string quotes that it
normally does for a string variable (though it will pretend to
itself that they are there). So if you type in...

bugs

...as the INPUT data, a$ will be given the value bugs. Because the
string quotes do not appear with the string, you cannot delete
them and type in a different sort of string expression for the
INPUT data. Remember that you cannot use LINE for numeric
variables.

There's an interesting side effect to INPUT. Whilst typing into an


INPUT request, the old Spectrum single-key entry system enjoys a
brief moment of freedom before being locked away again when you
press ENTER. Run this program if you're interested...

10 INPUT numbers
20 PRINT numbers
30 GO TO 10
Input a few numbers, and they'll be printed faithfully onto the
screen. Now press EXTEND MODE followed by the M key. The word PI
appears, and if you press ENTER, then 3.1415927 will appear as if
by magic. However, if you type PI as two letters without the aid
of EXTEND MODE then the +2A will stop with the report 2 Variable
not found, 10:1.

There's no simple explanation for this behaviour, and it's best


just to be aware that it can happen if you press some combinations
of keys during INPUT. If for some reason you're keen to
experiment, chapter 7 (Using 48 BASIC) will tell you which keys
produce which effects.

The control characters CHR$ 22 and CHR$ 23 have effects rather


like AT and TAB. Whenever the +2A is instructed to print one of
them, the character must be followed by two more characters that
do not have their usual effect, but that are treated instead as
numbers (their codes) to specify the line and column (for AT) or
the tab position (for TAB). You will almost always find it easier
to use AT and TAB in the usual way rather than use control
characters, however, they might be useful in some circumstances.
The AT control character is CHR$ 22. The first character after it
specifies the line number and the second specifies the column
number, so that...

PRINT CHR$ 22+ CHR$ 1+ CHR$ c;

...has exactly the same effect as...

PRINT AT 1, c;

This is so that even if CHR$ 1 or CHR$ c would normally have a


different meaning (for instance if c=13); the CHR$ 22 before them
overrides that.

The TAB control character is CHR$ 23 and the two characters after
it combine to give a number between 0 and 65535, specifying the
number you would have in a TAB item. The statement...

PRINT CHR$ 23+ CHR$ a+ CHR$ b;

...has the same effect as...

PRINT TAB a+256*b;

You can use POKE to stop the computer asking if you wish to
scroll? by typing...

POKE 23692, 255

...every so often. After this it will scroll up 255 times before


stopping with scroll? As an example try...
10 FOR n=0 TO 1000
20 PRINT n: POKE 23692,255
30 NEXT n

...and watch everything whizz off the screen!

Exercise...

1. Try this program on some children, to test their


multiplication tables...

10 LET m$=""
20 LET a= INT ( RND *12)+1: LE
T b = INT ( RND *12)+1
30 INPUT (m$) ' ' "what is ";(
a);" x ";(b);"?";c
100 IF c=a*b THEN LET m$="Right
.": GO TO 20
110 LET m$="Wrong. Try again.":
GO TO 30

If they are perceptive, they might manage to work out that they do
not have to do the calculation themselves. For instance, if the
+2A asks them to type the answer to 2x3, then all they have to do
is type in 2*3 literally.
Part 16
Colours
Subjects covered...

INK, PAPER, FLASH, BRIGHT, INVERSE, OVER


BORDER

Run this program...

10 FOR m=0 TO 1: BRIGHT m


20 FOR n=1 TO 10
30 FOR c=0 TO 7
40 PAPER c: PRINT " ";: REM
4 coloured spaces
50 NEXT c: NEXT n: NEXT m
60 FOR m=0 TO 1: BRIGHT m: PAP
ER 7
70 FOR c=0 TO 3
80 INK c: PRINT c;" ";
90 NEXT c: PAPER 0
100 FOR c=4 TO 7
110 INK c: PRINT c;" ";
120 NEXT c: NEXT m
130 PAPER 7: INK 0: BRIGHT 0

This shows the eight colours (including white and black) and the
two levels of brightness that the +2A can produce on a colour TV.
(If your TV is black-and-white, then you will see just various
shades of grey.) A quicker way to achieve a similar result is to
RESET the +2A whilst holding down BREAK - but that's a little
drastic. Here is a list of which numbers produce which colours
(for your reference)...

0 - black
1 - blue
2 - red
3 - magenta
4 - green
5 - cyan
6 - yellow
7 - white

On a black-and-white TV, these numbers are in order of brightness.


To use these colours properly you need to understand a bit about
how the picture is arranged.

The picture is divided up into 768 (24 lines of 32) positions


(cells) where characters can be printed.
A typical character cell

Each character cell consists of an 8 x 8 grid (such as above).


This should remind you of the user-defined graphics in part 14,
where we had 0s for the white dots and 1s for the black dots.

The character has two colours associated with it: the ink, or
foreground colour, which is the colour for the black dots in our
square, and the paper, or background colour, which is used for the
white dots. To start off with, every cell has black ink and white
paper so writing appears as black on white.

The character also has a brightness (normal or extra bright), and


something to say whether it flashes or not. Flashing is done by
continuously swapping the ink and paper colours. All this
information can be coded into numbers, so a character then has the
following...

(i) An 8 x 8 grid of 0s and 1s to define the shape of the


character, with 0 for paper and 1 for ink.

(ii) Ink and paper colours, each coded into a number between 0 and
7.

(iii)A brightness - 0 for normal, 1 for extra bright.

(iv) A flash number - 0 for steady, 1 for flashing.

Note that since the ink and paper colours cover a whole character
cell, you cannot possibly have more than two colours in a given
block of 64 dots. The same goes for the brightness and flash
numbers - they refer to the whole character cell, not individual
dots within the cell. The colour, brightness and flash number for
a given character cell are called attributes.

When you print something on the screen, you change the dot pattern
for that character cell. It is less obvious, but still true, that
you also change the cell's attributes. To start off with you do
not notice this because everything is printed with black ink on
white paper (at normal brightness and no flashing); however, you
can vary this with the INK, PAPER, BRIGHT and FLASH statements.
Using the edit menu's Screen option, go to the bottom screen, and
try...

PAPER 5

...and then PRINT a few items on the screen - they will appear on
cyan paper, because as they are printed, the paper colour for the
cells they occupy are set to cyan (which has code 5).

The others work the same way, so you may use the settings...

PAPER (whole number between 0 and 7)


INK (whole number between 0 and 7)
BRIGHT (whole number between 0 and 1)
FLASH (whole number between 0 and 1)

...and any printing will set the corresponding attributes for all
the character cells it subsequently uses.

Try some of these out. You should now be able to see how the
program at the beginning of this section worked (remember that a
space is a character that has its ink and paper the same colour).

There are some more numbers you can use in these statements that
have less direct effects.

8 can be used in all four statements, and means 'transparent' in


the same sense that the old attribute shows through. Suppose, for
instance, that you do...

PAPER 8

No character position will ever have its paper colour set to 8


because there is no such colour; what happens is that when a
position is printed on, its paper colour is left the same as it
was before. However, INK 8, BRIGHT 8 and FLASH 8 work the same way
as for the other attribute numbers.

9 can be used only with PAPER and INK, and means 'contrast'. The
colour (ink or paper) that you use it with is made to contrast
with the other by being made white if the other is a dark colour
(black, blue, red or magenta), or being made black if the other is
a light colour (green, cyan, yellow or white).

Try this by doing...

INK 9: FOR c=0 TO 7: PAPER c: PRINT c: NEXT c

A more impressive display of its power is to run the program at


the beginning to make coloured stripes (again, making sure that
you are in the lower screen when you type RUN), and then doing...
INK 9: PAPER 8: PRINT AT 0, 0;:
FOR n=1 TO 1000: PRINT n;: NEXT n

The ink colour here is always made to contrast with the old paper
colour for each character cell.

Colour TV relies on the fact that the human eye need see only
three colours of light (red, green and blue) in various
combinations and intensities in order to perceive all the colours
of the spectrum. The +2A also displays its spectrum of colours by
using mixtures of red, green and blue. For instance, yellow is
made by mixing red with green - which is why its code, 6, is the
sum of the codes for red and green.

To see how all eight colours fit together, imagine three


rectangular spotlights, coloured red, green and blue shining at
not quite the same place on a piece of white paper in the dark.
Where they overlap you will see mixtures of colours, as shown by
the following program (note that solid ink spaces are obtained by
entering graphics mode (pressing GRAPH) then holding down CAPS
SHIFT while pressing 8. To exit from graphics mode, press 9.)...

10 BORDER 0: PAPER 0: INK 7: C


LS
20 FOR a=1 TO 6
30 PRINT TAB 6; INK 1;"███████
███████████": REM 18 ink sq
uares
40 NEXT a
50 LET dataline=200
60 GO SUB 1000
70 LET dataline=210
80 GO SUB 1000
90 STOP
200 DATA 2,3,7,5,4
210 DATA 2,2,6,4,4
1000 FOR a=1 TO 6
1010 RESTORE dataline
1020 FOR b=1 TO 5
1030 READ c: PRINT INK c;"██████
";: REM 6 ink squares
1040 NEXT b: PRINT: NEXT a
1050 RETURN

There is a function called ATTR that finds out what the attributes
are at a given position on the screen. It is a fairly complicated
function, so it has been relegated to the end of this section.

There are two more statements, INVERSE and OVER, which control not
the attributes, but the dot pattern that is printed on the screen.
They use the numbers 0 for off, and 1 for on. If you use INVERSE
1, then each character cell's dot pattern will be the inverse of
its usual form, ie. paper dots will be replaced by ink dots and
vice versa. Thus the character cell containing 'a' (shown
previously) would be printed as follows...

If (as at switch on) we have black ink and white paper, then the
'a' will appear as white on black. The statement...

OVER 1

...sets into action a particular sort of overprinting. Normally


when something is written into a character position, it completely
obliterates what was there before; however, using OVER 1, the new
character is simply added on top of the old one. This can be
particularly useful for writing composite characters, like an
underlined letter, as in the following program. (Reset the
computer and select +3 BASIC. Note that the underline character is
obtained by pressing SYMB SHIFT together with 0.)...

10 OVER 1
20 PRINT "w"; CHR$ 8;"_";

(Notice we have used the control character CHR$ 8 (backspace)


before overprinting the w with _.)

There is another way of using INK, PAPER and so on which you will
probably find more useful than having them as statements. You can
put them as items in a PRINT statement (followed by ;), and they
then do exactly the same as they would have done if they had been
used as statements on their own, except that their effect is only
temporary, lasting as far as the end of the PRINT statement that
contains them. Thus if you type...

PRINT PAPER 6;"x";: PRINT "y"

...then only the x will be on yellow paper.

PAPER, INK, etc. when used as statements do not affect the colour
in the bottom part of the screen (where INPUT data is typed in and
reports are displayed). The bottom screen uses the colour of the
border for its paper colour, code 9 (for contrast) for its ink
colour, has flashing off, and everything at normal brightness. You
can change the border colour to any of the eight normal colours
(not 8 or 9) using the statement...

BORDER colour

When you type in INPUT data, it follows this rule of using


contrasting ink on border coloured paper; but you can change the
colour of the captions written by the +2A by using PAPER, INK,
etc. items in the INPUT statement, just as you would in a PRINT
statement. Their effect lasts either to the end of the statement,
or until some INPUT data is typed in, whichever comes soonest.
Try...

INPUT FLASH 1; INK 4;"Enter a number?";n

The +2A has a high regard for your sanity - no matter what
combination of effects and colours you manage to produce from a
BASIC program, the editor will always use black ink on white
paper.

There is one more way of changing the colours by using control


characters - rather like the control characters for AT and TAB in
part 15.

CHR$ 16 corresponds to INK


CHR$ 17 corresponds to PAPER
CHR$ 18 corresponds to FLASH
CHR$ 19 corresponds to BRIGHT
CHR$ 20 corresponds to INVERSE
CHR$ 21 corresponds to OVER

These are each followed by one character that shows a colour by


its code; so that (for instance)...

PRINT CHR$ 16+ CHR$ 9;"item"

...has the same effect as...

PRINT INK 9;"item"

On the whole, you would not bother to use these control characters
because you might just as well use the statements PAPER, INK, etc.
However, if you have some old 48K BASIC programs on cassette, you
may find such control characters embedded in the listing. In
general, the editor will actively ignore them, and remove them at
the first opportunity. It is not possible to insert them into
listings as with the old 48K Spectrum.

The ATTR function has the form...

ATTR (line,column)
Its two arguments are the line and column numbers that you would
use in an AT item, and its result is a number that shows the
colours and so on at the corresponding character position on the
TV screen. You can use this as freely in expressions as you can
any other function.

The number that is the result is the sum of four other numbers as
follows:

128 - if the character cell is flashing, 0 if it is


steady.
64 - if the character cell is bright, 0 if it is
normal.
8 - multiplied by the code for the paper colour.
1 - multiplied by the code for the ink colour.

For instance, if the character cell is flashing, normal


brightness, yellow paper and blue ink, then the four numbers that
we have to add together are 128, 0, 8x6=48 and 1, making 177
altogether. Test this with...

PRINT AT 0,0; FLASH 1; PAPER 6;


INK 1;" "; ATTR (0,0)

Exercises...

l. Try...

PRINT "B"; CHR$ 8; OVER 1;"/";

Where the / has cut through the B, it has left a white dot. This
is the way that overprinting works on the +2A - two papers or two
inks give a paper, one of each gives an ink. This has the
interesting property that if you overprint with the same thing
twice you end up with what you had at the beginning. If you now
type...

PRINT CHR$ 8; OVER 1;"/"

...why do you recover an unblemished B?

2. Run this program...

10 POKE 22527+ RND *704, RND *


127
20 GO TO 10

(Never mind how this program works.) The program is changing the
colours of squares on the TV screen and the RND should ensure that
this happens randomly. (The diagonal stripes that you eventually
see are a manifestation of the hidden pattern in RND, ie. pseudo-
random instead of truly random.)
Part 17
Graphics
Subjects covered...

PLOT, DRAW, CIRCLE


Pixels

For all of this section, type in the example programs, commands


and RUN in the small screen (use the edit menu's Screen option).

In this section we shall see how to draw pictures on the +2A. The
part of the screen you can use has 22 lines and 32 columns, making
22x32=704 character positions. As you may remember from part 16,
each of these character positions is made up of an 8 x 8 grid of
dots which are called pixels (picture elements).

A pixel is specified by two numbers - its coordinates. The first,


its x coordinate, says how far it is across from the extreme left-
hand column. The second, its y coordinate, says how far it is up
from the bottom. These coordinates are usually written as a pair
in brackets, so (0,0) (225,0) (0,175) and (255,175) are the bottom
left, bottom right, top left and top right corners of the screen.

If you have trouble memorising which coordinate is which, simply


remember that x is a cross (x is across).

The statement...

PLOT x coordinate,y coordinate...

...inks in the pixel with these coordinates, so this measles


program...

10 PLOT INT ( RND *256), INT (


RND *176): INPUT a$: GO TO
10

...plots a random point each time you press ENTER.

Here is a rather more interesting program. It plots a graph of the


function SIN (a sine wave) for values between 0 and 2π...

10 FOR n=0 TO 255


20 PLOT n, 88+80* SIN (n/128*
PI )
30 NEXT n
This next program plots a graph of SQR (part of a parabola)
between 0 and 4...

10 FOR n=0 TO 255


20 PLOT n, 80* SQR (n/64)
30 NEXT n

Notice that pixel coordinates are rather different from the line
and column in an AT item. You may find that the diagram in part 15
of this chapter is useful when working out pixel coordinates and
line and column numbers.

To help you with your pictures, the +2A will draw straight lines,
circles and parts of circles for you, using the DRAW and CIRCLE
statements.

The statement DRAW (to draw a straight line) takes the form...

DRAW x,y

The starting place of the line is the pixel where the last PLOT,
DRAW or CIRCLE statement left off (this is called the PLOT
position - RUN, CLEAR, CLS and NEW reset it to the bottom left-
hand corner, at 0,0); the finishing place of the line is x pixels
to the right of that and y pixels up. The DRAW statement on its
own determines the length and direction of the line, but not its
starting point.

Experiment with a few PLOT and DRAW commands, for instance...

PLOT 0,100: DRAW 80,-35


PLOT 90,150: DRAW 80,-35

Notice that the numbers in a DRAW statement can be negative, but


those in a PLOT statement can't.

You can also plot and draw in colour, although you have to bear in
mind that colours always cover the whole of a character cell and
cannot be specified for individual pixels. When a pixel is
plotted, it is set to show the full ink colour, and the whole of
the character cell containing it is given the current ink colour.
This program demonstrates that point...

10 BORDER 0: PAPER 0: INK 7: C


LS: REM black out screen
20 LET x1=0: LET y1=0: REM sta
rt of line
30 LET c=1: REM for ink colour
, starting blue
40 LET x2 = INT ( RND *256): LE
T y2= INT ( RND *176): REM
random finish on line
50 DRAW INK c;x2-x1,y2-y1
60 LET x1=x2: LET y1=y2: REM n
ext line starts where last
one finished
70 LET c=c+1: IF c=8 THEN LET
c=1: REM new colour
80 GO TO 40

The lines seem to get broader as the program goes on, and this is
because a line changes the colours of all the inked-in pixels of
all the character cells that it passes through. Note that you can
embed PAPER, INK, FLASH, BRIGHT, INVERSE and OVER items in a PLOT
or DRAW statement just as you could with PRINT and INPUT. They go
between the keyword and the coordinates, and are terminated by
either semicolons or commas.

An extra frill with DRAW is that you can use it to draw parts of
circles instead of straight lines, by including an extra number to
specify an angle to be turned through. The form is...

DRAW x,y,a

x and y are used to specify the finishing point of the line just
as before, and a is the number of radians that it must turn
through as it goes. If a is positive then it turns to the left; if
a is negative then it turns to the right. Another way of seeing a
is as showing the fraction of a complete circle that will be
drawn, (a complete circle is 2π radians) so if a equals π it will
draw a semicircle, if a equals 0.5xπ a quarter of a circle, and so
on.

For instance, suppose a equals π. Then whatever values x and y


take, a semicircle will be drawn. Try...

10 PLOT 100,100: DRAW 50,50, PI

...which will draw this...


Finish at (150,150)

Start at (100,100)

The drawing starts off in a south-easterly direction, but by the


time it stops, it is going north-west. In between, it has turned
through 180 degrees, or π radians (the value of a).
Run the program several times, with PI replaced by various other
expressions, eg. -PI, PI/2, 3*PI/2, PI/4, 1, 0, etc.

The last statement in this section is CIRCLE, which draws an


entire circle. You specify the coordinates of the centre and the
radius of the circle using...

CIRCLE x coordinate,y coordinate,radius

Just as with PLOT and DRAW, you can put the various sorts of
colour items in at the beginning of a CIRCLE statement.

The POINT function tells you whether a pixel is ink or paper


colour. Its two arguments are the coordinates of the pixel (which
must be enclosed in brackets) and its result is 0 if the pixel is
paper colour; or 1 if it is ink colour. Try...

CLS : PRINT POINT (0,0): PLOT 0,


0: PRINT POINT (0,0)

Type...

PAPER 7: INK 0

...and investigate how INVERSE and OVER work inside a PLOT


statement. These two affect just the relevant pixel, and not the
rest of the character cell. They are normally off (0) in a PLOT
statement, so you only need to mention them to turn them on (1).

Here is a list of the possibilities for reference:

PLOT; - This is the usual form. It plots


an ink dot, ie. sets the pixel to
show the ink colour.

PLOT INVERSE 1; - This plots a dot of 'ink


eradicator', ie. it sets the pixel
to show the paper colour.

PLOT OVER 1; - This exchanges the pixel colour


with whatever it was before, so if
it was ink colour then it becomes
paper colour, and vice versa.

PLOT INVERSE 1; OVER 1; - This leaves the pixel exactly as


it was before, but note that it also
changes the PLOT position, so you
might use it simply to do that.

As another example of using the OVER statement, fill the screen up


with writing using black on white, and then type...

PLOT 0,0: DRAW OVER 1;255,175


This will draw a fairly decent line, even though it has gaps in it
wherever it hits some writing. Now type in exactly the same
command again. The line will vanish without leaving any trace
whatsoever - this is the great advantage of OVER 1. If you had
drawn the line using...

PLOT 0,0: DRAW 255,175

...and erased it using...

PLOT 0,0: DRAW INVERSE 1;255,175

...then you would also have erased some of the writing.

Now try...

PLOT 0,0: DRAW OVER 1;250,175

...and try to 'undraw' it using...

DRAW OVER 1;-250,-175

This doesn't quite work because the pixels that the line uses on
the way back are not quite the same as the ones that it used on
the way there. You must therefore undraw a line in exactly the
same direction as you drew it.

One way to get unusual colours is to speckle two normal ones


together in a single square, using a user-defined graphic. Try
this program...

1000 FOR n=0 TO 6 STEP 2


1010 POKE USR "a"+n, BIN 0101010
1: POKE USR "a"+n+1, BIN 10
101010
1020 NEXT n
1030 REM now press GRAPH then A

...which gives the user-defined graphic corresponding to a


chessboard pattern. If you print this character (press GRAPH, then
A) you will find that the character is reproduced in a combination
of the current paper and ink colours.

Exercises...

1. Experiment with PAPER, INK, FLASH and BRIGHT items in a PLOT


statement. These are the parts that affect the whole of the
character cell containing the pixel. Normally it is as though
the PLOT statement had started off...

PLOT PAPER 8; FLASH 8; BRIGHT 8; ...etc...


...and only the ink colour of a character cell is altered when
something is plotted there, but you can change this if you wish.

Be especially careful when using colours with INVERSE 1, because


this sets the pixel to show the paper colour, and may change the
ink colour, which might not be what you expect.

2. If you have read part 10, see if you can work out how to draw
circles using SIN and COS. Run this program...

10 FOR n=0 TO 2* PI STEP PI /1


80
20 PLOT 100+80* COS n, 87+80*
SIN n
30 NEXT n
40 CIRCLE 150, 87, 80

You can see that the CIRCLE statement is much quicker, albeit less
accurate.

3. Try...

CIRCLE 100,87,80: DRAW 50,50

You can see from this that the CIRCLE statement leaves the PLOT
position at a rather indeterminate place - it is always somewhere
about halfway up the right-hand side of the circle. You will
usually need to follow the CIRCLE statement with a PLOT statement
before you do any more drawing.
Part 18
Timing
Subjects covered...

PAUSE, PEEK, INKEY$

Quite often you will want to make the program take a specified
length of time, and for this you will find the PAUSE statement
useful.

PAUSE n

...stops computing and displays the picture for n frames of the TV


(there are 50 frames per second in Europe and 60 in USA). The
value of n can be up to 65535, which gives you a pause of just
under 22 minutes. If n=0 then it means 'pause indefinitely'.

A pause can always be cut short by pressing a key.

This program works the second hand of a clock...

10 REM first we draw the clock


face
20 FOR n=1 TO 12
30 PRINT AT 10-10* COS (n/6* P
I ),16+10* SIN (n/6* PI );n
40 NEXT n
50 REM now we start the clock
60 FOR t=0 TO 200000: REM t is
the time in seconds
70 LET a=t/30* PI : REM a is t
he angle of the second hand
in radians
80 LET sx=80* SIN a: LET sy=80
* COS a
200 PLOT 128,88: DRAW OVER 1;sx
,sy: REM draw second hand
210 PAUSE 42
220 PLOT 128,88: DRAW OVER 1;sx
,sy: REM erase second hand
400 NEXT t

The clock will run down after about 55.5 hours because of line 60,
but you can easily make it run longer. Note how the timing is
controlled by line 210. You might expect PAUSE 50 to make it tick
once per second, however, the computing takes a bit of time as
well and has to be allowed for. This is best done by trial and
error, timing the +2A clock against a real one, and adjusting line
210 until they agree. You can't do this very accurately - an
adjustment of one frame per second is equal to 2% (or half an hour
in a day).

There is a much more accurate way of measuring time. This uses the
contents of certain memory locations. The data stored is retrieved
by using PEEK. Part 25 of this chapter explains what we're looking
at in detail. Type in the expression...

PRINT (65536* PEEK 23674+256* PE


EK 23673+ PEEK 23672)/50

This prints the number of seconds since the +2A was turned on (up
to about 3 days and 21 hours, after which it goes back to 0).

Here is a revised clock program to make use of this...

10 REM first we draw the clock


face
20 FOR n=1 TO 12
30 PRINT AT 10-10* COS (n/6* P
I ),16+10* SIN (n/6* PI );n
40 NEXT n
50 DEF FN t()= INT ((65536* PE
EK 23674+256* PEEK 23673+ P
EEK 23672)/50) : REM number
of seconds since start
100 REM now we start the clock
110 LET t1= FN t()
120 LET a=t1/30* PI: REM a is t
he angle of the second hand
in radians
130 LET sx=72* SIN a: LET sy=72
* COS a
140 PLOT 131,91: DRAW OVER 1;sx
,sy: REM draw hand
200 LET t= FN t()
210 IF t<=t1 THEN GO TO 200: RE
M will wait until time for
next hand
220 PLOT 131,91: DRAW OVER 1;sx
,sy: REM rub out old hand
230 LET t1=t: GO TO 120

The internal clock that this method uses should be accurate to


about 0.01% (approx 10 seconds per day) so long as the +2A is
simply running the program. However, when you use the BEEP
statement (described in part 19 of this chapter) or operate the
datacorder or any peripheral attached to the +2A (eg. a printer or
disk drive), the internal clock stops temporarily, losing time.

The numbers PEEK 23674, PEEK 23673 and PEEK 23672 are held inside
the +2A and used for counting in 50ths of a second. Each is
between 0 and 255 and they gradually increase through all the
numbers from 0 to 255; after 255 they drop straight back to 0.

The one that increases most often is PEEK 23672 - every 1/50
second it increases by 1. When it is at 255, the next increase
'nudges' it to 0, and at the same time it increments PEEK 23673 up
by 1. When (every 256/50 seconds) PEEK 23673 is nudged from 255 to
0, it in turn increments PEEK 23674 up by 1. This should be enough
to explain why the expression above works.

Now, consider this carefully; suppose our three numbers are 0 (for
PEEK 23674), 255 (for PEEK 23673) and 255 (for PEEK 23672). This
means that it is about 21 minutes after switch on. Our expression
ought to yield (65536x0+256x255+255)/50 which is equal to 1310.7.

But there is a hidden danger - the next time there is a 1/50


second count, the three numbers will change to 1, 0 and 0. Every
so often, this will happen when you are half way through
evaluating the expression - the +2A would evaluate PEEK 23674 as
0, but then change the other two to 0 before it can PEEK them. The
answer would then be (65536x0+256x0+0)/50 which is equal to 0,
which is obviously wrong.

A simple way of avoiding this problem is to evaluate the


expression twice in succession and take the larger answer.

Now if you look carefully at the previous program, you can see
that it does this implicitly.

Here is a trick to apply the rule. Define the functions...

10 DEF FN m(x,y)=(x+y+ ABS (x-


y))/2: REM the larger of x
and y
20 DEF FN u()=(65536* PEEK 236
74+256* PEEK 23673+ PEEK 23
672)/50: REM time (may be w
rong)
30 DEF FN t()= FN m( FN u(), F
N u()): REM time (correct)

You can change the three counter numbers so that they give the
real time instead of the time since the +2A was switched on. For
instance, to set the time at 10.00am, you work out that this is
10x60x60x50 which is equal to 1800000 fiftieths of a second (and
1800000 is equal to 65536x27 + 256x119 + 64x1).

To set the three numbers to 27,119 and 64, you type...

POKE 23674,27: POKE 23673,119: POKE 23672,64

In countries with mains frequencies of 60 Hz (cycles per second),


these programs must replace 50 by 60 where appropriate.
The function INKEY$ (which has no argument) reads the keyboard. If
you are pressing just one key (or say, CAPS SHIFT and just one
other key), then the result is the character which that key gives
normally, otherwise the result is an empty string.

Try this program, which works like a typewriter.

10 IF INKEY$ <> "" THEN GO TO


10
20 IF INKEY$ ="" THEN GO TO 20
30 PRINT INKEY$ ;
40 GO TO 10

Here line 10 waits for you to lift your finger off the keyboard,
and line 20 waits for you to press a new key.

Unlike INPUT, INKEY$ doesn't wait for you, so you don't have to
press ENTER.

Exercises...

1. What happens if you miss out line 10 in the 'typewriter'


program?

2. Another way of using INKEY$ is in conjunction with PAUSE as


in this alternative typewriter program...

10 PAUSE 0
20 PRINT INKEY$ ;
30 GO TO 10

To make this work, why is it essential that a pause should not


finish if it finds you already pressing a key when it starts?

3. Adapt the 'clock second hand' program so that it also shows


minute and hour hands, re-drawing them every minute. If
you're feeling ambitious, arrange so that every quarter of an
hour, it puts on some kind of show - perhaps you could
produce the 'Big Ben' chimes using PLAY (described in part 19
of this chapter).
Part 19
Sound
Subjects covered...

BEEP, PLAY

As you will have already noticed, the +2A can make a variety of
noises. To get the best quality of sound, it's important to make
sure that your TV is tuned-in properly (see chapter 2). If,
instead of a TV, you are using a VDU monitor (which won't
reproduce the +2A's sound), note that a separate sound signal
(which may be connected to an audio amplifier powering speaker(s)
or headphones) is available from the TAPE/SOUND socket at the back
of the +2A. Headphones may not be plugged into the TAPE/SOUND
socket directly.

Connections to the TAPE/SOUND socket are described in chapter 10.

To get the most out of the +2A's musical ability, it helps to have
a little knowledge about musical terms.

Note that in the examples that follow, it is important that you


type in the string expressions exactly as shown in upper case and
lower case letters, ie. the example "ga" should not be typed in as
"Ga", "gA" or "GA".

Type in this command (don't worry about what it means just yet)...

PLAY "ga"

Two notes were played - the second slightly higher than the first.
The difference between the notes is called a tone. Now try...

PLAY "g$a"

Again there were two notes played - the first one was the same as
the previous example, but there was less of a jump to the second.
If you didn't hear the difference, then try the first example
followed by the second again. The second example has half the
difference between notes, and this is called a semitone.

When you're happy with semitones, try this...

PLAY "gD"
This sort of difference is called a fifth, and occurs quite often
in music of all kinds. With that example ringing in your ears,
type...

PLAY "gG"

Although (hopefully) you noticed that there was a much bigger


difference that time than for the fifth, the two notes somehow
sounded much more similar. This is called an octave, and is the
point at which music starts to repeat itself. Don't worry about
that unduly, just remember what an octave sounds
like.

There are two ways of making music and sounds with the +2A. The
most elementary is the somewhat spartan BEEP command. This takes
the form...

BEEP duration,pitch

...where the duration and pitch parameters represent numerical


expressions. The duration is given in seconds, and the pitch is
given in semitones above middle C (negative numbers for notes
below middle C).

Here is a diagram to show the pitch values of all the notes in one
octave on the piano for BEEP...

Hence, to play the A above middle C for half a second, you would
use...

BEEP 0.5,9

...and to play a scale (for example, C major) a complete (albeit


short) program is needed...

10 FOR f=1 TO 8
20 READ note
30 BEEP 0.5,note
40 NEXT f
50 DATA 0,2,4,5,7,9,11,12

To get higher or lower notes, you have to add or subtract 12 for


each octave that you go up or down.

BEEP exists mostly to provide compatibility with the older designs


of Spectrum, though it can be useful for very short or rapid sound
effects. For any new programs you develop, the second way of
producing sound is much to be preferred, and this is achieved
using the PLAY command (if you worked through the simple examples
earlier in this section, you'll remember that that's what you
used).

PLAY is much more flexible than BEEP - it can play up to three


voices in harmony with all manner of effects, and gives a much
higher quality of sound. It's also much easier to use. For
example, to play A above middle C for half a second, simply type
in...

PLAY "a"

...and to play the C major scale (which needed a program to itself


before), use...

PLAY "cdefgabC"

Notice that the last C in the example above is in upper case. This
tells the PLAY command to play it an octave higher than the lower
case c. A scale, by the way, is the term used for a set of notes
spanning an octave. The example above is called the C major scale
because it's the set of notes between two C's. Why major? There
are two main classes of scale, major and minor, and this is just
musical shorthand for describing two different sets.

Just for interest, the C minor scale sounds like this...

PLAY "cd$efg$a$bC"

Preceding a note by $ drops it by a semitone (flattens it), and


preceding a note by # raises it by a semitone (sharpens it). The
PLAY command spans 9 octaves, and can be told which one to use by
having the upper case letter O followed by a number, in the list
of notes it is given. Type in this little program...

10 LET o$="05"
20 LET n$="DECcg"
30 LET a$=o$+n$
40 PLAY a$

There are a few new things in this program. Firstly, PLAY is just
as happy with a string variable as with a string constant. In
other words, providing that a$ has been set up beforehand, PLAY a$
works just as well as PLAY "05DECcg". In fact, using variables in
PLAY statements has certain distinct advantages, and we shall be
doing this from now on.

Notice also that the string a$ has been 'built up' by combining
the two smaller strings o$ and n$. While this doesn't make much
difference at this sort of level, PLAY can cope with strings many
thousands of notes long, and the only sensible way of creating and
editing those strings from BASIC is to combine lots of smaller
strings in this way.

Now run the above program. Edit line 10 so that "05" becomes "07",
and run it again, or if you want to be a big spaceship make it
"02". If you don't specify an octave number for a particular
string, then the +2A assumes that you want octave 5. Here follows
a diagram of the notes and octave numbers which correspond to the
standard even-tempered musical scale...

There is a lot of overlap, so for example, "03D" is the same as


"04d". This makes it easier to write tunes without having to
change octave all the time. Some of the notes in the lowest
octaves (0 and 1) aren't very accurate for technical reasons, and
so the computer just makes a brave attempt at getting as close as
possible.

PLAY can also handle many different lengths of note. Edit the
program above so that line 10 is now...

10 LET o$="2"

...and run it. Then alter the setting of o$ between "1" and "9".
The note length can be changed anywhere in a string by including a
number between 1 and 9, and this is effective for all subsequent
notes until a new number is encountered. Each of these nine note
lengths has a specific musical name, and looks different when
written down in musical notation. The following table shows which
is which...
PLAY can also cope with triplets, which are three notes played in
the time for two. Unlike simple note lengths, the triplet number
only applies for the three notes immediately following, and then
the previous note length number resumes. The triplet numbers are
as follows...

PLAY is quite happy about being told to 'shut up'! A timed period
during which no notes play is called a rest, and "&" is used to
signify this. The length of rest it produces is the same as the
current note length. To demonstrate, edit lines 10 and 20 to...

10 LET 0$="04"
20 LET n$="DEC&cg"

Two notes played together without a break are called tied notes,
which are signified in a PLAY command by an _ underline, so a
crotchet c and a minim c tied together would be "5_7c". (The
second value is then used as the note length for all subsequent
notes, as before.)

There are occasions when ambiguity creeps in. Say that a piece of
music needs octave 6 and a note length of 2, then...

10 LET o$="062"
...seems a good bet - but no! The computer will find the 0 and try
to read the number following it. When it finds 62, it will stop
with the report n Out of range. In cases like this, there is a
'dummy note' called N that just serves to split things up, so line
10 should be...

10 LET o$="06N2"

The volume can be set between 0 (minimum) and 15 (maximum) using


"V" followed by a number. In practice, only 10 to 15 are likely to
be useful, as 1 to 9 are too soft unless the +2A is being used
with an amplifier. As previously mentioned, BEEP is louder than a
single channel of PLAY, but if all three channels play a note at
volume 15, then it should be at the same level as a note produced
by BEEP.

Playing more than one channel at a time is very simple; you just
separate lists of notes by commas. Try this new program...

10 LET a$="04cCcCgGgG"
20 LET b$="06CaCe$bd$bD"
30 PLAY a$,b$

In general, there is no difference between the three channels, and


any string of notes can be put onto any channel. The overall speed
of the music (the tempo) must be in the string assigned to channel
A (the first string after PLAY), otherwise it will be ignored. To
set tempo in beats (crotchets) per minute, use "T" followed by a
number between 60 and 240. The standard value is 120, or two
crotchets per second. Modify the program above to...

5 LET t$="T120"
10 LET a$=t$+"04cCcCgGgG"
20 LET b$="06CaCe$bd$bD"
30 PLAY a$,b$

...and run it several times, changing line 5 for different tempos.

A common feature in music is the repetition of a group of notes.


Any part of a string can be repeated by enclosing it in brackets,
so if you change line 10 to...

10 LET a$=t$+"04(cC)(gG)"

PLAY treats it just the same as the old line 10. If you include a
closing bracket (with no matching opening bracket), then the
string up to that point is repeated indefinitely. This is useful
for rhythm effects and bass lines. To demonstrate, try this
(you'll have to press BREAK to stop the sound)...

PLAY "04N2cdefgfed)"

...and...
PLAY "04N2cd(efgf)ed)"

If you set up an infinitely repeating bass line, and then play a


melody with it, then it would be nice if the bass line stops when
the melody does. There is a device to do this - if PLAY comes
across "H" (for halt) in any of the strings it is playing, then it
stops all sound immediately. Run the following program (again,
you'll have to press BREAK to stop it)...

10 LET a$="cegbdfaC"
20 LET b$="04cC)"
30 PLAY a$,b$

Now modify line 10 to...

10 LET a$="cegbdfaCH"

...and run it again.

So far we've only used notes which start and stop at one level of
volume. The +2A can alter the volume of a note while it is
playing, so it can start loud and die away like a piano, or rise
and fall like a dog growling. To turn these effects on, use "W"
(for waveform) followed by a number between 0 and 7, together with
"U" for each channel you want to use the effect on. Any channel
with a volume setting ("V") will not respond to "U". This table
shows graphically how the volume changes for each setting...

0 - single decay then off.


1 - single attack then off.
2 - single decay then hold.
3 - single attack then hold.
4 - repeated decay.
5 - repeated attack.
6 - repeated attack-decay.
7 - repeated decay-attack.

This program plays the same note with each effect in turn, so you
can compare them against the diagram above.

10 LET a$="UX1000W0C&W1C&W2C&W
3C&W4C&W5C&W6C&W7C"
20 PLAY a$

The U turns on effects, and the W selects which waveform to use.


There's also an "X1000". X sets how long the effect will last for
(from 0 to 65535). If you don't include an X, then the +2A will
choose the longest value. Waveforms that settle down (0 to 3 in
the previous table) after the initial part, work best with X
settings of about 1000, whereas repetitive effects (4-7) are more
effective with short values like 300. Try varying the X setting in
the previous program to get some idea of how each works.

The PLAY command isn't limited to pure musical notes. There are
also three 'white noise' generators (white noise is a sound which
is like an un-tuned FM radio or TV), and any of the three channels
can play notes, white noise, or a mixture of both. To select a mix
of noise and note, you may use "M" followed by a number between 1
and 63. You can work out which number to use from this table...

Tone channels Noise channels


, A B C A B C
Number 1 2 4 8 16 32

Write down the numbers corresponding to the effects you want, and
then add them together. If you wanted A to be noise, B to be tone,
and C to be both tone and noise, then add 8, 2, 4 and 32 to get 46
(the order of the channels is the order of the strings which
follow the PLAY command). The best effects can be obtained with
the A channel - don't be afraid to experiment.

By now, you'll be writing symphonies! However, it can be difficult


to work out just which part of the music a particular section of
string is responsible for. To alleviate this problem, your music
string may include 'comments' enclosed between ! exclamation
marks; for example...

1090 LET z$="CDcE3Ge4_6f! end of


75th bar !egeA"

The PLAY command will simply 'hop over' any comments in the
string.

If you have an electronic musical instrument with MIDI, then the


+2A can control it using PLAY. Up to 8 channels of music can be
sent to synthesisers, drum machines or sequencers. The PLAY
command is constructed exactly as described so far in this
section, except that each string should include a "Y" followed by
a number between 1 and 16. The number after the Y controls which
channel the music data is assigned to. Up to eight strings can be
used; the first three strings will still be played through the TV
as before so you'll probably want to turn the TV sound down. You
can also send MIDI programming codes via the PLAY command, using
"Z" followed by the code number. Key velocities (loudness) are
calculated and sent at 8 times the V setting (so "V6" will send 48
as a key velocity).

So, to send a little tune (in four-part harmony) to a four-voice


synthesiser (after consulting your synth handbook to find out how
to allocate MIDI channels to different voices), you would use the
PLAY command with four strings, each starting with Y followed by a
number. This example program illustrates the PLAY command in some
of its full glory...

10 LET a$="Y1T100o2(((1CCg$b))
(($E$E$b$D))((FFC$E))((GGDF
))))"
20 LET b$="Y2o5N&&&&C$bfG)"
30 LET c$="Y3o4((3C&)C&1CCDD(3
$E&)$E&1$E$EEE(3F&)F&1FF$G$
G(3G&)G&1GG$EC))"
40 LET d$="Y4N9&&&&&&&&(9EGF7b
5CD))"
50 PLAY a$,b$,c$,d$

Summary table
Finally, here is a brief list of the parameters that can be used
in the string of a PLAY command together with the values they may
take...

STRING FUNCTION
a...g Specifies the pitch of the note within the current
A...G octave range.
$ Specifies that the note which follows must be flattened.
# Specifies that the note which follows must be sharpened.
0 Specifies the octave number to be used (followed by 0 to
8).
1...12 Specifies the length of notes to be used.
& Specifies that a rest is to be played.
_ Specifies that a tied note is to be played.
N Separates two numbers.
V Specifies the volume to be used (followed by 0 to 15).
W Specifies the volume effect to be used (followed by 0 to
7).
U Specifies that the volume effect is to be used in a
string.
X Specifies duration of volume effect (followed by 0 to
65535).
T Specifies tempo of music (followed by 60 to 240).
() Specifies that enclosed phrase must be repeated.
! ! Specifies that enclosed comment is to be skipped over.
H Specifies that the PLAY command must stop.
M Specifies the channel(s) to be used (followed by 1 to
63).
Y Specifies that MIDI channel is to be used (followed by 1
to 16).
Z Specifies MIDI programming code (followed by code
number).
Part 20
File operations
Subjects covered...

Disks and drives for the +2A


Disks and RAMdisk
FORMAT
Filenames
SAVE, LOAD
Disk catalog: CAT
Wildcards
MERGE
LINE, DATA, CODE, SCREEN$
Deleting and renaming files
ERASE, MOVE
File attributes
Copying files: COPY
SCREEN$, LPRINT, SPECTRUM FORMAT
The RAMdisk
Tape operations
SAVE, LOAD, MERGE
Tape catalog: CAT

Chapter 6 introduced you to some of the more simple file commands


(eg. SAVE, LOAD, etc.) on tape and disk. This section deals with
the whole subject of file operations in greater depth.

Much of the information given in this section will apply only if


you have connected an external disk drive (or drives) to the +2A
system. Information concerning the RAMdisk (drive M:), however,
will apply to all +2A users. The end of this section describes at
length the way in which default drives can be changed. It also
covers the use of tape in some detail, so it would be a good idea
for all +2A owners (even those who have not connected a disk drive
(and interface)) to read this section.
Disks and drives for the +2A
If you wish to connect an external disk drive to the +2A, you
should use the model AMSTRAD FD-1 together with a suitable
interface (the AMSTRAD SI-1 when available, or other
manufacturer's equivalent). See chapter 10 (Peripherals for your
+2A) for further details.

The AMSTRAD FD-1 uses 3 inch compact floppy disks. We strongly


recommend that for reliable data-to-disk transfer, you use AMSOFT
CF-2 compact floppy disks. Disks made by other leading
manufacturers, however, may also be used.

Disks and RAMdisk


Disk drives can be used to save and load your own programs, and to
load programs produced by other people. As it is possible to
connect two disk drives, BASIC must have some way of identifying
which drive is which. The first drive added to your +2A is known
as drive A: (always followed by a colon because +3 BASIC knows
that when you say A:, you mean 'disk drive A'). If a second disk
drive is present, then it is referred to as drive B:.

As the processor at the heart of the +2A can only converse with
64K of memory at a time, the extra RAM in the +2A's 128K memory is
used just like another drive. This is called the RAMdisk and is
identified by the letter M: (for memory drive). Drive M: exists on
all +2As (you don't have to add a disk interface to be able to use
it). All the commands (except FORMAT) that you can use on drives
A: and B: can also be used on drive M:. Drive M is much faster
than the mechanical disk drives, but it is very important to
remember that just like the contents of the program memory, the
contents of drive M: are erased if you press the RESET button or
switch off the +2A. BASIC'S NEW command, however, will leave any
files stored on drive M: intact.

If you have connected one disk drive (only) to your +2A, you can
still use the system as if a second drive (drive B:) were present;
if you ask the +2A to perform an operation on drive B: (you'll see
how to do this later), a message will appear asking you to...

Please put the disk for B: into


the drive then press any key

...whereupon you should put the disk that you would have used in
drive B: (if it had existed) into drive A: then press any key (for
example ENTER). From then on, the machine will treat your only
disk drive as if it really were drive B:. When the +2A next needs
to perform some operation on the disk that was originally in the
drive (ie. in drive A:), it will ask you to...
Please put the disk for A: into
the drive then press any key

This technique will be particularly useful when using the COPY


command (described later in this section).

Now that you know which drives are available and what they are
called, let's see what they can be used for. Type in the short
program (which displays coloured squares) that you first met at
the end of part 16, ie...

10 POKE 22527+ RND *704, RND *


127
20 GO TO 10

This is the program that you are going to save onto disk.

If you have not connected a disk drive to the +2A, then the
following information about using the FORMAT command can be
ignored, as the drive you are going to use, drive M:, does not
need to be formatted - in fact it is not possible to use FORMAT on
drive M:.

As previously explained (in chapter 6), you cannot simply unwrap a


brand new disk and hope to save programs onto it straight away; it
must first be made ready to use with the aid of the FORMAT
command. FORMAT will erase anything that was previously on the
disk and set it up for +3 BASIC to use. Be careful, therefore, not
to FORMAT any disk that has programs on it you might like to keep.
To format your new disk, type in the following...

FORMAT "a:"

If you haven't already put your new disk into the drive, don't
worry - the +2A will just come back with the report Drive not
ready.

In this case, put your new disk into drive A: and re-type the
command.

By the way, while you are using the various disk commands, you may
occasionally see the report Drive A: not ready (possibly followed
by - Retry, Ignore or Cancel?). This invariably means that you
have forgotten to put a disk into the drive.

Whenever a report appears that ends with - Retry, Ignore or


Cancel?, there are three options open to you:

The first is to take action to rectify the problem, for example,


if the report was Drive not ready, then put a disk into the drive
and type R (to retry). The disk system will then try to carry out
the same operation again and hopefully this time it will succeed.
If you were half way through copying a large file and an error
such as Missing address mark appeared, this would usually mean
that the disk being read has been damaged in some way. Try R a few
times and if the error persists, you indeed have a damaged disk.
At this stage, you'll probably want to salvage any undamaged data,
so try typing I (to ignore). Although this tells the disk system
to ignore the error, there is no guarantee that all your data will
be read intact - it's really just a last ditch operation when all
else has failed.

Finally, if you have tried to perform an operation where an error


occurs, you may realise that there is no point in trying to go on.
In this case type C (to cancel) which tells the disk system to
abandon the current command. Having typed C, BASIC will report an
error (usually very similar to the text of the previous report).

Back to our attempt to format a disk. If you have made a mistake


and the disk you put into drive A: has already been formatted, the
+2A will spot this and you will receive the report...

Disk is already formatted,


A to abandon, other key continue

This is a safety feature that will allow you to abandon the format
before the process gets going, if, by some chance, you inserted
the wrong disk. In this case you should type A (to abandon) and
nothing more will happen. If, however, you really do intend to
reformat the disk and don't mind losing what's on it, then press
any key apart from A (eg. press ENTER).

After about 30 seconds, the usual 0 OK report will appear. The


disk is then usable and should not need to be formatted again. You
can always reformat a disk if you wish to clear the disk of data
completely, but remember that it is an irreversible process.

Disks can occasionally become spoilt (corrupted). This can happen


if some dust or dirt comes into contact with the disk surface, if
the disk is left too close to a magnetic field (such as that
produced by a TV or a loudspeaker), if the disk is ejected while
it is being written to, or if the disk is left in the drive when
the computer or disk drive is switched on or off. A corrupted disk
will cause errors during LOAD, SAVE, etc. operations, and should
be reformatted before any more data is saved onto it.

If you want to recover files from a corrupted disk, you can try to
copy them individually (using COPY) to a known 'good' disk. If one
or more files prove uncopiable, then you have probably lost them
for good. We recommend that you keep at least two copies of
important files (on different disks) - one for day-to-day use, and
one kept in a safe place just in case the unthinkable happens.
Making regular copies of valuable data and programs is known as
backing-up and is an essential habit to get into. Backing-up can
save you untold misery and tears. You can, of course, make back-
ups onto tape (which may prove cheaper in the long run).

Unlike many computers, the +2A's FORMAT command is built-in and


can be used like any other BASIC command. It doesn't affect the
program you have in the computer, so you can now save the two-line
program you entered a moment ago.

If you have not connected a disk drive to the +2A type in the
following command...

SAVE "m:"

Now all +2A users should type in the following...

SAVE "squares"

The word SQUARES is just a name that you use to 'label' the
program you are going to store on disk. To prevent confusion,
everything stored on disk must be given a name. These names
(called filenames) are a little different from those that you may
use when storing programs on tape.

Filenames
The range of characters that you are allowed to use for disk
filenames is more limited than for tape filenames. The format of
filenames on disks for use with the +2A is the same as that used
by an operating system known as CP/M (Control Program/Monitor) by
Digital Research Inc. The fact that these formats are the same
means that you can take a disk used with a +2A (or +3) and use it
on other computers. In this way, data can be transferred between
the +2A and a CP/M system, and this is most likely to be useful
for people writing machine code programs or moving text from a +2A
word processor to a CP/M program. (It is extremely unlikely that
programs written in BASIC can be usefully converted from one
machine to another using this method.)

Filenames can be as simple as the example above - SQUARES (or even


simpler - S, for example). However a full CP/M-type filename can
be made up of as many as four parts; user number, drive letter,
name and type. Each of these parts is called a field, (eg. the
name field or the type field).

You needn't worry about what user number means; if you don't know
already, then it's probably best to remain blissfully ignorant.
However, for anyone who is interested: on CP/M machines with very
large disk capacities (or hard disks) with perhaps more than one
terminal connected, user numbers are used to partition files into
subsections (known as user areas) so that there isn't just one
huge directory with several thousand files. On the +2A, however,
disks cannot have more than 64 files, so the use of user areas is
not really necessary. Nevertheless, user areas can be specified in
filenames used in +2A disk commands. They take the form...

user number drive letter:filename

...where user number is in the range 0 to 15, and drive letter is


A:, B: or M:. If you specify a user number, then you must also
specify a drive letter (though you cannot specify A: or B: if you
haven't connected a disk drive). To save our example program to
drive A: in user area 5, we would use...

SAVE "5a:squares"

When saving to tape, a user number and drive letter will just be
taken as part of the tape filename (within which 10 characters
(maximum) are permitted). The tape itself will not be partitioned
into separate user areas.

The problem with using user areas on disk is that it's quite easy
to forget which user area you saved a file to, and so finding it
could take a while (as the CAT command can only catalog one user
area at a time).

As just mentioned, the drive letter will normally be A:, B: or M:.


Notice that the letter must be followed by a colon (eg.
a:squares). If you don't specify a drive letter, then +3 BASIC
will use the drive that was last used - this is known as the
default drive. (When you first switch on the +2A system (with a
disk drive connected), the default is set to A:.) So assuming you
have connected a disk drive, typing...

SAVE "squares"

...is just as if you had typed...

SAVE "a:squares"

If you have not connected a disk drive to the +2A, then the
default 'drive' is the datacorder and both of the above commands
would save the program to tape (though with differing filenames).
(This is why the message: Press REC & PLAY, then any key appears
each time.) Don't worry that there is no tape in the datacorder
and that nothing has been saved. We can use the RAMdisk drive M:
(the internal memory drive) for the following examples.

There are special forms of SAVE and LOAD which can be used to
change the default drive. When SAVE or LOAD is followed by a
filename that contains nothing but a drive letter and a colon, the
drive identified by the letter is then made the new default drive.
So the commands...

SAVE "m:"
SAVE "squares"
...will change the default drive to drive M: then save the program
onto drive M:. (If the above command had been SAVE "m:squares",
the program would still have been saved to drive M: but the
default drive would not have been changed.)

To switch the default back to drive A:, type the following. (If
you have not connected a disk drive to the +2A, then ignore this
command and leave the default as M:)...

SAVE "a:"

Note that SAVE and LOAD followed by just a drive letter (and
colon) will do nothing other than change the default drive. They
will not actually save or load a program. You must use SAVE or
LOAD followed by a real filename for this.

When using disks (including the RAMdisk drive M:), the name field
of a filename is the only field that you have to specify when
using SAVE, LOAD, etc. The name field can be from 1 to 8
characters long and may contain any of the following:

Letters: a b c d e f g h i j k l m n o p q r s t u
v w x y z (upper or lower case)
Digits: 0 1 2 3 4 5 6 7 8 9
Other characters: " # $ ' @ ↑ _ { } ~ `

Upper and lower case letters are the same in filenames, so EXAMPLE
and example would be identical.

A filename can end with an optional type field (which is just a


further three characters) that you may wish to use in order to
group together files of the same type. If a type field is
specified, then it must be preceded by a dot. (Unlike some other
BASICs, +3 BASIC does not automatically allocate a type field to
files if one is not specified.) You may find it useful to add your
own type fields - a popular convention is to use the type fields
.BAS to identify BASIC files and .BIN to identify CODE files (BIN
being short for binary). If you think this is a good idea, then
the previous example program could be saved using...

SAVE "squares.bas"

The characters * and ? have a special meaning to +3 BASIC, and


cannot be used in a filename for LOAD and SAVE. There are,
however, file commands in which * and ? can be used, and these
will be discussed later.

Here are some examples of valid disk filenames...

z
squares
m:picture.bin
a:fred
13a:hello
0M:CAPITALS
test.bas
philip
glass.mus
a:a.a

If you have not connected a disk drive to the +2A, then some of
these filenames will produce the error Drive not found. Don't
worry about this, because if you do add a disk drive in the
future, then these filenames will become valid.

Here are some illegal disk filenames (and reasons why)...

pac man (must not contain any spaces)

(test) (must not contain brackets)

/<>-+=!& (must not contain any of these characters)

excessive (more than 8 characters long)

.bas (has no name field)

later... (only one dot allowed)

7:dubious (if user number is specified, then filename


must also contain drive letter - eg. 7a:dubious)

Disk catalog
You may have spotted the fact that we have now saved the same
program twice with two different names (SQUARES and SQUARES.BAS).
It would be nice to be able to check what has been saved on a
particular disk, and this is where the CAT command comes in. CAT
displays a catalog of what you have stored on a disk.

Press ENTER then type in...

CAT

The +2A will take a quick look at the disk (if you have connected
a disk drive and are using drive A: for these examples) and
display a list of the disk's contents on the screen. If the
default drive is still set to M: then a list of the files on the
RAMdisk is displayed. The list is sorted into alphanumerical
order, and each file is followed by an indication of its size to
the nearest number of kilobytes (rounded up). At the end of the
list, the amount of free space on the disk is also displayed.
CAT (on its own) is the simplest form of the command. If you
wanted to list all the files on a different drive (eg. drive B:),
you would use...

CAT "b:"

If you have not connected a disk drive (or drives), don't worry
about the report Drive not found that appears.

When CAT is followed by a filename containing just a drive letter,


ie. a:, b: or m: (including the colon), all the files on the
nominated drive will be listed. CAT on its own gave a list of the
files on drive M: (or A: if a disk drive is connected) because M:
(A:) is the current default drive. You will remember that LOAD or
SAVE followed by a drive letter will make that drive the current
default. Only type the following if you have a disk drive
connected...

LOAD "b:"
CAT

...this will also list all the files on drive B:. This isn't quite
the same as CAT "b:", because now the default drive has been left
as B:. Before continuing, make sure the default is M:, using...

LOAD "m:"

We will now save several copies of our simple example program


using different names, so that you will be able to see what the
various forms of the CAT command will produce. Type in the
following...

SAVE "squares"
SAVE "squares.bas"
SAVE "fred"
SAVE "fat"
SAVE "santa.bin"
SAVE "trepur.bak"
SAVE "cliff.cjl"
SAVE "sausages.bas"

Don't worry about cluttering up drive M: with lots of copies of


the same thing - you'll be shown how files can be erased later.

Wildcards
If a disk has a large number of files, it is often desirable to
selectively list only those of interest. The +2A caters for this.
If, for example, you wished to list only those files that ended in
.BAS you would use...

CAT "*.bas"
The asterix character * is what's known as a wildcard. When a
filename containing a wildcard is specified, CAT will list only
the files that match the 'specification' given. When the *
wildcard is used (in either the name field or the type field) it
means 'any character from here to the end of this field'. So, in
the above command, we want CAT to display files that have any
characters in their name field and the letters BAS in their type
field. If there are no files on the disk that match the
specification, the report No files found will be displayed
(followed by the amount of free space). If you give a file
specification of *.* (ie. CAT "*.*") or no specification at all
(ie. CAT) and the report No files found is displayed, then this
means that the disk is empty. An empty disk in drive A: or B: (if
connected) will have a free space value of 173K (this value may be
different for disks from other types of computer). An empty drive
M: will usually have 62K free (this figure drops to 58K when a
disk drive is connected). If you catalog a disk containing a
commercial program (such as a game), it might appear to have no
files on it but very little space free. This is a protection
measure taken by the software writers to prevent illicit copying,
and shouldn't cause any concern.

If we use...

CAT "s*.bas"

...then all files that begin with the letter S and then have any
characters whatsoever between the S and the end of the name field,
followed by a type field of BAS, will be shown. Files with names
such as SQUARES.BAS, SAUSAGES.BAS, SUPER.BAS would all be listed,
but SQUARES.BIN, TOAST.BAS and SQUARES would not.

The * wildcard can also be used in the type field of a filename


(note, however, that you cannot use it in place of the user number
or drive letter). If we wanted to list all files that had SQUARES
as their name field and anything as their type field, we would
use...

CAT "squares.*"

Similarly, if we wanted to list all the files that began with a


letter S and had a type field that began with the letter B we
would use...

CAT "s*.b*"

When we type CAT (on its own), we want to list all files on a
disk. Therefore, CAT is just a shorthand way of saying...

CAT "*.*"

From the above you will notice that the * wildcard can only be
used as the last character in a field, and it is used to mean 'I
don't care what other characters are present between here and the
end of this field'. Sometimes, however, you may want to specify a
group of files but need to be a little more discerning. This is
when you use the ? question mark wildcard (in either the name
field or the type field). The ? wildcard means 'I don't mind what
character happens to be in this specific position'.

Therefore, if we used the command...

CAT "?at"

...then the files listed would be all those that are three
characters long, ending in AT, but we don't mind what character is
in the first position. Thus files such as CAT, SAT, MAT and FAT
would be listed, but CAR, CATTLE and AT would not. Unlike the *
wildcard, ? wildcards can be used in place of any of the 8
characters of the name field and the 3 characters of the type
field. There is no limit to the number of question marks you can
use (other than the 8 and 3 limits of the filename field lengths).

Valid disk file specifications containing ? wildcards include...

?.bas (one letter name with a type field of BAS)

s?uares.* (specific files whose second character


doesn't matter, with any type field)

ca??.?t? (files beginning CA with four characters


in the name field, and with a type field
of 3 characters whose second letter is T)

????????.??? (exactly the same as *.*)

If you have a printer connected to your +2A you may find it useful
to print-out the files listed by CAT. You can do this by directing
the output from CAT to stream 3 (streams are explained in part 22
of this chapter). The command to do this is...

CAT #3

If you only want some of the files printed-out, you can also
include a file specification in exactly the same way as before.
For example...

CAT #3,"m:*.bas"

(The above CAT #3 commands will not work unless a printer is


connected to the +2A and is on line. To abandon, press BREAK.)

Any form of the CAT command may also end with the word EXP, for
example, CAT "m:" EXP. The EXP is short for expanded, and as the
name might suggest, gives you a little more information about the
attributes of the files on a disk. Not only will the expanded
catalog display system files but it will also indicate whether
files are set to write protected mode, archive mode or system
status (these terms are explained in the section ahead entitled
'File attributes').

(There is one other specialist use for the CAT command, and this
will be dealt with in the section ahead entitled 'Tape catalog'.)

Note that there is a difference between resetting the +2A and


using the NEW command - if you reset, all the +2A's memory (RAM)
will be cleared. This includes any files you may have saved on
drive M:. When you use NEW, however, any files on drive M: will
remain intact. To prove this, type in...

NEW

...then select the option +3 BASIC from the opening menu, and type
in...

LOAD "m:squares"

Note that the LOAD command reads in a new program (and variables)
and then deletes any program (and variables) previously in the
memory. (If the program that you specified to load cannot be
found, then any program currently in the memory is not deleted.)
Just like SAVE, the LOAD command must be given a filename whose
name field is at least one character long. If you are familiar
with datacorder operations, then you will know that the command
LOAD "" means 'load the next program on the tape'. The concept of
a 'next program' on disk does not exist, so if you don't specify a
filename, the disk system won't know what to load and will report
an error. If you can't remember what name you saved a file under,
use CAT to check what's on the disk (this is why it's a good idea
to save programs on disk using 'mnemonic' names (names that remind
you what they contain) - eg. it is more obvious what sort of
program a file named TENNIS.BAS contains compared to one simply
named T).

If you have connected a disk drive to the +2A, there is a short


cut for loading disk based programs (such as games) that have been
specially set up - you can select the Loader option from the
opening menu. This option, when selected, attempts to load and run
programs. First of all, it looks for a program called * on the
disk in drive A:. If this exists, then it will be loaded and run.
The program has to be a machine code program saved in a particular
fashion (as BASIC can't use * as a filename for SAVE), and is,
therefore, only for use on commercial software or by those who
understand machine code.

If * can't be found, the +2A will then look for a file called DISK
on drive A: (assuming you have connected a disk drive). This can
be a BASIC program that you've previously written and saved, so if
the Loader option finds a program called DISK, it will load it and
wait for the next operation. (The program will automatically run
if it was saved using a LINE parameter - more about this later
on.)

At this point, pressing ENTER will just load the program again.

If you wish to run or edit the program after it has loaded, first
press the cursor down key ↓ once, then press ENTER. This selects
the +3 BASIC option from the opening menu.

If you have not connected a disk drive to the +2A, or if there


isn't a program called DISK on the disk (or if the +2A detects
that there isn't a disk in the disk drive), then the computer will
try to load a program from tape, displaying the message...

Insert tape and press PLAY


To cancel - press BREAK twice

This is the recommended method for loading Spectrum +3, +2 (+2A)


and Spectrum 128 software from tape (see chapter 4).

As previously mentioned, LOAD deletes the old program and


variables in the +2A whenever it loads in the new ones. However,
there is another command - MERGE, which is similar to LOAD but it
only deletes an old program line or variable if there is a new one
with the same line number or name. Clear the program memory using
the NEW command, then type in the 'dice' program from part 11 of
this chapter and SAVE it, using the commands...

LOAD "m:"
SAVE "m:"
SAVE "dice"

Use NEW to clear the program memory again, then enter and run the
following program...

1 PRINT 1
2 PRINT 2
10 PRINT 10
20 LET x=20

Now type in...

MERGE "dice"

When the program is merged, you will receive the message 0 OK. If
you then LIST the program, you will see that lines 1 and 2 have
survived, but lines 10 and 20 have been overwritten by those from
the 'dice' program. Note that the value of the variable x has also
survived (try PRINT x).
You have now seen simple forms of five of the commands that work
in conjunction with disk:

FORMAT Prepares brand new disks so that programs can be saved


onto them. FORMAT can be used to completely erase
everything on a disk that has already been used. If you
have not connected a disk drive to the +2A, the FORMAT
command will not work.

SAVE Stores the program and variables to disk.

LOAD Clears the computer of all its program and variables,


and replaces them with new ones read in from disk.

MERGE Similar to LOAD except that it does not clear the old
program lines and variables unless it has to (because
they are the same as those being loaded in from disk).

CAT Displays a list of the files contained on disk.

A variation on SAVE takes the form...

SAVE filename LINE number

A program which is saved using this command, is stored in such a


way that when it is loaded, it automatically jumps to the line
with the given number, then runs itself.

If you have not connected a disk drive to your +2A, then skip the
following example.

Type NEW to clear the program memory, select +3 BASIC, then enter
the following...

10 PRINT "program running"


20 PLAY "cdefgabC"

Now save this program using the command...

SAVE "disk" LINE 10

Again, type NEW to clear the program memory, and when the opening
menu appears, press the ENTER key. This will select the Loader
option which searches for a file called DISK. When it finds the
simple example program you just saved, it will load it, and as it
was saved using a LINE parameter, it will automatically start
running (from line 10).

At this point, pressing ENTER will load and run the program again.

If you wish to edit the program after it has run, press the cursor
down key ↓ once, then press ENTER. This selects the +3 BASIC
option from the opening menu.
Note that if you load a program called DISK which doesn't
automatically run (using the Loader option from the opening menu),
then you will have to select the +3 BASIC option (after the
program has loaded) before you can run it or edit it.

So far, the only kinds of information we have stored have been


programs (together with their variables). There are also two other
kinds of information, called arrays and bytes.

You can save arrays using the keyword DATA in a SAVE statement...

SAVE filename DATA array name ()

...where filename is the name that the information will be saved


under, and works in exactly the same way as when you save a
program.

The array name specifies the array you want to save, so it is just
a letter (or a letter followed by $). Remember to put the brackets
() after the array name.

Be clear about the separate roles of filename and array name. If


you say (for instance)...

SAVE "bloggs" DATA b ()

...then SAVE takes the array b() from the computer and stores it
under the name BLOGGS. The command...

LOAD "bloggs" DATA b ()

...sees if it is possible to load the array (ie. if there is room


for it in the computer), then if so, deletes any already existing
array called b() and loads the array BLOGGS, calling it b() in the
computer.

You cannot use MERGE with saved arrays.

You can save character (string) arrays in exactly the same way.
However, note that when you load a character array, it will delete
not only any previous character array with the same name, but also
any simple string variable with the same name.

When dealing with a large amount of data you may find it useful to
use the SAVE...DATA option and the LOAD...DATA option to and from
drive M:. Once saved on drive M: the space previously used by an
array can be re-used. Using drive M: will mean that saving and
loading are very fast.

Byte storage is used for pieces of information without any


reference to what the information is used for - it could be a
screen display, or perhaps some user-defined graphics, or just
something you have made up for yourself. It is specified using the
word CODE, as in...

SAVE "pic.bin" CODE 16384,6912

The unit of storage in memory is the byte (a number between 0 and


255), and each byte has an address (which is a number between 0
and 65535). The first number after CODE is the address of the
first byte to be stored; the second number is the amount of bytes
to be stored. In our case, 16384 is the address of the first byte
in the file (which contains the screen display), and 6912 is the
amount of bytes in it, so we are saving an actual copy of the
screen display. Try the above SAVE command. (You don't have to
save the bytes using the name PIC.BIN - it's merely a convenient
reminder of what's on the disk.)

To load it back, use...

LOAD "pic.bin" CODE

You can put parameters after CODE in the form...

LOAD filename CODE start,length

Here, the length parameter is used as a safety measure - when the


computer attempts to load the bytes, it will check the length and
refuse to load the bytes if there are more than specified (thereby
safeguarding against the extra bytes accidentally overwriting an
area of memory that you wished to preserve). In such a case, the
report Code length error is displayed (if you are trying to load
bytes from disk), or R Tape loading error (if you are trying to
load bytes from tape under 48 BASIC).

If you leave out the length parameter, the +2A will read in the
bytes however many there are.

The start parameter specifies the address where the first byte is
to be loaded back to - this can be different from the address it
was saved from; though if they are the same, you can leave out the
start parameter in the LOAD statement.

CODE 16384,6912 is such a useful area of memory (the screen


display) to save and load, that a special function (SCREEN$) has
been provided to represent it, so you can type (for example)...

SAVE "pic.bin" SCREEN$

..or...

LOAD "pic.bin" SCREEN$


Automatic back-ups
If you save something with a filename that has already been used,
what will happen? Well, each time you save a program, the disk
system checks to see if the filename you specify has already been
used. If it has, then the file already on the disk is given a
replacement filename before the information you have asked to save
is stored. The replacement filename given to the file already on
the disk will have the same name field, but its type field will
always be .BAK (short for backup).

If a .BAK version of the file already exists, then that will be


discarded in preference of the new .BAK file. This means that as
you save successive versions of a program with the same name, the
previous copy will still be there in a file called filename.BAK.
So, if you make a serious programming error and inadvertently save
the program, you can delete the newest version and rename the .BAK
file to the original filename. The next section shows you how to
do this; but first, type...

SAVE "m:squares"

...to save the program using the filename SQUARES yet again.

Deleting and renaming disk files


Files can be deleted from a disk using the ERASE command. This
should be followed by a filename that specifies which file or
files are to be deleted. Just like CAT, you can use the wildcards
* and ? to identify a group of files, or you can specify the name
in full if you only want to get rid of one particular file. If you
specify a single filename, then that file will immediately be
erased from the disk - so take care. If you specify a group of
files (by including * or ?), BASIC will ask you to confirm that
you really do mean to delete this group of files. Typing Y will
make the deletion process continue, so if you have made a mistake,
type N.

If, for example, you wanted to remove a file from drive M: called
FRED.BAS, you would use...

ERASE "m:fred.bas"

If drive M: had already been set as the default drive, then you
wouldn't need to include the M: at the start of the filename. It
doesn't hurt to include the drive letter anyway, and with as
powerful a command as ERASE, you might feel safer if you do. To
erase all the files on drive B: (if it were connected), you would
use...

ERASE "b:*.*"
Before doing this, BASIC, will ask for confirmation...

Erase b:*.* ? (Y/N)

...and assuming that you really did mean to wipe all the files
from the disk in drive B: you would then type Y.

If you ask to delete a single file (or a group of files using the
wildcards * and ?) and there are no files on the disk that match
the specification, then the report File not found will be
displayed.

Note that ERASE followed by just a drive letter (eg. ERASE "m:")
will erase all files on the specified drive without asking for
confirmation. Be careful, therefore, not to enter this form of the
command unless you really mean to delete everything! (The ERASE
process will stop and report an error if a write protected disk or
file is detected.)

The default drive that you have been using up to now has many
copies of the simple SQUARES program (saved under different names)
on it. This is a waste of space so you might as well erase those
that aren't needed. What you want to do in effect is erase
everything except SQUARES (though there is no simple way to do
this). However, some of the different files have the same letters
in common, so you may be able to use various forms of * and ?
specifications to cut down the amount of typing. See if you can
work out the fewest number of ERASE commands to erase all files
other than SQUARES.

Once a file has been saved, it can be given a new name using the
MOVE command. For example, if there is a file on drive M: called
SQUARES that you would like to call BLOCKS, its name could be
changed as follows (first we make sure there is a file called
SQUARES on drive M:). Type...

SAVE "m:squares"
MOVE "m:squares" TO "m:blocks"
CAT "m:"

Imagine we had saved a file called FRED, and then after working on
it and saving a new version with the same name, realised that we
had made a terrible mistake and would like to recover the last
version. This would be possible using the commands...

ERASE "fred"
MOVE "fred.bak" TO "fred"

Unlike ERASE, you cannot include the wildcards * or ? when


renaming files.

MOVE will take into account the current default drive so the
filename doesn't necessarily have to contain a drive letter. Note,
however, that it is not possible to use MOVE to rename files
between different drives. The command...

MOVE "m:fred" TO "a:eric"

...(for example) will fail with the error No rename between drives
reported. Instead, you can use the COPY command (explained ahead)
followed by ERASE to achieve the desired result.

File attributes
MOVE has another use besides renaming files. It can also be used
to change the attributes of a disk file. Attributes are bits of
information associated with a file that tell you (and the
computer) a little more about it.

There are three attributes that can be changed. The most useful
attribute is write protection. Once a file's write protection
attribute has been set, it will not be possible to erase it (or
save a file with the same name) until you remove the write
protection. It behaves a little like the write protect hole on a
disk, but works just on individual files. Unlike the write protect
hole, however, it offers no protection against FORMAT, which
erases everything on a disk, regardless of attributes. You can set
a file's write protection attribute to on with a command such
as...

MOVE "squares" TO "+p"

The letter P is short for protection (against overwriting). If you


now try to use the command...

ERASE "squares"

...you will receive an error report saying File is read only.

To switch write protection off, use...

MOVE "squares" TO "-p"

...and you'll then be able to erase the file as before.

In all the MOVE commands that change attributes, + means switch it


on, and - means switch it off.

When you are using MOVE to change attributes, the filename can
include the wildcards * and ?. So, to make all the files on drive
M: write protected, you would use...

MOVE "m:*.*" TO "+p"

As always, the drive letter can be omitted if it is the current


default drive.
You can repeatedly switch attributes on or off without causing an
error, so if you set write protect on a file that has already got
write protection, it will just stay protected.

The second attribute that can be changed is known as the system


status attribute. This is really provided just to afford
compatibility with other CP/M based computers; however, if you do
set a file's system attribute to on, then you will notice that the
file no longer appears in the list of files when you use CAT. The
system status attribute is identified by +S (or -S) in the MOVE
command. If you use the expanded catalog, (ie. CAT EXP), all the
files will then be listed including system status files (which are
followed by the letters SYS). You may also notice that any files
that are write protected are followed by the letters PROT. You can
use the system attribute to remove files from a catalog if they
would otherwise just clutter things up.

Bear in mind that you cannot have two files on the same disk with
the same filename, even if you want them to have different system
status attributes; so if you try to create or copy a file onto a
disk where a file of that name already exists (but is hidden from
CAT), the previous file will be deleted or made into a .BAK file.

The final attribute you can change is known as the archive


attribute. In an expanded catalog it shows up as ARC, and is
identified by +A (or -A) in the MOVE command. On the +2A, the
archive attribute is of no practical use and is only provided for
file compatibility with CP/M based computers.

Here are some attribute-setting MOVE commands. See if you can


predict what they will do...

MOVE "*.*" TO "+p"


MOVE "*.bas" TO "-s"
MOVE "s???.*" TO "+a"
MOVE "m:?.?" TO "-p"

If you try to use any letter other than A, S or P in setting or


resetting attributes, or if the 'attribute string' is not two
characters long, then you will receive the report Invalid
attribute.

Copying files
Quite often, a situation will arise when you would like to make a
copy of one of your disk files, (perhaps to generate a second copy
that you can experimentally change without damaging the original
copy). If you have connected a disk drive to your +2A, then the
COPY command can be used to copy files from one drive to another,
or even to make complete copies of disks. The very simplest form
of the COPY command will look something like this...

COPY "a:fred" TO "m:"


If you have not connected a disk drive to the +2A, this command
will fail with the error report Drive not found. (In fact, the
COPY command is probably of limited use unless you have connected
a disk drive.)

The above command means, put a copy of the contents of the file
called FRED (which is presently on drive A:) onto drive M:. As no
destination name has been specified (after M:), the new file will
also be called FRED.

The name before the word TO is known as the source filename, and
the name after TO is the destination filename.

The command...

COPY "fred" TO "eric"

...will take the contents of a file called FRED on the default


drive and copy it to a file called ERIC, also on the default
drive. The files FRED and ERIC then contain the same information.

You cannot copy one file to another with the same name and on the
same drive. Trying to do so will result in the error report File
already exists (or possibly File already in use).

The source filename for copying from can include the wildcards *
and ?, however, in this case the destination filename has to be
just a drive letter. So, for example...

COPY "a:*.ovr" TO "m:"

...will work (assuming that there are some files on drive A: that
match this specification), and transfers all files on A: with a
.OVR type field onto drive M:. However, the command...

COPY "a:*.bas" TO "m:*.bin"

...will fail with the error report Destination cannot be wild.

The COPY command does not copy any attribute information


associated with a file; you have to set any attributes you require
on the new file after copying.

COPY will always list the files it is copying in two columns. This
will allow you to check that any wildcard specification you use
encompasses all the files that you were intending to copy.

After copying, a report will appear to let you know how many files
were copied. (If you were copying a group of files, this may be
useful to check that you have copied the number of files you
intended to.)
If you wish to use the COPY command within a program, but do not
want the text generated by the command to spoil the text or
graphics display produced by the program itself, then you may
disable the listing of copied files to the screen by including the
command...

POKE 23739,78: POKE 23740,10

...before the COPY command, and...

POKE 23739,244: POKE 23740,9

...after it. For example...

10 POKE 23739,78: POKE 23740,1


0
20 COPY "a:disk.*" TO "m:"
30 POKE 23739,244: POKE 23740,
9

There is a special form of the COPY command as follows...

COPY "a:" TO "b:"

...which, on a +2A (with disk drive(s) connected) will perform a


complete 'sector by sector' copy of the disk in drive A: to an
already formatted disk in drive B:. Anything already stored on the
disk in drive B: will be lost - so, if there are only a few files
on the source disk to be copied, it will be quicker (and safer) to
use...

COPY "a:*.*" TO "b:"

Even if you have connected only one drive (drive A:) to the +2A,
you can take advantage of the fact that the single mechanism can
be used as if it were drive A: or drive B:. For example, suppose
you have a one-drive system and want to copy a couple of files
(that both end in .BAS) from one disk to another. Put the source
disk in the drive and type...

COPY "a:*.bas" TO "b:"

Once the +2A has read part of the first file that ends in .BAS, it
will ask you to...

Please put in the disk for B: into


the drive then press any key

Simply follow this instruction. After the +2A has written the
information onto the 'drive B:' disk, it will ask you to...

Please put in the disk for A: into


the drive then press any key
This process of swapping between disks will go on until all files
have been copied. Because the COPY command will try to use any
free space on drive M:, it is a good idea to clear drive M: (if
possible) before doing a lot of copying (as this can reduce the
number of disk swaps needed).

As well as copying files between drives, COPY can also be used to


copy files to the screen or to a printer (if connected). The
command...

COPY "words.txt" TO SCREEN$

...will display the contents of a file on the default drive called


WORDS.TXT. Any control characters (except carriage returns) will
be filtered out. This command cannot really be used to look at
BASIC program files as they contain various control codes. Its
main use will be to inspect the contents of ASCII text files such
as those produced by a word processor.

The command...

COPY "words.txt" TO LPRINT

...is similar to the above, but this time the contents of the file
will be sent to the printer. In this case, however, control codes
will be sent to the printer. If you have set the print output to
be via the RS232 with tokens unexpanded (using FORMAT LPRINT
"R";"U"), then this command can be used to 'export' files to other
computers. Once again, this command cannot be used for BASIC
programs - it is intended for sending ASCII text files only.

People writing machine code programs may find it easier to do so


on a larger development machine (such as one of the Amstrad PCW
range). Although the files produced by this method will probably
not be recognised by the +2A (as BASIC expects to find a 128 byte
header at the start of each file which contains information used
by the LOAD command), once a binary file has been produced on a
disk formatted for use with the +2A, it can have a header of the
correct type put on it using a command such as...

COPY "game.com" TO SPECTRUM FORMAT

This will produce a new file on the same drive, having the same
name field but with a type field of .HED (short for headed). In
the above example, a new file called GAME.HED will be created, and
it will be written to the default drive (as no drive letter was
specified).

Obviously this command will only be of use for machine code files.
Headed files produced in this way will have the length part in
their header set to the correct value and the type part set to be
a CODE file. However, BASIC cannot know what address the file
should be loaded to, so the load address should be specified when
the LOAD...CODE command is used. For example, if the above program
had been assembled to execute at 7000h (the h denotes a
hexadecimal number) or 28672 decimal, then the headed file could
be loaded with the command...

LOAD "game.hed" CODE 28672

As SCREEN$ files are just another type of CODE file, this


technique can be used to 'import' screens designed on another
machine, though they obviously wouldn't make much sense unless
they had been tailored to fit the +2A's size and layout.

The RAMdisk
You may have been wondering what point there is in storing
information in the RAMdisk (drive M:) as it will be lost once the
+2A is switched off. Well, perhaps the most obvious use of drive
M: is to store chunks of BASIC program (or routines) which can be
merged (using MERGE M:filename) into a smaller program, in
sequence. This makes it possible to write about 90K of BASIC
program, and hold it in the +2A (though to do this, the program
structure has to be well defined).

If you have connected a disk drive to the +2A, you can keep the
various routines on a floppy disk and use COPY to put them into
drive M: before you run the program. The benefit of doing this is
that drive M: is much quicker to access than the mechanical drives
(A: and B:). The mechanical drives, however, can hold much more
data, so you might like to evolve a system using both disk and
RAMdisk. Careful design and planning will repay itself many times
over in terms of speed and performance.

One of the more interesting uses of the RAMdisk is in animation,


where a series of pictures can be defined by a 'slow' BASIC
program, stored in drive M:, then called back to the screen at
high speed. The following program offers a taste of this.
Doubtless you can do better...

10 INK 5: PAPER 0: BORDER 0: C


LS
20 FOR f=1 TO 10
30 CIRCLE f*20,150,f
40 SAVE "m:ball"+ STR$ (f) COD
E 16384,2048
50 CLS
60 NEXT f
70 FOR f=1 TO 10
80 LOAD "m:ball"+ STR$ (f) COD
E
90 NEXT f
100 BEEP 0.01, 0.01
110 FOR f=9 TO 2 STEP -1
120 LOAD "m:ball"+ STR$ (f) COD
E
130 NEXT f
140 BEEP 0.01, 0.01
150 GO TO 70

Before running this program, always make sure that drive M: is


empty. If it isn't, first type ERASE "m:", then RUN.

Note that in line 40 of this program, the two numbers following


CODE are the address in memory of the start of the screen (16384)
and the length of the top third of it (2048). By saving and
loading only the top third, the overall speed is maintained.

Tape operations
Much of what has been said in this section about the use of LOAD,
SAVE and MERGE on disk will apply equally on tape. However, the
commands FORMAT, COPY, MOVE, CAT and ERASE do not apply on tape
(although there is a special form of CAT that can be used -
described in the section ahead entitled 'Tape catalog').

If you have connected a disk drive, then you may remember that
when you first switch on the system or reset the +2A the default
drive for all file operations is set to drive A:. This means that
if you use CAT, ERASE, LOAD, SAVE, etc. without specifying a drive
letter, then +3 BASIC will perform the operation on drive A:. You
will also know that the default drive can be changed using
either...

LOAD "drive letter:"

...or...

SAVE "drive letter:"

...where drive letter is either A:, B: or M: (which must include


the colon). You can also use T: as a drive letter, but only in
this one special form of the LOAD and the SAVE command...

LOAD "t:"

After LOAD "t:", all subsequent LOAD and MERGE operations are
performed from tape (until changed back to disk by, for example,
LOAD "a:"). Similarly, if you use...

SAVE "t:"

...then all subsequent SAVE operations will be performed to tape


(again, until changed back to disk by, for example, SAVE "a:").

If you have not connected a disk drive to the +2A, then the
default 'drive' for LOAD, SAVE, VERIFY and MERGE is already set to
"t:" (ie, the datacorder) when you first switch on, and so you
needn't ever issue the above commands.

Unlike A:, B: or M:, when you use T: as the drive letter, it will
change only future LOAD and MERGE commands (in the case of LOAD
"t:") or future SAVE commands (in the case of SAVE "t:"). The
default drive used for MOVE, COPY, CAT and ERASE will stay the
same as it was before (as these commands have no relevance to
tape).

If all this sounds a little complicated, a few examples might help


to make it a little clearer. Assuming you have just switched on
(or reset) the +2A and selected +3 BASIC, the default for all
operations will be tape (unless you have connected a disk drive,
in which case it will be A:). So if you now type...

SAVE "m:"

... then the default drive for all subsequent operations (except
LOAD and MERGE on a +2A without disk drives) will be set to drive
M:.

Using the command...

LOAD "b:"

...will then set the default drive for all operations to drive B:
(if connected).

It is important to realise that if you use LOAD and SAVE followed


by "A:", "B:" or "M:", then all future operations (LOAD, SAVE,
MERGE, CAT, ERASE etc.) will be from that drive. However, LOAD
"t:" will only affect the input used for future LOAD and MERGE
operations, while SAVE "t:" will only affect future SAVE
operations.

If we now use the command...

SAVE "t:"

...this will perform all future SAVE operations to tape, but all
other commands will still default to drive B:. Using the
command...

LOAD "t:"

...will also perform all future LOAD and MERGE operations to tape;
however, the default drive for all disk-only commands will still
be drive B:.

Finally, using the command...

SAVE "a:"
...will perform all future SAVE operations and all disk operations
(except LOAD and MERGE) to drive A:. LOAD and MERGE will still be
from tape, however.

Let's try to save our simple 'squares' program onto tape. Reset
the +2A, select +3 BASIC, then type in the following program...

10 POKE 22527+ RND *704, RND *


127
20 GO TO 10

If you have a disk drive connected to your +2A, then you can load
the version of this program that you saved earlier, using...

LOAD "squares"

This is the program that you are now going to save onto tape. Any
standard tape should work, although low noise tapes are
preferable.

Type in the following...

SAVE "t:"
SAVE "squares"

The SAVE "t:" command is not absolutely necessary for users of a


+2A without a disk drive connected. However, type it anyway, just
to make absolutely certain.

The above commands will save the program onto tape using the
filename SQUARES. When saving files on tape, you are allowed up to
ten characters in the name. Unlike disk, you can use any
characters you like and the name can include spaces.

Follow the instructions on the screen, ie...

Press REC & PLAY, then any key.

You may remember (from chapter 6) that the border changes colour
to indicate that tape saving is taking place.

When the +2A has finished (with the report 0 OK), stop the tape.

Whenever you save a program to tape, before clearing the saved


program from the +2A's memory, you should always make sure that
the program was correctly saved by using the VERIFY command
(described in chapter 6).

Now let us suppose that you have saved the program and
successfully verified it. Loading it back into the memory is just
a matter of typing...

LOAD "squares"
(Since the program verified properly, you should have no problem
loading it.)

The MERGE command will operate in a similar way to that described


for disk except, of course, that on tape you can use MERGE "" to
mean 'merge the next file on tape'. Filenames in a MERGE command
may conform to the less stringent limits for tape (ie. any
combination of 10 characters including spaces).

If you have connected a disk drive to the +2A, then you may have
some BASIC programs saved on tape that you wish to transfer to
disk. To do this, first
type in...

LOAD "t:"
SAVE "a:"

...and then for each BASIC file on the tape, use...

LOAD ""

...which will load the next file from the tape into the +2A's
program memory. Once loaded, the file can be saved to disk
using...

SAVE filename

Remember that files on disk must be given a filename which


conforms to the limitations outlined at the beginning of this
section.

If the BASIC programs have been saved with an automatic execution


LINE, you will find that attempting to LOAD them will also run
them. Obviously you don't want this, so, for each program you wish
to load, type NEW, select +3 BASIC and type...

MERGE ""

...(rather than LOAD "").

If you have saved data (numeric or string) arrays, it should be an


equally simple matter to LOAD them into memory from tape, then
SAVE them to disk.

The only file types that may cause difficulty when you want to
transfer them from tape to disk are CODE (and SCREEN$) files. To
be able to transfer a file of this type you need to know at least
two things about it:

1. The address it was saved from.


2. How many bytes it contains.
Tape catalog
This is where the final form of the CAT command comes in. If the
file specification given is simply T:, then a special form of the
CAT command comes into action. After you type...

CAT "t:"

...the +2A will wait for you to play a tape (the CAT "t:"
operation can be abandoned by pressing BREAK). When the +2A finds
a header on tape it will display the information (in the same form
it was saved). This means that there will be a ten character
filename in quotes. What follows the filename will depend upon the
type of file - if it is a BASIC program, the word (BASIC) will be
displayed. If a LINE parameter was specified when the file was
saved, then this will also be shown. If the file holds data, then
the word DATA followed by the array name will be displayed, and
finally, if the file was saved using CODE (or SCREEN$, which is
really just CODE 16384,6912), the word CODE will be printed
followed by the start address and length that were specified when
the file was saved.

Here is a sample display resulting from a CAT "t:" command, which


may make this a little clearer...

"simple " (BASIC)


"execute " LINE 10 (BASIC)
"numbers " DATA f()
"words " DATA c$()
"m/c " CODE 30000,12345
"picture " CODE 16384,6912

The last item was, in fact, saved using...

SAVE "picture" SCREEN$

Just like the other forms of CAT, its output can be directed to a
printer using stream 3, ie...

CAT #3,"t:"

(Streams are explained in part 22 of this chapter.) Note that the


above CAT #3,"t:" command will not work unless a printer is
connected to the +2A and is on line. To abandon, press BREAK.

From the above it can be seen that if you have loaded (using MERGE
"") a program containing an execution LINE parameter, the CAT "t:"
display will identify that line number for you. You may then wish
to save that program to disk using...

SAVE filename LINE line number


...so that the disk version of that program runs itself
automatically.

It is the values for the CODE files that you will probably find
most useful from the CAT "t:" display. Either note them down or
print them out, then rewind the tape so it is just before the
header that has been read, and type...

CLEAR start-1

...where start is the value printed for the start address. Now
type...

LOAD "" CODE

When the file has loaded into memory and the 0 OK report appears,
the file can be saved to disk using...

SAVE filename CODE start,length

This technique is only intended for transferring your own code


files (where you may have forgotten what start and length values
were used when you saved them). Note that using this method to
copy commercial software may be a breach of copyright - check with
the software author first.

There are several reasons why this simple scheme may not work:

1. The code, when loaded would overwrite some of the system


variables (in the range 23296 (5B00h) to 23755 (5CC6h)). This
upper address limit may vary - it is the value held in the
system variable PROG (see part 25 of this chapter).

2. Attempting to load code that has no header (or that is


protected in some other way) probably won't even produce any
output from CAT "t:" and you certainly won't be able to use
the BASIC LOAD command to load it.

3. If the code file is so long that it stretches right from the


screen display area to the end of memory, then it will be
possible to load it, but as soon as it has loaded, the
machine will crash. This is because BASIC will have 'lost'
its stack.

Exercise...

1. Practise the operations shown in this section until you are


completely au fait with manipulating files to and from the
datacorder, RAMdisk, and floppy disk (if connected).
Part 21
Printer operations
Subjects covered...

Parallel printers
Serial printers
LPRINT, LLIST
FORMAT
COPY

The +2A comes with an 8 bit Centronics parallel port and an RS232
serial port. Both are supported by built-in software enabling you
to use virtually any printer. These features are usable only in +3
BASIC mode.

The printer must have either a Centronics compatible (parallel) or


an RS232 (serial) interface, and if you want to reproduce pictures
of the screen, then the printer must have an Epson compatible
quadruple-density bit-image graphics mode (ESC L n n).

Make sure you have the correct lead to connect the printer to the
+2A - if in doubt, consult your Sinclair dealer.

For further information about which printer and connecting lead to


purchase, together with details of the +2A's PRINTER and RS232
socket connections, see chapter 10 (Peripherals for your +2A).

Parallel printers
When the +2A is first switched on it will assume that, if a
printer is present, it will be connected to the (parallel) PRINTER
socket. The hardware connection between computer and printer is
relatively straightforward - though you must make sure that you
don't connect the cable the wrong way up at the computer end (if
the cable doesn't have a locating 'key').

Once the connection has been made, the command...

LPRINT "hello"

...should produce some printed output. If not, check the


connection and make sure that your printer is set to 'on line'.

Once you have got your printer to print, you may skip to the
section ahead entitled 'General printing'.
Serial printers
Unlike parallel printers, the connections between the +2A and a
serial (or RS232) printer will vary for different manufacturers'
printers. Make sure that your dealer has provided a lead suitable
for connecting your particular printer to the +2A. A serial
printer must be connected to the +2A's RS232 socket, and details
of connections can be found in chapter 10 (Peripherals for your
+2A).

The +2A always uses what is known as hardware flow control, or


hardware handshaking. This means that it will not transmit
characters until certain control signals from the printer have the
right values. It is therefore very important that connections are
made to the control lines of the +2A as well as the transmit and
receive data lines. If your printer does not support hardware
handshaking then connect pins 4 and 5 of the +2A's RS232 connector
socket together. The drawback of not using hardware handshaking is
that the odd character may be lost when transmitting a lot of data
at high speed.

To get the +2A and the printer communicating with each other, they
must both use the same baud rate. The baud rate is the speed at
which data is transferred between computer and printer. Although
it is possible that your printer can be set to different baud
rates, it'll probably be easier to change the rate at the computer
end. Somewhere in the printer's operating manual, the baud rate
will be specified - find this out and then set the +2A to this
rate, using the command...

FORMAT LINE baud rate

For example...

FORMAT LINE 300

(You won't need to do this if your printer normally uses 9600


baud, as the +2A will assume this rate by default.)

As the +2A usually expects to be operating with a parallel


printer, it will be necessary to use the command...

FORMAT LPRINT "R"

...before the +2A will successfully operate with a serial printer.


(The R in the above command is short for RS232.)

The command to set the +2A back to parallel (Centronics) mode


is...

FORMAT LPRINT "C"


General printing
Once you have everything set up, you can use three BASIC commands
to print things out. The first two, LPRINT and LLIST, are just
like PRINT and LIST except that they use the printer instead of
the TV screen. Note that the Print option from +3 BASIC'S edit
menu has the same effect as LLIST, but is included as an easier
method of getting a listing.

Try this program for example...

10 LPRINT "This program..."'


20 LLIST 40
30 LPRINT '"...prints out the
character set, ie..."'
40 FOR n=32 TO 255
50 LPRINT CHR$ n;
60 NEXT n
70 LPRINT

It's important to note that LPRINT and LLIST normally take care to
screen out any embedded colour codes (and their parameters) before
printing or listing anything. Embedded colour codes are a bit of a
hangover from the old 48K Spectrum - when included in a string
they set INK, PAPER and so on. Printers on the whole tend to use
these codes for completely different things like setting italics,
underline, etc., so it would be quite dangerous to send colour
codes to the printer and hope that nothing untoward happens. A
side effect of this is that the +2A will normally not be able to
send escape control sequences to the printer. For example, suppose
your printer expects an escape character (character 27) followed
by "x";CHR$(1) to switch to its NLQ mode; you would normally use
the command...

LPRINT CHR$ (27);"x"; CHR$ (1);"


This is in Near Letter Quality"

However, in +3 BASIC, you must first issue the command...

FORMAT LPRINT "U"

This command tells the +2A not to interpret characters as


'Spectrum codes', but as ordinary unexpanded characters (the U is
short for unexpanded). If the above command is not issued, then
everything above code 165 (see part 28 of this chapter) will be
translated as one of the +2A's special words, or tokens. Likewise,
almost everything below code 32 will be screened out.

If you wish, you can instruct the +2A to interpret characters as


Spectrum codes by using...

FORMAT LPRINT "E"


...(where E stands for expanded). You'll need to do this if you're
going to use LLIST. The +2A starts off in expanded mode anyway, so
unless you've issued a FORMAT LPRINT "U" command, you won't need
to use FORMAT LPRINT "E".

So, to summarise:

* If you want to send special characters (such as ESC) to your


printer (in order to use different styles of printing), issue
the command...

FORMAT LPRINT "U"

...before printing.

* If you are writing or modifying a program, and want to get a


listing on the printer, issue the command...

FORMAT LPRINT "E"

...before listing the program.

The third BASIC statement used with a printer - COPY, prints out a
copy of the TV screen. To demonstrate, go into the small screen
(by selecting the Screen option from the edit menu) and type in
the following command.

FOR n=1 TO 20: PRINT n,: NEXT n

The numbers 1 to 20 will be printed in the top part of the screen.


Now type...

COPY

The COPY command takes about 15-30 seconds to get started, so


don't panic if nothing appears to happen immediately. After a
while, you'll see a copy of the screen reproduced on the printer.
(If all you get from COPY is a lot of random characters on the
printer, then it's likely that your printer isn't fully
compatible.)

You can always stop printing at any time by pressing the BREAK
key. Many printers have what's known as a buffer, which stores
text before printing. If your printer has a buffer, then pressing
BREAK will not stop the printer immediately (although the +2A will
register the break at once).

Note that if the COPY command is stopped by pressing the BREAK


key, the printer may be left in graphics mode (this will be
indicated by subsequent LPRINT statements producing a mass of
meaningless dots, or printing each line of text partly over the
previous line). In these circumstances, switching the printer off
then on again is the easiest way to get things back to normal.
As well as the rather simple COPY command, which just produces a
black dot on the printer for each dot on the screen (whatever its
colour may be), there is an expanded version (COPY EXP) which
prints differing combinations of dots depending on the colour of
ink that was used on the screen. To demonstrate, type in the
following new program...

10 FOR b=0 TO 1
20 BRIGHT b
30 FOR i=0 TO 6
40 FOR c=0 TO 31
50 PRINT INK i; i;
60 NEXT c
70 NEXT i
80 NEXT b

...then switch to the bottom part of the screen (using the edit
menu's Screen option). Run the program (which displays twelve
lines of coloured numbers on the screen), then type in...

COPY EXP

The printed output (or dump) from this command is slightly larger
than that from the standard COPY command - (EXP is short for
expanded). The command reproduces the coloured areas of the screen
as different densities of black dots on the printer. (All 24 lines
of the screen are reproduced.) Areas that have been printed with
BRIGHT 1 will appear lighter than areas printed normally (just as
happens on the screen).

The drawback of the COPY EXP command is that it takes a longer


time to print (about 10 minutes) but is ideally suited to dumping
graphic pictures. The quicker COPY command, on the other hand, is
a better bet if you wish to dump text only.

If the screen display to be dumped is predominantly black, then it


will not only wear out your printer ribbon rather quickly, but
also will probably take longer to dump than a screen that has
large areas of white. To prevent this, the COPY EXP command can be
followed by the word INVERSE, ie...

COPY EXP INVERSE

As the command suggests, the dump is printed in INVERSE (like a


photographic negative) so that all the dark areas of the screen
are printed-out light, and vice versa.

Note that INVERSE cannot be used after the simple COPY command -
it only works with COPY EXP.

The dump produced by COPY EXP and COPY EXP INVERSE is designed to
fit a sheet of A4 paper; however, some printers will not print
within about an inch at either end of a sheet. If this problem
occurs, then it is possible to reduce the size of the dump
slightly by using the command...

POKE 23419,8

This sets the number of 216ths inch used as a line feed at the end
of each pass of the print head. It is set to 9 when the +2A is
first switched on. Once set, it will not be changed even if the
NEW command is used. By reducing this value, each pass of the
print head will fractionally overlay the previous pass. As a
consequence, the quality of the dump reproduced will be degraded
slightly.

If you try to use any of the printer commands when there isn't a
printer attached (or if the printer is off line), then the +2A
will stop dead while it patiently waits for the (non-existent)
printer to respond. In such a case, pressing BREAK twice will
bring the +2A back to life.

Try this...

10 FOR n=31 TO 0 STEP -1


20 PRINT AT 31-n,n; CHR$ ( COD
E "0"+n);
30 NEXT n

You will see a pattern of characters working down diagonally from


the top right-hand corner until it reaches the bottom of the
screen, at which point the program asks if you want to scroll.

Now change AT 31-n,n in line 20 to TAB n. The program will have


exactly the same effect as before.

Now change PRINT in line 20 to LPRINT. This time there will be no


pause to scroll (this does not occur with the printer).

Now change TAB n back to AT 31-n,n still using LPRINT. This time
you will get just a single line of symbols. The reason for the
difference is that the output from LPRINT is not printed straight
away, but is stored in the buffer until either one line's worth of
printer output has accumulated, or something else 'flushes' the
buffer. Hence, printing only takes place:

1. When the buffer is full.

2. After an LPRINT statement that does not end in a comma or


semicolon.

3. When a comma, apostrophe or TAB item requires a new line.

4. At the end of a program, if there is anything left unprinted.


5. When you set the printer offline (this depends on your
particular printer).

Number 3 above explains why our program with TAB works the way it
does. As for AT, the line number is ignored, and the LPRINT
position (like the PRINT position) is moved to the column number.
An AT item can never cause a line to be sent to the printer.

Exercises...

1. Make a printed graph of a sine wave by running the first (3


line) program in part 17 of this chapter, then using COPY.

2. Run the program at the beginning of part 16 of this chapter,


and try both a COPY EXP and a COPY EXP INVERSE.
Part 22
Streams
Subjects covered...

Streams
Channels
FORMAT, OPEN, CLOSE

The +2A can 'read' data from the keyboard by using INPUT and
INKEY$, and it can 'write' data onto the TV screen or a printer by
using PRINT and LPRINT. However, these commands are really a form
of shorthand designed to protect the user from some of the
computer's more complex features.

To the BASIC PRINT command, for example, the screen and the
printer are no different. PRINT "Rosanne" really means 'take the
characters which make up the word 'Rosanne' and send them
somewhere else'. It's just convenient to use the screen most of
the time. Likewise, LPRINT usually sends data to the printer. In
fact, what these commands really do is to send data to one of a
number of channels.

A channel is the way in which the computer communicates with its


input and output devices. There are three channels normally
available to BASIC. These are...

* The screen (called S)


* The keyboard (called K)
* The printer (called P)

Of these, the screen is an output-only device, the keyboard is


both an input and output device, and the printer is either an
output-only device (if it uses the parallel PRINTER socket), or an
input and output device (if it uses the serial RS232 socket).
Outputting data to the keyboard might seem a funny idea, but the
computer uses the lower screen (like INPUT does) to display the
characters.

To access a channel, it has to be open. Opening a channel makes it


ready to receive or produce data. A channel is opened by
connecting it to a stream. From BASIC, you would use a command
like...

OPEN #4,"p"

...which means 'connect stream 4 to the printer channel'. Streams


are convenient ways for the computer to switch between channels by
referring to them as numbers. This idea makes it possible to write
programs that can send information to any device without having to
use different commands. (This is known as redirectable (or device-
independent) I/O.)

This might seem over-complicated, and you may well wish to stick
to the standard PRINT and LPRINT commands - that's why they're
there, after all.

PRINT and LPRINT are really the same command. When BASIC is
running, it has three streams normally open. Stream #1 is
connected to the keyboard device (K), and is used by INPUT and
INKEY$. Stream #2 is connected to the screen (S), and is used by
PRINT and LIST. Stream #3 is connected to the printer (P), and is
used by LPRINT and LLIST. All of these commands can be redirected
to use another device by including a # followed by a current
stream number, so...

PRINT #1;"This is the lower screen"

...will print the message on the lower screen. Similarly...

PRINT #3;"Who needs LPRINT, Gladys?"

...will use the printer. Conversely, LPRINT can behave like


PRINT...

LPRINT #2;"Confusing, or what?"

...behaves just as if the LPRINT #2 were PRINT.

As they stand, these examples are fairly useless but serve to


demonstrate a point. This sort of thing becomes useful if you want
to write a program where the results might go either to the
printer or the screen, like so...

10 REM squares program for pri


nter
20 INPUT "do you want to print
the results?";a$
30 LET stream=2
40 IF a$="y" OR a$="Y" THEN LE
T stream=3
50 FOR n=0 TO 10
60 PRINT #stream;n,n*n
70 NEXT n

The +2A can cope with 16 streams. As 3 are used by BASIC, and 1 is
used internally, this leaves you with 12. You can use these by...

10 REM program to read data fr


om RS232
20 FORMAT LINE 9600
30 FORMAT LPRINT "r"
40 OPEN #4,"p"
50 PRINT INKEY$ #4;
60 GO TO 50

...which takes characters in from the RS232 interface and prints


them onto the screen.

If you want to read in data from the RS232 into memory directly,
you can replace line 50 with...

POKE address, CODE (INKEY$ #4)

As we mentioned before, the screen and the parallel PRINTER socket


can only be used by the +2A for output. They cannot be used for
input, and if you try PRINT INKEY$ #2, for example, you'll receive
an error report.

It is theoretically possible to redirect BASIC'S normal output


streams, so by using...

10 CLOSE #2
20 OPEN #2,"p"

...all the PRINT output will go to the printer instead of the


screen. (If you try to do this during editing, the results will be
unpredictable, so it's best left alone.)

On the standard +2A system, streams and channels are of mostly


academic interest. However, certain peripherals and BASIC language
extensions do use the stream system for more complex functions.
Part 23
IN and OUT
Subjects covered...

IN
OUT

The processor can read from (ROM and RAM) and write to (RAM)
memory by using PEEK and POKE. The processor itself does not
really care whether memory is ROM or RAM - it just thinks that
there are 65536 memory addresses, and it can read a byte from each
one (even if it's nonsense), and write a byte to each one (even if
it gets lost). In a completely analogous way, there are 65536 of
what are called I/O ports (standing for input/output ports). These
are used by the processor for communicating with things like the
keyboard or the printer, and also for controlling the extra memory
and the sound chip. Some of them can be safely controlled from
BASIC by using the IN function and the OUT command, but there are
locations to which you must not write from BASIC as you will
probably cause the system to crash, losing any program and data.

IN is a function like PEEK. Its form is...

IN address

It has one argument - the port address, and its result is a byte
read from that port.

OUT is a statement like POKE. Its form is...

OUT address,value

...which writes the given value to the port with the given
address. How the address is interpreted depends very much upon the
rest of the computer. Quite often, many different addresses will
mean the same. On the +2A it is most sensible to imagine the
address being written in binary, because the individual bits (each
of which can have the value either 0 or 1) tend to work
independently. There are 16 bits, which we shall refer to (using A
for address) as...

A15, A14, A13, A12, A11, A10, A9, A8, A7, A6, A5, A4, A3,
A2, A1, A0

Here, A0 is the 1s bit, A1 is the 2s bit, A2 is the 4s bit, and so


on. Bits A0, A1, A2, A3 and A4 are the important ones. They are
normally 1, but if any one of them is 0, then this tells the
computer to do something specific. The computer cannot cope with
more than one thing at a time, so no more than one of these five
bits should be 0. Bits A6 and A7 are ignored, so if you are a
wizard with electronics you can use them yourself. The best
addresses to use are those that are 1 less than a multiple of 32,
so that A0 to A4 are all 1. Bits A8, A9, and so on are sometimes
used to give extra information, but mostly for the extra memory
and sound.

The byte being written or read has 8 bits, and these are often
referred to (using D for data) as...

D7, D6, D5, D4, D3, D2, D1, D0

Here follows a list of the port addresses used...

There is a set of input addresses that read the keyboard and the
datacorder.

The keyboard is divided up into 8 half-rows of 5 keys each, viz:

IN 65278 (FFFEh) reads the half-row CAPS SHIFT to V


IN 65022 (FDFEh) reads the half-row A to G
IN 64510 (FBFEh) reads the half-row Q to T
IN 63486 (F7FEh) reads the half-row 1 to 5 (and JOYSTICK 2)
IN 61438 (EFFEh) reads the half-row 0 to 6 (and JOYSTICK 1)
IN 57342 (DFFEh) reads the half-row P to Y
IN 49150 (BFFEh) reads the half-row ENTER to H
IN 32766 (7FFEh) reads the half-row (space) to B

(These addresses are 254+256x(255-2 ↑ n) as n goes from 0 to 7.)

Remember that digits followed by h signify hexadecimal numbers. If


you don't understand these refer to part 32 of this chapter.

In the byte read in, bits D0 to D4 stand for the five keys in the
given half-row. D0 is for the outside key and D4 is for the one
nearest the middle. The bit is 0 if the key is pressed, 1 if it is
not. D6 is set by the datacorder read data, and is effectively
random if no tape data is present.

For JOYSTICK 1, bit 0 is fire, bit 1 is up, bit 2 is down, bit 3


is right and bit 4 is left. For JOYSTICK 2, bit 0 is left, bit 1
is right, bit 2 is down, bit 3 is up and bit 4 is fire. From
BASIC, these read as the number keys.

Port address 00FEh (254 decimal) in output drives the sound (D4)
and the save signal to the datacorder (D3), and also sets the
border colour (D2, D1 and D0).

Port addresses 00FEh (254), 00F7h (247) and 00EFh (239) are
reserved.
Port address 7FFDh (32765) drives the extra memory. Executing an
OUT to this port from BASIC will nearly always cause the computer
to crash, losing any program and data. There is a fuller
description of this port in part 24 of this chapter (under the
heading 'Memory management'). This port is write only ie. you
cannot determine the current state of the paging by an IN
instruction. This is why the BANKM system variable is always kept
up to date with the last value output to this port.

Port address BFFDh (49149) drives the sound chip's data registers.
Port address FFFDh (65533) in output writes a register address,
and in input reads a register. Judicious use of these two
registers can allow sounds to be generated whilst BASIC gets on
with something else, but you should be aware that they also
control RS232/MIDI and AUX interfaces.

Port address 0FFDh (4093) is used for the parallel (Centronics)


interface (ie. PRINTER). When read using an IN instruction bit 0
shows the state of the BUSY signal produced by the printer. If the
printer is off line or non-existent, then this bit will be 1. When
this port is written to using OUT, it acts as the parallel port
data register. In order to print a character it is necessary to
wait until BUSY is 0, write the character code to port 0FFDh
(4093), and finally, take the STROBE bit in port 1FFDh (8189) low
then back high again.

Port address 1FFDh (8189) controls several aspects of the +2A.


Amongst other things, this port controls the ROM that is switched
into the memory area from 0000h...3FFFh (0...16383). As the port
is write only, +3 BASIC maintains a variable, BANK678, that holds
the value last output to this port. It is therefore very unwise to
OUT values directly to this port without first checking on the
current state and setting/resetting only the bits you are
interested in. This is also the case for the port at 7FFDh (which
holds its current state in BANKM). The bottom three bits (0...2)
of this port (1FFDh) are used to switch RAM/ROM - further details
can be found in part 24 of this chapter (under the heading 'Memory
management'). If a disk drive is connected, then bit 3 controls
the motor (0 is off; 1 is on), though it should not be necessary
to control the motor by writing to this port as there are +3DOS
routines that will achieve the desired effect. Bit 4 is the
parallel port STROBE which is active low - this means that to
print the character that has been output to port 0FFDh (4093), the
STROBE bit should be brought low and then returned to its normally
high state.

If you have connected an external disk drive (and interface) to


the +2A, then port addresses 2FFDh (12285) and 3FFDh (16381) can
be used as follows:

Port address 2FFDh (12285) can be used to read the disk controller
(μPD765A) chip's main status register. This is unlikely to be very
useful without an in-depth knowledge of how the chip operates.
Port address 3FFDh (16381) is the disk controller's data register.
This can be both read from and written to, but once again it is
unlikely to be useful to the BASIC programmer. Random OUTputting
to this port will probably confuse the poor disk controller chip
to such an extent that subsequent disk operations (like LOAD and
SAVE) will be unreliable. It is entirely possible that ill-
informed experiments will corrupt your disks and lose your data -
you have been warned!

Run this program to see how the keyboard works...

10 FOR n=0 TO 7: REM half-row


number
20 LET a=254+256*(255-2^n)
30 PRINT AT 20,0; IN a: GO TO
30

...and play around by pressing keys (start with the half-row from
CAPS SHIFT to V). When you have finished with each half-row, press
BREAK and then type...

NEXT n

The control, data and address busses are all exposed at the back
of the +2A on the EXPANSION I/O socket. This means that you can do
almost anything with a +2A that you could with a raw Z80 chip
(although sometimes, the computer's internal workings may get in
the way).

See chapter 10 for a diagram and pin-out of the EXPANSION I/O


socket.
Part 24
The memory
Subjects covered...

PEEK
POKE
CLEAR
Memory management

Deep inside the +2A, everything is stored as bytes, ie. numbers


between 0 and 255 (FFh). You may think you have stored away the
price of Ruddles or the players' names in the Arsenal football
team, but in fact, all the information has been converted into
collections of bytes, and bytes are what the computer sees.

Each place where a byte can be stored has an address, which is a


number between 0 (0000h) and 65535 (FFFFh). This means that an
address can be stored as two bytes. You can think of the memory as
a long row of numbered boxes, each of which can contain a byte.
Not all the boxes are the same, however - the boxes from 4000h to
FFFFh are RAM boxes, which means you can open the lid and alter
the contents, but those from 0 to 3FFFh are ROM boxes, which have
a glass lid that cannot be opened - you just have to read whatever
was put into them when the computer was made. In the +2A, we have
crammed in more than twice the amount of memory than can
comfortably fit. While the processor can address 65536 bytes,
there are in fact 131072 bytes of RAM and 65536 bytes of ROM
making 196608 bytes (192K) in all! All this is hidden from the
processor by the hardware using a process called paging - BASIC
(and the processor) always 'sees' the memory as 16K of ROM and 48K
of RAM (or 64K of RAM with no ROM - though this latter combination
is never used by BASIC).

The +2A memory map


To inspect the contents of a box, we use the PEEK function. Its
argument is the address of the box, and its result is the
contents. For example, this program prints out the first 21 bytes
in ROM (and their addresses)...

10 PRINT "Address"; TAB 8; "By


te"
20 FOR a=0 TO 20
30 PRINT a; TAB 8; PEEK a
40 NEXT a

All these bytes will probably be quite meaningless to you, but the
processor chip understands them to be instructions telling it what
to do.

To change the contents of a box (if it is RAM), we use the POKE


command. Its form is...

POKE address,contents

...where address and contents are numeric expressions. For


example, if you type...

POKE 31000,57

...then the byte at address 31000 is given the new value 57. Now
type...

PRINT PEEK 31000

...to prove this. (Try poking in other values, to show that there
is no cheating.) The new value must be between -255 and +255; if
it is negative, then 256 is added to it.

The ability to poke gives you immense power over the computer if
you know how to wield it, and immense destructive possibilities if
you don't. It is very easy (by poking the wrong value into the
wrong address) to lose vast programs that took you hours to type
in. Fortunately though, you won't do the computer any permanent
damage.

We shall now take a more detailed look at how the RAM is used.
Don't bother to read this unless you're really interested.

The memory is divided into different areas (shown in the diagram


ahead) for storing different kinds of information. The areas are
only large enough for the information that they actually contain,
and if you insert some more at a given point (for instance by
adding a program line or variable), then space is made by shifting
up everything above that point. Conversely, if you delete
information, then everything is shifted down.
The display file stores the contents of the TV screen. It is
rather curiously laid out, so you probably won't want to PEEK or
POKE in it. Each character position on the screen has an 8 x 8
grid of dots; each dot can be either 0 (paper) or 1 (ink), so by
using binary notation we can store the pattern as 8 bytes - one
for each row. However, these 8 bytes are not stored together. The
corresponding columns in the 32 characters of a single line are
stored together as a scan of 32 bytes, because this is what the
electron beam in the TV needs as it scans from the left-hand side
of the screen to the other. Since the complete picture has 24
lines of 8 scans each, you might expect the total of 192 scans to
be stored in order, one after the other - well, you'd be wrong!
First come the top scans of lines 0 to 7, then the next scans of
lines 0 to 7, and so on to the bottom scans of lines 0 to 7; then
the same for lines 8 to 15; and again for lines 16 to 23. The
upshot of all this is that if you're used to a computer that uses
PEEK and POKE on the screen, then you'll have to start using
SCREEN$ and PRINT AT instead (or PLOT and POINT).

The attributes are the colours and so on for each character


position, using the format of ATTR. These are stored line by line
in the order you'd expect.

The way that the computer organises its affairs changes slightly
between 48 BASIC and +3 BASIC mode. The area that was the printer
buffer in 48 BASIC mode, is used for extra system variables in +3
BASIC mode in much the same way as it was on the original Spectrum
+2. The variables have changed, though.

BASIC memory map


The system variables contain various pieces of information that
tell the computer what sort of state it's in. They are listed
fully in part 25 of this chapter, but for the moment, note that
there are some (called CHANS, PROG, VARS, E LINE, and so on) that
contain the addresses of the boundaries between the various areas
in memory. These are not BASIC variables, and their names will not
be recognised by the +2A.

The channel information contains information about the input and


output devices, namely the keyboard (together with the lower half
of the screen), the upper half of the screen, and the printer.

Each line of BASIC program has the form:

Note that, in contrast with all other cases of two-byte numbers in


the Z80, the line number here is stored with its most significant
byte first, ie. in the order that you'd write them down.

A numerical constant in the program is followed by its binary


form, using the character CHR$ 14 followed by five bytes for the
number itself.

The variables have different formats according to their different


natures. The letters in the names should be imagined as starting
off in lower case.

Number whose name is one letter only:

Number whose name is longer than one letter:


Array of numbers:

The order of the element is:

First - the elements for which the first subscript is 1.


Next - the elements for which the first subscript is 2.
Next - the elements for which the first subscript is 3...
...and so on for all possible values of the first subscript.

The elements with a given first subscript are ordered in the same
way using the second subscript, and so on down to the last.

As an example, the elements of the 3 x 6 array c in part 12 of


this chapter are stored in the order
c(1,1) c(1,2) c(1,3) c(1,4) c(1,5) c(1,6) and
c(2,1) c(2,2)...c(2,6) and c(3,1) c(3,2)...c(3,6).

Control variable of a FOR...NEXT loop:

String:

Array of characters:
The calculator is the part of the BASIC system that deals with
arithmetic, and the numbers on which it is operating are held
mostly in the calculator stack.

The spare area contains the space so far unused.

The machine stack is the stack used by the Z80 processor to hold
return addresses and so on.

The GO SUB stack was mentioned in part 5 of this chapter.

The byte 'pointed to' by RAMTOP has the highest address used by
the BASIC system. Even NEW, which clears the RAM, only does so as
far as this - so it doesn't change the user-defined graphics. You
can change the address RAMTOP by putting a number in a CLEAR
statement, ie...

CLEAR new RAMTOP

...which does the following:

1. Clears out all the variables.

2. Clears the display file (like CLS does).

3. Resets the PLOT position to the bottom left-hand


corner.

4. RESTOREs the DATA pointer.

5. Clears the GO SUB stack and puts it at the new RAMTOP


(assuming that this lies between the calculator and the
physical end of RAM; otherwise it leaves RAMTOP where it
was).

RUN also performs a CLEAR, although it never changes RAMTOP.

Using CLEAR in this way, you can either move RAMTOP up to make
more room for the BASIC by overwriting the user-defined graphics,
or you can move it down to make more RAM that is preserved from
NEW. It can also be used to ensure that the machine stack is below
BFE0h (49120) when intending to call +3DOS - this means that the
stack will not have to be subsequently moved within your own
machine code.

If you are in an experimental frame of mind you can also use CLEAR
to explore the extra memory. CLEAR 49151 moves all of BASIC below
the addresses that hold the switchable RAM paging. By using POKE
23388,16+n where n is a number between 0 and 7, you can make the
computer switch in page n of the RAM. You will then be able to use
PEEK and POKE in the normal way to examine and change the page.
Beware - the extra pages are normally used by the system for disk
(if connected) and editor operations, so always reset the +2A
after exploring in this way, before doing anything else.

Type NEW, select +3 BASIC, then enter the command CLEAR 23825 to
get some idea of what happens to the machine when it fills up.

If you then try to make the +2A compute, (for example, type in
PRINT 1+1) you will see the report 4 Out of memory displayed. This
means the computer has no more room for information. If you come
up against this message while entering a large program, you will
have to empty the memory slightly (delete a line or so) in order
to control the computer.

Memory management
We mentioned earlier that there is rather more memory in the
computer than the processor can deal with. While the processor can
indeed address only 64K of memory at once, the extra memory can be
slotted in and out of that 64K at will. Consider a TV set.
Although it (and you) can only deal with one channel at a time,
there are another three channels always there which can be
selected with the right buttons. So, even though there's four
times as much information as you can use at any one time, you can
pick and choose which part is relevant.

It is much the same for the processor. By setting the right bits
in an I/O port it can pick and choose which chunks of the 192K of
memory it wants to use. For the majority of the time in BASIC it
ignores most of the memory, but for games playing, having three
times as much RAM is really rather useful. Look again at the +2A's
memory map (shown at the beginning of this section). RAM pages 2
and 5 are always in the positions shown when BASIC is used, though
there's no reason why they shouldn't be in the banked section
(C000h to FFFFh) - however, it would be difficult to see any use
for this.

The RAM banks are of two types: RAM pages 4 to 7 which are
contended (meaning that they share time with the video circuitry),
and RAM pages 0 to 3 which are uncontended (where the processor
has exclusive use). Any machine code which has critical timing
loops (such as music or communications programs) should keep all
such routines in the uncontended banks. For example, executing
NOPs in contended RAM will give an effective clock frequency of
2.66MHz as opposed to the normal 3.55MHz in uncontended RAM. This
is a reduction in speed of about 25%.

The hardware switch normally used to select RAM is at I/O address


7FFDh (32765). The bit field for this address is as follows:

D0...D2 - RAM select


D3 - Screen select
D4 - ROM select
D5 - Disable paging
D2...D0 is a three bit number that selects which RAM page goes
into the C000h to FFFFh slot. In BASIC, RAM page 0 is normally in
situ. When editing or calling +3DOS routines, RAM page 7 is used
for various buffers and 'scratchpads'. D3 switches screens: screen
0 is held in RAM page 5 (normally beginning at 4000h) and is the
one that BASIC uses. Screen 1 is held in RAM 7 (beginning at
C000h) and can only be used by machine code programs. It is
entirely feasible to set up a screen in RAM 7 and then page it
out; this leaves the entire 48K free for data and program. Note
that the +2A's COPY (file) command may well use buffers in the
second screen area (corrupting a second screen which may be
'hidden' there). D4 determines which ROM is paged into 0000h to
3FFFh (in combination with bit 2 of port 1FFDh - see below). D5 is
a safety feature - once this bit has been set, no further paging
operations will work. This is normally used when the the machine
assumes a standard 48K Spectrum configuration and all the memory
paging circuitry is locked out. It cannot be turned back into a
128K machine other than by switching off or pressing the RESET
button; however, the sound chip can still be driven by OUT. If a
48K Spectrum game loaded from disk (if a disk drive is connected)
will not work, it is possible that by using the SPECTRUM command
followed by OUT 32765,48 (which locks bit 5 in this port), the
game might then work.

The +2A also uses I/O port 1FFDh for some ROM and RAM switching.
The bit field for this address is is follows:

D0 - Affects whether D1...D2 work on ROM/RAM


D1...D2 - ROM/RAM switching
D3 - Disk motor (if disk drive is connected)
D4 - Parallel port strobe (active low)

When bit 0 is 0, bit 1 has no effect and bit 2 is a 'vertical' ROM


switch (ie. between ROM 0 and ROM 2, or between ROM 1 and ROM 3).
Bit 4 in the port at 7FFDh is a 'horizontal' ROM switch (ie.
between ROM 0 and ROM 1, or between ROM 2 and ROM 3). The
following diagram serves to show the various ROM switching
possibilities...
Bit 4 7FFDh (23888)
ROM 0 (system variable: BANKM) ROM 1

Editor ← horizontal → Syntax

↑ ↑

Bit 2 1FFDh
(23399)
(system variable:
BANK678) vertical
vertical

↓ ↓

ROM 2 ROM 3

DOS ← horizontal → 48 BASIC

Horizontal and vertical ROM switching

It is best to think of bit 4 in port 7FFDh and bit 2 in port 1FFDh


combining to form a 2 bit number (0...3) which determines which
ROM occupies the memory area 0000h...3FFFh. Bit 4 of port 7FFDh is
the least significant bit and bit 2 of 1FFDh is the most
significant bit:

Bit 2 of 1FFDh Bit 4 of 7FFDh Switched ROM at


(System variable: (System variable: 0000h...3FFFh
BANK678) BANKM)
0 0 0
0 1 1
1 0 2
1 1 3

ROM switching (with Bit 0 of 1FFDh set to 0)


When bit 0 of port 1FFDh is set to 1, bits 1 and 2 switch in
various RAM combinations that occupy the full 64K address space.
These are not used by +3 BASIC but are provided for authors of
operating systems/games. When the +3DOS 'DOS BOOT' routine is
used, the bootstrap is loaded into the 4, 7, 6, 3 RAM page
environment. The various +2A extra RAM paging options are as
follows:

Bit 2 of 1FFDh Bit 1 of 7FFDh RAM pages used


(0000h...3FFFh),
(4000h...7FFFh, etc.)
0 0 0, 1, 2, 3
0 1 4, 5, 6, 7
1 0 4, 5, 6, 3
1 1 4, 7, 6, 3

Extended memory paging (with Bit 0 of 1FFDh set to 1)


Part 25
The system variables
Subjects covered...

POKE, PEEK

The bytes in memory from 5B00h (23296) to 5CB6h (23734) are set
aside for specific uses by the system. There are a few routines
(used to keep the paging in order), and some locations called
system variables. You can peek these to find out various things
about the system, and some of them can be usefully poked. They are
listed here with their uses.

There is quite a difference, as you might expect, between the


system variables' area in 48 BASIC mode and in +3 BASIC mode. In
48 BASIC mode, all the variables and routines below 5C00h (23552)
do not exist; instead there is a buffer between 5B00h (23296) and
5C00h (23552) which is used for controlling the printer. This was
quite a popular location for small machine code routines on the
old 48K Spectrum, and if any of these routines are tried in +3
BASIC mode, the computer will invariably crash. Any old program
that uses PEEK, POKE and USR is therefore a safer bet if it is run
in 48 BASIC mode (although it can be entered in +3 BASIC mode and
transferred using the SPECTRUM command). If there is a chance that
a program might inadvertently address the added I/O ports of the
+2A, then OUT 32765,48 will set bit 5 in port 7FFDh to disable
further use of the added ROM/RAM switching.

Although system variables have names, you should not confuse them
with the words and names used in BASIC. The computer will not
recognise the names as referring to system variables; they are
given solely as mnemonics for we humans.

The abbreviations in column 1 of the table ahead have the


following meanings:

X - The variables should not be poked because the system might


crash.

N - Poking the variables will have no lasting effect.

R - Routine entry point. Not a variable.

The number in column 1 is the number of bytes in the variable or


routine. For a two-byte word, the first byte is the least
significant - the reverse of what you might expect. So, to poke a
value v into a two-byte variable at address n, use...
POKE n,v-256* INT (v/256)
POKE n+1, INT (v/256)

...and to peek its value, use the expression...

PRINT PEEK n+256* PEEK (n+1)

NOTES ADDRESS HEX NAME CONTENTS


(DECIMAL)
R16 5B00h (23296) SWAP Paging subroutine.
R17 5B10h (23312) STOO Paging subroutine. Entered
with interrupts already
disabled and AF, BC on the
stack.
R9 5B21h (23329) YOUNGER Paging subroutine.
R16 5B2Ah (23338) REGNUOY Paging subroutine.
R24 5B3Ah (23354) ONERR Paging subroutine.
X2 5B52h (23378) OLDHL Temporary register store
while switching ROMs.
X2 5B54h (23380) OLDBC Temporary register store
while switching ROMs.
X2 5B56h (23382) OLDAF Temporary register store
while switching ROMs.
N2 5B58h (23384) TARGET Subroutine address in ROM 3.
X2 5B5Ah (23386) RETADDR Return address in ROM 1.
X1 5B5Ch (23388) BANKM Copy of last byte output to
I/O port 7FFDh (32765). This
port is used to control the
RAM paging (bits 0...2), the
'horizontal' ROM switch (0←→1
and 2←→3 - bit 4), screen
selection (bit 3) and added
I/O disabling (bit 5). This
byte must be kept up to date
with the last value output to
the port if interrupts are
enabled.
X1 5B5Dh (23389) RAMRST RST 8 instruction. Used by
ROM 1 to report old errors to
ROM 3.
N1 5B5Eh (23390) RAMERR Error number passed from ROM
1 to ROM 3. Also used by
SAVE/LOAD as temporary drive
store.
2 5B5Fh (23391) BAUD RS232 bit period in T
states/26. Set by FORMAT
LINE.
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
N2 5B61h (23393) SERFL Second-character-received-
flag, and data.
N1 5B63h (23395) COL Current column from 1 to
width.
1 5B64h (23396) WIDTH Paper column width. Defaults
to 80.
1 5B65h (23397) TVPARS Number of inline parameters
expected by RS232.
1 5B66h (23398) FLAGS3 Various flags. Bits 0, 1, 6
and 7 unlikely to be useful.
Bit 2 is set when tokens are
to be expanded on printing.
Bit 3 is set if print output
is RS232. The default (at
reset) is Centronics. Bit 4
is set if a disk interface is
present. Bit 5 is set if
drive B: is present.
X1 5B67h (23399) BANK678 Copy of last byte output to
I/O port 1FFDh (8189). This
port is used to control the
+2A extended RAM and ROM
switching (bits 0...2 - if
bit 0 is 0 then bit 2
controls the 'vertical' ROM
switch 0←→2 and 1←→3), the
disk motor (bit 3) if a disk
drive is connected, and
Centronics strobe (bit 4).
This byte must be kept up to
date with the last value
output to the port if
interrupts are enabled.
N1 5B68h (23400) XLOC Holds X location when using
the unexpanded COPY command.
N1 5B69h (23401) YLOC Holds Y location when using
the unexpanded COPY command.
X2 5B6Ah (23402) OLDSP Old SP (stack pointer) when
TSTACK in use.
X2 5B6Ch (23404) SYNRET Return address for ONERR.
5 5B6Eh (23406) LASTV Last value printed by
calculator.
2 5B73h (23411) RC LINE Current line being
renumbered.
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
2 5B75h (23413) RC START Starting line number for
renumbering. The default
value is 10.
2 5B77h (23415) RCSTEP Incremental value for
renumbering. The default is
10.
1 5B79h (23417) LODDRV Holds T if LOAD, VERIFY,
MERGE are from tape,
otherwise holds A, B or M.
1 5B7Ah (23418) SAVDRV Holds T if SAVE is to tape,
otherwise holds A, B or M.
1 5B7Bh (23419) DUMPLF Holds the number of l/216ths
used for line feeds in COPY
EXP. This is normally set to
9. If problems are
experienced fitting a dump
onto a sheet of A4 paper,
POKE this location with 8.
This will reduce the size of
the dump and improve the
aspect ratio slightly. (The
quality of the dump will be
marginally degraded,
however.)
N8 5B7Ch (23420) STRIP1 Stripe one bitmap.
N8 5B84h (23428) STRIP2 Stripe two bitmap. This
extends to 5B8Bh (23436).
X115 5BFFh (23551) TSTACK Temporary stack grows down
from here. Used when RAM page
7 is switched in at top of
memory (while executing the
editor or calling +3DOS). It
may safely go down to 5B8Ch
(and across STRIP1 and STRIP2
if necessary). This
guarantees at least 115 bytes
of stack when BASIC calls
+3DOS.
N8 5C00h (23552) KSTATE Used in reading the keyboard.
N1 5C08h (23560) LAST K Stores newly pressed key.
1 5C09h (23561) REPDEL Time (in 50ths of a second)
that a key must be held down
before it repeats. This
starts off at 35, but you can
POKE in other values.
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
1 5C0Ah (23562) REPPER Delay (in 50ths of a second)
between successive repeats of
a key held down - initially
5.
N2 5C0Bh (23563) DEFADD Address of arguments of user
defined function (if one is
being evaluated); otherwise
0.
N1 5C0Dh (23565) K DATA Stores 2nd byte of colour
controls entered from
keyboard.
N2 5C0Eh (23566) TVDATA Stores bytes of colour, AT
and TAB controls going to TV.
X38 5C10h (23568) STRMS Addresses of channels
attached to streams.
2 5C36h (23606) CHARS 256 less than address of
character set (which starts
with space and carries on to
©). Normally in ROM, but you
can set up your own in RAM
and make CHARS point to it.
1 5C38h (23608) RASP Length of warning buzz.
1 5C39h (23609) PIP Length of keyboard click.
1 5C3Ah (23610) ERR NR 1 less than the report code.
Starts off at 255 (for -1) so
PEEK 23610 gives 255.
X1 5C3Bh (23611) FLAGS Various flags to control the
BASIC system.
X1 5C3Ch (23612) TV FLAG Flags associated with the TV.
X2 5C3Dh (23613) ERR SP Address of item on machine
stack to be used as error
return.
N2 5C3Fh (23615) LIST SP Address of return address
from automatic listing.
N1 5C41h (23617) MODE Specifies K, L, C, E or G
cursor.
2 5C42h (23618) NEWPPC Line to be jumped to.
1 5C44h (23620) NSPPC Statement number in line to
be jumped to. Poking first
NEWPPC and then NSPPC forces
a jump to a specified
statement in a line.
2 5C45h (23621) PPC Line number of statement
currently being executed.
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
1 5C47h (23623) SUBPPC Number within line of
statement being executed.
1 5C48h (23624) BORDCR Border colour multiplied by
8; also contains the
attributes normally used for
the lower half of the screen.
2 5C49h (23625) E PPC Number of current line (with
program cursor).
X2 5C4B (23627) VARS Address of variables.
N2 5C4D (23629) DEST Address of variable in
assignment.
X2 5C4F (23631) CHANS Address of channel data.
X2 5C51 (23633) CURCHL Address of information
currently being used for
input and output.
X2 5C53 (23635) PROG Address of BASIC program.
X2 5C55 (23637) NXTLIN Address of next line in
program.
X2 5C57 (23639) DATADD Address of terminator of last
DATA item.
X2 5C59 (23641) E LINE Address of command being
typed in.
2 5C5B (23643) K CUR Address of cursor.
X2 5C5D (23645) CH ADD Address of the next character
to be interpreted - the
character after the argument
of PEEK, or the NEW LINE at
the end of a POKE statement.
2 5C5F (23647) X PTR Address of the character
after the marker.
X2 5C61 (23649) WORKSP Address of temporary work
space.
X2 5C63 (23651) STKBOT Address of bottom of
calculator stack.
X2 5C65 (23653) STKEND Address of start of spare
space.
N1 5C67 (23655) BREG Calculator's B register.
N2 5C68 (23656) MEM Address of area used for
calculator's memory (usually
MEMBOT, but not always).
1 5C6A (23658) FLAGS2 More flags. (Bit 3 set when
CAPS SHIFT or CAPS LOCK is
on.)
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
X1 5C6B (23659) DF SZ The number of lines
(including one blank line) in
the lower part of the screen.
2 5C6C (23660) STOP The number of the top program
line in automatic listings.
2 5C6E (23662) OLDPPC Line number to which CONTINUE
jumps.
1 5C70 (23664) OSPCC Number within line of
statement to which CONTINUE
jumps.
N1 5C71 (23665) FLAGX Various flags.
N2 5C72 (23666) STRLEN Length of string type
destination in assignment.
N2 5C74 (23668) T ADDR Address of next item in
syntax table (very unlikely
to be useful).
2 5C76 (23670) SEED The seed for RND. This is the
variable that is set by
RANDOMIZE.
3 5C78 (23672) FRAMES 3 byte (least significant
byte first), frame counter
incremented every 20mS.
2 5C7A (23675) UDG Address of 1st user-defined
graphic. You can change this,
for instance, to save space
by having fewer user-defined
graphics.
1 5C7Dh (23677) COORDS X-coordinate of last point
plotted.
1 5C7Eh (23678) Y-coordinate of last point
plotted.
1 5C7Fh (23679) P POSN 33-column number of printer
position.
1 5C80h (23680) PR CC Least significant byte of
address of next position for
LPRINT to print at (in
printer buffer).
1 5C81h (23681) Not used.
2 5C82h (23682) ECHO E 33-column number and 24-line
number (in lower half) of end
of input buffer.
2 5C84h (23684) DF CC Address in display file of
PRINT position.
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
2 5C86h (23686) DF CCL Like DF CC for lower part of
screen.
X1 5C88h (23688) S POSN 33-column number for PRINT
position.
X1 5C89h (23689) 24-line number for PRINT
position.
X2 5C8Ah (23690) SPOSNL Like S POSN for lower part.
1 5C8Ch (23692) SCR CT Counts scrolls - it is always
1 more than the number of
scrolls that will be done
before stopping with scroll?.
If you keep poking this with
a number bigger than 1 (say
255), the screen will scroll
on and on without asking you.
1 5C8Dh (23693) ATTR P Permanent current colours,
etc. (as set up by colour
statements).
1 5C8Eh (23694) MASK P Used for transparent colours,
etc. Any bit that is 1 shows
that the corresponding
attribute bit is taken not
from ATTR P, but from what is
already on the screen.
N1 5C8Fh (23695) ATTR T Temporary current colours,
etc. (as set up by colour
items).
N1 5C90h (23696) MASK T Like MASK P, but temporary.
1 5C91h (23697) P FLAG More flags.
N30 5C92h (23698) MEMBOT Calculator's memory area -
used to store numbers that
cannot conveniently be put on
the calculator stack.
2 5CB0h (23728) NMIADD Holds the address of the
users NMI service routine.
NOTE - On previous machines,
this did not work correctly
and these two bytes were
documented as 'Not used'.
Programs that used these two
bytes for passing values may
need to be modified.
2 5CB2h (23730) RAMTOP Address of last byte of BASIC
system area.
NOTES ADDRESS HEX NAME CONTENTS
(DECIMAL)
2 5CB4h (23732) P RAMT Address of last byte of
physical RAM.
Part 26
Using machine code
Subjects covered...

USR with numeric argument

This section is written for those who understand Z80 machine code,
ie. the set of instructions that the Z80 processor chip uses. If
you do not, but would like to, there are plenty of books about it.
You should get one called something along the lines of...'Z80
machine code (or assembly language) for the absolute beginner',
and if it mentions the '+2(+2A)' or other computers in the ZX
Spectrum range, so much the better.

Machine code programs are normally written in assembly language,


which, although cryptic, is not too difficult to understand with
practice. You can see the assembly language instructions in part
28 of this chapter. However, to run them on the +2A you need to
code the program into a sequence of bytes - then called machine
code. This translation is usually done by the computer itself
using a program called an assembler. There is no assembler built
in to the +2A, but you will be able to buy one on tape (or disk).
Failing that, you will have to do the translation yourself,
provided that the program is not too long.

Let's take as an example the program...

ld bc, 99
ret

...which loads the BC register pair with 99. This translates into
the four machine code bytes 1, 99, 0 (for ld bc, 99) and 201 (for
r e t). (If you look up codes 1 and 201 in part 28 of this
chapter, you will find that 1 corresponds to ld bc, NN - where NN
stands for any two-byte number; and 201 corresponds to ret.)

When you have got your machine code program, the next step is to
get it into the computer - (an assembler would probably do this
automatically). You need to decide whereabouts in memory to locate
it - the best thing is to make extra space for it between the
BASIC area and the user-defined graphics.

If you type...

CLEAR 65267

...this will give you a space of 100 (for good measure) bytes
starting at address 65268.
To put in the machine code program, you would run a BASIC program
something like...

10 LET a=65268
20 READ n: POKE a,n
30 LET a=a+1: GO TO 20
40 DATA 1,99,0,201

(This will stop with the report E Out of DATA when it has filled
in the four bytes you specified.)

To run the machine code, you use the function USR - but this time
with a numeric argument, ie. the starting address. Its result is
the value of the BC register on return from the machine code
program, so if you type...

PRINT USR 65268

...you will get the answer 99.

The return address to BASIC is 'stacked' in the usual way, so


return is by a Z80 ret instruction. You should not use the IY and
I registers in a machine code routine that expects to use the
BASIC interrupt mechanism. If you are writing a program that might
eventually run on an older Spectrum (up to and including the +2),
you should not load I with values between 40h and 7Fh (even if you
never use IM 2). Values between C0h and FFh for I should also be
avoided if contended memory (ie. RAM 4 to 7) is to be paged in
between C000h and FFFFh. This is due to an interaction between the
video controller and the Z80 refresh mechanism, and can cause
otherwise inexplicable crashes, screen corruption or other
undesirable effects. Thus, you should only vector IM 2 interrupts
to between 8000h and BFFFh unless you are very confident of your
memory mapping (or you are only going to run your program on the
+2A where this problem does not exist).

The system variable at 5CB0h (23728) was documented on previous


models of the Spectrum (except the +3) as 'Not used'. Like the +3,
it is used on the +2A as an NMI jump vector. If an NMI occurs this
address is checked. If it contains 0, then no action is taken.
However, for any other (non-zero) value, a jump will be made to
the address given by this variable. NMIs must not occur while the
disk system (if connected) is active.

There are a number of standard pitfalls when programming a banked


system such as the +2A from machine code. If you are experiencing
problems, check that your stack is not being paged out during
interrupts, and that your interrupt routine is always where you
expect it to be (it is advisable to disable interrupts during
paging operations). It is also recommended that you keep a copy of
the current bank register setting in unpaged RAM somewhere as the
ports are write-only. BASIC and the editor use the system
variables BANKM and BANK678 for 7FFDh and 1FFDh respectively.
If you call +3DOS routines, remember that interrupts should be
enabled upon entry to the routines. Remember also that the stack
must be below BFE0h (49120) and above 4000h (16384), and that
there must be at least 50 words of stack space available.

You can save your machine code program easily enough with (for
example)...

SAVE "name" CODE 65268,4

On the face of it, there is no way of saving the program so that


when loaded it automatically runs itself; however, you can get
round this by using the short BASIC program...

10 LOAD "name" CODE 65268,4


20 PRINT USR 65268

...which should also be saved (as a separate program) using the


command (for example)...

SAVE "loader" LINE 10

Then you may run the machine code from BASIC using the single
command...

LOAD "Loader"

...which loads and automatically runs the BASIC program which in


turn loads and runs the machine code.

Calling +3DOS from BASIC


When BASIC'S USR function is used, the code it references is
entered with the memory configured as illustrated below (left),
ie, the ROM switched in at the bottom of memory in the address
range (0000h...3FFFh) is ROM 3 (the 48 BASIC ROM). The RAM page at
the top of memory is page 0 and the machine stack resides in this
area (unless the CLEAR command has been used to reduce it to
somewhere below C000h). As explained in part 27 of this chapter
(which describes the +3DOS routines), DOS can only be called with
RAM page 7 switched in at the top of memory, the stack held
somewhere in the range 4000h...BFE0h, and ROM 2 (the DOS ROM)
switched in at the bottom of memory (0000h...3FFFh). This
configuration is illustrated below (right).
Consequently, it will be necessary to switch both ROM and RAM, and
move the stack before and after calling one of the entries in the
DOS jump table. The following very simple example shows one way of
achieving the desired set up in order to call DOS CATALOG.

If BASIC'S CLEAR command has been used so that the BASIC stack is
below BFE0h (49120), then it is not necessary to move the stack.
However, we have done so in the following example to demonstrate
the technique when this is not the case.

A simple example to call DOS CATALOG...

org 7000h

mystak equ 9FFFh ;arbitrary value picked to be below


BFE0h and above 4000h
staksto equ 9000h ;somewhere to put BASIC'S stack
pointer
bankm equ 5B5Ch ;system variable that holds the last
value output to 7FFDh
port1 equ 7FFDh ;address of ROM/RAM switching port in
I/O map
catbuff equ 8000h ;somewhere for DOS to put its catalog
dos_catalog equ 011Eh ;the DOS routine to call

demo:

di ;unwise to switch RAM/ROM without


disabling interrupts
ld (staksto),sp ;save BASIC's stack pointer
ld bc,port1 ;the horizontal ROM switch/RAM switch
I/O address
ld a,(bankm) ;system variable that holds current
switch state
res 4,a ;move right to left in horizontal ROM
switch (3 to 2)
or 7 ;switch in RAM page 7
ld (bankm),a ;must keep system variable up to date
(very important)
out (c),a ;make the switch
ld sp,mystak ;make sure stack is above 4000h and
below BFE0h
ei ;interrupts can now be enabled

;
; The above will have switched in the DOS ROM and RAM page 7. The
; stack has also been located in a "safe" position for calling DOS
;
; The following is the code to set up and call DOS CATALOG. This
; is where your own code would be placed.
;

ld hl,catbuff ;somewhere for DOS to put the catalog


ld de,catbuff+1
ld bc,1024 ;maximum is actually 64x13+13 = 845
ld (hl),0
ldir ;make sure at least first entry is
zeroised
ld b,64 ;the number of entries in the buffer
ld c,1 ;include system files in the catalog
ld de,catbuff ;the location to be filled with the
disk catalog
ld hl,stardstar ;the file name ("*.*")
call dos_catalog ;call the DOS entry
push af ;save flags and possible error number
returned by DOS
pop hl
ld (dosret),hl ;put it where it can be seen from BASIC
ld c,b ;move number of files in catalog to low
byte of BC
ld b,0 ;this will be returned in BASIC by the
USR function

;
; If the above worked, then BC holds number of files in catalog,
; the "catbuff" will be filled with the alphanumerically sorted
; catalog and the carry flag bit in "dosret" will be set. This
; will be peeked from BASIC to check if all went well.
;
; Having made the call to DOS, it is now necessary to undo the ROM
; and RAM switch and put BASIC's stack back to where it was on
; entry. The following will achieve this.
;

di ;about to ROM/RAM switch so be careful


push bc ;save number of files
ld bc,port1 ;I/O address of horizontal ROM/RAM
switch
ld a,(bankm) ;get current switch state
set 4,a ;move left to right (ROM 2 to ROM 3)
and F8h ;also want RAM page 0
ld (bankm),a ;update the system variable (very
important)
out (c),a ;make the switch
pop bc ;get back the saved number of files in
catalog
ld sp,(staksto) ;put BASIC's stack back
ret ;return to BASIC, value in BC is
returned to USR

stardstar:

defb "*.*",FFh ;the file name, must be terminated


with FFh

dosret:

defw 0 ;a variable to be peeked from BASIC


to see if it worked

As some of you may not have an assembler available, the following


is a BASIC program that pokes the above code into memory, calls
it, and then uses the value returned by the USR function and the
contents of 'dosret' to print a very simple catalog.

10 LET sum=0
20 FOR i=28672 TO 28758
30 READ n
40 POKE i,n : LET sum=sum+n
50 NEXT i
60 IF sum <> 9387 THEN PRINT "
Error in DATA" : STOP
70 LET x=USR 28672
80 IF INT ( PEEK (28757)/2)= P
EEK (28757)/2 THEN PRINT "D
isk error "; PEEK (28758):
STOP
90 IF x=1 THEN PRINT "No files
found": STOP
100 FOR i=0 TO x-2
110 FOR j=0 TO 10
120 PRINT CHR$ ( PEEK (32781+i*
13+j));
130 NEXT j
140 PRINT
150 NEXT i
160 DATA 243,237,115,0,144,1,25
3,127,58,92,91,203,167,246,
7,50,92,91,237,121,49,255,1
59,251
170 DATA 33,0,128,17,1,128,1,0,
4,54,0,237,176,6,64,14,1,17
,0,128,33,81,112,205,30,1,2
45,225,34,85,112,72,6,0
180 DATA 243,197,1,253,127,58,9
2,91,203,231,230,248,50,92,
91,237,121,193,237,123,0,14
4,201
190 DATA 42,46,42,255,0,0

The addresses picked for the above code and its data areas are
completely arbitrary. However, it is a good idea to keep things in
the central 32K wherever possible so as not to run into the
pitfall of accidentally switching out a vital variable or piece of
code.

If interrupts are to be enabled (as is the case in the above


example), it is imperative that the system is kept up to date
about the latest ROM switch. This means that the user must make
the BANK678 system variable reflect the last value output to the
port at 1FFDh. As shown by the above example, the general
technique is to take a copy of the variable in A, set/reset the
relevant bits, update the system variable then make the switch
with an OUT instruction. Interrupts must be disabled while the
system variable does not reflect the current state of the port.
The port at 1FFDh doesn't just control the ROM switch, so setting
the variable to absolute values would be very unwise. Using AND/OR
with a bit mask or SET/RES instructions is the preferred method of
updating the variable.

Just as BANK678 reflects the last value output to 1FFDh, BANKM


should also be kept up to date with the last value output to
7FFDh. Again, it is unwise to use absolute values, as the port is
used for other purposes. For example, the bottom 3 bits of the
port are used to select the RAM page that is switched into the
memory area C000h...FFFFh (this is also shown in the above
example). Naturally, when more than one bit is to be set/reset, a
bit mask used with OR/AND is the more efficient method. Note that
RAM paging was described in the section entitled 'Memory
management' in part 24 of this chapter.

The above was a very simple example of calling DOS routines. The
following shows one or two extra techniques that you may find
useful. However, if you are not already familiar with assembler
programming, it might be better to skip this example.

If you have not connected an external disk drive to the +2A, the
above example will still work, producing a catalog of drive M:
(which will be the default drive). The following example, however,
will work only if you have connected a disk drive (and interface)
to the +2A.

Although part 20 of this chapter suggested that the opening menu's


Loader option first looks for a file called * and then one called
DISK before trying to load the first file from tape - this isn't
exactly the whole story. The first operation actually tries to
load a bootstrap sector from the disk in drive A:. The sector on
side 0, track 0, sector 1 will be used as a loader (bootstrap) if
the system finds that the 8 bit checksum of the sector is 3. The
following program ensures that the checksum of 512 bytes conforms
to this requirement, then writes the information to the disk in
the correct position. Once a disk has been modified in this way,
the Loader option can be used to automatically load and run the
disk. Alternatively, the BASIC command LOAD "*" can be used.

This example was developed using M80 on a CP/M based machine - so


the method used to ensure that the code is assembled relative to
the correct address might be different from that used by your own
assembler...

;
; Simple example program to write a boot sector to the disk in
; drive A:.
;
; by Cliff Lawson
; copyright (c) AMSTRAD Plc. 1987
;

.z80 ;ignore this if not using M80

bank1 equ 07FFDh ;"horizontal" and RAM switch port


bankm equ 05B5Ch ;associated system variable
bank2 equ 01FFDh ;"vertical" switch port
bank678 equ 05B67h ;associated system variable

select equ 01601h ;BASIC routine to open stream


dos_ref_xdpb equ 0151h ;
dd_write_sector equ 0166h ;see part 27 of this chapter
dd_login equ 0175h ;

Erg 0

.phase 07000h

;
; (This allows M80 to generate a .COM file that has addresses
; relative to 7000h. Assemble with "M80 = prog" and link with
; "L80 /p:0,/d:0,prog,prog/n:p/y/e"
; This can be headed with COPY...TO SPECTRUM FORMAT and loaded
; with LOAD...CODE 28672.
;
; A different technique will probably be required for other
; assemblers.)
;
start:

ld (olstak),sp ;save BASIC's stack pointer


ld sp,mystak ;put stack below switched RAM
pages
push iy ;save IY on stack for the moment

ld a,"A" ;drive A:
ld y,dos_ref_xdpb ;make IX point to XDPB A:
call dodos (necessary for calling DD
;routines)

ld c,0 c,0 ;log in disk in unit 0 so


that writing sectors
push ix ;wont say "disk has been changed"
ld iy,dd_login
call dodos
pop ix

ld hl,bootsector
ld bc,512 ;going to checksum 512 bytes of
sector
xor a
ld (bootsector+15),a ;reset checksum for starters
ld e,a ;E will hold 8 bit sum
ckloop:

ld a,e
add a,(hl) ;this loop makes 8 bit checksum of
512 byte
ld e,a ;sector in E
inc hl
dec bc
ld a,b
or c
jr nz,ckloop

ld a,e ;A now has 8 bit checksum of the


sector
cpl ;ones complement (+1 will give
negative value)
add a,4 ;add 3 to make sum = 3 + 1 to make
twos complement
ld (bootsector+15),a ;will make bytes checksum to 3 mod
256

ld b,0 ;page 0 at C000h


ld c,0 ;unit 0
ld d,0 ;track 0
ld e,0 ;sector 1 (0 because of
logical/physical trans.)
ld hl,bootsector ;address of info. to write as boot
sector
ld iy,dd_write_secto
r
call dodos ;actually write sector to disk
pop iy ;put IY back so BASIC can
reference its system variables
ld sp,(olstak) ;put original stack back
ret ;return to USR call in BASIC
dodos:
;
; IY holds the address of the DOS routine to be run. All other
; registers are passed intact to the DOS routine and are returned
; from it.
;
; Stack is somewhere in central 32K (conforming to DOS
; requirements), so ; saved AF and BC will not be switched out.
;
push af
push bc ;temp save registers while switching
ld a,(bankm) ;RAM/ROM switching system variable
or 7 ;want RAM page 7
res 4,a ;and DOS ROM
ld bc,bank1 ;port used for horiz ROM switch and RAM
paging
di
ld (bankm),a ;keep system variables up to date
out (c),a ;RAM page 7 to top and DOS ROM
ei
pop bc
pop af

call jumptoit ;go sub routine address in IY

push af ;return from JP (IY) will be to here


push bc
ld a,(bankm)
and 0F8h ;reset bits for page 0
set 4,a ;switch to ROM 3 (48 BASIC)
ld bc,bank1
di
ld (bankm),a
out (c),a ;switch back to RAM page 0 and 48 BASIC
ei
pop bc
pop af
ret
jumptoit:

jp (iy) ;standard way to CALL (IY), by calling


this jump

olstak:

dw 0 ;somewhere to put BASIC's stack pointer


ds 100

Mystak: ;enough stack to meet +3DOS requirements

bootsector:

.dephase ;these are M80 pseudo ops. your assembler


.phase 0FE00h ;may use something different

;
; Bootstrap will load into page 3 at address FE00h. The code will
; be entered at FE10h.
;
; Before it is written to track 0, sector 1, the bootstrap has
; byte 15 changed so that it will checksum to 3 mod 256.
;
; Boot will switch the memory so that the 48 BASIC ROM is at the
; bottom. Next up is page 5 - the screen, then page 2, and the top
; will keep page 3, as it would be unwise to switch out the
; bootstrap. BASIC routines can be called with any RAM page
; switched in at the top, but the stack shouldn't be in the
; TSTACK area.
;

bootstart:
;
; The bootstrap sector contains the 16 byte disk specification at
; the start. The following values are for a AMSTRAD PCW range CF-2
; (Spectrum +3) format disk.
;

db 0 ;+3 format
db 0 ;single sided
db 40 ;40 tracks per side
db 9 ;9 sectors per track

db 2 ;log2(512)-7 - sector size


db 1 ;1 reserved track
db 3 ;blocks
db 2 ;2 directory blocks
db 02Ah 02Ah ;gap length (r/w)
db 052h 052h ;gap length (format)
ds 5,0 ;5 reserved bytes

cksum: db 0 ;checksum must = 3 mod 256 for the sector


;
; The bootstrap will be entered here with the 4, 7, 6, 3 RAM pages
; switched in. To print something, we need 48 BASIC in at the
; bottom, page 5 (the screen and system variables) next up. The
; next page will be 0, and the top will be kept as page 3 because
; it still contains the bootstrap and stack (stack is FE00h on
; entry).
;
di
ld a,(bankm)
and 0F8h
or 3 ;RAM page 3 (as it holds bootstrap)
set 4,a ;right-hand ROMs
ld bc,bank1
ld (bankm),a
out (c),a ;switch RAM and horizontal ROM
ld a,(bank678)
and 0F8h
Or 4 ;set bit 2 and reset bit 0 (gives ROM 3)
ld bc,bank2
ld (bank678),a
out (c),a ;should now have R3,5,2,3

ld a,2
call select ;BASIC ROM routine to open stream (A)
ld hl,message
call print ;print a message
eloop:
;
; end with an endless loop changing the border. This is where your
; own code for a game or operating system would go.
;
ld a,r ;a not-very-random random number
out (0feh),a ;switch the border
jr eloop ;and loop
print:
ld a,(hl) ;this just loops printing characters
cp 0FFh ;until it finds FFh
ret z
rst 10h ;with 48K ROM in, this will print char
in A
inc hl
jr print
message:
defb 16,2,17,7,19,0,22,10,1,"Hello, good evening and
welcome", 0ffh
cliff:
ds 512-(cliff-bootstart),0 ;fill to end of sector
with 0s

end

There are one or two things that may be worth noting about this
example. The first is that because BASIC normally has the address
of the ERR NR system variable held in IY (so it can easily
reference its system variables). It is important to store IY and
replace it before returning to the original USR call.

Just as before, the stack is moved so that it sits in the central


32K of memory. This will allow +3DOS routines to be called without
having to move it again.

The 'dodos' subroutine may be useful in your own programs. It only


uses the IY register - which isn't used by the +3DOS system and
allows a call to be made to any of the +3DOS routines.

The program uses DOS REF XDPB to make IX point at the relevant
XDPB for drive A:. It then logs in the disk in A: so that it can
be written to. After calculating and modifying the checksum byte
for the information to be written to the boot sector of the disk,
it writes the boot sector using DD WRITE SECTOR.

No checks are made to see that there is even a disk interface, and
possible errors are ignored - the routine isn't designed to be
used by those unfamiliar with possible pitfalls. The routine can
be called with the BASIC command...

USR 28672

...which will come back with whatever number BC happens to contain


after completion of the routine.

The boot sector that is written to the disk has a standard disk
specification in the first 16 bytes. This is followed by the
bootstrap code that will be entered at address FE10h. As will be
described in the interface for DOS BOOT (see part 27 of this
chapter), the memory will initially be set up as 4, 7, 6, 3;
however, the BASIC system variables are still intact and BASIC can
be operated by switching in the correct ROM (3) to the bottom of
memory and making sure that page 5 is in the 4000h...7FFFh area of
memory.

This very simple boot program just uses the BASIC ROM to print a
greeting then enters a tight loop changing the border colour. It
could be modified to load a large binary file and enter it or
perform any other action you desired.
Part 27
Guide to +3DOS
Subjects covered...

ROMs
+3DOS interface
File attributes and headers
Disk format and specification
Tracks and sectors
Disk parameter blocks
CP/M file compatibility
Changing disks
Logical to physical drive mapping
+3DOS messages and requirements
+3DOS routines

Much of the information given in this section will apply only if


you have connected an external disk drive (or drives) to the +2A
system.

This section describes +3DOS - the disk operating system provided


with the +2A. The information will probably be of most interest to
people familiar with assembly language (machine code) programming
(see part 26 of this chapter for more information on this
subject). What follows is highly technical, and should not be used
by the uninitiated.

Even though the +2A does not incorporate a built-in floppy disk
interface, many of the +3DOS routines may still be called and will
operate on drive M: (the RAMdisk). If you have connected a disk
drive (and interface) to the +2A, then all +3DOS routines are
available for use. See the section ahead entitled 'Using +3DOS
without a floppy disk interface' for further details.

The operating software of the +2A is, in effect, held in four ROMs
(though the information is actually contained in just two ICs).
All four ROMs are addressed between 0000h and 3FFFh, although only
one is switched in at a time.

ROM 0 is the 'editor' ROM and is the one entered when the +2A is
first switched on. This controls the high level 'menuing' and
editing functions.
ROM 1 is the 'syntax' ROM and handles the high level control of +3
BASIC. It contains the code for the BASIC parts of most of the
disk based commands.

ROM 3 is the '48 BASIC' ROM and is virtually identical to the ROM
used in the very first Spectrum. The only real area where it is
different is in the code executed when an interrupt occurs. If non
zero, a 'ticker' variable is decremented every second interrupt,
and when it reaches zero, the disk motor is switched off. This
variable is held in page 7 along with some of the editor and DOS
variables. Page 7 will only be switched in (and this variable
decremented) if bit 4 in the FLAGS system variable is set - this
is used by the software to identify whether it is running 48 BASIC
or +3 BASIC. When 48 BASIC is selected (from the main menu or by
the SPECTRUM command), this bit is reset so that this page-
switching and ticker-decrementing won't happen. However, if bit 4
in the FLAGS system variable is subsequently set by your own
program, this process will start again while interrupt mode 1 is
still selected.

The keypad scanning routines of the Spectrum 128 and the original
+2 have been removed from ROM 3 in the +2A.

A 'bug' in the original 48 BASIC ROM has been fixed in the +2A.
When a non maskable interrupt (NMI) occurs, a jump is made to
location 66h. This now checks the contents of the NMIADD system
variable. If it is zero, a RETN is executed, otherwise a jump is
made to the routine address held in NMIADD. The NMI code in ROM 2
consists of just a RETN.

ROM 3 not only provides the 48 BASIC mode for program


compatibility, but executes the majority of +3 BASIC commands that
don't make use of the more advanced hardware of the +2A.

The fourth ROM (ROM 2) holds +3DOS - the disk operating system.
This is the subject of this section. Unlike the other ROMs, which
are unlikely to be of much use for assembler programmers (except
the 48 BASIC ROM perhaps), the +3DOS ROM has a wealth of routines
that may well be of use in your own programs. We strongly
recommend that any software that uses the disk drives makes use of
these routines as they provide most of the facilities that one
could wish for (more than are currently used by BASIC, in fact).
Furthermore, the routines should only be accessed via the jump
block. This not only makes it easier to write software that can be
adapted to and from the AMSTRAD CPC range of computers, but also
affords upwards compatibility for the future. The entry points for
each routine are held in a jump table at address 0100h (256) in
the ROM. Part 26 of this chapter gave a couple of examples of the
way in which these routines can be called.
+3DOS provides the following facilities:

* Support for one or two floppy disk drives and a RAMdisk.


* CP/M Plus and CP/M 2.2 file compatibility.
* AMSTRAD CPC range and PCW range file and media
compatibility.
* Up to 16 files open at the same time.
* Reading and writing files to or from any page in
memory.
* Byte level random access.
* Deleting disk files; renaming disk files; changing disk
files' attributes.
* Selecting the default drive and user.
* Booting a game or operating system.
* Low level access to floppy disk driver.
* Optional mapping of two logical drives (A: or B:) onto
one physical drive (unit 0).

+3DOS interface
+3DOS's interface is a set of routines accessed via a jump block.
The routines provided fall into three categories:

* Essential filing system routines.


* Additional routines for games and operating systems.
* Low level floppy disk access routines for disk formatting,
copying, etc.

The following is a list of the routines in each of these


categories (together with brief descriptions of the routines'
functions):

Essential filing system routines


NAME OF ROUTINE FUNCTION
DOS INITIALISE Initialise +3DOS
DOS VERSION Get +3DOS issue and version numbers
DOS OPEN Create and/or open a file
DOS CLOSE Close a file
DOS ABANDON Abandon a file
DOS REF HEAD Point at the header data for this file
DOS READ Read bytes into memory
DOS WRITE Write bytes from memory
DOS BYTE READ Read a byte
DOS BYTE WRITE Write a byte
DOS CATALOG Catalog disk directory
DOS FREE SPACE Free space on disk
NAME OF ROUTINE FUNCTION
DOS DELETE Delete a file
DOS RENAME Rename a file
DOS BOOT Boot an operating system or other program
DOS SET DRIVE Set/get default drive
DOS SET USER Set/get default user number

Additional routines for games and operating


systems
NAME OF ROUTINE FUNCTION
DOS GET POSITION Get file pointer for random access
DOS SET POSITION Set file pointer for random access
DOS GET EOF Get end of file position for random access
DOS GET 1346 Get memory usage in pages 1, 3, 4, 6
DOS SET 1346 Re-allocate memory usage in pages 1, 3, 4, 6
DOS FLUSH Bring disk up to date
DOS SET ACCESS Change open file's access mode
DOS SET ATTRIBUTES Change a file's attributes
DOS OPEN DRIVE Open a drive as a single file
DOS SET MESSAGE Enable/disable error messages
DOS REF XDPB Point at XDPB for low level disk access
DOS MAP B Map B: onto unit 0 or 1

Low level floppy disk driving routines

NAME OF ROUTINE FUNCTION


DD INTERFACE Is the floppy disk driver interface present?
DD INIT Initialise disk driver
DD SETUP Specify drive parameters
DD SET RETRY Set try/retry count
DD READ SECTOR Read a sector
DD WRITE SECTOR Write a sector
DD CHECK SECTOR Check a sector
DD FORMAT Format a track
DD READ ID Read a sector identifier
DD TEST UNSUITABLE Test media suitability
NAME OF ROUTINE FUNCTION
DD LOGIN Log in disk, initialise XDPB
DD SEL FORMAT Pre-initialise XDPB for DD FORMAT
DD ASK 1 Is unit 1 (second drive) present?
DD DRIVE STATUS Fetch drive status
DD EQUIPMENT What type of drive?
DD ENCODE Set intercept routine for copy protection
DD L XDPB Initialise an XDPB from a disk specification
DD L DPB Initialise a DPB from a disk specification
DD L SEEK μD765A seek driver
DD L READ μPD765A read driver
DD L WRITE μPD765A write driver
DD L ON MOTOR Motor on, wait for motor-on time
DD L T OFF MOTOR Start the motor-off ticker
DD L OFF MOTOR Turn the motor off

Games and other non-BASIC programs


+3DOS provides facilities specifically for non-BASIC programs:

* Use DOS BOOT to load a single bootstrap sector, then take


over the whole machine (see the second example in part 26
of this chapter).
* Claim some store from +3DOS using DOS SET 1346. This
enables a non-BASIC program to take control of the machine
but still use the facilities of +3DOS if required. If +3DOS
is not required then the non-BASIC program should call DD L
OFF MOTOR to force the drive motor off and disable the
motor ticker. Bit 4 in the FLAGS system variable should be
reset to prevent any bank switching/variable decrementing
on interrupt.
* A drive can be opened as a single file. This enables files
and directories to be examined without going via the file
structure.

Using +3DOS without a floppy disk interface


Even though the +2A does not incorporate a built-in floppy disk
interface, +3DOS can still be used (subject to the following
restrictions):

* Only drive M: is available (the RAMdisk).


* The default drive for filenames is initialised to M: rather
than A:.
* Any attempt to use drives A: or B: will fail with error 22
– Drive not found.
* As the sector cache is not required for use with
RAMdisk, the size of the RAMdisk is increased to 64K (the
whole of pages 1, 3, 4, 6). This will give 62K of data and
2K of directory (64 entries).
* The presence of a floppy disk interface can be determined
by calling DD INTERFACE. If an interface is not present,
then none of the other low level floppy disk routines
(DD...etc.) can be called, the effect of so doing is
undefined.

If you have connected a floppy disk drive (and interface) to the


+2A, then none of the above restrictions apply.

File attributes
Bit 7 of the name and type field characters are the file
attributes. The top bits of the name field characters are denoted
f1...f8. The top bits of the type field characters are denoted
t1...t3. They have the following meanings:

f1...f4 - Available to the user


f5...f8 - Reserved (always 0)
t1 - 0 means file is read-write; 1 means file is read-
only
t2 - 0 means not system file; 1 means system file
t3 - 0 means not archived, 1 means archived

A read-only file cannot be written to, erased or renamed. System


files can, optionally, be omitted from the directory catalog. The
archive attribute is ignored by +3DOS.

Newly created files have all attributes set to 0. An existing


file's attributes can only be changed by DOS SET ATTRIBUTES (as
used by BASIC's MOVE command).

File headers
Tape files have headers which contain some system information.
+3DOS files may, or may not, have headers. All files created by
BASIC's SAVE command will have headers.

The +3DOS header mechanism provides a dedicated 8 byte area in


each headed file reserved for BASIC's use. The remainder of the
header is reserved for +3DOS. This 8 byte header is utilised in
files created by BASIC commands (see DOS OPEN description).

+3DOS files may have a single header in the first 128 bytes of the
file - the header record. These headers are detected by a
'signature' and checksum. If the signature and checksum are as
expected then a header is present; if not, then there is no
header. Thus, it is possible, but 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...7 - +3DOS signature - 'PLUS3DOS'


Byte 8 - 1Ah(26) Soft-EOF (end of file)
Byte 9 - Issue number
Byte 10 - Version number
Bytes 11...14 - Length of the file in bytes, 32 bit number,
least significant byte in lowest address
Bytes 15...22 - +3 BASIC header data
Bytes 23...126 - Reserved (set to 0)
Byte 127 - Checksum (sum of bytes 0...126 modulo 256)

The issue and version numbers are provided for any future
expansion. The issue number must equal the software's issue
number; the version number must be less than or equal to the
software's version number.

+3DOS performs all the necessary header 'house-keeping'. A pointer


to +3 BASIC's 8 byte header area may be returned using DOS REF
HEAD. It is never necessary to write directly to the 128 byte
header.

AMSDOS headers (as used on the AMSTRAD CPC range of computers)


will not be recognised. AMSDOS files will be treated by +3DOS as
headerless, and vice versa.

Disk formats
+3DOS supports exactly the same disk format as CP/M Plus and
LocoScript on the AMSTRAD PCW range of computer/word processors
(ie. the first format listed below).

The following formats are automatically detected when the disk is


first accessed:

* AMSTRAD PCW range single track (eg. as used on model


PCW8256)
* AMSTRAD PCW range double track (eg. as used on model
PCW8512)
* AMSTRAD CPC range system format
* AMSTRAD CPC range vendor format
* AMSTRAD CPC range data only format

Note that the AMSTRAD CPC range's IBM format is not supported.
Other disk formats can be used by patching the XDPB for a drive.
The XDPB is the same as for the first format listed above; it is
not the same as on the CPC range.

Disk formats are subject to the following restrictions:

* 512 byte sector size


* Maximum of 255 sectors per track
* Maximum of 255 tracks
* Maximum of 256 directory entries
* Maximum of 360 allocation units

Logical tracks and sectors


The disk driver routines require 'logical' tracks and sectors.
These are used to hide information concerning the number of sides
and the actual sector numbers from +3DOS, which knows nothing
about them.

Logical track numbers on a single sided disk are the same as


physical track numbers.

For double sided disks, two options are available:

1. Alternating sides...

side 0 track 0 = logical track 0


side 1 track 0 = logical track 1
side 0 track 1 = logical track 2
side 1 track 1 = logical track 3
...to...
side 0 last track = logical track n-1
side 1 last track = logical track n

2. Successive sides...

side 0 track 0 = logical track 0


side 0 track 1 = logical track 1
side 0 track 2 = logical track 2
...to...
side 0 last track = logical track n/2-1
...and then...
side 1 last track -1 = logical track n/2
side 1 last track -2 = logical track n/2+1
side 1 last track -3 = logical track n/2+2
...to...
side 1 track 0 = logical track n

...where n is the total number of logical tracks (ie. 2 x number


of tracks per side).

Logical sectors hide the actual physical sector numbers. Logical


sector numbers always start from 0.
Logical sector = physical sector - first sector

Disk specification
The PCW range disk format (also used by the +3) is, in fact, a
family of formats the precise member of which is defined in the
'disk specification' which is recorded on bytes 0...15 of sector
1, track 0 side 0. The format used on the +3 (and supported by the
+2A) is the same as disk type 0 below. The sector holding this
specification is also that used for a bootstrap program. An
example of how it may be set up is shown in the second example in
part 26 of this chapter.

Byte 0 Disk type


0 = Standard PCW range DD SS ST (and +3)
1 = Standard CPC range DD SS ST system format
2 = Standard CPC range DD SS ST data only
format
3 = Standard PCW range DD DS DT
All other values reserved

Byte 1 Bits 0...1 Sidedness


0 = Single sided
1 = Double sided (alternating sides)
2 = Double sided (successive sides)
Bits 2...6 Reserved (set to 0)
Bit 7 Double track

Byte 2 Number of tracks per side

Byte 3 Number of sectors per track

Byte 4 Log2(sector size)-7

Byte 5 Number of reserved tracks

Byte 6 Log2 (block size/128)

Byte 7 Number of directory blocks

Byte 8 Gap length (read/write)

Byte 9 Gap length (format)


Bytes Reserved
10...14

Byte 15 Checksum (used only if disk is bootable)

When a disk is logged on, the disk specification is used to


initialise the relevant XDPB.

Extended disk parameter blocks (XDPB)


Associated with each (logical) drive is an extended disk parameter
block (XDPB). This contains a standard DPB which is the same as
that used by CP/M Plus. It also contains information required by
+3DOS to support the different formats. It may be patched in order
to use differently formatted disks provided that the restrictions
detailed in the previous table are obeyed).

XDPB structure:

Bytes 0...1 SPT records per track


Byte 2 BSH log(Base 2)(blocksize/128)
Byte 3 BLM block size/128-1
Byte 4 EXM extent mask
Bytes 5...6 DSM last block number
Bytes 7...8 DRM last directory entry number
Byte 9 AL0 directory bit map
Byte 10 AL1 directory bit map
Bytes 11...12 CKS size of checksum vector (bit 15 = permanent)
Bytes 13...14 OFF number of reserved tracks
Byte 15 PSH log2(sector size/128)

Byte 16 PHM sector size/128-1


Byte 17 Bits 0...1 Sidedness
0 = Single sided
1 = Double sided (alternating sides)
2 = Double sided (successive sides)
Bits 2...6 Reserved (set to 0)
Bit 7 Double track
Byte 18 Number of tracks per side
Byte 19 Number of sectors per track
Byte 20 First sector number
Bytes 21...22 Sector size
Byte 23 Gap length (read/write)
Byte 24 Gap length (format)
Byte 25 Bit 7 Multi-track operation
1 = multi-track
0 = single track
Bit 6 Modulation mode
1 = MFM mode
0 = FM mode
Bit 5 Skip deleted data address mark
1 = skip deleted data address mark
0 = don't skip deleted address mark
Bits 0...4 = 0
Byte 26 Freeze flag
00h(0) = auto-detect disk format
FFh(255) = don't auto-detect disk format

Byte 25 is normally set to 60h(96). Multi-track operation is not


recommended.

Setting the freeze flag (byte 26) prevents +3DOS from trying to
determine the format of a disk. This should be used when patching
an XDPB for a non-standard format.

The XDPBs for the three main formats are as follows:

AMSTRAD PCW range single track format (type


0) (As used by the +3, supported by the +2A)
36 SPT, records per track
3 BSH, block shift
7 BLM, block mask
0 EXM, extent mask
174 DSM, number of blocks-1
63 DRM, number of directory entries-1
C0h(192) AL0, 2 directory blocks
00h(0) AL1
16 CKS, size of checksum vector
1 OFF, reserved tracks
2 PSH, physical sector shift
3 PHM, physical sector mask

0 Single sided
40 Tracks per side
9 Sectors per track
1 First sector number
512 Sector size
42 Gap length (read/write)
82 Gap length (format)
60h(96) MFM mode, skip deleted data address mark
0 Do auto select format

AMSTRAD CPC range SYSTEM format (type 1)


36 SPT, records per track
3 BSH, block shift
7 BLM, block mask
0 EXM, extent mask
170 DSM, number of blocks-1
63 DRM, number of directory entries-1
C0h(192) AL0, 2 directory blocks
00h(0) AL1
16 CKS, size of checksum vector
2 OFF, reserved tracks
2 PSH, physical sector shift
3 PHM, physical sector mask

0 Single sided
40 Tracks per side
9 Sectors per track
41h(65) First sector number
512 Sector size
42 Gap length (read/write)
82 Gap length (format)
60h(96) MFM mode, skip deleted data address mark
0 Do auto select format
AMSTRAD CPC range DATA ONLY format (type 2)
36 SPT, records per track
3 BSH, block shift
7 BLM, block mask
0 EXM, extent mask
179 DSM, number of blocks -1
63 DRM, number of directory entries -1
C0h(192) AL0, 2 directory blocks
00h(0) AL1
16 CKS, size of checksum vector
0 OFF, reserved tracks
2 PSH, physical sector shift
3 PHM, physical sector mask

0 Single sided
40 Tracks per side
9 Sectors per track
C1h(193) First sector number
512 Sector size
42 Gap length (read/write)
82 Gap length (format)
60h(96) MFM mode, skip deleted data address mark
0 Do auto select format

CP/M File compatibility


+3DOS uses the CP/M file structure, subject to the following
restrictions:

* Maximum file size of 8 megabytes (CP/M Plus supports a


maximum of 32 megabytes).
* Maximum drive size of 8 megabytes (CP/M Plus supports a
maximum of 128 megabytes).
* Directory labels are ignored.
* No passwords. XFCBs will be erased, renamed, etc., along
with their file(s) but are otherwise ignored.
* No date and time stamps. SFCBs are initialised to zero
when a file is created, but are otherwise ignored.
* The archive file attribute is ignored, ie. it is
unaffected by all routines except DOS SET ATTRIBUTES.
File model
A file is an array of bytes which may be of any length from 0 to 8
megabytes. Associated with each open file is a 24 bit file
pointer. The file pointer is the address of the next byte to be
written or read. The file pointer is automatically advanced after
each read or write operation; however, the user may set it to any
value required for random access.

The end of file position (EOF) is the lowest byte position that is
greater than all written byte positions. Files without headers can
only record their EOF position to the start of the next 128 byte
record, ie. ceiling (EOF/128). Files with headers have their EOF
position recorded exactly.

Writing a byte after the EOF position will extend the file and
advance the EOF position.

Reading a byte at (or beyond) the EOF position will return an EOF
error.

Reading an unwritten byte below the EOF position will either


return a nonsensical byte or an EOF error. (Reading unwritten
bytes is not recommended.)

Changing disks
Under +3DOS, a disk may be changed or removed whenever the drive
is not being accessed (and there are no files open on that drive).
There is no need to log in a disk.

A disk should not be changed while there are files open on it. If,
however, a disk is changed while there are still files open on it,
then as soon as +3DOS detects this, the user will be prompted to
insert the correct disk. +3DOS can only detect this change when it
reads the directory from the disk.

Note that changing a disk while it is still being written to may


corrupt the data on the disk.

Logical to physical drive mapping


If required, two logical drives (A: and B:) can be mapped onto a
single physical drive (unit 0). This may be useful if you have
connected a single disk drive to the +2A.

To enable this mapping, the routine DOS MAP B is called, passing


to it the address of a routine CHANGE DISK. Whenever unit 0 is
accessed, a check is made to see if the disk in unit 0 is for the
required logical drive. If not, then CHANGE DISK is called. CHANGE
DISK is passed the address of a message and the required logical
drive, and the user should be prompted with the message...
Please put the disk for x: into
the drive then press any key

...(where x is the name of the logical drive, eg. A: or B:). The


routine should then wait for a key to be pressed before returning,
after which it is assumed that the disk in unit 0 is for the
required logical drive.

DOS MAP B can also be used to re-map B onto unit 1. If unit 1 does
not exist, then drive B: is disabled.

+3DOS Error codes


Many +3DOS routines can fail. This is indicated with 'carry' false
and an error code in the A register. The error codes are...

Recoverable disk errors:

0 Drive not ready


1 Disk is write protected
2 Seek fail
3 CRC data error
4 No data
5 Missing address mark
6 Unrecognised disk format
7 Unknown disk error
8 Disk changed whilst +3DOS was using it
9 Unsuitable media for drive

Non-recoverable errors:

20 Bad filename
21 Bad parameter
22 Drive not found
23 File not found
24 File already exists
25 End of file
26 Disk full
27 Directory full
28 Read-only file
29 File number not open (or open with wrong access)
30 Access denied (file in use already)
31 Cannot rename between drives
32 Extent missing (which should be there)
33 Uncached (software error)
34 File too big (trying to read or write past 8 megabytes)
35 Disk not bootable (boot sector is not acceptable to DOS
BOOT)
36 Drive in use (trying to re-map or remove a drive with
files open)

As an example, the report Unsuitable media for drive is caused by


trying to write to a single track disk in a double track drive, or
trying to read or write a double track disk in a single track
drive.

The report Missing address mark is the error returned when trying
to access a disk that is not formatted (although this is not the
sole reason for the error).

+3DOS Messages
If error messages are enabled (DOS SET MESSAGE) then, in the event
of a recoverable disk error, +3DOS will pass the ALERT routine a
message and the user should be prompted to - Retry, Ignore or
Cancel? If the user replies R, then the disk operation is retried.
If the reply is I, then the error is ignored, and if the reply is
C, then the operation is cancelled and an error condition is
returned to the caller. If error messages are disabled or if the
error is not recoverable, then no message is displayed and an
error condition is returned to the caller.

The recoverable disk errors (in the range 0...9) are:

0 Drive x: not ready


1 Drive x: disk write protected
2 Drive x: track ttt, seek fail
3 Drive x: track ttt, sector sss, data error
4 Drive x: track ttt, sector sss, no data
5 Drive x: track ttt, sector sss, missing address mark
6 Drive x: bad format
7 Drive x: track ttt, sector sss, unknown error
8 Drive x: disk changed, please replace
9 Drive x: disk unsuitable

...where x is the disk drive (eg. A: or B:), ttt is the track


number, and sss is the sector number.

The above messages are all followed by - Retry, Ignore or Cancel?


The ALERT routine is called to produce one of these messages if
the error occurs once +3DOS is committed to execute a DOS routine.
For example, if DOS OPEN is called (with access of exclusive write
or read/write) and the disk in the drive is write protected, then
it will return immediately with 'carry' clear and A=1 (the ALERT
routine will not be called).

If, however, while reading data during DOS READ, a bad sector is
found, ALERT will be called to warn the user. This will then offer
the opportunity of retrying (if, for example, the disk was not
properly seated in the drive), ignoring (so that the bad sector
will be ignored allowing as much of the file as possible to be
recovered), or cancelling (perhaps because the problem is
obviously irrecoverable).

(Note that the routine interface for DOS SET MESSAGE has changed
between versions V1.0 and V1.1 of +3DOS. It is important,
therefore, that DOS VERSION is called, and that if the version and
mark are greater than V1.0, the new routine interface is used.
This is the only change between V1.0 and V1.1, and will only be
apparent in non-UK machines.)

+3DOS requirements
When any of the +3DOS routines are called, the following store
configuration is required:

C000h...FFFFh (49152...65535) - Page 7


8000h...BFFFh (32768...49151) - Page 2
4000h...7FFFh (16384...32767) - Page 5
0000h...3FFFh (0...16383) - ROM 2

The stack must be below BFE0h (49120) and above 4000h (16384). The
upper value is BFE0h (rather than C000h) because the top 30 bytes
of page 2 are used to implement inter-page block moves. This area
is not reserved by +3DOS; it is merely required that the stack is
not there. The stack must have at least 50 words available.

+3DOS supports up to 16 files open at any time. Note, however,


that file numbers 0...2 are utilised by +3 BASIC, so it would be
unwise to use these if there is a chance that a +3 BASIC command
might be executed while a file is still open. File 0 will always
be closed when BASIC reports an error (even if the report is 0
OK).

For each of the routines described in this section, interrupts


must be enabled on entry, and will still be enabled on exit.
+3DOS Store usage
RAM pages 1, 3, 4, 6 are treated as an array of 128 sector
buffers, (numbered 0...127), each of 512 bytes long. The RAMdisk,
M: and the sector cache occupy two separate (contiguous) areas in
this array. Their sizes and locations are preset during
initialisation and can be subsequently reset. Any buffers not used
by the RAMdisk or cache are free for any other purpose. Changing
the size or location of the RAMdisk deletes all of its files.

All +3DOS routines will exit with the same memory configuration as
on entry.

The addresses of filenames, buffers, etc., passed to these


routines must be visible, ie. the RAM page in which they are
located must be switched in.

The DOS jump block is located in ROM 2 from address 0100h (256)
onwards. The address and interface for each routine are as
follows:

Essential filing system routines


DOS INITIALISE
0100h(256)
Initialise +3DOS.
Initialise disk drivers.
Initialise cache and RAMdisk.
All files closed.
All drives logged out.
Default drive A: (if disk interface present), else M:.
Default user 0.
Retry count 15.
Error messages disabled.

ENTRY CONDITIONS
None

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved
DOS VERSION
0103h(259)
Get the DOS issue and version numbers.

ENTRY CONDITIONS
None

EXIT CONDITIONS
D = Issue
E = Version (within issue)
Always:
AF BC HL IX corrupt
All other registers preserved

DOS OPEN
0106h(262)
Create and/or open a file.

There is a choice of action depending on whether or not the file


already exists. The choices are 'open action' or 'create action',
and are specified in DE. If the file already exists, then the open
action is followed; otherwise the create action is followed.

Open action

1. Error - File already exists.


2. Open the file, read the header (if any). Position file
pointer after header.
3. Open the file, ignore any header. Position file
pointer at 0000h(0).
4. Assume given filename is filename.type. Erase
filename.BAK (if it exists). Rename filename.type to
filename.BAK. Follow create action.
5. Erase existing version. Follow create action.

Create action

1. Error - File does not exist.


2. Create and open new file with a header. Position file
pointer after header.
3. Create and open new file without a header. Position file
pointer at 000000h(0).

(Example: To simulate the tape action of...'if the file exists


open it, otherwise create it with a header', set open action = 1,
create action = 1.)
(Example: To open a file and report an error if it does not exist,
set open action = 1, create action = 0.)

(Example: To create a new file with a header, first renaming any


existing version to .BAK, set open action = 3, create action = 1.)

Files with headers have their EOF position recorded as the


smallest byte position greater than all written byte positions.

Files without headers have their EOF position recorded as the byte
at the start of the smallest 128 byte record position greater than
all written record positions.

Soft-EOF is the character 1Ah(26) and is nothing to do with the


EOF position, only the routine DOS BYTE READ knows about soft-EOF.

The header data area is 8 bytes long and may be used by the caller
for any purpose whatsoever. If open action = 1, and the file
exists (and has a header), then the header data is read from the
file, otherwise the header data is zeroised. The header data is
available even if the file does not have a header. Call DOS REF
HEAD to access the header data.

Note that +3 BASIC makes use of the first 7 of these 8 bytes as


follows:

BYTE 0 1 2 3 4 5 6
Program 0 file length 8000h or LINE offset to prog
Numeric array 1 file length xxx name xxx xxx
Character array 2 file length xxx name xxx xxx
CODE or SCREEN$ 3 file length load address xxx xxx

(xxx = doesn't matter)

If creating a file that will subsequently be LOADed within BASIC,


then these bytes should be filled with the relevant values.

If the file is opened with exclusive-write or exclusive-read-write


access (and the file has a header), then the header is updated
when the file is closed.

A file that is already open for shared-read access on another file


number may only be opened for shared-read access on this file
number.

A file that is already open for exclusive-read or exclusive-write


or exclusive-read-write access on another file number may not be
opened on this file number.
ENTRY CONDITIONS
B = File number 0...15
C = Access mode required
Bits 0...2 values:
1 = exclusive-read
2 = exclusive-write
3 = exclusive-read-write
5 = shared-read
Bits 3...7 = 0 (reserved)
D = Create action
E = Open action
HL = Address of filename (no wildcards)

EXIT CONDITIONS
If file newly created:
Carry true
Zero true
A corrupt
If existing file opened:
Carry true
Zero false
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS CLOSE
0109h(265)
Close a file.

Write the header (if there is one).

Write any outstanding data.

Update the directory.

Release the file number.

All opened files must eventually be closed (or abandoned). A file


number cannot be reused until it is closed (or abandoned).

ENTRY CONDITIONS
B = File number
EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS ABANDON
010Ch(268)
Abandon a file.

Similar to DOS CLOSE, except that any header, or data, or


directory data yet to be written to disk is discarded. This
routine should only be used to force a file closed in the event
that DOS CLOSE is unable to close the file (for example, if the
media is damaged or permanently changed or removed).

ENTRY CONDITIONS
B = File number

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS REF HEAD


010Fh(271)
Point at the header data for this file.

The header data area is 8 bytes long and may be used by the caller
for any purpose whatsoever. It is available even if the file does
not have a header; however, only files with a header and opened
with write access will have the header data recorded on disk.

Note that +3 BASIC uses these 8 bytes (see the note under DOS OPEN
which gives the details). If creating a file that will
subsequently be LOADed within BASIC, then these bytes should be
filled with the relevant values.

ENTRY CONDITIONS
B = File number

EXIT CONDITIONS
If OK, but file doesn't have a header:
Carry true
Zero true
A corrupt
IX = Address of header data in page 7
If OK, file has a header:
Carry true
Zero false
A corrupt
IX = Address of header data in page 7
Otherwise:
Carry false
A = Error code
IX corrupt
Always:
BC DE HL corrupt
All other registers preserved

DOS READ
0112h(274)
Read bytes from a file into memory.

Advance the file pointer.

The destination buffer is in the following memory configuration:

C000h...FFFFh (49152...65535) - Page specified in C


8000h...BFFFh (32768...49151) - Page 2
4000h...7FFFh (16384...32767) - Page 5
0000h...3FFFh (0...16383) - DOS ROM

This routine does not consider soft-EOF.

Reading EOF will produce an error.

ENTRY CONDITIONS
B = File number
C = Page for C000h(49152)...FFFFh(65535)
DE = Number of bytes to read (0 means 64K)
HL = Address for bytes to be read

EXIT CONDITIONS
If OK:
Carry true
A DE corrupt
Otherwise:
Carry false
A = Error code
DE = Number of bytes remaining unread
Always:
BC HL IX corrupt
All other registers preserved

DOS WRITE
0115h(277)
Write bytes to a file from memory.

Advance the file pointer.

The source buffer is in the following memory configuration:

C000h...FFFFh (49152...65535) - Page specified in C


8000h...BFFFh (32768...49151) - Page 2
4000h...7FFFh (16384...32767) - Page 5
0000h...3FFFh (0...16383) - DOS ROM

ENTRY CONDITIONS
B = File number
C = Page for C000h(49152)...FFFFh(65535)
DE = Number of bytes to write (0 means 64K)
HL = Address of bytes to write

EXIT CONDITIONS
If OK:
Carry true
A DE corrupt
Otherwise:
Carry false
A = Error code
DE = Number of bytes remaining unwritten
Always:
BC HL IX corrupt
All other registers preserved
DOS BYTE READ
0118h(280)
Read a byte from a file.

Advance the file pointer.

Tests for soft-EOF (1Ah(26)). As this condition is not latched, it


is possible to read past soft-EOF.

EOF is latched.

The caller must decide whether or not soft-EOF is of interest.


This would normally be the case only when reading an ASCII file.

Reading EOF will produce an error.

ENTRY CONDITIONS
B = File number

EXIT CONDITIONS
If OK - Byte <> 1Ah(26)(soft-EOF):
Carry true
Zero false
A corrupt
C = Byte
If OK - Byte = 1Ah(26)(soft-EOF):
Carry true
Zero true
A corrupt
C = Byte
Otherwise:
Carry false
A = Error code
C corrupt
Always:
B DE HL IX corrupt
All other registers preserved

DOS BYTE WRITE


011Bh(283)
Write a byte to a file.

Advance the file pointer.


ENTRY CONDITIONS
B = File number
C = Byte to write

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS CATALOG
011Eh(286)
Fills a buffer with part of the directory (sorted).

The filename specifies the drive, user and a (possibly ambiguous)


filename.

Since the size of a directory is variable (and may be quite


large), this routine permits the directory to be catalogued in a
number of small sections. The caller passes a buffer pre-loaded
with the first required filename, or zeros for the start of the
directory. The buffer is loaded with part (or all, if it fits) of
the directory sorted in ASCII order. If more of the directory is
required, this routine is re-called with the buffer re-initialised
with the last file previously returned. This procedure is followed
repeatedly until all of the directory has been catalogued.

Note that +3DOS format disks (which are the same as single sided,
single track AMSTRAD PCW range format disks) may have a maximum of
64 directory entries.

Buffer format:

Entry 0
Entry 1
Entry 2
Entry 3
...to...
Entry n

Entry 0 must be preloaded with the first filename.type required.


Entry 1 will contain the first matching filename greater than the
preloaded entry (if any). A zeroised preload entry is OK.
If the buffer is too small for the directory, this routine can be
called again with entry 0 replaced by entry n to fetch the next
part of the directory.

Entry format (13 bytes long):

Bytes 0...7 - Filename (ASCII) left justified, space


filled
Bytes 8...10 - Type (ASCII) left justified, space filled
Bytes 11...12 - Size in kilobytes (binary)

The file size is the amount of disk space allocated to the file,
not necessarily the same as the amount used by the file.

ENTRY CONDITIONS
B = n + 1, Size of buffer in entries, > = 2
C = Filter
bit 0 = include system files (if set)
bits 1...7 = 0 (reserved)
DE = Address of buffer (first entry initialised)
HL = Address of filename (wildcards permitted)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
B = Number of completed entries in buffer, 0...n.
(If B = n, there may be more to come)
Otherwise:
Carry false
A = Error code
B corrupt
Always:
C DE HL IX corrupt
All other registers preserved

DOS FREE SPACE


0121h(289)
How much free space is there on this drive?

ENTRY CONDITIONS
A = Drive, ASCII 'A'...'P'
EXIT CONDITIONS
If OK:
Carry true
A corrupt
HL = Free space (in kilobytes)
Otherwise:
Carry false
A = Error code
HL corrupt
Always:
BC DE IX corrupt
All other registers preserved

DOS DELETE
0124h(292)
Delete an existing file.

File must not be open on any file number.

ENTRY CONDITIONS
HL = Address of filename (wildcards permitted)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS RENAME
0127h(295)
Rename an existing file.

File must not be open on any file number. A file with the new
filename must not exist. The new name must specify, or default to,
the same drive as the
old name.
ENTRY CONDITIONS
DE = Address of new filename (no wildcards)
HL = Address of old filename (no wildcards)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS BOOT
012Ah(298)
Boot from disk.

This routine loads a single bootstrap sector from the disk in


drive A: (if connected) into memory and enters it. This is for
loading games or other operating systems.

Bootstrap environment:

C000h...FFFFh (49152...65535) - Page 3


8000h...BFFFh (32768...49151) - Page 6
4000h...7FFFh (16384...32767) - Page 7
0000h...3FFFh (0...16383) - Page 4

The bootstrap sector is on side 0, track 0, sector 1. It is loaded


at FE00h(65024) and entered at FE10h(65040). Interrupts are
disabled, SP is at FE00h (65024). The sum of all bytes in the
sector must equal 3 MOD 256 (byte 15 can be set to the required
value to achieve this).

Bytes 0...15 of the sector hold the disk specification.

ENTRY CONDITIONS
None

EXIT CONDITIONS
If OK:
No exit (as the bootstrap will be entered)
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS SET DRIVE


012Dh(301)
Set the default drive (ie. the drive implied by all filenames that
do not specify a drive).

The default drive is initially M: (or A: if a floppy disk


interface is connected).

Does not access the drive, but merely checks that there is a
driver for it (which does not imply that the drive exists).

This only affects routines that take filename parameters.

ENTRY CONDITIONS
A = Drive,ASCII'A'...'P'(FFh(255) = get default drive)

EXIT CONDITIONS
If OK:
Carry true
A = Default drive
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS SET USER


0130h(304)
Set the default user area, ie. the user area implied by all
filenames that do not specify a user number.

The default user number is initially 0.

This only affects routines that take filename parameters.

ENTRY CONDITIONS
A = User 0...15(FFh(255) = get default user)
EXIT CONDITIONS
If OK:
Carry true
A = Default user
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

Additional routines for games and operating


systems
DOS GET POSITION
0133h(307)
Get the file pointer.

ENTRY CONDITIONS
B = File number

EXIT CONDITIONS
If OK:
Carry true
A corrupt
E HL = File pointer 000000h...FFFFFFh(0...16777215)
(E holds most significant byte; L holds least
significant byte)
Otherwise:
Carry false
A = Error code
E HL corrupt
Always:
BC D IX corrupt
All other registers preserved

DOS SET POSITION


0136h(310)
Set the file pointer.

Does not access the disk.

Does not check (or care) if pointer is > = 8 megabytes.


ENTRY CONDITIONS
B = File number
E HL = File pointer 000000h...FFFFFFh (0...16777215)
(E holds most significant byte; L holds least significant
byte)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS GET EOF


0139h(313)
Get the end of file (EOF) file position, ie. the lowest byte
position greater than all written byte positions.

Does not affect the file pointer.

Does not consider soft-EOF.

ENTRY CONDITIONS
B = File number

EXIT CONDITIONS
If OK:
Carry true
A corrupt
E HL = File pointer 000000h...FFFFFFh(0...16777215)
(E holds most significant byte, L holds least
significant byte)
Otherwise:
Carry false
A = Error code
E HL corrupt
Always:
BC D IX corrupt
All other registers preserved
DOS GET 1346
013Ch(316)
Get the current location of the cache and RAMdisk.

Pages 1, 3, 4, 6 are considered as an array of 128 sector buffers


(numbered 0...127), each of 512 bytes. The cache and RAMdisk
occupy two separate (contiguous) areas of this array.

Any unused sector buffers may be used by the caller.

Note that the sizes may be smaller than those specified in DOS SET
1346, as there is an (unpublished) maximum size of cache and a
minimum size of RAMdisk (4 sectors).

ENTRY CONDITIONS
None

EXIT CONDITIONS
D = First buffer for cache
E = Number of cache sector buffers
H = First buffer for RAMdisk
L = Number of RAMdisk sector buffers
Always:
AF BC IX corrupt
All other registers preserved

DOS SET 1346


013Fh(319)
Rebuild the sector cache and RAMdisk.

This routine is used to make some store available to the user, or


to return store to DOS.

Note that if the RAMdisk is moved, or its size is changed, then


all files thereon are erased.

Pages 1, 3, 4, 6 are considered as an array of 128 sector buffers


(numbered 0...127), each of 512 bytes. The cache and RAMdisk
occupy two separate (contiguous) areas of this array.

The location and size of the cache and RAMdisk can be specified
separately; any remaining buffers are unused by DOS and are
available to the caller.

The cache and RAMdisk must not overlap. +3DOS does not check this;
responsibility lies with the caller.
Note that the sizes actually used may be smaller than those
specified as in practice, there is a maximum cache size and a
minimum size of RAMdisk (4 sectors).

A cache size of 0 will still work but will seriously impair the
floppy disk performance.

This routine will fail if there are any files open on drive M:.

ENTRY CONDITIONS
D = First buffer for cache
E = Number of cache sector buffers
H = First buffer for RAMdisk
L = Number of RAMdisk sector buffers
(Note that E + L < = 128)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS FLUSH
0142h(322)
Write any pending headers, data, directory entries for this drive.

This routine ensures that the disk is up to date. It can be called


at any time, even when files are open.

ENTRY CONDITIONS
A = Drive,ASCII'A'...'P'

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS SET ACCESS


0145h(325)
Try to change the access mode of an open file.

This routine will fail if the file is already open, in an


incompatible access mode, or if write access is required for a
read-only file or disk.

ENTRY CONDITIONS
B = File number
C = Access mode required
Bits 0...2 values:
1 = exclusive-read
2 = exclusive-write
3 = exclusive-read-write
5 = shared-read
(all other bit settings reserved)
Bits 3...7 = 0 (reserved)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS SET ATTRIBUTES


0148h(328)
Set a file's attributes.

Only the file attributes f1'...f4', t1'...t4' can be set or


cleared. The interface attributes f5'...f8' are always 0.

This routine first sets the attributes specified in D, then clears


those attributes specified in E, ie. E has priority.
ENTRY CONDITIONS
D = Attributes to set:
bit 0 = t3' Archive
bit 1 = t2' System
bit 2 = t1' Read-only
bit 3 = f4'
bit 4 = f3'
bit 5 = f2'
bit 6 = f1
E = Attributes to clear:
bit 0 = t3' Archive
bit 1 = t2' System
bit 2 = t1' Read-only
bit 3 = f4'
bit 4 = f3'
bit 5 = f2'
bit 6 = f1'
HL = Address of filename (wildcards permitted)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DOS OPEN DRIVE


014Bh(331)
Open the disk in this drive as a single file.

The whole disk is presented as a single file regardless of any


real files on the disk. This routine can be used to examine/poke
directories, files, etc. It should not be used by the uninitiated,
the faint hearted or by anyone who values their files!

Sets file pointer to 000000h (0).

If there are any files open on this drive from other file numbers
with shared-read access, then the disk can only be opened with
shared-read access from this file number.

If there are any files open on this drive from other file numbers
with exclusive access, then the disk cannot be opened from this
file number.
ENTRY CONDITIONS
A = Drive, ASCII'A'...'P'
B = File number
C = Access mode required
Bits 0...2 values:
1 = exclusive-read
2 = exclusive-write
3 = exclusive-read-write
5 = shared-read
(all other bit settings reserved)
Bits 3...7 = 0(reserved)

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL corrupt
All other registers preserved

DOS SET MESSAGE


014Eh(334)
Enable/disable disk error messages.

This should be used to make +3DOS aware of your own ALERT


subroutine. When +3DOS detects an error, it will call your ALERT
subroutine, passing to it the values documented below. The ALERT
subroutine should print the text of the message that +3DOS passes
it, then should wait for the user to press a key. If the key is in
the reply string (that +3DOS also passes - version V1.0 only),
then a ret should be made with A = 0, 1 or 2, or containing the
character (depending on the version of +3DOS).

ENTRY CONDITIONS
A = Enable/disable
FFh(255) = enable
00h(0) = disable
HL = Address of ALERT routine (if enabled)

EXIT CONDITIONS
HL = address of previous ALERT routine (0 if none)
Always:
AF BC DE IX corrupt
All other registers preserved

NOTE
Note that if you are substituting your own ALERT subroutine, the
'entry conditions' are the conditions passed to your subroutine
and the 'exit conditions' are the values that your subroutine must
produce and the registers you are allowed to corrupt.

Note that there are two routine interfaces for ALERT. The first,
(which is used in machines with +3DOS version V1.0) should have
the entry and exit conditions shown ahead.

ALERT (VERSION V1.0 ONLY)

ENTRY CONDITIONS
DE = Address of reply string (in page 7) terminated by
FFh (255)
HL = Address of error message (in page 7) terminated by
FFh (255)

EXIT CONDITIONS
A = Reply character
Always:
F BC DE HL IX corrupt
All other registers preserved

The second version of ALERT, which allows the user to provide non-
UK error messages and is generally more flexible, is present in
+3DOS versions V1.1 and upwards.

ALERT (VERSION V1.1 AND ABOVE)

ENTRY CONDITIONS
B = Error number
C = Drive,ASCII'A'...'P'
D = Logical track (if required for message)
E = Logical sector (if required for message)
HL = Address of UK error message (page 7) terminated by
FFh (255)

EXIT CONDITIONS
A = Reply
0 = cancel
1 = retry
2 = ignore
Always:
F BC DE HL IX corrupt
All other registers preserved

If you provide an ALERT function, you should have two


subroutines (or one with switchable entry and exit
conditions), and check the +3DOS version number before
deciding which one to use.

DOS REF XDPB


0151h(337)
Point at the XDPB for this drive. (The XDPB is required by the
floppy disk driver routines.)

ENTRY CONDITIONS
A = Drive,ASCII'A'...'P'

EXIT CONDITIONS
If OK:
Carry true
A corrupt
IX = Address of XDPB
Otherwise:
Carry false
A = Error code
IX corrupt
Always:
BC DE HL corrupt
All other registers preserved

DOS MAP B
0154h(340)
Map drive B: to unit 0 or unit 1. (This routine will fail if drive
B: has files open.)

If mapping B: to unit 0, then each time unit 0 is accessed, a


check is made that the drive mapping is correct. If it isn't, then
a reverse call to CHANGE DISK is made, to ask the user to change
the disk in unit 0.

If mapping B: to unit 1, then if unit 1 does not exist, drive B:


is disabled.
ENTRY CONDITIONS
C = Unit (0/1)
HL = Address of CHANGE DISK routine if unit = 0

EXIT CONDITIONS
If OK:
Carry true
A corrupt
HL = Address of previous CHANGE DISK routine (0 if
none)
Otherwise:
Carry false
A HL corrupt
Always:
BC DE IX corrupt
All other registers preserved

NOTE
The definition of the subroutine CHANGE DISK is as shown
ahead. Note that if you are substituting your own CHANGE DISK
subroutine, the 'entry conditions' are the conditions passed
to your subroutine, and the 'exit conditions' are registers
you are allowed to corrupt.

CHANGE DISK
Ask the user to change the disk in unit 0.

Wait for the user to acknowledge the change.

ENTRY CONDITIONS
A = Logical drive, ASCII'A'...'P'
HL = Address of message (page 7) terminated by FFh (255)

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved

Low level floppy disk driving routines


The following are the floppy disk driver routines. The unit number
is 0...3 for the μPD765A. Unit 0 is drive A: and unit 1 is drive
B:, or optionally, both A: and B: may be mapped onto unit 0. Units
2 and 3 are not used.
If you have not connected a disk drive (and interface) to the +2A
it is important to note that (with the exception of DD INTERFACE),
none of the following routines may be called.

All routines assume that interrupts are enabled on entry, and will
still be enabled on exit.

DD INTERFACE
0157h(343)
Is the floppy disk drive interface present? (This information is
also held by BASIC in bit 4 of the FLAGS3 system variable.)

ENTRY CONDITIONS
None

EXIT CONDITIONS
If present:
Carry true
Otherwise:
Carry false
Always:
A BC DE HL IX corrupt
All other registers preserved

DD INIT
015Ah(346)
Initialise the disk driver.

ENTRY CONDITIONS
None

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved

DD SETUP
015Dh(349)
Set up disk parameters.

Send a specify command.


Parameter block format:

Byte 0 - Motor on time (in 100 mS units)


Byte 1 - Motor off time (in 100 mS units)
Byte 2 - Write off time (in 10 μS units)
Byte 3 - Head settle time (in mS units)
Byte 4 - Step rate (in mS units)
Byte 5 - Head unload time (in 32 mS units, 32...480)
Byte 6 - (Head load time x2) + 1, (in 4 mS units, 4...508)

ENTRY CONDITIONS
HL = Address of parameter block

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved

DD SET RETRY
0160h(352)
Set the try and retry count. (A value of 1 will try the operation
once, ie. no retry.)

ENTRY CONDITIONS
A = Try/retry count > = 1

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved

DD READ SECTOR
0163h(355)
Read a sector.

ENTRY CONDITIONS
B = Page for C000h(491S2)...FFFFh(65535)
C = Unit (0/1)
D = Logical track, 0 base
E = Logical sector, 0 base
HL = Address of buffer
IX = Address of XDPB
EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DD WRITE SECTOR
0166h(358)
Write a sector.

ENTRY CONDITIONS
B = Page for C000h(49152)...FFFFh(65535)
C = Unit (0/1)
D = Logical track, 0 base
E = Logical sector, 0 base
HL = Address of buffer
IX = Address of XDPB

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DD CHECK SECTOR
0169h(361)
Check a sector. (Uses the μPD765A scan equal command.)

Checks that the sector on disk is the same as the copy in memory.

Note that FFh(255) on disk or in memory always matches anything


(see μPD765A specification for further details).
ENTRY CONDITIONS
B = Page for C000h(49152)...FFFFh(65535)
C = Unit (0/1)
D = Logical track, 0 base
E = Logical sector, 0 base
HL = Address of copy of sector
IX = Address of XDPB

EXIT CONDITIONS
If OK (equal):
Carry true
Zero true
A corrupt
If OK (not equal):
Carry true
Zero false
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DD FORMAT
016Ch(364)
Format a track. (Uses the μPD765A format track command.)

Buffer contains 4 bytes for each sector as follows:

C - Track number (0...39)


H - Head number (always 0 on the single sided drives
supported by +3DOS)
R - Sector number (0...255)
N - Log2(sector size)-7 (2 for 512 byte sectors)

ENTRY CONDITIONS
B = Page for C000h(49152)...FFFFh(65535)
C = Unit (0/1)
D = Logical track, 0 base
E = Filler byte, usually E5h(229)
HL = Address of format buffer
IX = Address of XDPB
EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DD READ ID
016Fh(367)
Read a sector identifier.

ENTRY CONDITIONS
C = Unit (0/1)
D = Logical track, 0 base
IX = Address of XDPB

EXIT CONDITIONS
If OK:
Carry true
A = Sector number from identifier
Otherwise:
Carry false
A = Error code
Always:
HL = Address of result buffer in page 7
BC DE IX corrupt
All other registers preserved

DD TEST UNSUITABLE
0172h(370)
Check that disk is suitable to write to.

A single track disk will not work in a double track drive, and
vice versa.

ENTRY CONDITIONS
C = Unit (0/1)
IX = Address of XDPB
EXIT CONDITIONS
If suitable:
Carry true
A corrupt
Otherwise:
Carry false
A = Error code
Always:
BC DE HL IX corrupt
All other registers preserved

DD LOGIN
0175h(373)
Log in a new disk.

Initialise the XDPB.

This routine does not affect or consider the freeze flag.

ENTRY CONDITIONS
C = Unit (0/1)
IX = Address of destination XDPB

EXIT CONDITIONS
If OK:
Carry true
A = Disk type
DE = Size of allocation vector
HL = Size of hash table
Otherwise:
Carry false
A = Error code
DE HL corrupt
Always:
BC IX corrupt
All other registers preserved

DD SEL FORMAT
0178h(376)
Initialise an XDPB for a standard format.

This routine does not affect or consider the freeze flag.


ENTRY CONDITIONS
A = Disk type
0 = Spectrum +3 format (AMSTRAD PCW range – DD SS ST)
1 = AMSTRAD CPC range system format
2 = AMSTRAD CPC range data-only format
3 = AMSTRAD PCW range - DD DS DT
(other values = error)
IX = Address of XDPB

EXIT CONDITIONS
If OK:
Carry true
A = Disk type
DE = Size of 2 bit allocation vector
HL = Size of hash table
Otherwise:
Carry false
A = Error code
DE HL corrupt
Always:
BC IX corrupt
All other registers preserved

DD ASK 1
017Bh(379)
Check to see if unit 1 is present. (BASIC holds this information
in bit 5 of the FLAGS3 system variable.)

Turn motor on.

Fetch drive status.

If unit 1 is not-ready and write-protected, then unit 1 is


missing. Start motor off timeout.

Note that this routine can be fooled by disks which are almost,
but not quite, inserted in the drive.

This routine assumes that when a disk is not in the drive, then
write-protect is true. This is indeed the case for 3 inch and 8
inch disk drives, but is not the case for 5¼ inch disk drives.

ENTRY CONDITIONS
None
EXIT CONDITIONS
If unit 1 present:
Carry true
Otherwise:
Carry false
Always:
A BC DE HL IX corrupt
All other registers preserved

DD DRIVE STATUS
017Eh(382)
Issue a sense drive status command.

ENTRY CONDITIONS
C = Unit/head
bits 0...1 = unit
bit 2 = head
bits 3...7 = 0

EXIT CONDITIONS
A = ST3 (Status register 3 of μPD765A)
Always:
F BC DE HL IX corrupt
All other registers preserved

DD EQUIPMENT
0181h(385)
Ask what type of drive this is (ie. single/double track,
single/double sided).

Track information can only be determined once a disk has been seen
and had its type identified during logging in.

Side information can only be detected after a double sided disk


has been seen and had its type identified during logging in.

ENTRY CONDITIONS
C = Unit (0/1)
IX = Address of XDPB

EXIT CONDITIONS
A = Side/track information
bits 0...1 = side information
0 = unknown
1 = single sided
2 = double sided
bits 2...3 = track information
0 = unknown
1 = single track
2 = double track
Always:
F BC DE HL IX corrupt
All other registers preserved

DD ENCODE
0184h(388)
Set the copy protection ENCODE subroutine.

Copy protected disks have some of their track and sector numbers
encoded on disk. Before each disk access, the ENCODE subroutine is
called to encode the physical track and sector numbers.

These encoded track and sector numbers must match those in the
sector identifier.

Note that tracks 0...2 on either side of a disk should not be


encoded.

ENTRY CONDITIONS
A = Enable/disable
00h(0) = disable
FFh(255) = enable
HL = (If enabled) address of ENCODE subroutine

EXIT CONDITIONS
HL = Address of previous ENCODE subroutine (0 if none)
Always:
AF BC DE IX corrupt
All other registers preserved

NOTE
The definition of the subroutine ENCODE is as shown ahead. Note
that if you are substituting your own ENCODE subroutine, the
'entry conditions' are the conditions passed to your subroutine,
and the 'exit conditions' are the values that your subroutine must
produce and the registers you are allowed to corrupt.
ENCODE
ENTRY CONDITIONS
C = Unit/side
bits 0...1 = unit
bit 2 = side
bits 3...7 = 0
D = Physical track
E = Physical sector
IX = Address of DPB

EXIT CONDITIONS
D = Encoded physical track
E = Encoded physical sector
Always:
AF corrupt
All other registers preserved

DD L XDPB
0187h(391)
Initialise an XDPB for a given format.

This routine does not affect or consider the freeze flag.

ENTRY CONDITIONS
IX = Address of destination XDPB
HL = Address of source disk specification

EXIT CONDITIONS
If OK:
Carry true
A = Disk type recorded on disk
DE = Size of allocation vector
HL = Size of hash table
If bad format:
Carry false
A = Error code
DE HL corrupt
Always:
BC IX corrupt
All other registers preserved
DD L DPB
018Ah(394)
Initialise a DPB for a given format.

This routine does not affect or consider the freeze flag.

ENTRY CONDITIONS
IX = Address of destination DPB
HL = Address of source disk specification

EXIT CONDITIONS
If OK:
Carry true
A = Disk type recorded on disk
DE = Size of allocation vector
HL = Size of hash table
If bad format:
Carry false
A = Error report
DE HL corrupt
Always:
BC IX corrupt
All other registers preserved

DD L SEEK
018Dh(397)
Seek to required track.

Retry if fails.

ENTRY CONDITIONS
C = Unit/head
bits 0...l = unit
bit 2 = head
bits 3...7 = 0
D = Track
IX = Address of XDPB

EXIT CONDITIONS
If OK:
Carry true
A corrupt
Otherwise:
Carry false
A = Error report
Always:
BC DE HL IX corrupt
All other registers preserved

DD L READ
0190h(400)
Low level μPD765A read command.

Read data.

Read deleted data.

Read a track.

Parameter block format:

Byte 0 - Page for C000h(49152)...FFFFh(65535)


Bytes 1...2 - Address of buffer
Bytes 3...4 - Number of bytes to transfer
Byte 5 - Number of command bytes
Bytes 6... - Command bytes

Writes commands.

Reads data.

Reads results.

Motor must be running.

ENTRY CONDITIONS
HL = Address of parameter block

EXIT CONDITIONS
HL = Address of result buffer in page 7
Always:
AF BC DE IX corrupt
All other registers preserved

DD L WRITE
0193h(403)
Low level μPD765A write command.

Write data.

Write deleted data.


Format a track.

Scan equal.

Scan low or equal.

Scan high or equal.

Parameter block format:

Byte 0 - Page for C000h(49152)...FFFFh(65535)


Bytes 1...2 - Address of buffer
Bytes 3...4 - Number of bytes to transfer
Byte 5 - Number of command bytes
Bytes 6... - Command bytes

Writes commands.

Writes data.

Reads results.

Motor must be running.

ENTRY CONDITIONS
HL = Address of parameter block

EXIT CONDITIONS
HL = Address of result buffer in page 7
Always:
AF BC DE IX corrupt
All other registers preserved

DD L ON MOTOR
0196h(406)
Turn on the motor.

Wait for the motor on time as set by DD SETUP.

ENTRY CONDITIONS
None

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved
DD L T OFF MOTOR
0199h(409)
Start the motor off time-out.

ENTRY CONDITIONS
None

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved

DD L OFF MOTOR
019Ch(412)
Turn off the motor.

ENTRY CONDITIONS
None

EXIT CONDITIONS
Always:
AF BC DE HL IX corrupt
All other registers preserved
Part 28
Spectrum character set
Subjects covered...

Control codes
Characters
Z80 assembler mnemonics

This is the complete Spectrum character set, with codes in decimal


and hex. If one imagines the codes as being Z80 machine code
instructions, then the right hand columns give the corresponding
assembly language mnemonics. As you may be aware, certain Z80
instructions are 'compounds' starting with CBh or EDh; these are
shown in the two right hand columns. Where a character changes
between 48K and +2A (128K) modes, the 48K version is given in
brackets after the +2A one.

CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

0 00 nop cb
1 01 ld bc,NN rlc c
2 02 ld(bc),a rlc d
not used
3 03 inc bc rlc e
4 04 inc b rlc h
5 05 dec b rlc l
6 PRINT comma 06 ld b,N rlc (hl)
7 EDIT 07 rlca rlc a
8 cursor left ← 08 ex af,af rrc b
9 cursor right → 09 add hl,bc rrc c
10 cursor down ↓ 0A ld a,(bc) rrc d
11 cursor up ↑ 0B dec bc rrc e
12 DELETE 0C inc c rrc h
13 ENTER 0D dec c rrc l
14 number 0E ld c,N rrc (hl)
15 not used 0F rrca rrc a
16 INK control 10 djnz DIS rl b
17 PAPER control 11 ld de,NN rl c
18 FLASH control 12 ld (de),a rl d
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

19 BRIGHT control 13 inc de rl e


20 INVERSE control 14 inc d rl h
21 OVER control 15 dec d rl l
22 AT control 16 ld d,N rl (hl)
23 TAB control 17 rla rl a
24 18 jr DIS rr b
25 19 add hl,de rr c
26 1A ld a,(de) rr d
27 1B dec de rr e
not used
28 1C inc e rr h
29 1D dec e rr l
30 1E ld e,N rr (hl)
31 1F rra rr a
32 space 20 jr nz,DIS sla b
33 ! 21 ld hl,NN sla c
34 “ 22 ld (NN),hl sla d
35 # 23 inc hl sla e
36 $ 24 inc h sla h
37 % 25 dec h sla l
38 & 26 ld h,N sla (hl)
39 ' 27 daa sla a
40 ( 28 jr z,DIS sra b
41 ) 29 add hl,hl sra c
42 * 2A ld hl,(NN) sra d
43 + 2B dec hl sra e
44 , 2C inc l sra h
45 - 2D dec l sra l
46 . 2E ld l,N sra (hl)
47 / 2F cpl sra a
48 0 30 jr nc,DIS
49 1 31 ld sp,NN
50 2 32 ld (NN),a
51 3 33 inc sp
52 4 34 inc (hl)
53 5 35 dec (hl)
54 6 36 ld (hl),N
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

55 7 37 scf
56 8 38 jr c,DIS srl b
57 9 39 add hl,sp srl c
58 : 3A ld a,(NN) srl d
59 ; 3B dec sp srl e
60 < 3C inc a srl h
61 = 3D dec a srl l
62 > 3E ld a,N srl (hl)
63 ? 3F ccf srl a
64 @ 40 ld b,b bit 0,b in b,(c)
65 A 41 ld b,c bit 0,c out (c),b
66 B 42 ld b,d bit 0,d sbc hl,bc
67 C 43 ld b,e bit 0,e ld (NN),bc
68 D 44 ld b,h bit 0,h neg
69 E 45 ld b,l bit 0,l retn
70 F 46 ld b,(hl) bit 0,(hl) im 0
71 G 47 ld b,a bit 0,a ld i,a
72 H 48 ld c,b bit 1,b in c,(c)
73 I 49 ld c,c bit 1,c out c,(c)
74 J 4A ld c,d bit 1,d adc hl,bc
75 K 4B ld c,e bit 1,e ld bc,(NN)
76 L 4C ld c,h bit 1,h
77 M 4D ld c,l bit 1,l reti
78 N 4E ld c,(hl) bit 1,(hl)
79 O 4F ld c,a bit 1,a ld r,a
80 P 50 ld d,b bit 2,b in d,(c)
81 Q 51 ld d,c bit 2,c out (c),d
82 R 52 ld d,d bit 2,d sbc hl,de
83 S 53 ld d,e bit 2,e ld(NN),de
84 T 54 ld d,h bit 2,h
85 U 55 ld d,l bit 2,l
86 V 56 ld d,(hl) bit 2,(hl) im l
87 W 57 ld d,a bit 2,a ld a,i
88 X 58 ld e,b bit 3,b in e,(c)
89 Y 59 ld e,c bit 3,c out (c),e
90 Z 5A ld e,d bit 3,d adc hl,de
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

91 [ 5B ld e,e bit 3,e ld de,(NN)


92 \ 5C ld e,h bit 3,h
93 ] 5D ld e,l bit 3,l
94 ↑ 5E ld e,(hl) bit 3,(hl) im 2
95 _ 5F ld e,a bit 3,a ld a,r
96 £ 60 ld h,b bit 4,b in h,(c)
97 a 61 ld h,c bit 4,c out (c),h
98 b 62 ld h,d bit 4,d sbc hl,hl
99 c 63 ld h,e bit 4,e ld (NN),hl
100 d 64 ld h,h bit 4,h
101 e 65 ld h,l bit 4,l
102 f 66 ld h,(hl) bit 4,(hl)
103 g 67 ld h,a bit 4,a rrd
104 h 68 ld l,b bit 5,b in l,(c)
105 i 69 ld l,c bit 5,c out(C),l
106 j 6A ld l,d bit 5,d adc hl,hl
107 k 6B ld l,e bit 5,e ld hl,(NN)
108 l 6C ld l,h bit 5,h
109 m 6D ld l,l bit 5,l
110 n 6E ld l,(hl) bit 5,(hl)
111 o 6F ld l,a bit 5,a rld
112 p 70 ld (hl),b bit 6,b in f,(c)
113 q 71 ld (hl),c bit 6,c
114 r 72 ld (hl),d bit 6,d sbc hl,sp
115 s 73 ld (hl),e bit 6,e ld (NN),sp
116 t 74 ld (hl),h bit 6,h
117 u 75 ld (hl),l bit 6,l
118 v 76 halt bit 6,(hl)
119 w 77 ld (hl),a bit 6,a
120 x 78 ld a,b bit 7,b in a,(c)
121 y 79 ld a,c bit 7,c out(c),a
122 z 7A ld a,d bit 7,d adc hl,sp
123 { 7B ld a,e bit 7,e ld sp, (NN)
124 | 7C ld a,h bit 7,h
125 } 7D ld a,l bit 7,l
126 ~ 7E ld a,(hl) bit 7,(hl)
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

127 © 7F ld a,a bit 7,a


128 □ 80 add a,b res 0,b
129 81 add a,c res 0,c
130 82 add a,d res 0,d
131 83 add a,e res 0,e
132 84 add a,h res 0,h
133 85 add a,l res 0,l
134 86 add a,(hl) res 0,(hl)
135 87 add a,a res 0,a
136 88 adc a,b res 1,b
137 89 adc a,c res 1,c
138 8A adc a,d res 1,d
139 8B adc a,e res 1,e
140 8C adc a,h res 1,h
141 8D adc a,l res 1,l
142 8E adc a,(hl) res 1,(hl)
143 ■ 8F adc a,a res 1,a
144 (a) 90 sub b res 2,b
145 (b) 91 sub c res 2,c
146 (c) 92 sub d res 2,d
147 (d) 93 sub e res 2,e
148 (e) 94 sub h res 2,h
149 (f) 95 sub l res 2,l
150 (g) 96 sub (hl) res 2,(hl)
151 (h) 97 sub a res 2,a
152 (i) 98 sbc a,b res 3,b
153 (j) 99 sbc a,c res 3,c
154 (k) user 9A sbc a,d res 3,d
graphics
155 (l) 9B sbc a,e res 3,e
156 (m) 9C sbc a,h res 3,h
157 (n) 9D sbc a,l res 3,l
158 (o) 9E sbc a,(hl) res 3,(hl)
159 (p) 9F sbc a,a res 3,a
160 (q) A0 and b res 4,b ldi
161 (r) A1 and c res 4,c cpi
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

162 (s) A2 and d res 4,d ini


163 SPECTRUM (t) A3 and e res 4,e outi
164 PLAY (u) A4 and h res 4,h
165 RND A5 and l res 4,l
166 INKEY$ A6 and (hl) res 4,(hl)
167 PI A7 and a res 4,a
168 FN A8 xor b res 5,b ldd
169 POINT A9 xor c res 5,c cpd
170 SCREEN$ AA xor d res 5,d ind
171 ATTR AB xor e res 5,e outd
172 AT AC xor h res 5,h
173 TAB AD xor l res 5,l
174 VAL$ AE xor (hl) res 5,(hl)
175 CODE AF xor a res 5,a
176 VAL B0 or b res 6,b ldir
177 LEN B1 or c res 6,c cpir
178 SIN B2 or d res 6,d inir
179 COS B3 or e res 6,e otir
180 TAN B4 or h res 6,h
181 ASN B5 or l res 6,l
182 ACS B6 or (hl) res 6,(hl)
183 ATN B7 or a res 6,a
184 LN B8 cp b res 7,b lddr
185 EXP B9 cp c res 7,c cpdr
185 INT BA cp d res 7,d indr
187 SQR BB cp e res 7,e otdr
188 SGN BC cp h res 7,h
189 ABS BD cp l res 7,l
190 PEEK BE cp (hl) res 7,(hl)
191 IN BF cp a res 7,a
192 USR C0 ret nz set 0,b
193 STR$ C1 pop bc set 0,c
194 CHR$ C2 jp nz,NN set 0,d
195 NOT C3 jp NN set 0,e
196 BIN C4 call nz,NN set 0,h
197 OR C5 push bc set 0,l
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

198 AND C6 add a,N set 0,(hl)


199 <= C7 rst 0 set 0,a
200 >= C8 ret z set 1,b
201 <> C9 ret set 1,c
202 LINE CA jp z,NN set 1,d
203 THEN CB set 1,e
204 TO CC call z,NN set 1,h
205 STEP CD call NN set 1,l
206 DEF FN CE adc a,N set 1,(hl)
207 CAT CF rst 8 set 1,a
208 FORMAT D0 ret nc set 2,b
209 MOVE D1 pop de set 2,c
210 ERASE D2 jp nc,NN set 2,d
211 OPEN # D3 out (N),a set 2,e
212 CLOSE # D4 call nc,NN set 2,h
213 MERGE D5 push de set 2,l
214 VERIFY D6 sub N set 2,(hl)
215 BEEP D7 rst 16 set 2,a
216 CIRCLE D8 ret c set 3,b
217 INK D9 exx set 3,c
218 PAPER DA jp c,NN set 3,d
219 FLASH DB in a,(N) set 3,e
220 BRIGHT DC call c,NN set 3,h
221 INVERSE DD prefixes set 3,l
instructions
using ix
222 OVER DE sbc a,N set 3,(hl)
223 OUT DF rst 24 set 3,a
224 LPRINT E0 ret po set 4,b
225 LLIST E1 pop hl set 4,c
226 STOP E2 jp po,NN set 4,d
227 READ E3 ex(sp),hl set 4,e
228 DATA E4 call po,NN set 4,h
229 RESTORE E5 push hl set 4,l
230 NEW E6 and N set 4,(hl)
231 BORDER E7 rst 32 set 4,a
CODE CHARACTER HEX Z80 Assembler -AFTER CBh -AFTER EDh

232 CONTINUE E8 ret pe set 5,b


233 DIM E9 jp (hl) set 5,c
234 REM EA jp pe,NN set 5,d
235 FOR EB ex de,hl set 5,e
236 GO TO EC call pe,NN set 5,h
237 GO SUB ED set 5,l
238 INPUT EE xor N set 5,(hl)
239 LOAD EF rst 40 set 5,a
240 LIST F0 ret p set 6,b
241 LET F1 pop af set 6,c
242 PAUSE F2 jp p,NN set 6,d
243 NEXT F3 di set 6,e
244 POKE F4 call p,NN set 6,h
245 PRINT F5 push af set 6,l
246 PLOT F6 or N set 6,(hl)
247 RUN F7 rst 48 set 6,a
248 SAVE F8 ret m set 7,b
249 RANDOMIZE F9 ld sp,hl set 7,c
250 IF FA jp m,NN set 7,d
251 CLS FB ei set 7,e
252 DRAW FC call m,NN set 7,h
253 CLEAR FD prefixes set 7,l
instructions
using iy
254 RETURN FE cp N set 7,(hl)
255 COPY FF rst 56 set 7,a
Part 29
Reports
Subjects covered...

Reports and messages


CONTINUE

Reports appear at the bottom of the screen whenever the +2A has
stopped executing some BASIC. They explain why it has stopped - be
it for some natural reason, or because an error has occurred.

Most reports have a code number or letter (so that you can refer
the table ahead), a brief message explaining what happened, and
the line number (and the statement number within the line) where
BASIC stopped. (A command is shown as line 0. Within a line,
statement 1 is at the beginning, statement 2 comes after the first
colon (or THEN), and so on.)

Reports pertaining to disk operation (or +3DOS) do not start with


a number or letter - they are shown ahead in alphabetical order.

The behaviour of the CONTINUE command depends very much on the


reports. Normally, CONTINUE goes to the line and statement
specified in the last report, but there are exceptions with
reports 0, 9 and D.

Here is a table showing all the reports. The right-hand column


tells you in which circumstances the report can occur, and this
refers you to part 31 of this chapter. For example, you can see
from the table that the error A Invalid argument can occur with
SQR, LN, ACS, ASN and USR. If you then look up these keywords in
part 31 of this chapter, you will be able to find out just which
arguments are invalid.

Disk errors marked by RIC (in the left-hand column) will normally
be displayed followed by the options: - Retry, Ignore or Cancel?.
If the cancel option is chosen, then the report shown in the
second column will be displayed.

CODE REPORT/EXPLANATION SITUATION

0 OK Any
Successful completion, or jump to a line
number bigger than any existing. This
report does not change the line and
statement jumped to by CONTINUE.
CODE REPORT/EXPLANATION SITUATION

1 NEXT without FOR NEXT


The control variable does not exist (it
has not been set up by a FOR statement),
but there is an ordinary variable with
the same name.

2 Variable not found Any


For a simple variable, this will happen
if the variable is used before it has
been assigned to by a LET, READ or INPUT
statement, loaded from tape (or disk), or
set up in a FOR statement. For a
subscripted variable, it will happen if
the variable is used before it has been
dimensioned in a DIM statement, or loaded
from tape (or disk).

3 Subscript wrong Subscripted


A subscript is beyond the dimension of variables,
the array, or there are the wrong number Substrings
of subscripts. If the subscript is
negative or bigger than 65535, then error
B will result.

4 Out of memory LET, INPUT, FOR,


There is not enough room in the computer DIM,
for what you are trying to do. If the GO SUB, LOAD,
computer really seems to be stuck in this MERGE
state, you may have to clear out the Sometimes during
command line using DELETE and then delete expression
a program line or two (with the intention evaluation
of putting them back afterwards) to give
yourself room to manoeuvre.

5 Out of screen INPUT,


An INPUT statement has tried to generate PRINT AT
more than 23 lines in the lower half of
the screen. Also occurs with PRINT AT
22,xx.

6 Number too big Any arithmetic


Calculations have yielded a number
38
greater than approximately 10 .
CODE REPORT/EXPLANATION SITUATION

7 RETURN without GO SUB RETURN


There has been one more RETURN than there
were GO SUBs.

9 STOP statement STOP


After this, CONTINUE will not repeat the
STOP, but carries on with the statement
after.

A Invalid argument SQR, LN, ASN, ACS,


The argument for a function is unsuitable USR (with string
(for some reason). argument)

B Integer out of range RUN, RANDOMIZE,


When an integer is required, the floating POKE, DIM, GO TO,
point argument is rounded to the nearest GO SUB, LIST,
integer. If this is outside a suitable LLIST, PAUSE,
range, then this error results. PLOT, CHR$, PEEK,
USR (with numeric
For array access, see also error 3. argument)

C Nonsense in BASIC VAL, VAL$


The text of the (string) argument does
not form a valid expression. Also used
when the argument for a function or
command is outrageously wrong.

D BREAK - CONT repeats LOAD, SAVE,


BREAK was pressed during some peripheral VERIFY, MERGE.
operation. The behaviour of CONTINUE Also used when
after this report is normal in that it the computer asks
repeats the statement. Compare with scroll? and you
report L. press N, BREAK or
the space bar

E Out of DATA READ


You have tried to READ past the end of
the DATA list.

F Invalid filename SAVE


SAVE with filename longer than 10
characters using tape (or with filename
empty using disk).
CODE REPORT/EXPLANATION SITUATION

G No room for line Entering a line


There is not enough room left in memory into the program
to accommodate the new program line.

H STOP in INPUT INPUT


Some INPUT data started with STOP. Unlike
the case with report 9, after this
report, CONTINUE will behave normally, by
repeating the INPUT statement.

I FOR without NEXT FOR


There was a FOR loop to be executed no
times (eg. FOR n=1 TO 0) and the
corresponding NEXT statement could not be
found.

J Invalid I/O device Stream operations;


You are attempting to input characters OPEN #,
from (or output characters to) a device CLOSE #,
that doesn't support it. For example, it INPUT #,
is not possible to input characters from PRINT #, etc.
the screen stream. A command such as
INPUT #2,a$ will therefore result in this
error.

K Invalid colour INK, PAPER,


The number specified is not an BORDER, FLASH,
appropriate value. BRIGHT, INVERSE,
OVER;
also after one of
the corresponding
control characters

L BREAK into program Any


BREAK pressed. This is detected between
two statements. The line and statement
number in the report refer to the
statement before BREAK was pressed, but
CONTINUE goes to the statement after
(allowing for any jumps to be made), so
that it does not repeat any statements.
CODE REPORT/EXPLANATION SITUATION

M RAMTOP no good CLEAR; possibly in


The number specified for RAMTOP is either RUN
too big or too small.

N Statement lost RETURN, NEXT,


Jump to a statement that no longer CONTINUE
exists.

O Invalid Stream INPUT #,


Trying to input from (or output to) a OPEN #,
stream that isn't open or that is out of PRINT #
range (0...15); or trying to open a
stream that is out of range.

P FN without DEF FN
User-defined function used without a
corresponding DEF in the program.

Q Parameter error FN
Wrong number of arguments, or one of them
is the wrong type (string instead of
number, or vice versa).

R Tape loading error VERIFY, LOAD,


A file on tape was found, but for some MERGE
reason could not be read in, or would not
verify.

d Too many brackets PLAY


Too many brackets around a repeated
phrase in one of the arguments.

j Invalid baud rate FORMAT LINE


The baud rate for the RS232 was set to
zero.

k Invalid note name PLAY


PLAY came across a note or command it
didn't recognise, or a command which was
in lower case.
CODE REPORT/EXPLANATION SITUATION

l Number too big PLAY


A parameter for a command is an order of
magnitude too big.

m Note out of range PLAY


A series of sharps or flats has taken a
note beyond the range of the sound chip.

n Out of range PLAY


A parameter for a command is too big or
too small. If the error is very large,
error l results.

o Too many tied notes PLAY


An attempt was made to tie too many notes
together.

Bad filename CAT, COPY, ERASE,


The filename used in any of the disk FORMAT, LOAD,
commands does not conform to the limits MERGE, MOVE, SAVE
described in part 20 of this chapter.

Bad parameters Unlikely


One of the values passed to +3DOS by
BASIC is out of range. It is unlikely
that this error will ever be seen.

RIC CRC data error CAT, COPY, ERASE,


The cyclic redundancy check (checksum FORMAT, LOAD,
byte) for a sector is incorrect. This is MERGE, MOVE, SAVE
a rare error that is produced if the disk
being read has been corrupted in some way
(perhaps magnetically).

Code length error LOAD...CODE


Trying to load a CODE file from disk that
is longer than the value given in the
LOAD command.
CODE REPORT/EXPLANATION SITUATION

Destination cannot be wild COPY...TO


Trying to give a wildcard file
specification for the destination file in
a COPY command when the source also
contains wildcard characters. In this
case, the destination can only be a drive
letter.

Destination must be drive COPY...TO


The source filename in a COPY command
contains wildcard characters, but the
destination is only a single file name.
In this case, the destination can only be
a drive letter.

Directory full COPY, SAVE


Trying to create the 65th file on a disk;
(the normal disk directory can only have
64 entries).

Disk full COPY, SAVE


Saving or copying files to a disk has
used the last byte of free space. The CAT
command can be used to check that there
is sufficient free space before
attempting such an operation. When
copying, any partially-copied files will
be deleted. However, when saving, it is
possible that part of the file may be
left on the disk - this part should be
erased, as any attempt to use it will
fail.

RIC Disk has been changed CAT, COPY, ERASE,


While executing a command, +3DOS has FORMAT, MOVE, SAVE
noticed that the disk in the drive is not
the same one that was present at the
beginning of command execution. If a
machine code program has opened files on
a disk (then the disk is changed) and a
+3 BASIC command tries to access the
disk, then this report will be produced.
LOAD “*”
Disk is not bootable
An attempt has been made to load the
'bootstrap' program from a disk that
doesn't have a boot sector.
CODE REPORT/EXPLANATION SITUATION

RIC Disk is write protected COPY, ERASE,


An attempt has been made to write to a FORMAT, MOVE, SAVE
disk whose write protect hole is open.
Write protection may be disabled by
sliding closed the appropriate tab,
before the disk is written to.
FORMAT
Drive B: is not present
An attempt has been made to use the
FORMAT command on the second disk drive
(drive B:) when it has not been
connected. Unlikely

Drive in use
An attempt has been made to re-map a
drive that has files open on it. It is
very unlikely that this error will ever
be seen. CAT, COPY, ERASE,
LOAD, MERGE, MOVE,
Drive not found SAVE
A filename used in a disk command
contains a drive letter specifying a
drive that isn't present. For example,
ERASE "c:fred".

RIC Drive not ready CAT, COPY, ERASE,


A disk command has been attempted when FORMAT, LOAD,
the drive was not ready. This usually MERGE, MOVE, SAVE
happens because there is no disk in the
drive. It will usually be possible to
simply put a disk in the drive and type
R.

End of file found Unlikely


An attempt has been made to read a byte
past the end-of-file position. It is
unlikely that this report will be seen.

File already exists MOVE...TO


The destination filename in a MOVE
command (that is being used to rename a
file) already exists.
CODE REPORT/EXPLANATION SITUATION

File already in use Unlikely; COPY,


If a machine code program has opened LOAD, MERGE, SAVE
files 1...3, then a +3 BASIC command
might fail with this error when it tries
to open a file that was already open. It
is unlikely that this error will ever be
seen.
File is read only COPY, ERASE, MOVE,
Trying to update, erase or save using the SAVE
name of a file that has its protection
attribute set (using the command MOVE
filename TO "+P"). Use the command MOVE
filename TO "-P" to remove write
protection.

File not found COPY, ERASE, LOAD,


The filename given for one of the disk MERGE, MOVE
reading commands specifies a file that
does not exist.

File not open Unlikely


A disk command has tried to operate on a
file which has not been opened. It is
very unlikely that this error will ever
be seen.

File too big Unlikely


An attempt has been made to write a file
that is greater than 8 megabytes in
length. It is very unlikely that this
error will ever be seen.

Invalid attribute MOVE...TO


The attribute character following + or -
in a MOVE command is not P, S or A (or
there is more than one character after
the + or -).

Invalid drive FORMAT, SAVE


A drive letter other than A: or B: has
been specified in a FORMAT command, or an
attempt has been made to set a default
drive that does not exist.
CODE REPORT/EXPLANATION SITUATION

RIC Missing address mark CAT, COPY, ERASE,


A sector being read from the disk does LOAD, MERGE, MOVE,
not contain the usual information that is SAVE
used by the system to identify where it
is on the disk. This almost invariably
means that an attempt is being made to
read a disk that has not been formatted.
The error may possibly occur when trying
to read a disk that has become corrupted
in some way, or one that employs some
form of in-built protection.

Missing extent Unlikely; COPY,


Files are essentially made up of 16K LOAD, MERGE
blocks and each of these is known as an
extent. This error might occur while
reading a file from disk if the disk is
changed after the system has read the
directory entry for a file (but before it
has read a particular extent). However,
it is very unlikely that this error will
ever be seen.

RIC No data CAT, COPY, ERASE,


This is a low level disk error that LOAD, MERGE, MOVE,
occurs when a sector identifier cannot be SAVE
found. It is possible that the error
might occur while trying to copy a disk
that employs some form of in-built
protection.
MOVE...TO
No rename between drives
An attempt has been made to use the MOVE
command specifying source and destination
filenames that are on different drives.

RIC Seek fail CAT, COPY, ERASE,


This is a hardware error that means the FORMAT, LOAD,
drive is unable to locate the track that MERGE, MOVE, SAVE
has been requested. If this error
persists, it may indicate that the
computer needs to be serviced.

Uncached Unlikely
This is an internal system error and it
is very unlikely that it will ever be
seen.
CODE REPORT/EXPLANATION SITUATION

RIC Unknown disk error Unlikely; CAT,


An error has occurred that the system is COPY, ERASE,
not familiar with. It is very unlikely FORMAT, LOAD,
that it will ever be seen. MERGE, MOVE, SAVE

RIC Unrecognised disk format CAT, COPY, ERASE,


While trying to read/write a disk, +3DOS LOAD, MERGE, MOVE,
has been unable to recognise its format, SAVE
ie. it has read the disk specification
but has found information there that
doesn't make sense. This error may occur
when trying to access disks which employ
some form of in-built protection.

RIC Unsuitable media CAT, COPY, ERASE,


The disk in the drive has a format that FORMAT, LOAD,
is not suitable. This error might occur MERGE, MOVE, SAVE
when, for example, trying to write to an
80 track disk placed in a 40 track disk
drive (eg. the AMSTRAD FD-1) connected to
the +2A.

+2A does not support format FORMAT


If you have not connected a disk drive to
the +2A, then attempting to format a disk
will produce this error.
Part 30
Reference information
Subjects covered...

Hardware

The +2A is designed around the Z80A microprocessor, which runs at


a speed of 3.5469MHz (about three and half million cycles per
second).

The +2A's memory is divided into 64K ROM and 128K RAM, arranged in
16K pages. The four ROM pages (0-3) can be mapped into the bottom
16K (0000h-3FFFh) of the memory map. The eight RAM pages (0-7) are
usually mapped into the top 16K (C000h-FFFFh) of the memory map.
RAM page 5 is also mapped into the range 4000h-7FFFh, and RAM page
2 is mapped into the range 8000h-BFFFh. There are also several RAM
page combinations that occupy the full 64K address range. These
were given in part 24 of this chapter, under the heading 'Memory
management'.

Physically speaking, the ROMs are two 32K devices (similar to the
27256), which are both treated by the system as two 16K chips. The
RAM is composed of four 64K x 4 bit chips (41464), some of which
(RAM banks 4-7) are time-shared between the circuitry that
produces the screen display, and the Z80A. The others (RAM banks
0-3) are for the exclusive use of the Z80A, as is the ROM.

For the contended RAM (which shares time between the video
circuitry and the processor), during 128 out of every 228 CPU T
states (1 TV line), and during 192 out of every 311 TV lines (1
frame) the CPU is allowed only 1 access to contended RAM in every
8 T states. The CPU is controlled by introducing wait states.

Executing NOP instructions in contended RAM will have an effective


average clock frequency of 2.66MHz (a reduction of about 25%).

The Uncommitted Logic Array (ULA) handles most of the I/O such as
keyboard, datacorder, part of the printer interface and screen
handling. It converts bytes in memory into patterns and colours on
the screen, and allows the Z80A to scan the keyboard and read and
write data to tape.

The three-channel sound is produced by the AY-3-8912 - a very


popular sound chip, and this device also controls the RS232/MIDI
and AUX ports.
The two serial ports can be driven only by software. The +2A has
no software support for the AUX port - this is left to the user's
discretion. The RS232/MIDI port is fully supported from +3 BASIC.

The way in which the AY-3-8912 works is quite complex, and the
would-be experimenter is advised to get the manufacturer's data
sheet. The following information should be enough to get things
underway, however:

The sound chip contains sixteen registers which are selected by


writing first to the address write port FFFDh (65533) with the
register number, and then reading the register value (same
address), or writing to the data register write address BFFDh
(49149). Once a register has been selected, any number of data
read/writes can be made; the address write port need only be re-
written if a different register needs to be accessed.

The basic clock frequency of the circuit is 1.7734MHz (to 0.01%).

The registers do the following:

R0 - Fine tone control channel A


R1 - Coarse tone control channel A
R2 - Fine tone control channel B
R3 - Coarse tone control channel B
R4 - Fine tone control channel C
R5 - Coarse tone control channel C

The tone of a channel is a 12 bit value taken from the sum of D3-
D0 of the coarse register, and D7-D0 of the the fine register. The
basic unit of tone is the clock frequency divided by 16 (ie.
110.83KHz), and with a 12 bit counter range, frequencies from 27Hz
to 110KHz can be generated.

R6 - Noise generator control, D4-D0

The period of the noise source is taken by counting down the lower
5 bits of the noise register every sound clock period divided by
16.

R7 - Mixer and I/O control

D7 - Not used
D6 - 1 means input port
- 0 means output port
D4 - Channel B noise
D5 - Channel C noise
D3 - Channel A noise
D2 - Channel C tone
D1 - Channel B tone
D0 - Channel A tone
This register controls both the mixing of noise and tone values
for each channel, and the direction of the 8 bit I/O port. A zero
in a mix bit indicates that the function is enabled.

R8 - Amplitude control channel A


R9 - Amplitude control channel B
RA - Amplitude control channel C

D4 - 1 means use envelope generator


- 0 means use value of D3-D0 for amplitude
D3-D0 - Amplitude

These three registers control the amplitude of each channel and


whether or not it is modulated by the envelope registers.

RB - Envelope coarse period control


RC - Envelope fine period control

The eight bit values in RB+RC are summed to produce a 16 bit


number which is counted down in units of 256 multiplied by the
sound clock. Envelope frequencies can be between 0.1Hz and 6KHz.

RD - Envelope control

D3 - Continue
D2 - Attack
D1 - Alternate
D0 - Hold

The diagram of envelope shapes (in part 19 of this chapter) gives


a graphic illustration of the possible settings for this register.

If you have connected a disk drive to the +2A, it will be


controlled by the μPD765A floppy disk controller chip in the
external interface. As described in part 23 of this chapter, the
data register for this device is at address 3FFDh (16381) and the
status register is at 2FFDh (12285). This is a very complex device
and it would be unwise to attempt to use it without full details
of its operation (see the manufacturer's data sheet).

The Centronics parallel printer port is basically just an 8 bit


data latch (74273) whose address is 0FFDh (4093). The STROBE
signal for the printer is produced by the ULA and is accessed
using bit 4 of address 1FFDh (8189). The state of the BUSY line
from the printer is read from bit 0 of address 0FFDh (4093).
Part 31
The BASIC
Subjects covered...

Number handling
Variables
Strings
Functions
Brief summary of keywords
Mathematical operations

Numbers are stored to an accuracy of 9 or 10 digits. The largest


number you can get is about 1038, and the smallest (positive)
number is about 4 x 10-39.

Unless a number represents an exact power of 2 there is a


possibility that mathematical inaccuracies may become apparent
after repeated addition, subtraction, etc. This is true of all
computers that do not use BCD arithmetic. Use of integers is
suggested if absolute mathematical accuracy is required.

A number is stored in the +2A in floating point binary with one


exponent byte e(1<=e<=255), and four mantissa bytes m(½<=m<1).
This represents the number m x 2e-128.

Since ½<=m<1, the most significant bit of the mantissa m is always


1. Therefore, in actual fact we can replace it with a bit to show
the sign - 0 for positive numbers, 1 for negative.

Small integers have a special representation in which the first


byte is 00h(0), the second is a sign byte (00h or FFh) and the
third and fourth are the integer itself (in twos complement form)
with the least significant byte first.

Numeric variables have names of arbitrary length, starting with a


letter and continuing with letters and digits. Spaces are ignored
and all letters are converted internally to lower-case letters.

Control variables of FOR...NEXT loops have names a single letter


long.

Numeric arrays have names a single letter long, which may be the
same as the name of a simple variable. They may have many
dimensions of arbitrary size. Subscript values start at 1.
Strings are completely flexible in length. The name of a string
consists of a single letter followed by $.

String arrays can have many dimensions of arbitrary size. The name
is a single letter followed by $ but may not be the same as the
name of a simple string variable. All the strings in a given array
have the same fixed length, which is specified as an extra final
dimension in the DIM statement. Subscript values start at 1.

Slicing: substrings of strings may be specified using slicers. A


slicer can be one of the following:

(i) empty

...or...

(ii) a numerical expression

...or...

(iii) optional numerical expression TO optional numerical


expression

...and is used in expressing a substring by either:

(a) string expression (slicer)

...or...

(b) string array variable (subscript...subscript,slicer)

...which is the same as...

string array variable (subscript...subscript)(slicer)

In (a), suppose the string expression has the value s$, then if
the slicer is empty, the result is s$ (considered as a substring
of itself).

If the slicer is a numerical expression with value m, then the


result is the mth character of s$ (a substring of length 1).

If the slicer has the form (iii), then suppose the first numerical
expression has the value m (the default value is 1), and the
second, n (the default value is the length of s$). If 1<=m<=n<=the
length of s$, then the result is the substring of s$ starting with
the mth character and ending with the nth.

If 0<=n<m, then the result is the empty string. Otherwise, error 3


results.

Slicing is performed before functions or operations are evaluated


(unless brackets dictate otherwise).
Substrings can be assigned to (see LET). If a string quote is to
be written in a string literal, then it must be doubled.

Functions
The argument of a function does not need brackets if it is a
constant or a variable (optionally subscripted or sliced).

FUNCTION TYPE OF ARGUMENT RESULT

ABS number Absolute magnitude.

ACS number Arccosine in radians. Error


A if x not in the range -1
...+1.

AND binary operation, right


operand
always a number
numeric left operand: a AND b a if b<>0
0 if b=0

string left operand: a$ AND b a$ if b<>0


"" if b=0

AND has priority 3.

ASN number Arcsine in radians. Error A


if x not in the range -1
...+1.

ATN number Arctangent in radians.

ATTR two arguments, x and y, both A number whose binary form


numbers (enclosed in codes the attributes of line
brackets) x, column y on the screen.
Bit 7 (most significant) is
1 for flashing, 0 for
steady.
FUNCTION TYPE OF ARGUMENT RESULT

Bit 6 is 1 for bright, 0 for


normal. Bits 5...3 are the
paper colour. Bits 2...0 are
ink colour. Error B unless
0<=x<=23 and 0<=y<=31.

BIN binary number This is not really a


function, but an alternative
notation for numbers: BIN
followed by a sequence of 0s
and 1s is the number with
such a representation in
binary.

CHR$ number The character whose code is


x, rounded to the nearest
integer.

CODE string The code of the first


character in x (or 0 if x is
the empty string).

COS number (in radians) Cosine x.

EXP number ex.

FN FN followed by a letter
calls up a user-defined
function (see DEF). The
arguments must be enclosed
in brackets - (even if there
are no arguments, the
brackets must still be
present).

IN number The result of inputting at


processor level from port x
(0<=x<=FFFFh). Loads the BC
register pair with x and
does the assembly language
instruction in a,(c).
FUNCTION TYPE OF ARGUMENT RESULT

INKEY$ none Reads the keyboard. The


result is the character
representing the key pressed
(if there is exactly one),
else the empty string.

INT number Integer part (always rounds


down).

LEN string Length.

LN number Natural logarithm (to base


e). Error A if x<=0.

NOT number 0 if x<>0, 1 if x=0. NOT has


priority 4.

OR binary operation,
both operands numbers: a OR b 1 if b<>0
a if b=0

OR has priority 2.

PEEK number The value of the byte in


memory whose address is x
(rounded to the nearest
integer). Error B if x is
not in the range 0...65535.

PI none π (3.1415927...).

POINT two arguments, x and y, both 1 if the pixel at (x,y) is


numbers (enclosed in ink colour. 0 if it is paper
brackets) colour.

Error B unless 0<=x<=255 and


0<=y<=175.
FUNCTION TYPE OF ARGUMENT RESULT

RND none The next pseudo-random


number in a sequence
generated by taking the
powers of 75 modulo 65537,
subtracting 1 and dividing
by 65536. Yields a number in
the range 0<=x<1.

SCREEN$ two arguments, x and y both The character that appears


numbers (enclosed in (either normally or
brackets) inverted) on the screen at
line x, column y. Returns
the empty string if the
character is not recognised.

Error B unless 0<=x<=23 and


0<=y<=31.

SGN number Sign of number. Returns -1


for negative, 0 for zero, or
+1 for positive.

SIN number (in radians) Sine x.

SQR number Square root.


Error A if x<0.

STR$ number The string of characters


that would be displayed if x
were printed.

TAN number (in radians) Tangent.

USR number Calls the machine code


subroutine whose starting
address is x.
On entry to the routine at
address x the memory is
configured so that
0000h...3FFFh(0...16383) is
FUNCTION TYPE OF ARGUMENT RESULT

occupied by ROM 3 (48


BASIC), 4000h...7FFFh
(16384...32767) is occupied
by RAM page 5,
8000h...BFFFh(32768...49151)
is occupied by RAM page 2,
and
C000h...FFFFh(49152...65535)
is occupied by RAM page 0.
If +3DOS routines are to be
called, RAM page 7 should be
switched in at
C000h...FFFFh(49152...65535)
, and ROM 2 (+3DOS) should
be switched in at
0000h...3FFFh(0...16383).
See part 26 of this chapter
for further details.

On return, the result is the


contents of the BC register
pair.

USR string The address of the bit


pattern for the user-defined
graphic corresponding to x.
Error A if x is not a single
letter between a and u, or a
user-defined graphic.

VAL string Evaluates x (without its


bounding quotes) as a
numerical expression.
Error C if x contains a
syntax error, or gives a
string value. Other errors
possible, depending on the
expression.

VAL$ string Evaluates x (without its


bounding quotes) as a string
expression.
FUNCTION TYPE OF ARGUMENT RESULT

Error C if x contains a
syntax error or gives a
numerical value.
Other errors possible (as
for VAL).

- number Negation.

The following are binary operations:

+ Addition (on numbers), or concatenation (on strings)


- Subtraction
* Multiplication
/ Division
↑ Exponentiation (error B if the left operand is negative)
= Equal to Both operands must be of
> Greater than the same type. The result
< Less than is a number: 1 if the
<= Less than or equal to comparison holds; 0 if it
>= Greater than or equal to does not
<> Not equal to

Functions and operations have the following priorities:

OPERATION PRIORITY
Subscripting and slicing 12
All functions except NOT and unary minus 11
↑ (exponentiation) 10
- Unary minus (used to negate) 9
*,/ (multiplication, division) 8
+,- (addition, subtraction) 6
=,>,<,<=,>=,<> (relational operators) 5
NOT 4
AND 3
OR 2
Statements
The following notation is applicable in the remainder of this
section:

1 represents a single letter.


v represents a variable.
x,y,z represent numerical expressions.
m,n represent numerical expressions that are rounded to
the nearest integer.
e represents an expression.
f represents a string valued expression.
d represents a string that evaluates to a valid drive,
ie. A:, B:, M: or T:.
u represents an unambiguous DOS filename.
a represents a DOS filename that may be ambiguous, ie.
one that may contain the wildcards * or ?.
s represents a sequence of statements separated by
colons.
c represents a sequence of colour items, each terminated
by commas or semicolons. A colour item has the form of
a PAPER, INK, FLASH, BRIGHT, INVERSE, or OVER
statement.

Note that optional expressions are enclosed in [square brackets].

Arbitrary expressions are allowed everywhere (except for the line


number at the beginning of a statement).

All statements except INPUT, DEF FN and DATA can be used either as
commands or in programs (although they may be more sensible in one
than the other). A command or program line can have several
statements, separated by colons. There is no restriction on
whereabouts in a line any particular statement can occur; however,
see IF and REM.

BEEP x,y Sounds a note through the TV's speaker


for x seconds at the pitch y semitones
above middle C or below middle C if y
is negative).

BORDER m Sets the border colour around the


screen, and also the paper colour for
the lower part of the screen.
Error K unless 0<=m<=7 (ie. unless m
is not in the range 0...7).
BRIGHT m Sets brightness of characters
subsequently printed; 0 for normal, 1
for bright, 8 for transparent.
Error K unless m is 0, 1 or 8.

CAT [#n,] [d] [a] The CAT command produces an


alphanumerically sorted catalog of
files on a disk (if connected) or the
RAMdisk. If used in the form CAT
#n,...the output is directed to stream
n. If an unambiguous filename (or an
ambiguous file specification) is
included, then only those files that
'match' will be displayed. When CAT is
followed by a drive letter only, then
all files on that drive will be
displayed. If the drive letter
specified is T:, then a catalog of
tape filenames will be displayed
(together with information that will
be useful for tape-to-disk file
transfer).

CAT [#n,] [d] [a] EXP Operates as per the CAT command, but
produces an expanded catalog that
includes system files, and displays
those files whose write protection,
system status and archive attributes
have been set. (See MOVE u TO f.)

CIRCLE x,y,z Draws an arc of a circle, centre (x,


y) radius z.

CLEAR Deletes all variables, freeing the


space they previously occupied.
Executes a RESTORE and CLS, resets the
PLOT position to the bottom left-hand
corner and clears the GO SUB stack.

CLEAR n Like CLEAR, but if possible, changes


the system variable RAMTOP to n and
puts the new GO SUB stack there.
(Note that this command may be used to
ensure the machine stack is below
BFE0h (49120) when entering a routine
that calls +3DOS from BASIC.)
CLOSE #n Marks stream n as being unattached to
any channel. It may then be used in a
subsequent OPEN #n,f statement.

CLS (Clear screen). Clears the display


file.

CONTINUE Continues executing a program from the


point at which it stopped with a
report (other than 0). If the report
was 9 or L, then execution continues
with the following statement (taking
any jumps into account); otherwise
repeats the statement where the report
occurred. If the last report was in a
command line, then CONTINUE will
attempt to continue the command line,
and will either go into a loop (if the
error was in 0:1), generate report 0
(if it was in 0:2), or report N (if it
was in 0:3 or greater).

COPY Sends (dumps) a copy of the top 22


lines of the screen display to the
printer (if connected) in quad density
Epson bit map format; otherwise does
nothing.
Report D if BREAK pressed. Note that
if the dump is prematurely stopped,
the printer may be left in graphics
mode and the line feed set to an odd
value.

COPY EXP [INVERSE] Sends a copy of all 24 lines of


display to the printer (if connected)
in quad density Epson bit map format;
otherwise does nothing. Each coloured
dot on the screen is printed with a
different pixel pattern thus providing
different grey levels for each colour.
The BRIGHT attribute is also taken
into account. The optional INVERSE
modifier allows the dump to be
'reversed' (like a negative) in order
to save ribbon wear when printing-out
predominantly black dumps.
Report D if BREAK pressed. Note that
if the dump is prematurely stopped,
the printer may be left in graphics
mode and the line feed set to an odd
value.

COPY u1 TO u2 Disk file commands. Copies the first


COPY a TO d named file to the second named file.
COPY d TO d The names must be different. Drive
letters and user numbers may be
specified within the filename. If the
source (u1) is an ambiguous file
specification, then the destination
(u2) must only be a drive letter. (In
this case, the destination files will
have the same name as the source.)

If both source and destination names


are just drive letters, a complete
disk-to-disk transfer will be made
(note that any files previously on the
destination disk will be deleted). If
the destination disk is not +3 format
(supported by the +2A), then the disk-
to-disk transfer will not work.

When copying files, if the destination


filename already exists, then the
report File already exists will be
displayed. If the report Missing
address mark is displayed, then it is
likely that the destination disk has
not been formatted.

COPY u TO SCREEN$ Displays the contents of a disk file


on the screen. Control characters
(tabs, line feeds, etc.) are replaced
by spaces. This command can only
sensibly be used to inspect ASCII
files (though BASIC programs will be
displayed, albeit without the correct
formatting).
COPY u TO LPRINT The contents of the named disk file
are sent to the printer. No character
translations are made. If the command
FORMAT LPRINT "R" has been issued (to
divert printer output to the serial
(RS232 socket), then this form of the
COPY command may be used as a method
of exporting programs to an external
machine.

COPY u TO SPECTRUM FORMAT This allows a +3DOS file header to be


added to a binary file created on a
different type of machine. A new file
with the name: u.HED is created.

DATA e1, e2, e3,... Part of the DATA list. Must be in a


program; otherwise has no effect.

DEF FN l(ll,...lk)=e User-defined function definition. Must


be in a program; otherwise has no
effect. Each of l and ll,...lk is
either a single letter or a single
letter followed by $ for string
argument or result.
Takes the form DEF FN l()=e if no
arguments.

DIM l(nl,...nk) Deletes any array with the name l, and


sets up an array l of numbers with k
dimensions nl,...nk.
Initialises all the values to 0.

DIM l$(nl,...nk) Deletes any array or string with the


name l$, and sets up an array 1$ of
characters with k dimensions nl,...nk.
Initialises all the values to "". This
can be considered as an array of
strings of fixed length nk, with k-l
dimensions nl,...nk. An array is
undefined until it is dimensioned by
DIM.
Error 4 if there is no room to fit the
array in.

DRAW x,y DRAW x,y,0


DRAW x,y,z Draws a line from the current plot
position, moving x horizontally and y
vertically relative to it, while
turning through angle z.
Error B if line runs off the screen.

ERASE a Disk file commands. If a single file


ERASE d is specified, then that file will be
erased from either the default drive
or the drive identified in the
filename. If an ambiguous file name is
specified, a message asking for
confirmation will appear. If Y is
pressed, then all files that match the
specification will be erased. If ERASE
is followed by a drive letter only,
then all files on that drive will be
erased without confirmation being
sought.

FLASH Defines whether characters will be


flashing or steady; n=0 for steady,
n=1 for flash, n=8 for no change.

FOR l=x TO y FOR l=x TO y STEP 1

FOR l=x TO y STEP z Deletes any simple variable l and sets


up a control variable l with value x,
limit y, step z, and looping address
referring to the statement after the
FOR statement.
Checks if the initial value is greater
(if z>=0) or less (if z<0) than the
limit, and if so then skips to
statement NEXT l, giving error 1 if
there is none. See NEXT.
Error 4 if there is no room for the
control variable.
FORMAT d Prepares the disk in the specified
drive (A: or B:) to be used. If the
disk has already been formatted on a
+2A (or a +3), a message allowing the
operation to be abandoned will be
produced. Disks formatted on other
machines (except the AMSTRAD PCW range
(CF-2) format) will not be recognised.
If you have not connected a disk drive
to the +2A, this command will generate
an error.

FORMAT LINE n Sets the baud rate of the RS232


interface to n. Valid baud rates are
in the range 75...19200.

FORMAT LPRINT f1[;f2] Allows printer output to be redirected


and token expansion to be switched on
or off. If string f1 is "C", then
subsequent printer output will be via
the Centronics interface (the PRINTER
socket). If string f1 is "R", then
printer output will be directed to the
RS232 socket. String f1 can also be
"E" (for expanded), in which case
characters below CHR$ 32 are not sent
to the printer, and those above CHR$
127 are converted to the letters of
the appropriate BASIC token. When
string f1 is "U" (for unexpanded), all
characters that follow are sent to the
printer without translation. This
allows ESC (escape) sequences to be
sent. If f1 is either "C" or "R", a
second string, f2, may be specified,
this can be either "E" or "U"
(described above).

GO SUB n Pushes the line number of the GO SUB


statement onto a stack; then operates
as per GO TO n.
Error 4 may occur if there are not
enough RETURNs.

GO TO n Jumps to line n (or, if there is none,


the first line after that).
IF x THEN s If x is true (non-zero), then s is
executed. Note that s comprises all
the statements until the end of the
line. The form 'IF x THEN line number'
is not allowed.

INK n Sets the ink (foreground) colour of


characters subsequently printed; n is
in the range 0...7 for a colour, 8 for
transparent, 9 for contrast.
Error K unless 0<=n<=9.

INPUT [#n,]... The '...' is a sequence of INPUT


items, separated (as in a PRINT
statement) by commas, semicolons or
apostrophes. An INPUT item can be any
of the following:

(i) Any PRINT item not beginning with


a letter.
(ii) A variable name.
(iii) LINE, then a string type
variable name.
The PRINT items and separators in (i)
are treated exactly as in PRINT,
except that everything is printed in
the lower part of the screen. For (ii)
the computer stops and waits for input
of an expression from the keyboard -
the value of this is assigned to the
variable. The input is echoed in the
usual way and syntax errors give the
flashing . For string type
expressions, the input buffer is
initialised to contain two string
quotes (which can be erased if
necessary). If the first character in
the input is STOP (SYMB SHIFT and A),
then the program stops with error H.
(iii) is like (ii) except that the
input is treated as a string literal
without quotes, and the STOP mechanism
won't work; to stop it you must press
cursor down ↓ instead.
INVERSE n Controls inversion of characters
subsequently printed. If n=0, then
characters are printed in normal
video, ie. as ink colour on paper
colour. If n=1, then characters are
printed in inverse video, ie. paper
colour on ink colour.
Error K unless n=0 or 1.
Note that in 48 BASIC, pressing the
INV VIDEO key is equivalent to INVERSE
1; pressing the TRUE VIDEO key is
equivalent to INVERSE 0.

LET v=e Assigns the value of e to the variable


v. LET cannot be omitted. A simple
variable is undefined until it is
assigned to in either a LET, READ or
INPUT statement. If v is a subscripted
string variable, or a sliced string
variable (substring), then the
assignment is Procrustean (fixed
length), ie. the string value of e is
either truncated or filled out with
spaces on the right, to make it the
same length as specified in v.

LIST [#m] LIST [#m,] 0

LIST [#m,] n Lists the program to the upper part of


the screen, starting at the first line
whose number is at least n, and makes
n the current line. If #m is included,
the output is sent to the channel
currently assigned to stream m.

LLIST LLIST 0

LLIST n Like LIST, but using the printer. By


default, output will be to the
Centronics (PRINTER) socket; however,
printer output can be directed to the
RS232 socket using the command FORMAT
LPRINT "R".
In order that BASIC listings appear
correctly, token codes are expanded to
the relevant letters of each token,
(codes below 32 are not printed). The
command FORMAT LPRINT "E" can be used
to restore this state if it has been
changed (by FORMAT LPRINT "U").

LOAD d Makes the named drive the current


default input device for all
subsequent disk operations (COPY,
ERASE, MOVE etc.). If the drive letter
specified is T:, then all subsequent
LOADs and MERGEs will default to tape.

LOAD f Loads the program and variables from


tape (or disk). The string f that
specifies the file to be loaded may
optionally include a drive letter and
user number when operating from disk.
If a drive letter is not specified,
then the default drive is used.
If the string f contains just an
asterisk, ie. LOAD "*", an attempt is
made to boot the disk in drive A:.
This may be used to load alternative
operating systems or some games disks.

LOAD f DATA l() Loads a numeric array: l () from file


f.

LOAD f DATA l$() Loads character array: l$ () from file


f.

LOAD f CODE m,n Loads (at most) n bytes, starting at


address m.

LOAD f CODE m Loads bytes starting at address m. If


a file from another machine has been
converted to Spectrum format (using
the command COPY u TO SPECTRUM
FORMAT), then this is the form of LOAD
command to use (as the header will not
contain a load address).
LOAD f CODE Loads bytes back to the address from
where they were saved.

LOAD f SCREEN$ LOAD f CODE 16384,6912

LPRINT... Like PRINT, but using the printer. Use


the FORMAT LPRINT command to direct
output to the Centronics (PRINTER) or
RS232 socket and to set expansion of
tokens on or off. By default, output
will be sent to the PRINTER socket
with tokens expanded and codes below
32 not printed. If ESC (escape)
sequences are to be printed (for print
formatting), issue the command FORMAT
LPRINT "U" before using LPRINT. If
printer output has been set to RS232
(using the command FORMAT LPRINT "R"),
then LPRINT can be used to send
strings of characters to a remote
computer/terminal.

MERGE f Like LOAD f, but does not delete old


program lines or variables, except to
make way for new ones with the same
line number or name. Like LOAD, the
filename may include a drive letter
and user number. If a drive letter is
not specified, the default drive will
be used.

MOVE f1 TO f2 Disk file command. This will rename


file f1 to f2. Both files f1 and f2
must be on the same drive.
MOVE u TO f Disk file command. The string f may be
"+P", "+S", "+A", "-P", "-S" or "-A".
This allows the attributes of the file
specified by u to be set (+) or unset
(-). The attribute letters in the
string f control write protection (P),
system status (S), or archive status
(A). The CAT...EXP command can be used
to display current settings. Protected
files cannot be erased, saved over, or
have any operation that would change
them in any way performed upon them.
System files are hidden from the
normal catalog display and are only
shown by the CAT...EXP command.
Archive status is provided for
compatibility with CP/M based
machines, and has no other relevance
to the +2A.

NEW Starts the BASIC system afresh,


deleting any program and variables,
and using the memory up to and
including the byte whose address is in
the system variable RAMTOP. The system
variables UDG, P RAMT, RASP and PIP
are preserved. Returns control to the
opening menu, but does not erase files
held on drive M: (the RAMdisk).

NEXT l (i) Finds the control variable l.


(ii) Adds its step to its value.
(iii) If the step >=0 and the value >
the limit; or if the step <0 and the
value < the limit, then jumps to the
looping statement.
Error 2 if there is no variable l.
Error 1 if variable l does not match
control variable in FOR statement.
OPEN #n,f Allows stream number n to be attached
to the channel identified by string f.
Stream numbers may be in the range
0...15, however the system itself
makes use of 0...3 (so their use is
not advised). Possible strings are "S"
(for the screen channel), "K" (for the
keyboard channel) and "P" (for the
printer channel). The printer channel
may be further re-directed to the
Centronics (PRINTER) or RS232 sockets
using the FORMAT LPRINT command.
Trying to input from a stream that is
set to a channel that only supports
output, or vice versa, will cause an
Invalid I/O device report.

OUT m,n Outputs byte n at port m at processor


level.
(Loads the BC register pair with m,
the A register with n, and executes
the assembly language instruction
out(c),a.)
Error B unless 0<=m<=65535 and
-255<=n<=255.

OVER n Controls overprinting for characters


subsequently printed. If n=0,
characters obliterate previous
characters at that position. If n=1,
then new characters are mixed in with
old characters to give ink colour
wherever either (but not both) had ink
colour, and paper colour where they
were both paper or both ink.
Error K unless n is 0 or 1.

PAPER n Like INK, but controlling the paper


(background) colour.

PAUSE n Stops computing and displays the


display file for n frames (there are
50 frames per second), or until a key
is pressed. If n=0 then the pause is
not timed, but lasts until a key is
pressed.
Error B unless 0<=n<=65535.
PLAY f1[,f2,...f8] Interpret up to eight strings and play
them simultaneously. The first three
strings play via the TV speaker and
(optionally) via the MIDI socket; any
subsequent strings can be output only
via MIDI.

PLOT c;m,n Prints an ink dot (subject to OVER and


INVERSE) at the pixel (m,n), moving
the PLOT position thereto. Unless the
colour items c specify otherwise, the
ink colour at the character position
containing the pixel is changed to the
current permanent ink colour, and the
others (paper colour, flashing and
brightness) are left unchanged.
Error B unless 0<=m<=255 and
0<=n<=175.

POKE m,n Writes the value n to the byte in


store with address m.
Error B unless 0<=m<=65535 and
-255<=n<=255.

PRINT [#n,]... The '...' is a sequence of PRINT


items, separated by commas, semicolons
or apostrophes, and they are written
to the display file for output to the
screen.
When used in the form PRINT
#n,...output is directed to stream n
rather than the screen (unless that
stream has been opened to the screen
channel "S").
A semicolon between two items has no
effect - it is used purely to delimit
the items. A comma shifts printing
forward to the next print zone, while
an apostrophe generates a carriage
return/line feed (which is generated
by default if a PRINT statement is not
terminated by a semicolon, comma or
apostrophe).
A PRINT item can be:

(i) Empty, ie. nothing.


(ii) A numerical expression: First a
minus sign is printed if the value is
negative. Now let x be the modulus of
value -lf x<=10-5 or x>=1013, then it
is printed using scientific notation.
The mantissa part has up to eight
digits (with no trailing zeros), and
the decimal point (absent if only one
digit) is after the first. The
exponent part is E, followed by + or -
, followed by one or two digits.
Otherwise x is printed in ordinary
decimal notation with up to eight
significant digits, and no trailing
zeros after the decimal point. A
decimal point right at the beginning
is always followed by a zero, so for
instance .03 and 0.3 are printed as
such. Zero is printed as a single
digit 0.
(iii) A string expression: The tokens
in the string are expanded, possibly
with a space before or after.
Control characters have their control
effect.
Unrecognised characters print as ?.
(iv) AT m,n: Outputs an AT control
character followed by a byte for m
(the line number) and a byte for n
(the column number).
(v) TAB n: Outputs a tab control
character followed by two bytes for n
(least significant byte first) - the
tab stop.
(vi) A colour item, which takes the
form of a PAPER, INK, FLASH, BRIGHT,
INVERSE or OVER statement.

RANDOMIZE RANDOMIZE 0

RANDOMIZE n Sets the system variable (called SEED)


used to generate the next value of
RND. If n<>0, then SEED is given the
value n. If n=0 then SEED is given the
value of another system variable
(called FRAMES) that counts the frames
so far displayed on the screen, and so
should be fairly random.
Error B unless 0<=n<=65535.
READ v1, v2,...vk Assigns to the variable using
successive expressions in the DATA
list.
Error C if an expression is the wrong
type.
Error E if there are variables left to
be read when the DATA list is
exhausted.

REM... No effect. The '...' can be any


sequence of characters terminated by
ENTER. No statements in the line will
be acted upon after the REM, and
colons will not be treated as
separators.

RESTORE RESTORE 0

RESTORE n Restores the DATA pointer to the first


DATA statement in line n. If line n
doesn't exist (or is not a DATA
statement), then the first DATA
statement after line n is restored,
and the next READ statement will start
reading from there.

RETURN Takes a reference to a statement off


the GO SUB stack, and jumps to the
line after it.
Error 7 when there is no statement
reference on the stack - (this
probably means that there is some
mistake in your program - ensure that
all GO SUBs are balanced by RETURNs).

RUN RUN 0

RUN n CLEAR, and then GO TO n.

SAVE d Makes the named drive the current


default output device for all
subsequent disk operations (COPY,
ERASE, MOVE etc.). If the drive letter
specified is T:, then all subsequent
SAVEs will default to tape.
SAVE f Saves the program and variables to
tape (or disk), giving it the name f.
The filename may optionally include a
drive letter and user number when
operating with disks. If a drive
letter is not specified, then the
default drive is used.
Error F if f is empty, or is greater
than ten characters in length (on
tape).

SAVE f LINE m Saves the program and variables so


that if they are loaded, there is an
automatic jump to line m.

SAVE f DATA l() Saves the numeric array: l() to the


file f.

SAVE f DATA l$() Saves the character array: l$() to the


file f.

SAVE f CODE m,n Saves n bytes starting at address m.

SAVE f SCREEN$ SAVE f CODE 16384,6912. Saves the


current screen display.

SPECTRUM Switches from +3 BASIC into 48 BASIC,


maintaining any program in RAM. There
is no switch back to +3 BASIC. Note
that ROM/RAM switching is not disabled
when entering 48 BASIC using this
command; (this is not the case when
the option 48 BASIC is selected from
the opening menu).

STOP Stops the program with report 9. The


CONTINUE command will resume the
program from the following statement.
VERIFY f Like LOAD (from tape), but the tape
information is not loaded into RAM -
instead, it is just compared against
what is already in RAM.
If the filename specifies a disk file
(or if the current default drive is
A:, B: or M:), then no action is
taken.
Error R if the comparison shows
different bytes.
Part 32
Binary and hexadecimal
Subjects covered...

Number systems
Bits and bytes

This section describes how computers count, using the binary


system.

Most European languages count using a more or less regular pattern


of tens - in English, for example, although it starts off a bit
erratically, it soon settles down into regular groups...

twenty, twenty one, twenty two,...twenty nine


thirty, thirty one, thirty two,...thirty nine
forty, forty one, forty two,...forty nine

...and so on, and this is made even more systematic with the
numerals that we use. However, the only reason for using ten (the
decimal system) is that we happen to have ten digits on our hands
(fingers and thumbs).

Instead of using the decimal system - based on ten, computers use


a form of binary called hexadecimal (or 'hex' for short) which is
based on sixteen. As there are only ten digits available in our
number system we need six extra digits to do the counting. So we
use A, B, C, D, E and F. And what comes after F? Well, just as we,
with ten fingers, write 10 for ten (a hand full), so computers use
10 for sixteen. Comparing counting in decimal to hex...

DECIMAL HEX
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 A
DECIMAL HEX
11 B
12 C
13 D
14 E
15 F
16 10
17 11
...continued...
25 19
26 1A
27 1B
...etc...
31 1F
32 20
33 21
...etc...
158 9E
159 9F
160 A0
161 A1
...etc...
255 FF
256 100
...and so on.

If you are using hex notation and you want to make the fact quite
plain, then write 'h' at the end of the number, and say 'hex'. For
instance, for one hundred and fifty eight (decimal), write '9Eh'
and say 'nine E hex'.

You may be wondering what all this has to do with computers. In


fact, computers behave as though they had only two digits,
represented by a low voltage (or off) known as 0, and a high
voltage (or on) known as 1. This is called the binary system, and
the two binary digits are called bits - so a bit is either 0 or 1.
So to expand the previous table of counting to include binary...

DECIMAL HEX BINARY


0 0 0
1 1 1
2 2 10
3 3 11
4 4 100
5 5 101
6 6 110
7 7 111
8 8 1000
9 9 1001
10 A 1010
11 B 1011
12 C 1100
13 D 1101
14 E 1110
15 F 1111
16 10 10000
17 11 10001
...etc...

It is customary to 'pad out' binary numbers with leading zeros so


that they always contain at least four bits - for example, 0000,
0001, 0010, 0011 (representing 0 to 3 decimal).

Converting between binary and hex is very easy (use the previous
table to help you):

To convert a binary number to hex, split the binary number into


groups of four bits (starting at the right of the number) and
convert each group of four bits into its corresponding hex digit.
Finally, put the hex digits together to form the complete hex
number. For example, to convert 10110100 binary into hex, convert
the first (right-hand) group of four bits (0100) to 4 hex, then
convert the next group of four bits (1011) to B hex, put them
together, and you have the complete hex number - B4h. If the
binary number is longer than eight bits, you can continue
converting each group of four bits into one hex digit. For
example, 11101011110000 binary corresponds to 3AF0h.

To convert a hex number to binary, change each hex digit into four
bits (again, starting at the right) then put the bits together to
form the complete binary number. For example, to convert F3h to
binary, first convert 3 which corresponds to 0011 binary (remember
- you must use zeros to make the binary number four bits long),
then convert F which corresponds to 1111 binary, put them
together, and you have the complete binary number - 11110011.

Although computers use a pure binary system, humans often write


the numbers stored inside a computer using hex notation - after
all, the number 3AF0h (for example) is far more likely to be
easily and correctly read than 0011101011110000 in sixteen bit
binary notation.

The bits inside the computer are mostly grouped into sets of eight
- these are called bytes. A single byte can represent any number
from 0 to 255 decimal (11111111 binary or FFh).

Two bytes can be grouped together to make what is technically


called a word. A word can be expressed using sixteen bits or four
hex digits, and represents a number from 0 to 65535 decimal
(1111111111111111 binary or FFFFh).

A byte is always eight bits, but words vary in length from


computer to computer.

The BIN notation (used in part 14 of this chapter) provides a


means of entering numbers in binary on the +2A, ie. BIN 10
represents 4 decimal, BIN 111 represents 7 decimal, BIN 11111111
represents 255 decimal, and so on.

You can only use 0s and 1s for this, so the number must be a non-
negative whole number - for instance, you can not use BIN -11 to
represent -3 decimal, but you can use -BIN 11 instead. The number
must also be no greater than decimal 65535 - ie. it can't have
more than sixteen bits. If you pad out a binary number with
leading zeros, for example, BIN 00000001, the BIN function will
rightly ignore them and treat the number as if it were BIN 1.
Part 33
Example programs
Programs...

Renumber
Clock
Bustout
Telly tennis

Renumber
This short program is an aid to the renumbering facility provided
by the edit menu's Renumber option. If you MERGE this program into
the program you are developing (or wish to renumber), you will be
able to select both the starting line number and the step size
(between successive program lines).

Type RUN 9000 to run the program, enter the start line (in the
range 1...9999), enter the step size (in the range 1...9999), then
press the EDIT key and select the Renumber option from the edit
menu.

9000 INPUT "Start line",st


9010 INPUT "Step size",sp
9020 LET hst= INT (st/256)
9030 LET hsp= INT (sp/256)
9040 POKE 23413,st-256*hst
9050 POKE 23414,hst
9060 POKE 23415,sp-256*hsp
9070 POKE 23416,hsp
9080 PRINT "Press EDIT then sele
ct Renumber option"

Clock
This program sets up the +2A as an analogue (and digital) clock.

Type RUN to start the program, enter the hour (in the range
1...12) and enter the minute (in the range 0...59). The clock will
then start.

10 DIM s(60): DIM c(60)


20 BORDER 0: PAPER 0: BRIGHT 1
: INK 7: CLS
30 PRINT AT 10,1;"Hold on whil
e I calculate"
40 PRINT AT 11,2;"some sines a
nd cosines"
50 GO SUB 370
60 LET z$="00"
70 CLS
80 INPUT "What hour is it ";h
90 INPUT "How many minutes pas
t ";m
100 LET s=0: POKE 23672,0: POKE
23673,0
110 IF h=12 THEN LET h=0
120 LET xc=112: LET yc=90: LET
r=70: LET rh=r/2: LET rm=r*
3/4: LET rs=r*5/6
130 CIRCLE xc,yc,r
140 INK 1
150 FOR i=0 TO 359 STEP 30
160 PLOT (r+1)*s(i/6+1)+xc,(r+1
)* c(i/6+1)+yc
170 NEXT i
180 INK 4
190 OVER 1: GO SUB 500
200 GO SUB 470
210 GO SUB 440
220 LET tm= INT (( PEEK 23672+2
56* PEEK 23673)/50)
230 IF s+1=tm THEN LET os=s: LE
T s=s+1: GO TO 250
240 GO TO 220
250 IF s=60 THEN LET s=0: POKE
23672,0: POKE 23673,0: LET
om=m: LET m=m+1: GO TO 290
260 PLOT xc,yc: DRAW rs*s(os+1)
,rs*c(os+1)
270 GO SUB 440
280 GO TO 220
290 IF m=60 THEN LET m=0: LET o
h=h: LET h=h+1: GO TO 330
300 PLOT xc,yc: DRAW rm*s(om+1)
,rm*c(om+1)
310 GO SUB 470
320 GO TO 260
330 IF h=12 THEN LET h=0
340 PLOT xc,yc: DRAW rh*s(oh*5+
1),rh*c(oh*5+1)
350 GO SUB 500
360 GO TO 300
370 PRINT AT 14,0
380 FOR i=6 TO 360 STEP 6
390 PRINT ".";
400 LET s(i/6)= SIN ((i-6)* PI
/180)
410 LET c(i/6)= COS ((i-6)* PI
/180)
420 NEXT i
430 RETURN
440 PLOT xc,yc: DRAW rs*s(s+1),
rs*c(s+1)
450 LET s$= STR$ (s): PRINT OVE
R 0; AT 18,27; INK 4;":"; I
NK 6;z$( TO 2- LEN (s$));s$
460 RETURN
470 PLOT xc,yc: DRAW rm*s(m+1),
rm*c(m+1)
480 LET m$= STR$ (m): PRINT OVE
R 0; AT 18,24; INK 2;":"; I
NK 5;z$( TO 2- LEN (m$));m$
490 RETURN
500 PLOT xc,yc: DRAW rh*s(h*5+1
),rh*c(h*5+1)
510 LET ph=h: IF ph=0 THEN LET
ph=12
520 LET h$= STR$ (ph): PRINT OV
ER 0; INK 3; AT 18,22;" "(
TO 2- LEN (h$));h$
530 RETURN

Bustout
This program provides a colourful and entertaining little game for
one player against the computer.

To play the game, type RUN, then press any key to start.

Options:

Cursor left ← moves the bat left.


Cursor right → moves the bat right.
The space bar trades a life for a new screen.
See if you can get the highest 'hiscore'!

Note the following when typing in the listing:

1. The "BBBBBBB..."s shown in lines 30 and 50 are graphics


characters. They are produced by pressing the GRAPH key once (to
switch graphics mode on), typing the characters (using the B
key), then pressing the GRAPH key again (to switch graphics mode
off).

2. The "3333"s shown in line 210 are also graphics characters.


Again, they are produced by pressing GRAPH once, pressing the 3
key four times, then pressing GRAPH again. (Note that these
characters will look like black blocks on the screen.)
3. The "A" shown in line 430 is also a graphics character. Again,
it is produced by pressing GRAPH once, pressing the A key once,
then pressing GRAPH again.

10 BORDER 0: INK 0: PAPER 0: C


LS : BRIGHT 1
20 GO SUB 560
30 LET b$="BBBBBBBBBBBBBBBBBBB
BBBBBBBBB": REM 28 Bs
40 LET s$="
": REM 32 spac
es
50 PRINT AT 3,12; INK 7; FLASH
1;"BUSTOUT"; FLASH 0; AT 6
,9; INK 1;"B"; INK 7;" = 20
Points"; AT 8,9; INK 4;"B"
; INK 7;" = 10 Points"; AT
10,9; INK 2;"B"; INK 7;" =
5 Points"
60 PRINT AT 14,1; INK 4;"Press
SPACE or FIRE to trade"; A
T 16,3;"a life for a new sh
eet."
70 PAUSE 200
80 LET hiscore=0
90 LET tscore=0
100 LET lives=5
110 LET score=0
120 CLS
130 INK 7: PLOT 12,13: DRAW 0,1
60: DRAW 230,0: DRAW 0,-160
: INK 0
140 PRINT AT 1,2; INK 1;b$; AT
2,2; INK 4;b$
150 FOR r=5 TO 6: PRINT AT r,2;
INK 2;b$: NEXT r
160 LET bx=9
170 PRINT AT 19,5; INK 6;"PRESS
ANY KEY TO START"; AT 17,4
;"Use < and > to move bat"
180 PAUSE 0
190 PRINT AT 19,5; INK 0;s$( TO
24); AT 20,0;s$( TO 32); A
T 17,4;s$( TO 24)
200 PRINT AT 21,0; INK 0;s$( TO
32): GO SUB 540: GO TO 220
210 PRINT AT 20,bx; INK 0;" ";
INK 5;"3333"; INK 0;" ": RE
TURN
220 LET xa=1: LET ya=1: IF INT
( RND *2)=1 THEN LET xa=-xa
230 GO SUB 210
240 LET x=bx+4: LET y=11: LET x
c=x: LET yc=y
250 REM main loop
260 IF score>1100 THEN GO TO 11
0
270 IF INKEY$ =" " OR INKEY$ ="
0" THEN IF lives>1 THEN LET
lives=lives-1: GO TO 110
280 LET xc=x+xa: LET yc=y+ya
290 REM scan the keyboard
300 GO SUB 470
310 IF yc=20 THEN IF ATTR (yc,x
c)=69 THEN PLAY "N1g": LET
ya=-ya: LET yc=yc-2: IF xc=
bx+1 OR xc=bx+4 THEN LET xa
=-xa: LET xc=x+xa
320 IF yc=21 THEN PLAY "03N7#d"
: PRINT AT y,x;" ": GO TO 4
50
330 GO SUB 470
340 IF yc=20 THEN GO TO 430
350 LET t= ATTR (yc,xc)
360 IF t=71 THEN GO TO 410
370 IF t=64 THEN GO TO 420
380 LET ya=-ya: LET xz=xc: LET
yz=yc: LET yc=yc+ya: GO SUB
510: IF t=66 THEN PLAY "N1
e": LET score=score+5: LET
tscore=tscore+5: GO SUB 540
: GO TO 350
390 IF t=68 THEN PLAY "N1c": LE
T score=score+10: LET tscor
e=tscore+10: GO SUB 540: GO
TO 350
400 IF t=65 THEN PLAY "N1a": LE
T score=score+20: LET tscor
e=tscore+20: GO SUB 540: GO
TO 350
410 LET xa=-xa: LET xc=xc+2*xa:
PLAY "N1f"
420 IF yc=1 THEN LET ya=1
430 PRINT AT y,x; INK 0;" "; AT
yc,xc; INK 3;"A": LET x=xc
: LET y=yc
440 GO TO 250
450 LET lives=lives-1: IF lives
=0 THEN GO TO 530
460 GO SUB 540: GO TO 220
470 LET a$=INKEY$
480 IF (a$= CHR$ (8) OR a$="6")
AND bx>1 THEN LET bx=bx-1:
GO SUB 210: RETURN
490 IF (a$= CHR$ (9) OR a$="7")
AND bx<25 THEN LET bx=bx+1
: GO SUB 210: RETURN
500 RETURN
510 IF yz=20 THEN RETURN
520 PRINT AT yz,xz; INK 0;" ":
RETURN
530 GO SUB 540: PRINT AT 10,10;
INK 7;"GAME OVER"; AT 12,8
;"You scored : ";tscore: FO
R i=1 TO 300: NEXT i: GO TO
90
540 IF tscore>hiscore THEN LET
hiscore=tscore
550 PRINT AT 21,11; INK 6;"HISC
ORE ";hiscore; AT 21,1;"SCO
RE ";tscore; AT 21,24;"LIVE
S ";lives: RETURN
560 FOR i= USR "a" TO USR "b"+7
570 READ b
580 POKE i,b
590 NEXT i
600 RETURN
610 REM ball
620 DATA 0,60,126,126,126,126,6
0,0
630 REM brick
640 DATA BIN 11111111
650 DATA BIN 10000001
660 DATA BIN 10111101
670 DATA BIN 10111101
680 DATA BIN 10111101
690 DATA BIN 10111101
700 DATA BIN 10000001
710 DATA BIN 11111111

Telly tennis
This program sets up the +2A to play one of the most well-known
and enduring of computer games. For two players, or one player
against the computer.

Type RUN to start the program, then type 1 or 2 (for the number of
players) to play.

Options:

Player 1 - A moves the bat up, Z moves the bat down


Player 2 - K moves the bat up, M moves the bat down
The first player to score 15 points wins.

Note the following when typing in the listing:

1. The "66"s shown in line 150 are graphics characters. They are
produced by pressing the GRAPH key once (to switch graphics
mode on), typing the characters (using the 6 key), then
pressing the GRAPH key again (to switch graphics mode off).
(Note that these characters will look like black blocks on
the screen.)

2. The "8"s shown in lines 150, 250 and 540 are also graphic
characters. Again, they are produced by pressing GRAPH once,
holding down CAPS SHIFT and pressing the 8 key once, then
pressing GRAPH again. (Again, note that these characters will
look like black blocks on the screen.)

3. The "A" shown in line 330 is also a graphics character.


Again, it is produced by pressing GRAPH once, pressing the A
key once, then pressing GRAPH again.

10 PAPER 4: INK 0: BRIGHT 0: B


ORDER 4
20 CLS
30 GO SUB 730
40 DIM x(2): DIM y(2): DIM p(2
)
50 LET comp=1: LET sc1=0: LET
sc2=0: LET z$="0"
60 PRINT AT 2,9; INK 7;"TELLY
TENNIS"
70 PRINT AT 8,3;"ONE OR TWO PL
AYERS (1/2)?"
80 LET i$=INKEY$
90 IF i$="1" THEN PRINT AT 12,
8;"Use A to go up"; AT 14,8
;"and Z to go down": GO TO
120
100 IF i$ ="2" THEN PRINT AT 10
,3;"Player 1 use A to go up
"; AT 12,12;"and Z to go do
wn"; AT 14,3;"Player 2 use
K to go up"; AT 16,12;"and
M to go down": LET comp=0:
GO TO 120
110 GO TO 80
120 FOR i=0 TO 200: NEXT i
130 LET x(1)=2: LET y(1)=3
140 LET x(2)=29: LET y(2)=18
150 LET e$="8": LET f$="66"
160 PRINT AT 1,0;
170 GO SUB 400: REM top edge
180 FOR i=3 TO 19
190 PRINT AT i,0; INK 6;f$; INK
0; TAB 30; INK 6;f$
200 NEXT i
210 PRINT AT 20,0;
220 GO SUB 400: REM bottom edge
230 PRINT AT 0,0; INK 1;"Player
1: 00"; AT 0,19; INK 2;"Pl
ayer 2 : 00"
240 LET n= INT ( RND *2)
250 FOR i=1 TO 2: PRINT AT y(i)
,x(i); INK i;"8"; AT y(i)+1
,x(i);"8": NEXT i
260 IF n=0 THEN LET xb=21: LET
dx=1: GO TO 280
270 LET xb=19: LET dx=-1
280 LET yb=12: LET dy= INT ( RN
D *3)-1
290 GO SUB 440: REM move bats
300 LET oxb=xb: LET oyb=yb: LET
scd=0
310 GO SUB 580: REM move ball
320 PRINT AT oyb,oxb; INK 0;" "
330 PRINT AT yb,xb; INK 7;"A"
340 IF scd=0 THEN GO TO 290
350 PRINT AT yb,xb; INK 0;" "
360 GO SUB 380
370 GO TO 240
380 PRINT AT 0,10; INK 1;z$( TO
2- LEN ( STR$ (sc1)));sc1;
AT 0,30; INK 2;z$( TO 2- L
EN ( STR$ (sc2)));sc2
390 RETURN
400 FOR i=1 TO 64
410 PRINT INK 5;e$;
420 NEXT i
430 RETURN
440 LET a$=INKEY$
450 IF a$="a" THEN LET p(1)=-1
460 IF a$="z" THEN LET p(1)=2
470 IF comp=1 THEN LET p(2)=(2*
(y(2)<(yb))-(y(2)>(yb))): G
0 TO 500
480 IF a$="k" THEN LET p(2)=-1
490 IF a$="m" THEN LET p(2)=2
500 FOR i=1 TO 2
510 LET a= ATTR (y(i)+p(i),x(i)
)
520 IF p(i)=2 THEN LET p(i)=1
530 IF a=32 THEN PRINT INK 0; A
T y(i),x(i);" "; AT y(i)+1,
x(i);" ": LET y(i)=y(i)+p(i
)
540 PRINT AT y(i),x(i); INK i;
"8"; AT y(i)+1,x(i);"8"
550 LET p(i)=0
560 NEXT i
570 RETURN
580 LET w= ATTR (yb+dy,xb+dx)
590 IF w=32 THEN LET xb=xb+dx:
LET yb=yb+dy: RETURN
600 IF w=33 OR w=34 THEN LET dx
=-dx: PLAY "V15O7N1g": LET
dy= INT ( RND *3)-1: RETURN
610 IF w=38 THEN GO TO 640
620 IF w=37 THEN PLAY "V15O7N1c
": LET dy=-dy
630 RETURN
640 PLAY "O3V15#d": IF dx>0 THE
N LET sc1=sc1+1: GO TO 660
650 LET sc2=sc2+1
660 LET d=(sc1=15)+2*(sc2=15):
LET scd=1
670 IF d <> 0 THEN GO SUB 380:
PRINT INK 7; AT 10,8;"Playe
r ";d;" wins."; AT 12,7;"Pl
ay again (y/n)?": GO TO 690
680 RETURN
690 IF INKEY$ ="" THEN GO TO 69
0
700 IF INKEY$ ="y" THEN RUN
710 IF INKEY$ ="n" THEN STOP
720 GO TO 690
730 FOR i=0 TO 7
740 READ n
750 POKE USR "a"+i,n
760 NEXT i
770 RETURN
780 DATA 0,60,126,126,126,126,6
0,0
Chapter 9
Using the calculator

Subjects covered...

Selecting the calculator


Entering numbers
Running total
Using built-in mathematical functions
Editing the screen
Assigning variables
User defined functions
Exit-ing from the calculator

The +2A can be used as a full function calculator.

To use the calculator, call up the opening menu and select the
Calculator option. (If you don't know how to select a menu option,
refer back to chapter 2.)

The calculator may be selected as soon as the +2A is switched on.


Alternatively, if you are working on a +3 BASIC program, you may
select the calculator by choosing the Exit option from the edit
menu (which returns you to the opening menu), at which point you
can select the Calculator option. Note that any BASIC program
which was being worked on (when you selected the calculator) will
be remembered and restored when you exit from the calculator and
return to +3 BASIC.

When you have selected the Calculator option, the screen will
change to...

...and the +2A's calculator is ready to accept your first entry.


Type in...

6+4

As soon as you press ENTER, the answer 10 will appear. (Note that
you don't key in = as you would on a conventional calculator.)

You will see that the cursor is positioned to right of the answer,
which is a running total (like on a conventional calculator). This
means that you can simply type in the next operation to be carried
out on the running total (without having to type in a whole new
calculation). So, with the cursor still positioned to the right of
the 10 on the screen, type in...

/5

...and back comes the answer 2. Now type in...

*PI

This produces the result 6.2831853 on the screen. The +2A has used
its built-in pi function - all you had to do was type in PI. This
applies to all the +2A's mathematical functions. To demonstrate,
type in...

*ATN 60

...which gives the result 9.7648943. You may also 'edit' the
contents of the screen. To demonstrate, move the cursor (using the
cursor left key ←) to the beginning of the line and then type in
INT so that the line reads...

INT 9.7648943

...and as soon as ENTER is pressed, back comes the answer 9. This


also demonstrates that the +2A doesn't have to perform a
calculation in order to print the value of an expression. As
another example, press ENTER then type...

1E6

...and back will come the value of that expression. Notice that
before you typed in 1E6, you pressed ENTER on its own - this tells
the +2A that you are about to start a new calculation.

One extremely useful feature of the +2A's calculator is that it


will allow you to assign values to variables and then use them in
subsequent calculations. This is achieved by using the LET
statement (as you would in BASIC). To demonstrate, press ENTER and
type in the following...

LET x=10
(You must then press ENTER twice for the +2A to accept the
variable assignment.) Now verify that the variable x is being
used, by typing...

x+90

...then...

+x*x

If you are using the calculator whilst working on a BASIC program,


then any variables used by the calculator should be chosen so that
they do not conflict with those used by the program itself.

BASIC keywords are not allowed to be used as variable names.

When you have finished using the calculator, press the EDIT key.
The screen will change to...

Select the Exit option to return to the opening menu. If you were
working on a +3 BASIC program before you started using the
calculator, then you may return to the program by selecting the +3
BASIC option. (If you wish to continue using the calculator, then
select the Calculator option.)

Note that if you have set up any user defined functions (using the
DEF FN statement) whilst working on a BASIC program, you will be
able to invoke that function when using the calculator. To
illustrate this point, return to +3 BASIC and type in (for
example)...

9000 DEF FN c(n)=n*n*n

...which sets up the user defined function FN c(n) which returns


the 'cube' of n (the number you type into the brackets). Now exit
from +3 BASIC and return to the calculator - you can now use this
user defined function as if it were one of the +2A's own built-in
functions. For example, enter...

FN c(3)

...and the calculator will print the number 27 (ie. the cube of
3).
Chapter 10
Peripherals for your +2A

Subjects covered...

Printer
Joystick(s)
VDU Monitor
Amplifier
Serial devices
MIDI device
Auxiliary interface
Expansion devices
Disk drive(s)

The +2A is capable of operating with a wide range of add-ons


(peripherals) such as joystick(s), disk drive(s), printer, etc.
This section contains all the information necessary to connect
these.

Printer
The +2A may be used with any Centronics compatible parallel
printer. We would particularly recommend the AMSTRAD DMP range of
printers (eg. models DMP2000, DMP3000, DMP3160 or DMP4000) for use
with the +2A.

If you intend to connect the AMSTRAD DMP2000 to the +2A, simply


use the interconnecting lead provided with the printer.

If you wish to use any other Centronics compatible printer, you


will require the AMSOFT PL-1 printer interconnecting lead.

Connect the end of the lead which is fitted with the flat edge-
connector plug, into the socket marked PRINTER at the back of the
+2A.

Connect the other end of the lead (which is fitted with a


Centronics style plug) into the socket on the printer. If your
printer is equipped with security clips at each side of the
socket, these may be clipped into the cut-outs at the side of the
printer plug.
(viewed from rear)

PRINTER socket

PIN FUNCTION PIN FUNCTION


1 STROBE 19 GND
2 D0 20 GND
3 D1 21 GND
4 D2 22 GND
5 D3 23 GND
6 D4 24 GND
7 D5 25 GND
8 D6 26 GND
9 D7 27 not used
10 not used 28 GND
11 BUSY 29 not used
12 not used 30 not used
13 not used 31 not used
14 GND 32 not used
15 not used 33 GND
16 GND 34 not used
17 not used 35 not used
18 does not exist 36 does not exist

Although there are only 34 terminations at the +2A's PRINTER


socket, the pins are numbered 1...17 and 19...35 (with 18 and 36
non-existent) for equivalence with the Centronics socket on the
printer itself.

Note that printers for use with the +2A must generate their line
feeds internally. If you experience problems with printer line
feeds, try adjusting the appropriate 'DIP switch' inside your
printer. (On the AMSTRAD DMP range of printers, DIP switch DS1-4
controls the line feed setting.)

The +2A may also be used with most serial printers conforming to
the RS232 standard. It is recommended that inexperienced users do
not attempt to experiment with serial interface connections. You
should obtain a suitable computer-to-serial printer lead from your
Sinclair dealer, and you should always follow the printer
manufacturer's installation and operation instructions.
A serial printer should be connected to the RS232/MIDI socket at
the back of the +2A.

Details of (parallel and serial) printer operation will be found


in chapter 8 parts 21 and 22.

Joystick(s)
We recommend that you use the Sinclair SJS range of joystick(s)
with the +2A. Other types of joystick (eg. Atari) will not operate
directly, as their connecting plugs are wired differently.

There are two joystick sockets at the left-hand side of the +2A.
In general, games use the JOYSTICK 1 socket.

If a program offers you a choice of joystick types, then choose


the 'Interface Two' (or 'Sinclair') option (as the +2A's joystick
circuitry is designed to work exactly like the Interface Two).

It is safe to plug in (or unplug) a joystick while the +2A is


switched on.

PIN FUNCTION
1 not used
2 common
3 not used
4 fire
5 up
JOYSTICK 1 and JOYSTICK 2 sockets
6 right
7 left
8 common
9 down

VDU Monitor
The +2A can use an RGB colour VDU monitor (or a French standard
PERITEL TV) instead of (or in addition to) an ordinary TV. If the
monitor that you wish to use isn't quoted as being Spectrum +2A
(or +3) compatible, then the chances are you'll have to buy a lead
for it (contact your Sinclair dealer).

A VDU monitor (or PERITEL TV) should be plugged into the


RGB/PERITEL socket at the back of the +2A.
PIN SIGNAL
1 +12V
2 GND
3 audio out
4 composite sync
5 +12V
RGB/PERITEL socket
6 green
7 red
8 blue

When using a monitor, some provision may have to be made for sound
(if required). If the monitor has an audio input, then then this
should be connected either to pin 3 of the RGB/PERITEL socket or
to the TAPE/SOUND socket at the back of the +2A. If the monitor is
not capable of producing sound, then an external amplifier will
have to be used. See the next paragraph for further details.

Amplifier
The +2A normally reproduces sound through the TV set it is
connected to. However, if a VDU monitor is being used, or if you
would like to record or amplify the sound further, then a sound
signal is available from the TAPE/SOUND socket at the back of the
+2A. This is a 3.5mm stereo jack socket producing 200mV pk-pk at
approximately 5 Kohms impedance. You must not insert a mono jack
plug into the TAPE/SOUND socket - doing so will make all
subsequent datacorder operations fail. When using an amplifier, it
is worth remembering that the datacorder's 'load' and 'save'
signals are also fed to the TAPE/SOUND socket (and therefore the
amplifier's volume control should be turned down when performing
these operations).

Another point to note is that the level of sound produced by the


BEEP command is set to be the same as that of all three channels
of PLAY running at the same time. In practice, this means that
BEEP will sound quite a lot louder than PLAY (which may cause
problems if sound levels are critical).

It is safe to plug in (or unplug) an amplifier, tape recorder,


etc. into the TAPE/SOUND socket while the +2A is switched on.
(reserved for internal use)
DO NOT MAKE
ANY CONNECTION
(reserved for
internal use)
DO NOT MAKE
ANY CONNECTION

Audio output

GND (common)

Audio output GND (common)

TAPE/SOUND socket

Details of the +2A's sound facilities will be found in chapter 8


part 19.

Serial devices
To connect any serial device to the +2A, you will require a
Spectrum +2A serial lead - available from your Sinclair dealer.

If you wish to wire-up your own, then the connections are as


follows...

PIN FUNCTION
1 GND
2 TXD
3 RXD RS232 socket
4 DTR
5 CTS
6 +12V

Details of serial operations will be found in chapter 8 part 21.

MIDI device
Although the +2A's MIDI (Musical Instrument Digital Interface)
socket shares the same socket as the RS232, you will need a
different lead for it (available from your Sinclair dealer). The
lead should be connected into the 'MIDI IN' socket on your
synthesiser, drum machine, etc. There is no provision for the +2A
to receive MIDI data - it can only act as a source. No setting up
of the MIDI is necessary before use (except the inclusion of the Y
parameter within the PLAY command to turn it on).
Using the MIDI interface will not disturb the RS232's baud rate
setting.

PIN FUNCTION
1 RETURN
2 not used
3 not used MIDI socket
4 not used
5 DATA OUT
6 not used

Details of MIDI operations will be found in chapter 8 part 19.

Auxiliary interface
The AUX (auxiliary interface) socket supports two input lines
(pins 3 and 5) and two output lines (pins 2 and 4). The I/O lines
are driven by 1488 and 1489 line driver chips which are, in turn,
connected to the I/O lines of the AY-3-8912 (see the
manufacturer's data sheet for this device). Basically, register 14
of the AY-3-8912 controls eight I/O lines; the bits are designated
as follows:

BIT SIGNAL
0 AUX pin 2 (out)
1 AUX pin 4 (out)
2 RS232 pin 5 (CTS out)
3 RS232 pin 3 (RXD out)
4 AUX pin 3 (in)
5 AUX pin 5 (in)
6 RS232 pin 4 (DTR in)
7 RS232 pin 5 (TXD in)

Using software control loops, the I/O lines could be driven as a


second RS232 port (in the same way a the RS232/MIDI socket is
driven using bits 2, 3, 6 and 7). Alternatively, the I/O lines
could be used to drive, for example, a robot or some other
external device.
PIN FUNCTION
1 GND
2 OUTPUT BIT 0
3 INPUT BIT 4 AUX socket
4 OUTPUT BIT 1
5 INPUT BIT 5
6 +12V

Expansion devices
The +2A can connect to a very wide range of peripherals via the
EXPANSION I/O socket at the back of the machine. Although this
socket is much the same as on the old-style Spectrum 48K, there is
no guarantee that a device which ran correctly on a Spectrum 48K
will run on a +2A. You should, therefore, before you purchase any
expansion device or add-on, verify that it will work with the +2A,
and not just with a 48K Spectrum.

WARNING - It is very dangerous indeed to plug in (or unplug) any


device from the EXPANSION I/O socket while the +2A is switched on
- you will probably damage both the +2A and the expansion device
if you do so.

EXPANSION I/O socket

PIN UPPER ROW (U) LOWER ROW (L)


1 A15 A14
2 A13 A12
3 D7 +5V
4 ROM 1 OE not used
5 D0 GND
6 D1 GND
7 D2 CK
8 D6 A0
9 D5 A1
10 D3 A2
11 D4 A3
12 INT not used
13 NMI GND
PIN UPPER ROW (U) LOWER ROW (L)
14 HALT ROM 2 OE
15 MREQ DISK RD
16 IORQ DISK WR
17 RD MOTOR ON
18 WR BUSRQ
19 not used RESET
20 WAIT A7
21 +12V A6
22 -12V A5
23 M1 A4
24 RFSH not used
25 A8 BUSACK
26 A10 A9
27 RESET A11

Details of the +2A's hardware will be found in chapter 8 part 30.

Disk drive(s)
If you wish to connect an external disk drive (or drives) to the
+2A, you should use the model AMSTRAD FD-1 drive(s) together with
a suitable interface (the AMSTRAD SI-1 when available, or other
manufacturer's equivalent). The SI-1 interface connects to the
EXPANSION I/O socket at the back of the +2A, and will support up
to two FD-1 drives.

AMSTRAD FD-1 drives use 3 inch compact floppy disks. We strongly


recommend that for reliable data-to-disk transfer, you use AMSOFT
CF-2 compact floppy disks. Disks made by other leading
manufacturers, however, may also be used.

Thanks to the versatility of +3 BASIC, you can do all necessary


file maintenance; copying, erasing, etc., on a single disk drive.
However, a second drive will certainly speed up these processes
and reduce the scope for accidents.

Before connecting or disconnecting any disk drive(s), make sure


that disks are removed, and that the system is switched off.

WARNING - It is very dangerous indeed to plug in (or unplug) the


disk interface from the EXPANSION I/O socket while the +2A is
switched on - you will probably damage both the +2A and the disk
interface if you do so.
Whenever you use the +2A system with a disk drive connected, first
switch on the FD-1 using the POWER ON/OFF switch at the back of
the drive, then switch on the +2A (by plugging in the PSU). The
power indicator (green) at the front of the FD-1 should be
illuminated.

If you have connected two disk drives, switch them both on before
switching on the +2A. The power indicators (green) at the front of
both FD-1s should be illuminated. In addition, the read/write
indicator (red) on the second drive (drive B:) should also be
illuminated.

Details of disk drive operations will be found in chapter 6 and


chapter 8 parts 20 and 27.
Index

A
Abandoning loading ..........................................20,25
ABS ........................................................88,283
ACS ....................................................97,271,283
Aerial lead ..................................................9,15
AFC .........................................................14,15
AFT .........................................................14,15
Amplifier .................................................140,320
AMSTRAD computers .....................................215,219,223
AMSTRAD peripherals .................................19,27,317,325
AND .......................................................105,284
Animation .....................................................170
Apostrophe .................................................64,297
Archive status files ..........................................166
Argument ...................................................86,271
Arithmetic operations ..................................92,282,287
Arrays ........................................101,161,192,271,282
ASN ................................................... 97,271,284
Assembler .................................................204,264
AT ............................................116,129,181,271,297
ATN ........................................................97,284
ATTR ..................................................126,128,284
Attributes ........................................124,158,165,218
Auxiliary interface .......................................186,322
AUX socket ................................................279,322

B
Back-ups ................................................8,152,163
Backspace .................................................113,127
BASIC .................................................5,33,55,282
Baud rate .....................................................177
BEEP ..................................................141,289,320
BIN ...................................................111,284,302
Binary ....................................................111,300
Bits ......................................................185,301
Bootstrap .................................................209,217
BORDER ................................................128,273,289
Brackets ...............................................85,105,119
BREAK key ..................................14,25,35,59,66,179,272
BRIGHT ............................................125,273,289,297
Brightness ..................................................14,16
Bytes .............................................161,185,188,302
C
Calculator ....................................................313
CAPS LOCK key ............................................38,51,56
CAPS SHIFT key ...................................38,50,56,109,139
Cassette operations .....................................21,38,170
CAT ............................................46,155,174,274,289
Centronics ............................................176,186,317
Channels ......................................................182
Characters ........................................108,124,154,264
CHR$ ..................................................108,271,284
CIRCLE ....................................................132,289
Circles .................................................94,95,132
CLEAR .........................................175,194,204,273,289
CLOSE .................................................184,272,289
CLS ....................................................68,118,289
C mode .........................................................51
CODE ..............................108,162,169,174,274,284,294,298
Colon ..........................................................65
Colour ..............................................14,16,123,297
Comma ..................................................64,112,297
Commands ................................................37,55,288
Compatibility ...............................................5,215
Connections ................................................10,317
Contents ........................................................1
CONTINUE ............................................64,66,270,290
Contrast ................................................14,16,125
Control codes/characters ......................112,121,128,178,264
Coordinates ...............................................117,130
COPY ..............................................166,179,274,290
Copying files .............................................166,173
COS ........................................................96,284
CP/M ..................................................152,219,225
Cursor .............................................18,34,35,54,58

D
DATA ...........................................77,161,291,294,298
Datacorder operations ...................................21,38,170
Decimal .......................................................300
DEF ....................................................89,291,315
Degrees ........................................................97
Default drive .............................................153,170
Deleting files ................................................163
DELETE key ...............................................35,54,58
Destination file ..............................................166
DIM .................................................. 101,271,291
Disks .........................................8,19,43,150,219,226
Disk drive(s) .................................8,19,27,149,281,325
Disk format ......................................43,45,47,151,219
DOS(+3DOS) ............................................206,214,229
DRAW ......................................................131,291
E
EDIT key .............................................18,34,54,315
Editing ..................................................35,54,60
Edit menu ...................................................18,34
Ejecting a disk .............................................30,31
E mode .........................................................52
ENTER key .........................................17,35,54,58,314
Epson .........................................................176
ERASE .................................................163,274,291
Erasing files .................................................163
Error messages .........................................46,226,267
Escape code ...................................................178
EXP ............................................94,158,179,284,290
EXPANSION I/O socket ..................................187,323,325
Exponents ...................................................81,92
EXTEND MODE key .............................................52,56
External disk drive(s) .....................................19,325

F
Fields .....................................................45,153
Filenames ...............................................39,45,152
FLASH .........................................125,128,273,292,297
FN .................................................89,273,285,315
FOR ....................................................71,270,292
FORMAT .................................45,151,169,177,273,291,292
Functions ..............................................86,283,314

G
G mode .........................................................53
GO SUB .................................................75,271,292
GO TO ............................................63,64,65,271,292
GRAPH key ...............................................53,57,109
Graphics ............................................53,57,109,130

H
Hardware ..........................................176,185,279,322
Headers .......................................................218
Headphones ....................................................140
Hexadecimal ...................................................300

I
IF .....................................................68,105,292
IN ........................................................185,285
INK ...............................................125,273,293,297
INKEY$ ................................................139,182,285
INPUT ..........................................63,119,182,271,293
Inserting disks ............................................ 19,27
Installation ...................................................10
Instructions ............................................37,55,288
INT ........................................................88,285
Interface Two .................................................319
INV VIDEO key .................................................293
INVERSE ...............................126,133,180,273,290,293,297
I/O .......................................................185,195

J
Joysticks .................................................186,319
JOYSTICK sockets ..............................................319

K
Keyboard .............................................54,55,58,186
Keypad ........................................................214
Keywords ................................................37,80,267
K mode ......................................................50,54

L
LEFT$ ..........................................................91
LEN ........................................................86,285
LET ................................................60,271,293,314
LINE ..................................120,160,174,177,273,292,298
Line feed .................................................113,318
Line numbers .............................................34,36,60
LIST ................................................58,62,271,293
Listing .................................................35,58,294
LLIST .................................................178,271,294
L mode .........................................................51
LN .....................................................94,271,285
LOAD ...................................41,156,159,170,205,272,294
Loading a BASIC program ................................42,159,170
Loading software ............................................20,21
LocoScript ....................................................219
Logarithmic function ...........................................94
Logical expressions ...........................................105
Looping ........................................................70
LPRINT ........................................168,176,182,291,295

M
Machine code ..............................................204,264
Mains plug ...............................................10,13,15
Maintenance .....................................................7
Mathematical operations ................................92,282,287
Memory ............................................185,188,228,279
Menus .......................................................16,18
MERGE .........................................159,169,173,272,295
MID$ ...........................................................91
MIDI ..............................................147,187,296,322
MIDI socket ...............................................279,322
Monitor ...................................................140,319
MOVE ..................................................164,274,295
Music .........................................................140

N
Nesting ........................................................72
NEW ................................................63,150,158,295
NEXT ...................................................71,270,295
Noise .....................................................147,280
NOT .......................................................105,285

O
OPEN ..................................................182,272,296
Opening menu ...................................................16
OR ........................................................105,285
OUT .......................................................185,296
OVER ..........................................126,133,273,296,297
Overprinting ..........................................125,127,133

P
PAPER .............................................125,273,296,297
Parabola ......................................................130
PAUSE .................................................136,271,296
PEEK ..............................................111,189,271,285
Peripherals ...................................................317
PI .........................................................94,285
Pixels ....................................................117,130
PLAY ..........................................140,273,296,320,322
PLOT ..................................................130,271,296
POINT .....................................................133,285
POKE ..............................................111,189,271,296
Ports .....................................................176,317
Power indicator lamp ........................................13,15
Power supply unit .......................................8,9,15,18
Precautions .....................................................8
PRINT .......................................60,64,116,182,271,297
Printer .......................................158,174,176,186,317
PRINTER socket ........................................176,182,317
Procrustean assignment .........................................84
Pseudo-random ..............................................98,129
PSU .....................................................8,9,15,18
PSU socket .....................................................10
Q
Quotes ...................................................65,82,88

R
Radians ........................................................97
RAM ...........................................158,185,188,228,279
RAMdisk ...................................................150,169
RAMTOP ........................................................194
RANDOMIZE ..............................................99,271,297
Random numbers .................................................98
READ ...................................................77,271,298
Read/write indicator lamp .............................20,30,31,45
Recursion ......................................................76
Relational operators ...............................69,105,113,287
REM ........................................................63,298
Renaming files ................................................163
Renumbering a program ...................................34,62,303
Reports .......................................46,54,59,63,226,270
RESET button ..........................................14,16,20,24
Resetting the computer ......................................20,24
RESTORE ....................................................78,298
RETURN .................................................75,271,298
RGB/PERITEL socket ............................................320
RIGHT$ .........................................................91
RND ....................................................98,129,286
ROM ...............................................185,188,228,279
Rounding numbers ............................................88,90
RS232 .................................................176,186,321
RS232 socket ..................................177,182,279,318,321
RUN ...........................................36,61,64,65,271,298

S
Safety ....................................................8,10,18
SAVE .......................................39,152,160,171,272,298
Saving a program ...............................38,152,160,171,205
Screen display ............................33,35,54,58,130,162,179
SCREEN$ ...........................116,162,168,174,286,291,294,298
Scrolling ............................................58,64,73,121
Semicolon ..................................................64,297
Serial interface ..................................... 177,186,321
Servicing .......................................................7
Setting up .....................................................10
SGN ........................................................88,286
Sign .......................................................88,286
SIN ....................................................96,130,286
Sine wave .....................................................130
Slicing ................................................83,104,282
Software ..................................................5,20,21
Sound ................................................ 140,279,320
Source file ...................................................166
Speakers ......................................................140
SPECTRUM ...................................50,169,195,214,291,298
Spectrum 48 .............................................23,49,214
SQR ................................................89,130,271,286
Square root ....................................................89
Stack ......................................................75,205
STEP .......................................................71,292
STOP ................................................69,76,271,298
Stopping a program .......................................63,65,66
STR$ .......................................................87,286
Streams ...........................................158,174,182,297
String expressions ............................65,80,82,83,103,282
Subroutines ....................................................75
Subscript .................................................101,271
Substring ..................................................83,282
Switching on/off ..........................................8,13,18
SYMB SHIFT key ...........................................35,50,56
Syntax error ...................................................54
System status files ...........................................165
System variables ..........................................191,198

T
TAB ...................................................118,181,297
TAN ........................................................97,286
Tape operations .........................................21,38,170
TAPE/SOUND socket ........................................ 140,320
Test signal ..............................................13,15,16
THEN ...................................................68,105,292
Timing ....................................................136,279
TL$ ............................................................91
TO ..................................71,83,104,164,274,283,290,295
Tokens .........................................50,108,112,117,178
Transparent ...................................................125
Trigonometrical functions ......................................92
Troubleshooting ................................................15
TRUE VIDEO key ................................................293
Tuning-in TV ................................................13,15
TV ..................................................10,13,126,319
TV socket ......................................................10

U
ULA ...........................................................279
Unpacking .......................................................9
User area/number ..............................................153
User defined function ......................................89,315
User defined graphics ..................................57,110,134
USR ...............................................111,205,271,286
V
VAL ....................................................87,272,287
VAL$ ...................................................88,272,287
Variables ...............................61,80,159,191,271,282,314
VDU .......................................................140,319
VERIFY .................................................41,272,298
Volume ..................................................13,15,320

W
Warnings ................................................8,323,325
Wildcards .................................................156,163
Write protection ........................................28,47,165

X
X-axis .........................................................96
X-coordinate ..............................................117,130

Y
Y-axis .........................................................96
Y-coordinate ..............................................117,130

Z
Z80 micro processor ...........................187,195,204,264,279

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy