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



Mastering Machine Code on Your Spectrum

part 4 of 8 - from ZX Computing Apr/May'83



Following in her series, Toni Baker, author of "Mastering

Machine Code on your ZX81", transforms your Spectrum into a

musical machine.





Long, long ago in a galaxy far, far away, great battles were

waged between the humanoids and the space invaders, the

spaceships and the asteroids. This world was brought to your

attention with the coming of the video age - first in

arcades, and now in home computers like the Spectrum. In the

comfort of your own home you can gently soothe away all your

frustrations by killing untold millions of malevolent

aliens, fighting with mystical dragons to rescue beautiful

princes from evil wizards, or testing your intelligence with

maze games and mastermind puzzles. After all - what else are

computers for?



In another sector of the galaxy lay-accountants and

businessfolk ponder over the strings of figures being reeled

off by the ZX Printer telling them to the nearest penny how

much tax they can fiddle before they get caught, or staring

for hours at the bland bar-charts and friendly graphs

plotting current profit returns against the popularity of

'Crossroads'. After all, computers weren't designed for

playing games - or were they?





Strumming your Spectrum



Then one day, as I sat drinking coffee and chatting away to

my fellow compatriots, wishing I could play the guitar as

well as they, a friend introduced me to a new concept. Maybe

computers have a purpose in life beyond simple sport and

science. Surely computers like the ZX81 (for this was a long

time ago) had meaning in the fields of art and music and

culture. A program, it was suggested, could be viewed as a

work bf art, with the programmer being the artist. If this

were so then most of the programs we see around us are

functional - analogous to chairs or tables - they were not,

in general, beautiful - analogous to a painting or a piece

of music. It is to this friend that I dedicate this article

and, in particular, the program which goes with it.



This is called Cathy's Program, the original version of

which appeared in my book Mastering Machine Code On Your

ZX81 and was written for the Sinclair ZX81. This new updated

version, however, is written for the ZX Spectrum. Although

its basic structure is the same, the individual parts have

needed to be entirely rewritten.



The purpose of the program is to turn the Spectrum keyboard

into a musical one, so that each key produces a different

note, and continues to produce it for as long as the key is

held down. The diagram in Fig.2a shows which key produces

which note; there are two octaves, with the lower two rows

producing notes from middle C upwards, and the upper two

rows the next octave above this. The program is entirely in

machine code and once set in motion will continue to run

until you break out by pressing Break (Caps Shift and Space)

as normal.





New wave music



A small amount of explanation is required before the listing

will make sense, and so the first thing I ought to do is

explain the principle by which notes are produced on the

Spectrum. The most important instruction is OUT (FE),A. The

Spectrum can only produce one type of sound - that is, one

type of waveform - essentially, a square wave or a

rectangular wave. A square wave is a wave which at any

instant in time may be either at HIGH potential or at LOW

potential; it may never be at an intermediate potential.



Here's what the instruction OUT (FE),A does: suppose A

contains the (binary) number 'xxxnxgrb; (each letter

represents a binary digit). The xs are for our purposes

effectively meaningless, but the other letters: n, g, r and

b are quite important. They switch hardware devices on and

off (see Fig.1).



Bits 2, 1 and 0 then control the overall colour output to

the screen. (In practice it is only the BORDER colours which

may be changed in this way - the screen colours are

controlled by the attribute bytes).



The principle of creating music then is to create a square

wave. The procedure for doing this is 'short delay / OUT

(FE),xxx1xxxx / short delay / OUT (FE),xxx0xxxx / repeat for

as many cycles as required'. Note that doing this will

automatically change the BORDER colour. If you wish to avoid

this then you must slightly modify the procedure to 'short

delay / OUT (FE),xxx1xbbb / short delay / OUT (FE),xxx0xbbb

/ repeat for as many cycles as required' where bbb

represents the current BORDER colour number in binary.





On that note ...



Before we look at the finished program, I'd like to

introduce you to one of the subroutines in the ROM. The

subroutine is called KEY-SCAN, and its effect is to

determine which keys, if any, are currently depressed. You

can use the subroutine simply by the instruction CALL

KEY-SCAN (CD 8E02). The machine code registers will all be

wiped out by the subroutine so, if you wish to preserve

them, you must PUSH them onto the stack and then POP them on

return. Register DE will contain the final output of the

subroutine as shown in Fig.3. Also, in the case of two or

more keys being pressed simultaneously, the zero flag will

be RESET. In all other cases, the zero flag will be SET.



The key codes mentioned in the above description are in all

cases a number between 00 and 27. A different number is

returned for each key. The codes themselves are listed in

Fig.2b; you can see for yourselves that the keys are covered

in what at first glance seems to be a very strange order.



There is one final point I have to make before we can turn

the Spectrum into a musical instrument. Little things called

Interrupts. Fifty times a second, the Spectrum hardware

sends a little pulse down one of the pins connected to the

Z80 chip. When this happens, one of the following sequences

of things will happen, depending upon a previously unheard

of flag called the (IFF1 Interrupt Flip/Flop one). (The

people who name these things must have some sense of

humour!):



If IFF1 = 0 then: do nothing.



If IFF1 = 1 then: Stack all registers onto the machine

stack;

CALL 0038 is executed - this does the following:

increment the system variable FRAMES;

scan the keyboard, updating the system variables KSTATE and

LAST_K.

POP all registers from the stack and carry on as before.



The normal state of the flag IFF1 is one, so that all

programs, machine code or BASIC, are slowed down because the

subroutine at 0038 is executed 50 times a second without our

knowledge or consent. With regard to music, it means the

exact timing we require in order to produce square waves of

the right wavelength will be totally wrong since we shall

have no idea as to whether or when the interrupt routine

will be carried out in any given cycle. In order to overcome

this problem, it is necessary to reset IFF1 to zero so that

the above sequence of events will not be carried out. The

instruction DI (Disable Interrupts) is equivalent to saying

LET IFF1 =0, and so this, then, is the instruction we need.



When the Spectrum, in normal use, waits for a key to be

pressed, what is really happening is that it is waiting for

KSTATE to change. Note that this can only happen if IFF1 =

1, for otherwise the subroutine at 0038 will never be called

and the Spectrum will just sit there waiting forever, while

the poor old user can do nothing but gnash teeth and throw

bricks at the television. In order to prevent this from

happening EI, (Enable Interrupts or LET IFF1=1) must be

executed before returning to BASIC. Any machine code program

which runs while the interrupts are disabled may only scan

the keyboard by using IN r,(FE) instructions, or by CALLing

KEY-SCAN, not by examining KSTATE or LAST_K.



Figure 4, then, is the final result: Cathy's Program for the

Spectrum. Despite its lengthy appearance, it is actually

quite short and doesn't take very long to feed in at all. To

all musicians out there - behold your new instrument!



In my next article I shall continue on the theme of

creativity, but with attention turned toward the visual,

rather than the audial.





- Fig.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 



A breakdown of the individual letters of A in the instruction, OUT (FE),A



b: 0 = switch the blue  gun off, 1 = switch the blue  gun on.

r: 0 = switch the red   gun off, 1 = switch the red   gun on.

g: 0 = switch the green gun off, 1 = switch the green gun on.

n: 0 = switch the note generator to LOW  potential,

   1 = switch the note generator to HIGH potential.





- Fig.2a  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 



Which key on the Spectrum produces which note? There are two

octaves, the bottom two rows producing notes above middle C

and the top two rows producing the next octave above that.

(Note that the sharp (#) notes are indicated with an asterisk.)



 --    --    --    --    --    --    --    --    --    --

[  ]  [  ]  [C*]  [D*]  [  ]  [F*]  [G*]  [A*]  [  ]  [  ]

 --    --    --    --    --    --    --    --    --    --



   --    --    --    --    --    --    --    --    --    --

  [  ]  [C ]  [D ]  [E ]  [F ]  [G ]  [A ]  [B ]  [C ]  [  ]

   --    --    --    --    --    --    --    --    --    --



     --    --    --    --    --    --    --    --    --    --

    [  ]  [C*]  [D*]  [  ]  [F*]  [G*]  [A*]  [  ]  [  ]  [  ]

     --    --    --    --    --    --    --    --    --    --



 ----    --    --    --    --    --    --    --    --    ----

[    ]  [C ]  [D ]  [E ]  [F ]  [G ]  [A ]  [B ]  [C ]  [    ]

 ----    --    --    --    --    --    --    --    --    ----





- Fig.2b  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 



The codes, and how they are allocated on the keys of the Spectrum.



 --    --    --    --    --    --    --    --    --    --

[24]  [1C]  [14]  [0C]  [04]  [03]  [0B]  [13]  [1B]  [23]

 --    --    --    --    --    --    --    --    --    --



   --    --    --    --    --    --    --    --    --    --

  [25]  [1D]  [15]  [0D]  [05]  [02]  [0A]  [12]  [1A]  [22]

   --    --    --    --    --    --    --    --    --    --



     --    --    --    --    --    --    --    --    --    --

    [26]  [1E]  [16]  [0E]  [06]  [01]  [09]  [11]  [19]  [21]

     --    --    --    --    --    --    --    --    --    --



 ----    --    --    --    --    --    --    --    --    ----

[ 27 ]  [1F]  [17]  [0F]  [07]  [00]  [08]  [10]  [18]  [ 20 ]

 ----    --    --    --    --    --    --    --    --    ----





- Fig.3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 



The contents of the register DE.



SITUATION               VALUE OF DE

No key at all           FFFF

Caps Shift only         FF27

Symbol Shift only       FF18

Both Shifts together    2718

Any key without Shift   FFaa, where aa is the key code of the key concerned.

Any key with Caps Shift 27aa, where aa is the key code of the key concerned.

Any key with Symb Shift 18aa, where aa is the key code of the key concerned.

Any two keys together   aabb, where aa and bb are the key codes concerned.





- Fig.4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 



Cathy's program.



9E93464B  NOTES  G   G#  G+  F+#  Keys B, H, Y and 6

0050A9B4         -   F+  F#  F    Keys 5, T, G and V

8A813D42         A   A#  A+  G+#  Keys N, J, U and 7

5C5600C1         D+# E+  -   E    Keys 4, R, F and C

78003539         B   -   B+  A+#  Keys M, K, I and 8

6962CFDD         C+  D+  D#  D    Keys 3, E, D and X

70003200         C+# -   C++ -    Keys Symbol Shift, L, O and 9

0070ECFD         -   C+  C#  C    Keys 2, W, S and Z

00000000         -   -   -   -    Keys Space, Enter, P and 0

00000000         -   -   -   -    Keys 1, Q, A and Caps Shift



00        SOUND  NOP              This subroutine causes a

00               NOP              very short delay - the exact

00               NOP              timing of which is determined

10FB             DJNZ SOUND       by B, before sounding

D3FE             OUT (FE),A       a pulse.

C9               RET



call here:

3A485C    START  LD A,(BORDCR)    Bits 5, 4 and 3 contain the BORDER colour.

1F               RRA

1F               RRA

1F               RRA

E607             AND 07           A: BORDER colour

F610             OR 10            A: BORDER colour but with bit 4 set

4F               LD C,A           C: BORDER colour + bit 4 set

F3               DI               Disable Interrupts

C5        LOOP   PUSH BC          Preserve the value of C

CD8E02           CALL KEY_SCAN    Scan the keyboard

C1               POP BC           Restore the value of C

212027           LD HL,2720       HL: the key value for 'Caps Shift Space'

A7               AND A            Reset Carry flag

ED52             SBC HL,DE        Compare key pressed (if any)

                                  with 'Caps Shift Space'

281B             JR Z,EXIT        Exit program if desired

7B               LD A,E           A: key code (ignoring Shifts)

3C               INC A

28EF             JR Z,LOOP        Loop if no key pressed

AF               XOR A            A: zero

57               LD D,A           DE: key code ignoring Shifts

21????           LD HL,NOTES

19               ADD HL,DE        Point HL to note value in table

46               LD B,(HL)        B: note value

B8               CP B             Compare B with zero

28E5             JR Z,LOOP        Loop if no note on that key

79               LD A,C           A: BORDER colour (bit 4: 1)

C5               PUSH BC          Preserve the value of B

CD????           CALL SOUND       Generate first half cycle

C1               POP BC           Restore the value of B

E607             AND 07           A: BORDER colour (bit 4: 0)

CD????           CALL SOUND       Generate second half cycle

18D8             JR LOOP          Repeat sequence

FB        EXIT   EI               Enable Interrupts

C9               RET              End of routine



[In the accompanying program file ZX83044]

[these addresses have been used:         ]

[       NOTES: 60000: EA60               ]

[       SOUND: 60040: EA88               ]

[       START: 60048: EA90               ]

[The routine is 102 bytes long.       JG.]



--

Another Fine Product transcribed by:

Jim Grimwood (jimg@globalnet.co.uk), Weardale, England

--

