                    Spectrum Tool Kit



          Bobby Rao offers some handy hints to

          would-be machine-code users. Here are

            some useful off-the-peg routines.



Here are about 20 machine-code graphics routines, any com-

bination of which may be used in your programs to enhance

the screen displays, or to give them that extra touch of

elegance that comes only from the use of machine code. Also

included are renumber and memory-left routines which may be

used to aid your programming.

  No understanding of machine code is necessary to use the

routines - just a good working knowledge of the Spectrum

and its manual. Machine code is the computer's first lan-

guage - it only speaks Basic out of courtesy to humans -

and its use results in greater speed, flexibility and more

economical use of memory than does the use of Basic.

  To get the machine code into the computer a hex loader

must be used - see program 1. Type this in and save it.

Machine code can either be stored above RAMTOP or in a REM

statement at the beginning of a program. I prefer the

latter method, for each different routine may be stored in

a REM statement with a different line number and then

merged into a program as required. However, if you wish to

use the first method then change line 5 as shown under-

neath the program listing. [I.e., "change line 5 to read

5 CLEAR x: LET a=x where x is the address they need to move

RAMTOP to". Note that this is wrong, though: it should read

"CLEAR x-1", unless you like confusing the GO SUB stack.]

  Here is an examnple of how you go about loading in the

memory-left routine, see figure 1. [Or rather, listing 1;

it's on the TZX as "memoryleft".] First load in the hex

loader and type in a REM statement as line 1. This REM

statement should consist of 14 full stops because the

memory-left routine is 14 bytes - characters - long. If you

are using the RAMTOP method then you will not need to do

this - just CLEAR yourself enough memory space above

RAMTOP. Now carefully type in the DATA line in figure 1 and

after checking this line run the program. Listing it will

show that line 1 is now a meaningless jumble - if you have

a line 1, that is - but do not worry, for this is supposed

to happen.  Also it is likely that listing the program when

the REM line is in this state will cause the computer to

stop with an error report. To avoid this and view the rest

of the program you must always used LIST -line number of

first line after the REM line- so that the Spectrum does

not try to list the unlistable REM line.

  Now the routine is ready to be saved. Erase all of the

hex loader except the REM line - do not use NEW whatever

you do - and save this with a filename like "Mem Left".

Now NEW the computer and reload the hex loader. Repeat the

above process for the rest of the routines, but make sure

you never use the same REM line number for two different

routines because this will cause trouble when you come to

merging routines together. [Which would a good trick,

seeing that REM must be the first line of the program and

the first line of the loader is line 5...]

  RAMTOP-method users may save their routines by using the

SAVE filename CODE method detailed in the manual on pages 

143 and 180.

[ And now the method for TZX-users, which is even simpler.

Load the program called "Hexloader", then merge the

required routine (e.g., "memoryleft"). Note that a. the

mergeable routines have their required REM statements

already added; b. each of these has a different line

number; c. to accomodate this, the hexloader starts at

line 1000 instead of at 5. Note also that you will get the

error "E Out of DATA, 1010:2"; this is normal and would

also have occurred, albeit at line 10 instead, had you

typed in the listings yourself.

  And if you want it even easier: at the end of the TZX,

you will find pre-REMmed versions of all routines, with

all the other lines removed. Just merge them into your

program and you're ready to go. They're the ones with the

capitals in the names (e.g., "ScrInvert", where the

version for the loader would be "scrinvert".]

  Once the tedious task of typing in and saving the rou-

tines has been accomplished [you're welcome] you are ready

to use these routines. If you wish to use some of the rou-

tines in one of your programs then start that program at,

for example, line 100, leaving the earlier line numbers

free for the machine-code REM lines. After typing in the

program, merge in the routines you require. To run machine

code rather than Basic the USR function must be used.

  The argument of this function is the address of the first

byte of the machine-code routine you want to run, and this

may be found, if you are using the REM method, by using

program 2 [on the TZX as "linefinder"]. On running this

program - whilst the machine-code routines are in the

computer - line numbers and the start addresses of the

routines in those lines are printed until the computer

finds a non-REM line, when it will stop. Note these start

addresses down, or better still, define variables equal to

these values by placing a lot of LET statements somewhere

in your program, for example:

        LET inv=23760

Now just typing PRINT inv will tell you the address of the

first byte of the invert-screen routine.

  RAMTOP method users will not need to use program 2

because they will already know the addresses of their rou-

tines or they would not have been able to get them above

RAMTOP in the first place.

  To use the routines use the command RANDOMIZE 0*USR X,

where X is the address of the routine you are using. The

result of the USR function is multiplied by 0 to keep RND

truly random, that is, it acts like a RANDOMIZE 0 command.



  Below there is a description of all the routines and how

to use them. In these descriptions the variable X stands

for the address of the first byte of the routine in ques-

tion. All numbers are in decimal and unless otherwise

stated all the screen routines operate on all 24 lines of

the screen.

  When you are told to poke something somewhere the pokes

must be done before you use the routines and they may be

entered as a series of direct commands before you run the

program or they may be built into the program.



  Memory Left: running this, listing 1 ["memoryleft"],

using PRINT USR X will tell you the exact number of free

bytes of memory you have left.

  Hi-Res Up Scroll: this, listing 2 ["hiscrup"], routine

scrolls the screen up by one hi-res pixel, replacing the

bottom line of pixels with blanks.

  Hi-Res Down Scroll: as in listing 2, but this - listing 3

["hiscrdown"] - scrolls down, blanking the top line of

pixels.

  Hi-Res Left Scroll: this scrolls the screen left one

pixel, replacing the rightmost column of pixels with

blanks. See listing 4 ["hiscrleft"].

  Hi-Res Right Scroll: as in listing 4, but listing 5

["hiscrright"] scrolls right, blanking the leftmost column

of pixels.

  One Character Left Scroll: the listing 6 ["chscrleft"]

routine scrolls the screen left one character, replacing

the rightmost column with either blanks - for this effect

POKE X+16,54 - or the previous leftmost column, a wrap-

around effect - for this POKE X+16,119.

  One Character Right Scroll: the listing 7 ["chscrright"]

routine scrolls right. POKE X+16,54 causes the leftmost

column to be blanked and POKE X+16,119 replaces this

column with the previous rightmost column.

  These last two routines are adjustable in which part of

the screen they scroll, but you only have five options. The

table below tells you how to adjust the routines. The first

column tells you which part of the screen is to be

scrolled. The next two columns tell you what to poke in X+1

and in X+4 respectively for the left scroll routine. The

last two columns tell you what to poke in X+1 and X+4

respectively for the right scroll routine.

    Top one-third         64 64    64  71

    Middle one-third      64 72    64  69

    Bottom one-third      64 80    64  87

    Top two-thirds       128 64   128  79

    Bottom two-thirds    128 72   128  87

  [ Whole screen         192 64   192  87 - these were not

given in the article, being the default setting when you

poke nothing at all, but they're useful to know if you want

to restore them after using the others.]

  Invert Screen: the listing 8 ["scrinvert"] inverts the

actual pixels on the screen, that is, all pixels on are

turned off and all pixels off are turned on, and so it is

different from the INVERSE function on the Spectrum which

only inverts the INK and PAPER colours - which this routine

does not alter.

  Screen Fill: this routine, listing 9 ["scrfill"], fills

in a box of height a, width b, and a top left-hand corner

at point c,d - where c and d are co-ordinates used by the

PRINT AT system - with any character of your choice.

    POKE X+1,character code   POKE X+3,a

    POKE X+4,c   POKE X+6,b   POKE x+7,d

So if a=22, b=32, c=0 and d=0 then the normal 22-line

screen is filled. You must have printed something somewhere

before using this routine or it will not work properly.

Also note that you cannot print on line 24 with this

routine.

  Ink Change: this - see listing 10 ["chngink"] - changes

the ink colour of the screen without altering anything

else. Poke X+1, the number of the colour you want to change

the ink to.

  Paper Change: as listing 10 but changes the paper colour.

Poke X+1, the number of the colour you want to change the

paper to. See listing 11 ["chngpaper"].

  Flash On/Off: this routine, listing 12 ["chngflash"],

sets the whole screen flashing - for this POKE X+9,254 - or

returns the screen to normal non-flashing mode - for this

POKE X+9,190.

  Bright On/Off: the routine shown in listing 13

["chngbright"] makes the whole screen bright - POKE X+9,246

- or returns it to normal brightness - POKE X+9,182.

  Attr Fill: the fourteenth listing ["attrfill"] changes

the attributes for a box height a, width b and of top left-

hand corner at point c,d wheew c and d are co-ordinates

used by the PRINT AT system to denote a point on the

screen.

    POKE X+3,d   POKE X+4,c   POKE X+6,b

    POKE X+7,a   

  POKE X+1, the value you want to change the attributes to.

This value may be calculated thus: first assume that the

new ATTR value is Y and initially Y=0. If flash is on add

128 to Y, if off add 0. If bright is on add 64 to Y, if off

add 0. Add eight times the number of the paper colour to Y.

Add the number of the ink colour to Y.

  This means that an attribute of flashing, bright yelllow

ink on blue paper would be 128+64+(1x8)+6=206.

  With this routine you can change the attributes of the

whole 24-line screen.

  Attr Up Scroll: this routine, listing 15 ["atscrup"],

allows you to scroll up the attributes for a box height a,

width b, and top left-hand corner at point c,d. The bottom

line of the box is replaced with an attribute of value Y -

see Attr Fill for how to calculate Y.

    POKE X+1,y   POKE X+3,d   POKE X+4,c

    POKE X+6,b   POKE X+7,a

  Attr Down Scroll: listing 16 ["atscrdown"] scrolls down

replacing the top line of the box with the new attribute.

The pokes are the same as for the previous routine.

  Attr Left Scroll: as listing 16 but scrolls left re-

placing the rightmost column of the box with either a new

attribute - for this POKE X+36,0 - with what was previously

in the leftmost column of the box - for this POKE X+36,26.

This last effect, wrap-around, allows this routine to be

used fully with the one character left scroll routine given

above. See listing 17 ["atscrleft"].

  Attr Right Scroll: the routine shown in listing 18

["atscrright"] scrolls right, replacint the leftmost column

of the box with either a new attribute - for this POKE 

X+43,0 - or with what was previously in the rightmost

column of the box - for this POKE X+43,26. This last effect

allows this routine to be used fully with the one charac-

ter right scroll given previously.



  The next three routines allow you to store screens cur-

rently being displayed in spare memory and then recall them

on to the display, either making them swap memory position

with the screen currently being displayed, or overprinting

them on to the current display. To store screens you must

firstly CLEAR some memory space so you can store the

screens there. Each screen - with attributes - is 6,912

bytes long, so this much space is required for each screen.

  The memory location of RAMTOP - the last byte of the

computer's memory - can be found by using PRINT PEEK 23730+

256*PEEK 23731. If this number is W then W-Q*6912 - where Q

is the number of screens to be stored - will tell you the

address to CLEAR RAMTOP to - see manual page 168. You must

have cleared this space or the routines will not function

correctly.

  If you only have 16K of memory then space exists for

storing only one screen so CLEAR 25685 is all you need to

use. In order that the routines know where in the memory a

screen is to be fetched from or sent to you must do the

following for all the routines:

        POKE X+1,W-256*INT(W/256)

        POKE X+2,INT(W/256)

If you have 48K and you wish to store more than one screen

then it might be advisable to leave a gap of a few bytes in

between screens so as to lower the risk of one screen

running over on to another by accident.

  If you are using the RAMTOP method for storing the

machine-code routines then be extra careful, or you will

end up ruining the routines and crashing the computer. Make

sure you take into account the length of the routines when

deciding where you CLEAR RAMTOP to.

  Store Screen: This replaces the current display with one

already in the memory. See listing 19 ["scrstore"].

  Swap Screens: This routine swaps the current display with

one higher up in the memory so that the screen that was

being displayed is stored in the memory and the screen that

was in the memory is now displayed. See listing 20.

["scrswap". The listings for this and the next routine were

printed the other way 'round in the magazine. The order on

the TZX is the one in this text.]

  Overprint Screens: This overprints a screen from higher

up in the memory onto the current display. The old display

is lost in its original form - it is not stored anywhere by

this routine before it is altered - but the screen used to

PRINT OVER the old display still remains intact higher up

in the memory. [Note that this, and the reversible nature

of OVER, means that you can get the original screen back by

calling the routine a second time.] The attributes are not

changed by this routine so after the routine has been used

the attributes being displayed are those of the old

display. See listing 21 ["scrover"].



  Renumber: this routine, listing 22 ["renumber"...],

instantly renumbers all the line numbers of your program

starting the first line at a specified value and increasing

this value by a specified amount as it renumbers the rest

of the lines. Note that this does not change the GO TOs and

GO SUBs so you will have to alter these manually. If the

first line is renumbered L and the value by which L is in-

creased is M then

        POKE X+5,M-256*INT(M/256)

        POKE X+6,INT(M/256)

        POKE X+8,L-256*INT(L/256)

        POKE X+9,INT(L/256)

For fun you might try renumbering all lines 0 or try using

a starting value greater than 9999.



  The uses of these routines are many and varied, limited

only by the imagination of the user. For example, the left

and right scrolls with wrap-around may be used to create a

constantly moving background for a space game. Any of the

scrolling routines may be used to clear all or part of the

screen in a novel way.

  The ink and paper changing routines may be used to create

a surprise effect by first drawing a picture on the screen

using the same ink and paper colour and then altering

either so that the picture appears instantly. Animated

cartoon effects are possible using the screen swapping

routines and stunning explosion effects may be simulated by

using the Invert Screen routine repeatedly - in a loop. The

list is endless and these are just a few broad guidelines

that you can experiment with and doubtless improve on.



  Just as a bit of fun try the following POKE next time you

have a program in your Spectrum: POKE 23606,8. This makes

the computer speak Russian - nearly. POKE 23606,0 restores

normality. [No, I have no idea what this has to do with the

rest of the article, either.]