.........1.........2.........3.........4.........5.........6.........7.........8

Mastering Machine Code on Your Spectrum
part 5 of 8 - from ZX Computing Jun/Jul'83

Machine code master, Toni Baker, shows you how to
incorporate machine code within your BASIC programs with an
incredible program to add visual accompaniment to your
stereo.


I'd like to cheat a bit now, if I may, by giving you a BASIC
program. (Shrieks of horror!) Well, it has got some machine
code in it, but nothing new. This is a lesson in how to
incorporate machine code into BASIC, for finding a use for
all these weird and wonderful routines that keep cropping
up. Almost the hardest task you have in programming is the
hanging around at bus stops and tedious dinner parties
waiting for that most illusive of qualities - inspiration.

The machine code routine in question was featured in part
three of this series of articles - it's a routine to change
the colours of PAPER and INK throughout the whole screen
faster than you can say 'The sixth sick sheik's sixth
sheep's sick' without falling over. The BASIC that surrounds
it is new, however. This is a program to impress your next
door neighbours and fanatics of laser shows, or a new way of
running a disco. This is visual accompaniment to your
stereo!


Sound's great!

It's not technically a sound- to- light unit, for the
program has no way of knowing whether or not your stereo is
even switched on, let alone what's playing on it. What it
is, however, is a very good optical illusion of sound and
vision being synchronised. What you do is RUN the program
and input answers to the various questions asked, put your
favourite record on, switch the lights off and close the
curtains, then just sit back while your brain dances round
in circles.

The program is featured in Figs. 1 and 2. You should enter
the machine code first (using a BASIC program to do so) and
then delete this BASIC program to input the one given. Take
a look at this now.

I'll now give you some examples on how to RUN the program.
Type RUN. (Easy so far, isn't it?) For the question 'NUMBER
OF LINES', you should input (say) 5. For 'INK', input 'INT
(4*RND)+4', and for 'PAPER' input '0'. Finally, for 'STARS?'
you should input 'Y'. This is just an example - try it out
for yourself.


What's the plot?

The program has a couple of extra features which you ought
to know about. RUN 200 enables you to define the initial INK
and the initial PAPER colours. For instance, RUN 200 and
then input 0 / 7 / 4 / '7-X' / '7-Y' / 'Y' / ('/' counts as
ENTER). RUN 400 will SAVE and VERIFY the program and the
machine code.

I won't turn the above program into machine code just yet.
Before I do, I'll give you some information on PLOT and
DRAW.

CALL PLOT_BC (Hex CD E522) requires B to hold the Y
co-ordinate, and C to hold the X co-ordinate. This will PLOT
the required point. Bit zero of P_FLAG (5C91) must be zero
for OVER 0 or one for OVER 1.

CALL DRAW_3 (Hex CDBA24) requires B to hold the absolute
value of the Y parameter, and C the absolute value of the X
parameter. If Y is greater than or equal to zero then D
should hold 01 Hex, otherwise D should hold FF Hex. If X is
greater than or equal to zero then E should hold 01 Hex,
otherwise E should hold FF Hex. The sequence of instructions
LD HL,2758 / EXX must be carried out between CALL DRAW_3 and
RET (to BASIC) otherwise the Spectrum will crash.


Transformation time

We still can't rewrite the program into machine code yet,
since we don't have a routine for INT (X*RND). It is
possible to write a simple random number subroutine which
creates random numbers between 0000 and FFFF Hex in the HL
register pair, so take a look at Fig.3 which illustrates
such a subroutine. It works using the random number seed
already used by the ROM, but does not actually call the
ROM's RND routine (since this is highly impractical). The
subroutine does, however, work in more or less the same way
as RND - it takes the value of the system variable SEED, and
multiplies it by some constant. Only the remainder modulo
65536d is taken as the new result. This is not quite RND,
but it does give fairly random results.

Figure Four, on the other hand, is another kettle of fish
altogether. This is a subroutine I've called RAND_A in order
to distinguish it from the subroutine in Fig.3. It requires
that A contains a number between 00 and A-1. Of particular
note is the subroutine MULT which is called from within
RAND__A; this is a subroutine which will multiply the number
held in the A register by the number held in the DE register
pair. The result will be formed in the AHL register triplet
(the result will always fit in three bytes). RAND_A works
just like the ROM's RND routine - it takes a value, SEED,
which is multiplied by 4B, and then the remainder is found
from a division by Hex 10001, less one. Can you see how the
program calculates this remainder? To find the random number
required, this new seed is multiplied by A and the high part
only becomes the random number.

Now we are almost ready to turn the program Patterns
entirely into machine code. Well - not quite entirely as we
still can't do VAL. Let's ignore that part for the time
being and leave VAL in BASIC. I'd like you now to study
Figs. 5 and 6, which list the revised program, now called
Patterns 2. If you now compare it with Figs. 1 and 2, see if
you can work out how the translation is achieved. Note that
the instruction CALL RAND_A is used - this is a reference to
the subroutine in Fig. 4.

You can use any addresses you like for this program. I chose
to use the following:

Label	Hex	Dec
RAND_A	7000	28672
MULT	7021	28705
FIND_A	7030	28720
PL_DR	703B	28731
INIT	7078	28792
MAIN	7098	28824
P_VAL	7105	28933
P_OVER	7106	28934
P_DRAW	7107	28935
LINES	7108	28936
INK	7109	28937
PAPER	710A	28938
STARS	710B	28939
ARRAY	710C	28940

It is essential, however, that P_OVER and P_DRAW be
adjacent, and also that ARRAY points to the start of a
segment of spare RAM.


- Fig.1 The program, Patterns: part one - the BASIC - - - - - - - - - - - - 

  10 INPUT "NUMBER OF LINES";n
  20 DIM x(n+1): DIM y(n+1)
  30 INPUT "INK";x$            (use the keyword INK here)
  40 INPUT "PAPER";y$          (use the keyword PAPER here)
  50 INPUT "STARS?";a$: LET s=a$="N" OR a$="n"
  60 CLS: LET p=1
  70 LET p1=p+1: IF p1>n+1 THEN LET p1=1
  80 LET p2=p1+1: IF p2>n+1 THEN LET p2=1
  90 PLOT x(p1),y(p1)
  95 DRAW x(p2)-x(p1),y(p2)-y(p1)
 100 PLOT OVER s;x(p1),y(p1)
 105 DRAW OVER 1;x(p2)-x(p1),y(p2)-y(p1)
 110 LET x(p1)=INT (256*RND)
 120 LET y(p1)=INT (176*RND)
 130 PLOT x(p),y(p)
 140 DRAW x(p1)-x(p),y(p1)-y(p)
 150 LET x=VAL x$: LET y=VAL y$
 160 POKE 32769,x: POKE 32770,y: LET p=p1+USR 32768
 170 GO TO 70
 200 INPUT "INITIAL INK";x
 210 INPUT "INITIAL PAPER";y
 220 GO TO 10
 400 SAVE "PATTERNS" LINE 430
 410 SAVE "PATTERNS" CODE 32768,34
 420 VERIFY "": VERIFY "" CODE: STOP
 430 CLEAR 32767: LOAD "" CODE: STOP	[I added the CLEAR. JG.]


- Fig.2 The program, Patterns: part two - the machine code  - - - - - - - - 

01????    PATTERNS LD BC,????     To be POKEd by BASIC
78                 LD A,B
76                 HALT
D3FE               OUT (FE),A
78                 LD A,B
87                 ADD A,A
87                 ADD A,A
87                 ADD A,A
81                 ADD A,C
218D5C             LD HL,ATTR_P
77                 LD (HL),A
210058             LD HL,ATTRS
110158             LD DE,ATTRS+1
01FF02             LD BC,02FF
77                 LD (HL),A
EDB0               LDIR
C9                 RET


- Fig.3 The machine code random number subroutine - - - - - - - - - - - - - 

D5        RAND     PUSH DE
2A765C             LD HL,(SEED)
54                 LD D,H
5D                 LD E,L
29                 ADD HL,HL
29                 ADD HL,HL
19                 ADD HL,DE
29                 ADD HL,HL
29                 ADD HL,HL
29                 ADD HL,HL
19                 ADD HL,DE
22765C             LD (SEED),HL
D1                 POP DE
C9                 RET


- Fig.4 The INT(A*RND) routine  - - - - - - - - - - - - - - - - - - - - - - 

C5        RAND_A   PUSH BC
D5                 PUSH DE
E5                 PUSH HL
F5                 PUSH AF
3E4B               LD A,4B
ED5B765C           LD DE,(SEED)
CD????             CALL MULT
A7                 AND A
4F                 LD C,A
ED42               SBC HL,BC
3801               JR C,AA
2B                 DEC HL
22765C    AA       LD (SEED),HL
54                 LD D,H
5D                 LD E,L
F1                 POP AF
CD????             CALL MULT
E1                 POP HL
D1                 POP DE
C1                 POP BC
C9                 RET
0608      MULT     LD B,08
210000             LD HL,0000
29        LOOP     ADD HL,HL
17                 RLA
3003               JR NC,BB
19                 ADD HL,DE
CE00               ADC A,00
10F7      BB       DJNZ LOOP
C9                 RET


- Fig.5 The program, Patterns2; the BASIC - - - - - - - - - - - - - - - - - 

  10 INPUT "NUMBER OF LINES";n
  20 POKE lines,n: LET n=USR init
  30 INPUT "INK";x$
  40 INPUT "PAPER";y$
  50 INPUT "STARS?";a$: POKE stars,a$="N" OR a$="n"
  60 POKE ink,VAL x$: POKE paper,VAL y$
  70 LET n=USR main
  80 GO TO 60
 200 INPUT "INITIAL INK";x
 210 INPUT "INITIAL PAPER";y
 220 GO TO 10
 400 SAVE "P2" LINE 450
 410 SAVE "P2" CODE rand_a,263
 420 VERIFY ""
 430 VERIFY "" CODE
 440 STOP
 450 CLEAR rand_a-1: LOAD "" CODE	[I added the CLEAR. JG.]


- Fig.6 The program, Patterns2; the machine code  - - - - - - - - - - - - - 

D5        FIND_A   PUSH DE
11????             LD   DE,ARRAY
6F                 LD   L,A
2600               LD   H,#00
29                 ADD  HL,HL
19                 ADD  HL,DE
D1                 POP  DE
C9                 RET
C5        PL_DR    PUSH BC
D5                 PUSH DE
7A                 LD   A,D
D5                 PUSH DE
CD????             CALL FIND_A
4E                 LD   C,(HL)
23                 INC  HL
46                 LD   B,(HL)
C5                 PUSH BC
3A????             LD   A,(P_OVER)
32915C             LD   (P_FLAG),A
CDE522             CALL PLOT_BC
C1                 POP  BC
D1                 POP  DE
7B                 LD   A,E
CD????             CALL FIND_A
7E                 LD   A,(HL)
23                 INC  HL
1E01               LD   E,#01
91                 SUB  C
3004               JR   NC,PD2
ED44               NEG
1EFF               LD   E,#FF
4F        PD2      LD   C,A
7E                 LD   A,(HL)
1601               LD   D,#01
90                 SUB  B
3004               JR   NC,PD3
ED44               NEG
16FF               LD   D,#FF
47        PD3      LD   B,A
3A????             LD   A,(P_DRAW)
32915C             LD   (P_FLAG),A
CDBA24             CALL DRAW_3
D1                 POP  DE
C1                 POP  BC
C9                 RET
210040    INIT     LD   HL,D_FILE
110140             LD   DE,D_FILE+1
01FF17             LD   BC,#17FF
3600               LD   (HL),#00
EDB0               LDIR
ED4B????           LD   BC,(LINES-1)
04                 INC  B
21????             LD   HL,ARRAY
AF                 XOR  A
77        IN2      LD   (HL),A
23                 INC  HL
77                 LD   (HL),A
23                 INC  HL
10FA               DJNZ IN2
32????             LD   (P_VAL),A
C9                 RET
ED4B????  MAIN     LD   BC,(P_VAL)
3A????             LD   A,(LINES)
51                 LD   D,C
14                 INC  D
BA                 CP   D
3002               JR   NC,M2
1600               LD   D,#00
5A        M2       LD   E,D
1C                 INC  E
BB                 CP   E
3002               JR   NC,M3
1E00               LD   E,#00
210000    M3       LD   HL,#0000
22????             LD   (P_OVER),HL
CD????             CALL PL_DR
3A????             LD   A,(STARS)
32????             LD   (P_OVER),A
3E01               LD   A,#01
32????             LD   (P_DRAW),A
CD????             CALL PL_DR
7A                 LD   A,D
CD????             CALL FIND_A
3EFF               LD   A,#FF
CD????             CALL RAND_A
77                 LD   (HL),A
23                 INC  HL
3EB0               LD   A,#B0
CD????             CALL RAND_A
77                 LD   (HL),A
5A                 LD   E,D
51                 LD   D,C
210000             LD   HL,#0000
22????             LD   (P_OVER),HL
CD????             CALL PL_DR
7B                 LD   A,E
32????             LD   (P_VAL),A
76                 HALT
3A????             LD   A,(PAPER)
D3FE               OUT  (#FE),A
87                 ADD  A,A
87                 ADD  A,A
87                 ADD  A,A
2A????             LD   HL,(INK)
B5                 OR   L
328F5C             LD   (ATTR_T),A
210058             LD   HL,ATTRS
110158             LD   DE,ATTRS+1
01FF02             LD   BC,#02FF
77                 LD   (HL),A
EDB0               LDIR
215827             LD   HL,#2758
D9                 EXX
C9                 RET


--
Another Fine Product transcribed by:
Jim Grimwood (jimg@globalnet.co.uk), Weardale, England
--
