ZX-81 TOOLKITS
by Michael Fox & Dale McLoughlin
from Your Computer, November 1982

These two articles, the first by Michael Fox and the
second by Dale McLoughlin, set out handy machine-
code routines, with a variety of uses.


Michael Fox

MANY USERS WHO have no knowledge of machine code may, nevertheless,
want to use it in their Basic programs to enhance speed and
presentation. But most machine-code routines lead only to the
development of one game or objective. The utility machine-code
routines in this article are for the ZX-81, but they can also be used
on a ZX-80 with 8K ROM. The effect on the last routine will be lost on
the ZX-80 because of the lack of a Slow mode.

The routines contain no absolute addresses, except subroutine calls,
so that you can stack them on top of another routine that does use
absolute addresses, or on top of each other and they can be called
individually.

The routines need a 16K RAM because they all manipulate the display
file. There are four routines and I have also supplied a comprehensive
loader program. The four routines are;
* A screen fill
* A downward scroll
* A text-window system
* A super-cursor

Line 1 of the machine-code loader program should contain the number of
Qs needed for the machine code plus a few extra - just in case. It is
best to use line 1, although any number will do as long as it is the
first line. Line 1 is best because there is no risk of putting a line
before it - the ZX-81 has no line 0. The length of the line can be
checked by
	PRINT (PEEK 16511)-2
or	PRINT (PEEK 16511 + 256*PEEK 16512)-2
if the length of the line contains more than 254 Qs.

To enter the machine code, run the program and enter the start
location of the machine code, which is usually 16514. Now start
entering the values in the third column. If you make a mistake or
enter a wrong value - it has a safeguard against entering an empty
string - then enter R for repeat and the program will re-input a value
for the last byte address. If you find a discrepancy in the addresses
or some such fault, type L to list the code. The program will input a
new start location and list from that point onwards. If at any time
you want to pause while you are checking the copy, just hold down any
key - other than R - or Space and Break, and the listing will stop
until the key is released.

If you press R, the program will return to loading mode and input a
new start location. Whenever the location you broke out from is to be
retained, enter A and it will carry on from where it left off.

It may be a good idea to type in a large line 1 and then Save the
program on tape, rather than typing it in every time it is needed. To
stack two or three machine-code routines in one Rem statement, the
best way is to type them in one after the other and note the starting
address of each routine. This is the address you should Rand USR to
call the sub- routine - all subroutines, when on their own, should be
called by
	RAND USR 16516
Also note that only in the first routine should the two 118s Newline
appear. These disable the listing of the Rem statement but should only
appear at the start. You will find that on listing only 1 Rem appears,
the rest of the Basic program can be listed by List 2, or the number
of any other Basic line. To avoid this problem Poke 16419 with the
number of the lowest line below 255; then list that line.

Listing 1 is the screen-fill routine which fills the screen with any
CHR$ except tokens and 118 which will crash the system. It works by
filling the line, looking ahead one square for a Newline and when it
finds one it jumps over that square.

It counts the number of Newlines and after a specified number it
returns to Basic. This number - the number of lines filled can be
Poked into location 16517 - is set at 22. Do not Poke it with more
than 24 or with 0 for there are only 24 lines on the screen and 0 will
be decremented to 255 which is above 24 and so will cause a crash. The
character printed is at location 16528; it is set as a black square in
the listing.

The second listing, listing 2, is a downward scroll. It works by
starting at the bottom of the display file and going up loading the
accumulator with what is on the screen, copies HL into DE, adds 33 to
DE. This is equivalent to moving it down a line. Then it puts the
contents of the accumulator in that location and goes on to the next
square.

It also looks ahead for a Newline, counts the number of the Newlines
found - the number of lines scrolled - and after 22 it returns to
Basic. The number of lines scrolled can be altered by Poking location
16520 with the number of lines - 1. If it is less than 21, the lines
scrolled will be at the bottom of the screen. When you move the bottom
of the screen location and reduce the number of lines scrolled, it
will only scroll the top lines of the screen.

The top line of the display should be only background as this is what
is copied. It must not be used after computer scrolling but can be
used before. Values higher than 21 and value 0 should not be used for
the number of lines.

To set the bottom of the display file the program must contain these
four lines:
	LET P=1+PEEK 16396+256*PEEK 16397
	LET P=P+(22*33)-2
	POKE 16517,P-256*INT(P/256)
	POKE 16518,INT (P/256)

The number 22 in the second of these lines is the number of lines to
move down. If you move the bottom of the display file as mentioned,
this number should be altered accordingly. It does not upset the
display file as the computer's upward scroll does.

After seeing Timothy Gilbert's article on how to protect lines at the
bottom of the screen by creating a text window at the top in the
February issue of Your Computer, I decided to write a routine to
produce a text window at the bottom of the display, thereby protecting
the top of the screen.

The program works by finding the start of the display file and then
moving down to the top of the text window. It then moves each square
on the screen up a line, looking ahead for Newlines and counting them.
When it has scrolled the correct number of lines, it sets the next
print position to the bottom scrolled line and sets the column number
to 21. This number in the window is at location 16517 and is set at 5.
Location 16519 should be Poked with 23 minus the number of lines.

The bottom line of the window is left clear after a scroll because it
scrolls the top line of the bottom part of the screen which is always
blank. Input does not affect the routine and vice versa. When using it
in a program, rather than using scroll, use
	RAND USR 16516
but do not type this in every time it is needed - it is quicker to
type in the program and make a list on paper of all the scroll lines.
Then, after typing in the rest of the program, insert a
	RAND USR 16516
then edit it and change the line number to produce the other Rand USRs
needed as this is quicker and easier on the fingers.

The routine can also be used to generate windows at any height
anywhere on the screen. To do this, Poke 16517 with the number of
lines and 16519 with the number of lines down to the top line of the
window. Then use the routine as normal but you will have to leave a
blank line below the window and, because it looks better, a blank line
above as well. This enables two protected, separate and unmoving
pictures or text to be displayed above and below a window.

The fourth and final listing is a Super Cursor. It runs a vertical
line from left to right across the screen leaving a clear screen
behind it. This is very impressive and the only routine which contains
absolute addresses. They are in the form of subroutine calls, so if
you stack the routines on top of each other; this one would have to be
placed at location 16514.

The routine sets itself for the first line and calls a subroutine to
draw the line. It then draws another line which clears the first and
moves on in this manner across the screen looking for the end of the
line. When found, it clears the last line and returns to Basic.

The location of the first cursor line CHR$ is at 16521 and is set to
8; the location of the main cursor line CHR$ is at 16532 and is also
set to 8. The location of the trail left is at location 16538 and the
last trail line is at 16547.



HANDY HINTS
Dale McLoughlin

THE ZX-81 instruction set offers very little in the way of
screen-controlling commands. To make up for this deficiency, these
machine- code routines provide a variety of functions including
flashing single characters or whole lines, a fast CLS, reverse
scrolling and much more.

By far the easiest method of using machine code is to store it in a
Rem statement at the beginning of a Basic program. Program 1 enables
you to enter a group of machine-code instructions into the first line
of the program, which can then be Saved, Loaded and used as part of
longer Basic routines. Lines 10 to 80 can be removed once all the
machine code has been entered - but under no circumstances should the
Rem line be edited as this can remove vital instructions from the
machine code.

Each routine can be used on its own since each is totally independent
of the others, or they could all be entered together to form one large
toolkit to be called at various points throughout a long Basic program.

Some of the routines require a Poke of some data before they are
called - a line number to be deleted - and where this is necessary it
is assumed that the data has already been checked for validity. For
example, you cannot delete line 25 since it will cause the system to crash.

Most of the routines are called by the Basic
	RAND USR 16514
where it is the first or only routine in the Rem line. If you intend
to use more than one at a time you will have to calculate the
appropriate calling address by adding the length of previous routines
to 16514.

As a convention I have used the label Start to indicate the calling
point of each routine, and any bytes to be Poked are shown in relation
to this. For example:
	POKE START+5;
if
	START=16514
then
	 POKE 16519

To enter the machine code, type in program 1, counting carefully the
number of Xs in line 1 - it may be best to enter them in Fast mode -
and Run it. Then input the machine code in manageable blocks. Use the
hex codes and watch carefully as you do it as mistakes are difficult
to locate afterwards. When the code is finished enter S to stop the
program.

These routines are for the ZX-81 with expanded display file - that is,
with more than 3.25K of RAM - and they apply to the later ROM design.
If some of them do not work it is because your ZX-81 is an early model
and consequently you should change all occurrences of CD1D15 to
CD1915. Additionally, if Scroll has been used to create the display
then it must be cleared with CLS to recreate the expanded file, since
Scroll collapses the display as if there were less than 3.25K present.
Routine 10 will of course work with any memory size.

Routine 1 will fill the whole screen with a specified character if you
	POKE START+21
with the code of that character. It must be a non-expanded one - that
is not
	RND, PI, INPUT, etc

Repeatedly calling routine 2 - for example with a For-Next loop -
appears to flash the whole screen. The following Basic program would
flash the screen until a key is pressed:
	100 RAND USR 16514
	110 IF INKEY$<>"" THEN GOTO 130
	120 GO TO 100
	130 rest of program
