.........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

--

