FASTER BASIC
by Richard Taylor
from Your Computer, March 1985


GO-FASTER BASIC

Richard Taylor with an ingenious way of speeding up
Sinclair BASIC by overcoming the Spectrum's ponderous
method of searching through lines.


SINCLAIR BASIC is rather slow to say the least. Moreover, in common
with most other machines, Spectrum programs become slower as they
increase in length. This is a result of the way in which the computer
finds a line when you make a reference to it. For instance, if you
have a program in memory and the computer comes across the statement
GOTO 9999 it looks at the very first line of the program and asks
itself "Is this line 9999?", the answer will be no so it will go onto
the next line and ask the same question. It will carry on doing this
until it eventually finds 9999.

Even though the Spectrum hunts through the lines at a lightning fast
rate the length of the program ensures that this can slow a program
down considerably, especially if the program makes frequent use of
subroutines right at its end. One of the methods used to combat this
slowing effect is to put important sub-routines that need to run at
maximum speed at the start of the program and less important routines,
such as initialisation and data statements near the end.

Although helpful this method is by no means perfect. For instance,
what if you've got a lot of program that needs to run at maximum
speed, it can't all be at the start! Secondly, it tends to be
unnatural to structure programs in this way, most people like to write
programs in the same order as they are executed, i.e. initialisation
routines etc. first. In most programs this slowing down effect isn't
too important, but BASIC games using animation of any sort are slow
enough to start with without any additional speed reducing effects.

There is, however, a better way of solving the problem that prevents
the computer from needing to go through the whole rigmarole of
searching through the program for a particular line. Once a program is
RUN the addresses of program lines in memory don't change. It's only
when you add to or edit a program etc. that any address changes occur.
Say you have a GOTO 5000 statement in your program. Every time this
GOTO is encountered line 5000's address has to be laboriously found.
But, like the line numbers, its address is a constant.

It seems pointless to spend a great deal of time and effort for a
result that you know will be the same as the last time it was
calculated. If the line number reference in a GOTO, is exchanged for
its equivalent address then no searching is necessary. Lo and behold,
this is exactly what my program for the 48K Spectrum does. In fact,
GOSUB and NEXT statements are speeded up in a similar way. They are
not the only commands to divert the execution of a program: CONTINUE,
RUN and RETURN do as well but these are a damn sight harder to speed
up and, in the cases of RUN and CONTINUE, aren't much used anyway.

When writing the program I've attempted to abide by the following two
aims:

* Faster BASIC must work with all BASIC programs even if they were
typed in without Faster BASIC being in memory at the time.
* Faster BASIC should be totally user transparent; i.e. it should do
its job without any special action from you, such as calling machine
code.

The 1.25K of machine code is sandwiched between RAMTOP and the user
definable graphics area. Before running remember to save it, just to
be on the safe side. All the BASIC does is to POKE the machine code
into memory, a task that takes a couple of minutes. When it's
successfully finished the machine code can be saved with:
	SAVE "FAST CODE" CODE 64058,1310
You can reload at any time with:
	CLEAR 64057: LOAD "" CODE

Initialising the program is a simple task, just type:
	RANDOMIZE USR 64082
You'll get a new startup message, informing you that the machine code
is up and running. You'll get the same message if you use NEW, it
replaces the usual Sinclair copyright message.

Obviously you don't want to have to use memory addresses directly in
GOTO and GOSUB statements but stick with the good old system of using
line numbers. The computer therefore has the burden of having to
remember both the line number and its corresponding address for each
GOTO and GOSUB. Because of the way programs are stored in memory this
isn't too difficult to organise. When you list a program you don't see
the whole story; parts of the program - as it's stored in memory -
aren't shown, mainly because these parts are for internal use by the
computer and look like gibberish to anything but a computer. One such
example of concealed program is the six bytes of data that follow
every number used in the program. The first of these six bytes always
has the value 14; a number which signifies to the listing routine that
it shouldn't attempt to display the contents of the following five
bytes.

These bytes contain the binary form of the preceding decimal number.
When a program is run these binary forms save the computer a great
deal of time by being able to use these binary forms directly without
having to convert the decimal representation that you typed in
originally. For instance the statement GOTO 100 is represented in
memory as in Figure 1. There's a similar format for a GOSUB statement.

Faster BASIC replaces the binary representation of the line number
with the address of the line. This is perfectly legal as the computer
no longer requires the binary bit as it no longer uses the line number
directly - it's there for your reference only. Occasionally in a
program you find a GOTO or GOSUB with not just a line number but a
whole expression; ie. GOSUB 2000+a*300, so the value of 'a' determines
which line is jumped to. In such an instance Faster BASIC doesn't
alter anything, and when encountered it is treated as normal. This
isn't a great handicap as statements of this sort are pretty rare
anyway.

Speeding up a NEXT statement poses much more of a problem since there
are no conveniently placed free bytes where the address of the line
can be dumped and, secondly, it's not obvious where the NEXT must
branch to; i.e. where's the FOR associated with that particular NEXT?
The way to get around the first difficulty is simple - if there is no
storage area then make one. A dummy binary representation area is
inserted just after the name of the variable in the NEXT statement as
shown in Figure 2.

The second problem isn't quite as easy to solve. Clearly it's
necessary to find the line number of the FOR connected with the NEXT
in question. You could find it by locating the last FOR statement
before the NEXT with the same variable. However, this could prove a
slow process and not totally reliable. In any case, you've always got
to make allowances for people who derive great pleasure from watching
other people's programs crash, they might be evil enough to write
something like:

	10 GO TO 40
	20 NEXT a
	30 STOP
	40 FOR a=0 to 100
	50 GO TO 20

A far safer alternative is to not mark the line to which the NEXT is
to jump to at all initially, just fill the five storage bytes with
zeroes. The first time the NEXT is used in the program the computer
will think to itself "Look, that NEXT hasn't been marked with the
address of the line it should jump to, I'd better find out what it
is". The appropriate line, and therefore its address can be found by
the usual method of searching through the program - in the same way as
a NEXT would be treated normally. Before the jump to the line is made
its address is carefully noted in the first two of the NEXT's five
byte store, along with the statement number within that line. The
following time the NEXT is used no searching is necessary - the
address of the FOR line is already there.

One problem with this is that a program's length increases by six
bytes for every NEXT in the program. This, along with the fact the
Faster BASIC machine code has already consumed over 1K above RAMTOP,
means that if a program was crammed into the Spectrum's memory to
start with then, chances are, after Faster BASIC has been at it, it
won't fit at all - well, you can't win them all. If this is the case
then you'll get an 'Out of Memory' report when you try to run the
program. Be warned, once a program's been "compiled" it'll never run
again without Faster BASIC in memory. The moral of the story? Always
keep a copy of the pre-compiled version.

When using the Faster BASIC you'll often find yourself with a blank
screen while a program's being compiled, either if you RUN it or try
and use GOTO - be patient, the program hasn't crashed. A BASIC program
is re-compiled every time it's re-entered after you've modified it in
any way - and I include loading or merging in another program in that
- even from Microdrive. Autorun is handled - loading an autorun
program will result in a short delay while the program's compiled
before it bursts into action.

Because of the mischievous way the shadow ROM in Interface 1 operates
every time an Interface 1/Microdrive command is used, Faster BASIC is
forced inactive. After such a command use RANDOMIZE USR 64061. You'll
get the start message printed up again but the program in memory is
preserved. Unfortunately this method can only be used with Interface 1
statements used as direct commands, it's not possible to use these
commands in an actual program at all.

It's difficult to give even a rough estimate of the speed increase
gained by using Faster BASIC. A program 30K or so in length can be
considerably improved speed-wise especially if it wasn't written with
the most speed dependant parts at the start. The most important factor
is, of course, the amount of times NEXTs, GOTOs and GOSUBs are used in
the program; but I think you'll agree that they are well used commands.
