Your Spectrum
Issue 6, August 1984 - ZIP compiler (part 4 of 4)
Home Contents KwikPik


See also these other articles & letters in the series:
Issue 3part 1: "Adding ZIP!"
Issue 4part 2: "Adding ZIP 2!"
Issue 5part 3: "Unzipping ZIP"
Issue 7letter: "Unzipping Zapped ZIP"
Issue 10letter: "ZIPping on a Pension"
This program is available on "ZIPi'T'ape",
which holds the files for all four parts of the article.


title
If you're looking for further proof that Simon Goodwin's ZIP compiler is nothing short of miraculous, type in this example program and give it the treatment.
graphics, orbiting aliens, 'High Score' tables and so on. The listing only occupies about a third of the memory available to ZIP, so there's plenty of room for extra features should you feel enthusiastic.
Reset your computer before typing in the program as listed. Run it using the normal Basic interpreter, to ensure that you've made no copying mistakes. In Basic the game is very slow, especially at the higher levels when up to five aliens can attack you at once. The program starts by asking you to enter a speed factor - even zero, the highest speed, is pretty slothful in Basic. ZIP is clearly called for.
The next step is to save the Star Base program on cassette or microdrive. Load ZIP and its library, then use the MERGE command to add the Star Base program. Start ZIP by typing GO TO 5035, then wait as the game is compiled. ZIP runs slowly - it takes about half an hour to compile the game - but the results are impressive. You can save the compiled code separately and run it later with a simple USR call.

LINE BY LINE

Most of the Star Base program is quite straightforward. Lines 10 to 1210 initialise the game, and the loop between lines 2000 and 2100 calls a group of subsequent subroutines which handle the graphics and sound.
The subroutine from lines 3000 to 3040 reads the control keys. It's compatible with the Sinclair Research joystick interface, and is used in preference to the INKEY$ subroutine because it can detect cases when more than one key is pressed - allowing you to turn and fire at the same time, for example.
The position of each alien, and the direction in which it is moving, is stored in the arrays P() and D(). The subroutine from line 3400 onwards converts this 'vector' information into vertical and horizontal coordinates, making it easy to add extra directions. The values zero to seven in D() represent a ring of directions around the base, at 45 degree intervals.
The current number of simultaneous attackers is stored in N. Make the arrays bigger and alter the test in line 3800 if you think you can handle more than five attackers at once! Line 3610 generates appropriate effects when the aliens finally zap you. The compiled routine is about 400 times faster than the original BASIC.
Line 4530 is a simple pseudo- random number generator. It stores an unpredictable value between zero and 100 in the variable Q each time it is called. The Spectrum timer is used to jumble the sequence. A statistician would probably find the technique horribly crude, but it works well. A short machine code routine is used to call the Spectrum's BEEP routine;
ZIP does not allow string handling, which makes it a little difficult to handle text entry. The INLEY$ subroutine provided within this article is suitable for reading 'High Score' names and other simple text - GO SUB 4500 has the same effect as the Basic line:

LET k=CODE INKEY$

As you might expect, k is set to zero if no key is depressed. You can use this routine to store strings of text in numeric arrays. If you are writing a game, it's unlikely that the INKEY$ function would have been useful anyway since it cannot detect cases when more than one key is depressed. The Star Base program shows how multiple key presses can be detected and also contains short routines to simulate the BEEP statement and the RND function.

SPEEDING UP YOUR ROM

One of the main weaknesses of ZIP is that it compiles slowly. In our experiments we found a single change which brought about a remarkable increase in speed. After an extra line was added Pass 1 was more than twice as quick, and Pass 2 was accelerated by about 40 per cent. The line:

5047 LET t=1: LET i=t: LET j=t: LET s=t: LET p=t: LET pc=t: LET z=t: LET s2=t

Was the only change needed to produce this speed-up!
To understand the way line 5047 works, you need to go back to the 'reasons for using a compiler' which we listed in Part One of this series. Compiled programs are faster than their interpreted equivalents, partly because the computer does not have to search for lines, variables and errors once a program has been compiled.
When you ran the original version of ZIP, ZX Basic built a table of variable names and values in the order they were encountered in the program. To make
the listing easy to read, ZIP uses lots of 'manifest constants' - names instead of numbers - and consequently the variable table gets filled up with entries like 'CAPITAL A', 'ENTER', 'INDEX' and so on. ZX Basic has to wade through all of these entries before it finds the 'working variables' used later on. Line 5047 makes sure that the most commonly- used variable names are at the start of the table.
This change reduces the time spent searching the variable table so much that it dramatically increases the speed of ZX Basic. The tip is just as valid in other ZX Basic programs, though it will not yield much advantage in programs which use few variables.

IT'S IN THE STARS

The program, Star Base was written to show the power of the ZIP compiler. Star Base is a graphics game with sound effects: you find yourself in the space- station at the centre of the screen with green meanies tumbling towards you from all directions. Armed only with a Super Sub-Meson Warp Laser (and a limited supply of Sub-Mesons) you must repel the alien hordes in the usual manner. You can swivel the laser to point in any direction, but you must be quick - the longer you play the faster the game gets and the more aliens attack at once.

4495 REM **** INKEY$ routine
4500 LET k=IN 254
4505 LET k=k-INT (k/32)*32
4510 IF k=31 THEN POKE 23560,0
4520 LET k=PEEK 23560: RETURN

The routine to recreate a ZIPpable INKEY$. To use it, type GOSUB 4500, and then the code of the last key pressed will be held in the variable 'k' on return from the subroutine.

As it stands, Star Base is a simple but addictive game - it would be easy to enhance it by adding user-defined

  10 REM STARBASE ZIP DEMO GAME
  20 REM
  30 REM © 1984 Simon N Goodwin
  40 REM
  80 REM
  90 REM **** INITIALISATION
 100 DIM d(5): DIM  p(5): LET p=
1: LET q=PEEK 23692+1: LET j=1: 
LET a=500: LET s=0
 110 OVER 0: PAPER 0: INK 5: FLA
SH 0: BRIGHT 0: INVERSE 0: CLS
 120 PRINT TAB 11;"STAR BASE!"''
'TAB 7;"By Simon N Goodwin"''''"
     Control keys... 0 Fire"''" 
7 Clockwise   6 Anticlockwise"''
''"Enter Delay factor (0=fastest
)"
 130 INPUT d: IF d<0 THEN GO TO 
130
 140 BORDER 0: CLS
 150 INK 6: FOR i=16 TO 160: GO 
SUB 4530: LET x=q*2+28: PLOT x,i
: NEXT i: INK 4
 170 PAPER 1: PRINT AT 21,0; INK
 7;"  AMMO=500           SCORE=0
    ";AT 0,0;" STAR BASE!  HYPER
SPACE SCANNER "
 180 FLASH 1: INK 0: FOR y=1 TO 
20: PRINT AT y,0;CHR$ 140;CHR$ 1
40;AT y,30;CHR$ 140;CHR$ 140;: N
EXT y: INK 4: PAPER 0: FLASH 0
 200 POKE 23500,17: POKE 23501,7
: POKE 23502,0: POKE 23503,33: P
OKE 23505,5: POKE 23506,195: POK
E 23507,181: POKE 23508,3
1000 PRINT AT 10,15;CHR$ 141;CHR
$ 142;AT 11,15;CHR$ 135;CHR$ 139
;
1010 OVER 1: PRINT AT 10,15;")("
;AT 11,15;")(";
1100 PAUSE 0
1200 LET w=0: LET n=1: FOR i=1 T
O n: GO SUB 3800: NEXT i
1210 GO SUB 3000: GO TO 2010
1980 REM
1990 REM **** MAIN LOOP
2000 GO SUB 3000
2005 PLOT 127,88: DRAW x,y
2010 LET p=p+r-l: IF p>95 THEN L
ET p=0
2015 IF p<0 THEN LET p=95
2020 LET t=p-INT (p/24)*24: IF p
<24 THEN LET y=12: LET x=t-12: G
O TO 2040
2025 IF p<48 THEN LET x=15: LET 
y=12-t: GO TO 2040
2030 IF p<72 THEN LET x=12-t: LE
T y=-12: GO TO 2040
2035 LET x=-15: LET y=t-12
2040 PLOT 127,88: DRAW x,y
2070 GO SUB 3200
2080 IF f THEN IF a THEN LET a=a
-1: PRINT OVER 0;AT 21,7;a: POKE
 23505,0: FOR t=2 TO 5: POKE 235
04,t*2: INK t: DRAW x*5,y*5: INK
 4: GO SUB 3200: RANDOMIZE USR 2
3500: INK t: DRAW x*-5,y*-5: NEX
T t: INK 4: POKE 23505,5
2090 FOR i=0 TO d: NEXT i
2100 GO TO 2000
2980 REM
2990 REM **** READ KEYBOARD
3000 LET k=IN 61438
3010 LET k=k-INT (k/32)*32
3020 LET l=k>=16: IF l THEN LET 
k=k-16
3030 LET r=k>=8: IF r THEN LET k
=k-8
3040 LET f=INT (k/2)*2=k: LET l=
NOT l: LET r=NOT r: RETURN
3180 REM
3190 REM **** MOVE ENEMIES
3200 LET j=j+1: LET i=INT (j/7):
 IF i>n THEN LET j=0: POKE 23505
,2: RANDOMIZE USR 23500: POKE 23
505,5: RETURN
3205 IF i*7<j THEN RETURN
3210 IF p(i)=9 THEN GO TO 3600
3220 IF p(i)<0 THEN LET p(i)=-p(
i): GO SUB 3400: PRINT OVER 0;AT
 v,h;" ";: GO SUB 3800: GO TO 33
00
3230 GO SUB 3400: PRINT AT v,h;
3240 IF ATTR (v,h)=5 THEN PRINT 
OVER 0; INK 2;"*";: POKE 23504,2
50: RANDOMIZE USR 23500: LET p(i
)=-p(i): LET s=s+10*n: PRINT OVE
R 0;AT 21,27;s;: POKE 23504,127:
 RANDOMIZE USR 23500: GO TO 3300
3250 LET p(i)=p(i)+1
3260 PRINT INK 6;"O";: GO SUB 34
00: PRINT AT v,h;"O";
3300 RETURN
3380 REM
3390 REM **** CONVERT VECTOR
3400 LET v=10: LET h=16
3410 IF d(i)=7 OR d(i)<2 THEN LE
T v=p(i)
3420 IF d(i)>2 THEN IF d(i)<6 TH
EN LET v=21-p(i)
3430 IF d(i)>4 THEN LET h=5+p(i)
3440 IF d(i)<4 THEN IF d(i)<>0 T
HEN LET h=26-p(i)
3450 RETURN
3580 REM
3590 REM **** GAME OVER FX
3600 PRINT AT 2,11; OVER 0;"GAME
 OVER!"
3610 POKE 23505,3: FOR i=7 TO 48
: POKE 23504,i*4: RANDOMIZE USR 
23500: FOR j=22528 TO 23295: POK
E j,i: NEXT j: NEXT i: STOP
3780 REM
3790 REM **** MAKE AN ENEMY
3800 LET w=w+1: IF w>20 THEN LET
 w=0: IF n<5 THEN LET n=n+1: LET
 p(n)=-1: LET d=d/2
3810 LET p(i)=1: GO SUB 4530: LE
T d(i)=INT (q/13): GO SUB 3400: 
PRINT AT v,h;"O";
3820 RETURN
4510 REM
4520 REM **** RANDOMish NUMBER
4530 LET q=q*99+PEEK 23692: LET 
q=q-INT (q/101)*101: RETURN
Star Base - not quite "the final frontier" while running in Basic, but when this program is ZIPped ... smooth action arrives. Prevent the invaders from overtaking your base using the key '7' to turn clockwise, '6' for anti- clockwise and '0' to fire your lasers.

line 200 POKEs in the machine code. RAND USR 23500 produces a single beep. All Spectrum sound- effects are made up of a sequence of 'ticks' sent to the loudspeaker. The pitch generated (the time delay between ticks) is stored in locations 23504 and 23505, and the duration (number of ticks sent) occupies locations 23501 and 23502. In both cases the first location provides 'fine tuning' and the second allows large changes in pitch or duration. The 'Shift
Enter' facility to stop machine code is temporarily turned off during a BEEP call - otherwise the intermittent keyboard check would make the note sound unsteady.
The Spectrum BEEP command allows you to specify note durations in seconds and pitches in tones. However, this versatility makes BEEP very slow - it's hard to produce interesting effects from Basic because of the gaps between notes while the durations and pitches are converted into a form which the computer can use. The ZIP routine is much faster, but the values must be converted and POKEd by the programmer. This is fine for Basic but inconvenient for music.
If you find the game too easy or too hard, you can alter the relative speed of aliens and laser by replacing the '7' in lines 3200 and 3210 with some other value - increase the number to slow the aliens. This is the sort of feature that it is easy to incorporate when you use a compiler, but much harder when you write a game in Basic (where everything must go flat out if the game is to be worth playing at all).
The main limitations on the speed of Star Base are the sound effects, PRINT and DRAW commands. These ROM routines take longer than all the rest put together. Even so, ZIP speeds up Star Base by an overall factor of about 20. The longer the program, the greater this

factor will be, since Basic takes progressively longer to find each variable or line.
It takes a little thought to design programs to be compiled using ZIP, but the results are well worthwhile. Armed with the listing and these notes, you should be able to expand the program to support other features of ZX Basic.

FINALLY ...

This series was intended to be more than just a useful listing and a set of user notes. The aim was to show that you don't need a degree, disk drives or a mainframe to write complex software. What you do need is a good plan of attack, lots of paper and plenty of time to think.
One of the most exciting things about personal computing is that it gives people at home the chance to be at the very forefront of a discipline. You can't split atoms with an axe, or discover new elements on the hob of your stove, but your Spectrum can plod through almost everything that the academics can do with their air- conditioned superconducting Megamachines (which sometimes even then is not very much!)
Yet many hobbyists get bogged down when they try to write programs more complicated than simple games or 'Hex- to- decimal' converters (our postbag suggests that about 25 per cent of all programs are Hex- to- decimal converters!). You need some sort of 'design' skill before you can write complex software, and the skill has to be learnt - no one is born a programmer.
Structured programming teaches that skill. We've shown the (albeit imperfect) structure of a Basic compiler, and the way it was designed, to illustrate just how you could tackle a big programming project. May the ZIP be with you!
coupon

Original text © 1984 Simon N Goodwin. Used with permission.
The ZIP Compiler offer is now closed ... but an updated printed manual is still available from Simon, with old and new programs.

Home Contents KwikPik