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