A TOUCH OF CULTURE | ||||||||
MUSICMusic from your TV speaker? Is it possible? More to the point - is it possible on a ZX? The answer is yes!As you know, your machine is designed to work without sound. It does make a kind of horrible buzzing noise, but hardly anything you'd want to make music out of. The manual itself tells us to turn the volume right down so as to cut the noise out completely. The little computer, on the other hand, has a mind of its own. Completely ignoring its own design specifications it thinks to itself "Anything a bigger computer can do, I can do better", and as a result of this rebellion you'll find that REAL MUSICAL NOTES can be produced with just a tiny speck of machine code. Those of you who have tried the music routines in Interface are undoubtedly thinking to yourselves "Huh! I've heard this so called 'music' - it's rubbish!" Well I assure you this is not the same thing. The reason? Well one big advantage machine code does have over BASIC is precision - and this program is in machine code, not BASIC. The music is musical. You can even tune it if you have a tuning fork handy. This is called CATHY'S PROGRAM, dedicated to someone who believes computers should be artful, not just attack you with space invaders. The machine code is best stored in a REM statement. The addresses given in the listing assume you have a NEW ROM machine. If you have an OLD ROM machine all you have to change is the addresses (although you will have to supply two of the subroutines yourself [(KSCAN and FINDCHR)] - see chapter ten). Cathy's Program
If you store the whole machine code routine in a single REM statement in line one [(of size 77 characters)], then you only need one more line of BASIC to make the program complete. This is line 2 RUN USR 16558, which calls the machine code from the address labelled START. Delete any extra lines you may have, and SAVE the program a couple of times before you RUN it. You now have two octaves at your disposal - the keyboard below shows where the notes are. A fair number of tunes may be played quite successfully. Always run the program in the FAST mode - it's not that the speed makes the notes sound differently - it's simply that the program doesn't work AT ALL when in SLOW. Download available for 16K ZX81 -> chapter12-cathys.p.[I've moved BASIC line 2 to 3, added 2 FAST and 4 STOP.]Download available for 16K ZX80 -> chapter12-cathys.o.[Addresses used: 4A1A to 4B3A is occupied by HEXLD3D, NOTES is 4B3B, PAUSE is 4B62, START is 4B67, KSCAN is 4BA5 and FINDCHR is 4BC6.]The notes as listed in the program are roughly right, but exactly how they sound will depend mainly on your television set (incidentally you may have to alter the tuning slightly to get the best sound quality), so in case you need to "re-tune" the notes, here's how you do it: The data at the start of the program (labelled NOTES) contains one byte for each note. A zero indicates there is no note on that key. The data is in the following order:
To alter the frequency of any note just change the byte of data that represents it. To make a note higher you must decrease the number, and to make it lower you must increase the number. THE PROGRAM'S DISADVANTAGESThe biggest disadvantage is the lack of a RET instruction anywhere in the program, which means that once you enter the program you can never leave. You can cure this by adding a few lines somewhere near the START label. As an exercise, see if you can adjust the program so that it returns to BASIC whenever the key SHIFT-ZERO (rubout) is pressed (HINT: HL equals FCEF when it returns from KSCAN).The second disadvantage is that if you press SHIFT while playing notes some very random things seem to happen. See if you can make the shift key inactive (except for breaking out as described above) by adding a SET 0,H instruction somewhere in the program. ZX music is a fascinating subject, and it is possible to store in data a list of notes to be played, and how long each note is to be played - a tune in other words. I'll leave that one to you though, because the only real way to learn is by experimenting. We'll leave the subject of music altogether now and turn to something slightly different: pictures.... PICTURESThis is yet another program which relies on the artistic ability of the human operator. It is strictly for NEW ROM users ONLY, but it is intended to be run in the FAST mode. You will require at least four-K for this.The program stores in memory three or more different pictures, and cycles through them one at a time, displaying each on the screen for as long as you want. A "picture" can be anything whatsoever - you can compose it out of graphics symbols, letters, spaces, inverse asterisks - whatever. The first thing you do it to reserve some memory in which to store these pictures. If you have 4K type POKE 16388,182/POKE 16389,70/NEW for three pictures, or POKE 16388,206/POKE 16389,73/NEW for two pictures. If you have 16K you can find enough room for about twenty pictures. To work out how far down you have to move RAMTOP with 16K just start off with 32768 and subtract 793 for each picture. Now you're ready: Write the following machine code to a REM statement in line one:
The address labelled PICTURE1 refers to those people using 4K. For those same people PICTURE2 would be 49CE and PICTURE3 would be 4CE7. If only two pictures will be used you should omit PICTURE1, not PICTURE3. If you have 16K you have more or less limitless freedom. In the interests of simplicity you could use addresses 5000, 5400, 5800, 5C00, and so on. Now type POKE 16389,77 followed by CLS if you are using 4K, or if you are using 16K but earlier POKEd 16389 with a number less than 77. Now write a BASIC program (without deleting line one) which prints a picture. The last line of this program should be RAND USR 16514. 4K users may find themselves running out of space. If this is so you'll just have to give up and make do with two pictures instead of three. A useful fact to know is that if you make the first line of your program (first apart from the REM that is) POKE 16418,0 then you can print to all twenty-four lines of the screen. Even PRINT AT 23,0; works! Now delete all the PRINT lines. DO NOT TYPE NEW. Change the address in the machine code to that of a different picture, and write a new BASIC program printing a different picture, again ending in RAND USR 16514. Do this until every picture you wish to cycle through has been stored. Now move RAMTOP back to the address described in paragraph three. Type NEW. Now you are ready.... For the first time in the book we are going to make use of the PAUSE facility. The instruction CALL PAUSE will display the TV picture indefinitely, or until a key is pressed. To PAUSE for a specific number of TV frames it is necessary to LD (FRAMES) with the required number first. Enter this machine language program:
This is the complete program. See how it works - the first picture is copied into the display file using LDIR, and the PAUSE subroutine is called from the ROM. Then when the PAUSE is over the next picture is copied onto the screen, and so on. The value of HL is not changed between each picture, since they are stored in memory immediately after each other. If they are not (for instance if you are using easy to remember addresses) you'll need to alter the program slightly. HL should point to the start of a new picture each time round the loop. The BASIC program to go with this is
In this way you can break out of the program at the end of the sequence. Alternatively you could replace the last RET instruction by JR PICTURES, which would eliminate the need for a second BASIC instruction. You can of course always break out during a PAUSE. LIFEIn the last program in this chapter we turn the tables slightly. We humans have been artistic for long enough - now it's time to let the computers take their turn....This program is called LIFE - it is supposed to represent the birth/growth/death cycle of a colony of cells living on a square grid. It produces rather fascinating results. Before your very eyes you see a constantly evolving pattern - starting off totally random - which finishes sometimes with the ultimate death of the cell colony, sometimes with a fixed and unmoving cell structure which has reached equilibrium, and sometimes with a continuous cycle of patterns, called dynamic equilibrium. It really is amazing to watch. LIFE was invented in 1970 by a man called John Conway of Cambridge University, and it's rather surprising that the Tate Gallery hasn't yet got a copy of it. Although it is in fact about the growth of cells which follow hard and fast mathematical rules it in reality becomes a rather effective pattern generating algorithm. The principle of LIFE is very simple. A grid - usually square - is dotted with approximately one quarter of its available squares filled with cells. These positions are usually chosen entirely at random. This configuration of the grid is called GENERATION ZERO. Successive generations are then worked out by a fairly simple to understand principle. Each square on the grid has eight neighbouring squares. These squares either contain another cell or they are empty. Every cell with two neighbouring cells; or with three neighbouring cells, will survive to the next generation, but no other cells will survive. A new cell is born in every empty space which has precisely three neighbouring cells, but no other cells are born. With these fairly simple rules it is rather surprising that the game should produce the rather impressive results that it does. In this version of LIFE our grid is sixteen by sixteen, because of course sixteen is a fairly easy number to work with in hexadecimal. Further, our grid is rather strangely constructed in a curved space continuum, meaning that every square on the left hand edge is connected to the corresponding square on the right hand edge, and vice versa, also every square on the top edge is connected to the corresponding square on the bottom edge and vice versa. The program is best run in SLOW, although of course it will run in FAST if you add a PAUSE or INPUT statement. NEW ROM people are advised to store the machine code in a REM statement. OLD ROM people are advised to store the machine code anywhere but a REM statement, since it contains character 76h. The machine code contains exactly one hundred and thirty nine bytes. The surrounding BASIC program is
where START and NEXTGEN are addresses in the machine code program. In the following listing we assume that the first address is 4082. You can quite easily change it if you wish.
If you used the same addresses as in the listing then START is 16522 and NEXTGEN is 16562. SAVE the program. Do not RUN it yet because if you do it will crash! NEW ROM users MUST first of all type POKE 16389,67 followed by NEW, and OLD ROM users should ensure that they have at least 2K of memory. You will then have to reLOAD the program from tape. The first thing you should type is RAND/RANDOMISE. You may now type RUN. An interesting point about this program is that it is capable of producing its own random numbers. The part labelled NEXT does this - you should study how this is achieved, and by all means use the same principle in your own programs. LIFE will print out a randomly constructed generation zero in just ONE SECOND when in the SLOW mode. The successive generations will then be produced at the staggering rate of three and a half generations per second! If you find this is much too rapid you can slow it down by adding a few more lines of BASIC - I suggest Let X=0/LET X=X+1/PRINT AT 17,0;X with the last two being inside the loop - this has the added advantage of telling you how many generations have been shown. Download available for 16K ZX81 -> chapter12-life.p.[As I used HEXLD3D to load this high, the instructions are as follows: Set RAMTOP to 4A00 (18944) with POKE 16389,74/NEW. You don't need to type RAND as I added it to the BASIC program. Type RUN to execute Life and press any key to return to BASIC where you can RUN it again. I did first write Life to a line 1 REM statement but the first 3E76 truncated the BASIC listing, so I wrote it to high memory instead following HEXLD3D. Addresses used: 4A82 to 4B77 is occupied by HEXLD3D, TABLE is 4B82, START is 4B8A (19338), NEXTGEN is 4BB2 (19378) and I relocated DUMP to 4D00.]Finally you should follow the manner in which this program, unlike some other LIFE programs, calculates each new generation entirely on the basis of the previous one. It does not work out the new first row and then calculate the second row by counting the neighbours in the now-changed new first row, the second row is determined by the previous status of the first row (this is what the area of memory labelled DUMP in the machine code listing is for), thus each new generation is correctly set up. There are many other pattern generating programs, some much simpler, but none with the elegance of LIFE. If you own 16K you might like to try writing a 24 by 24 LIFE, or even a 24 by 32 version - remember, in machine code there is nothing to stop you printing on the very bottom two lines. The biggest LIFE you could possibly hope to achieve is 48 by 64 using white quarter-squares for cells, but that would be quite a complicated program. If you feel really enthusiastic you might like to have a bash at this monumental task. I will let that decision rest with your sanity. The next chapter completes the discussion on DRAUGHTS and leaves you with the horrifying prospect of completing the program.... |