MULTICOLOURED INVADERS (aka. Spectrum Animation)
from Your Computer, April 1983, p.111

Blast off into a new fast-action, flicker-free universe with
Robert Newman's smooth-animation machine-code routines.

[There was a LD (IX+9),8 missing from the assembler listing,  ]
[and a corresponding 221/54/9/8 missing from the m/code dump, ]
[in the magazine article. To avoid overwriting the UDGs used  ]
[by the program, inserting the correction entailed moving down]
[the routine by four bytes in memory. All the addresses in the]
[article transcription below, and in the accompanying program ]
[files, have thus been changed accordingly.              JimG ]

[There was also a redundant JR NZ,L3 in the assembler listing,]
[just before the L8 label, which did not appear in the m/code ]
[dump. This has been discarded from the accompanying listing. ]


THE PROVISION of colour, sound and user-definable high-resolution graphics
on the Sinclair Spectrum encourages many people to try writing arcade-style
games for their computer. Such programs require fast-action, flicker-free
graphics if they are to be successful and excitingly implemented on
Spectrums.

The usual method of producing the illusion of movement involves first
printing an object at one position, and then erasing it and printing one
character position further along the screen. This method is certainly fast
enough when used in BASIC programs on the Spectrum if only one or two
graphics characters require animation, but the movement has a jerky
appearance, because the smallest distance that a character can be moved is
one print position. There are only 32 positions across the screen, or 22 from
top to bottom.

Another disadvantage of BASIC is that the action slows down noticeably when
several characters are required to move, or if the graphics are large,
involving printing on a number of lines or across several columns. Most
commercially-written software uses machine code in order to achieve the
required speed and smoothness of movement, but writing an entire game in
machine code is not a task that most home programmers would relish. It is
therefore necessary to consider other methods for speeding up the action in
BASIC programs.

Smooth routine
On the ZX-81 it is possible to short-cut the PRINT statement by POKEing
characters directly into the display file, thereby getting slightly faster
graphics. Unfortunately the Spectrum's display file is laid out in a very
complicated fashion - see page 164 of the manual - and it is not really
feasible to do the same thing on this computer.

For this reason I have written a machine-code routine especially for the
purpose of enabling games programmers to obtain faster, smoother animation
from BASIC. It is intended to be used with user-defined graphics characters,
which can be made as large as desired and printed by a single call to the
routine. In addition, the graphics can be located at any position on the
256x176 high-resolution screen, and can therefore be made to move by as
little as one point at a time. This is a considerable improvement over the
coarse 32x22 resolution normally obtainable. The colour of the graphics can
be controlled from BASIC with the normal INK, PAPER, BRIGHT and FLASH
statements.

The machine code occupies 201 bytes, and the safest way to store it is to
move RAMTOP downwards in memory, using the CLEAR command, and place the code
between the BASIC area and the user-defined graphics.

The address of the routine will therefore be different for 48K and 16K
Spectrums. The routine itself, however, is the same for both computers, and a
dump of the machine code is given in listing 1. Owners of 48K machines can
use the loader program in listing 2. Enter this program and RUN it, inputting
the numbers from listing 1 as prompted: read the numbers from left to right.
I would advise you to check the machine code before SAVEing it or attempting
to use it. This can be done with the same loader program by deleting lines
20, 30, 70 and 90, and changing line 80 to:
	80 PRINT TAB 10; PEEK i
If all is correct, you should SAVE the routine with the command:
    SAVE "animate" CODE 65156,201
Owners of 16K computers need to make the following changes. In listing 2,
change line 20 to:
	CLEAR 32385
and line 50 to:
	FOR i=32386 TO 32586
SAVE the routine with the command
	SAVE "animate" CODE 32386,201
You can now test the routine by clearing the screen and issuing the command:-
	RANDOMIZE USR 65167 (48K)
	RANDOMIZE USR 32397 (16K)

Whereupon the character in user-defined graphic "a" - usually a capital
letter A - should appear at the top left-hand corner of the screen. If this
does not happen you have made a mistake while entering the machine code.

If the computer has crashed you must remember to reset RAMTOP by giving the
appropriate CLEAR command before reloading your copy of the routine and
checking it.

If all went as expected, here is how to use the routine from a BASIC program.
If you examine the disassembled routine in listing 3, you will see that the
first 6 bytes are used as variables, XPOS, YPOS and so on. These names will
not be recognised if you try to use them in a BASIC program, but by POKEing
different values into these six bytes you can control the operation of the
routine as follows.

Routine control
XPOS - address 32386 for 16K, 65156 for 48K - is the X co-ordinate of the top
left-hand corner when the graphic character is printed on the screen. Possible
values are the same as are allowed for the PLOT command, that is 0 to 255.

YPOS - address 32387 or 65157 - is the Y coordinate of the top left-hand
corner of the graphic character when printed on the screen. It may take
values from 0 - bottom of screen - to 175 - top of screen.

Width - address 32388 or 65158 - this is the number of points left-right in
the character to be printed.

HT - address 32389 or 65159 - is the number of points top-bottom in the
character to be printed.

Mode - address 32390 or 65160 - has the value 1 if you wish to print a
character at the current position, or 0 if you wish to erase a block of
WidthxHT points at the current position.

UDGCH - address 32391 or 65161 - this must have a value from 1 to 21, and it
tells the routine where to find the data for the character that you want to
print. A value of 1 means that the first byte of data is held at address USR
"a", that is, the first byte of the user graphic "a", while a value of 21
means that it is held in address USR "u".

Values POKEd into these six bytes before calling the routine will be unchanged
on exit; so, if printing more than one character, you may not need to update
every byte. You will get strange results, or possibly cause a crash if you
attempt to set XPOS and YPOS to values which do not permit the character you
wish to print to fit onto the screen, and so your BASIC program may need to
include a check to prevent this.

Different colours
The routine prints the graphic character in the colour defined by the current
contents of system variable ATTR_T - location 23695. If you want to print
characters in different colours, you can set ATTR_T from BASIC without
changing the current print position by using a dummy PRINT statement such as
	PRINT PAPER 6; INK 1;
before calling the routine. The FLASH and BRIGHT statements can also be used.

If you use the routine to print user-graphics consisting of 8x8 points, then
the method of storing the pattern is exactly the same as described in chapter
14 of the user manual. However, the routine can handle graphics of any size,
and the method for larger characters is slightly different.

Firstly, design your character on a piece of squared paper. I am going to use
the routine to move the character across the screen by two points at a time,
and so it is best to leave a margin at left and right edges of two blank
columns. The operation of moving left or right by two points and printing at
the new position will then automatically print over the old space invader,
saving the trouble of erasing it first. The character we want to use
therefore consists of 14x11 points.

If the width is not an exact multiple of eight, you must add the required
number of blank columns to the right-hand edge. The width of the character is
then divided into eight-bit sections, which can be described by a BIN number
as usual and stored in the user-defined graphics area. A program like that in
listing 4 can be used for this. The first byte of data for the character is
going to be stored in address given by USR "a". When entering data for your
own characters, remember that the data for the top line is stored first, then
the second line and so on.

Since the space invader occupies 22 bytes, that is, all of graphics "a" and
"b", plus most of "c", the next unused sect ion begins at USR "d". This is
where the four bytes of data needed for the character in figure 2 can be
stored. When these two lines are printed over the bottom two lines of the
space invader, its legs will appear to move while it moves across the screen.
Enter and RUN listing 4. You can save the user-graphics if you wish with:
	SAVE "chars" CODE USR "a",32
Erase listing 4 - you can do this with NEW since the routine and the
user-graphics are safe above RAMTOP - and enter the program in listing 5.
This will make a row of seven multi-coloured space invaders walk across and
down the screen in the manner so familiar to all devotees of the arcade game.
Note that all seven invaders can be erased with one call to the routine when
moving down a line by setting Mode to 0, Width to 140 and HT to 11 - lines
130-160.

Other sections of the program are as follows: Lines 300-340 print the row of
seven characters in the seven different INK colours. Lines 200-260 call the
subroutine at line 300 to print first the row of space invaders at a certain
position and then overprints their legs with the character in figure 2. Lines
100-170 make the invaders move first left to right across the screen, and
then walk back in the reverse direction. Lines 20-60 make the invaders move
down the screen after walking across it.

Fast graphics
From this example, you should be able to see how the routine can be used to
advantage in your own programs, producing spectacular, fast-action graphics.

Finally, should you find that the user-defined graphics area is not large
enough to store the number or size of characters that you wish to print with
this routine, you can relocate the routine and use a larger area of RAM for
character storage.

This can be done very easily since the machine-code routine can be put
anywhere, provided that its first byte - that is, XPOS - comes immediately
after RAMTOP. For example, if you wanted to use the routine to generate 40
characters per line printing, you would need to define your own 6x8 character
set, or copy the Sinclair one, missing out the left and right hand margins
which give spaces between the letters. This would require a large area of
memory - about 800 bytes - for storage, and so 48K owners would need to
relocate the routine at, say, address 64000 by issuing a command:
	CLEAR 63999
and then loading with:
	LOAD "animate" CODE 64000
The user-defined graphics area can now be moved to start at address 64300 by
POKEing system variable UDG - location 23675/6 - accordingly. This gives ample
space for an alternative character set or for any other user graphics.