home *** CD-ROM | disk | FTP | other *** search
- WHEN IT'S VIEWED AS AN ALREADY ASSEMBLED 'MODULE'. ╘HE SECOND GOES THROUGH AN
- OVERVIEW OF THE MUSIC AND INSTRUMENT DATA FORMAT, AND IS GREAT FOR GETTING AN
- OVERALL FEEL FOR WHAT THE CODE IS DOING. ╘HE THIRD DESCRIPTION LOOKS AT THE
- VARIOUS SECTIONS OF THE CODE, AND HOW THEY COME TOGETHER.
-
-
- ╚OW TO USE THE SOURCECODE:
- *************************
-
- JSR MUSIC+0 TO INITIALIZE THE MUSIC NUMBER IN THE ACCUMULATOR
- JSR MUSIC+3 TO PLAY THE MUSIC
- JSR MUSIC+6 TO STOP THE MUSIC AND QUIETEN ╙╔─
-
- ╘HE MUSIC IS SUPPOSED TO RUN AT 50╚Z, OR 50 TIMES PER SECOND. ╘HEREFORE
- ╨┴╠ USERS CAN RUN THE MUSIC ROUTINE OFF THE ╔╥╤ LIKE THIS:
-
- LDA #$00 ; INIT MUSIC NUMBER 0
- JSR MUSIC+0
- SEI ; INSTALL THE IRQ AND A RASTER COMPARE
- LDA #<IRQ
- LDX #>IRQ
- STA $314
- STX $315
- LDA #$1B
- STA $D011
- LDA #$01
- STA $D01A
- LDA #$7F
- STA $DC0D
- CLI
- LOOP =*
- JMP LOOP ; ENDLESS LOOP (MUSIC IS NOW PLAYING OFF INTERRUPT :-)
-
- IRQ =*
- LDA #$01
- STA $D019
- LDA #$3C
- STA $D012
-
- INC $D020 ; PLAY MUSIC, AND SHOW A RASTER FOR THE TIME IT TAKES
- JSR MUSIC+3
- DEC $D020
-
- LDA #$14
- STA $D018
- JMP $EA31
-
- ╔F THIS METHOD IS USED ON ╬╘╙├ MACHINES, THEN THE MUSIC WILL BE RUNNING AT
- 60╚Z AND WILL SOUND MUCH TO FAST - POSSIBLY IT MIGHT SOUND TERRIBLE. ╔'M
- AFRAID YOU'LL HAVE TO PUT UP WITH THIS UNLESS ┘╧╒ ARE GOOD ENOUGH TO MAKE A
- ├╔┴ INTERRUPT AT 50╚Z. ┴S ╔ HAVN'T HAD TO WORRY ABOUT ╬╘╙├ USERS BEFORE,
- PERHAPS SOMEONE WILL SEND ME THE BEST WAY TO DO THIS...
-
- [┼D. ╬OTE: ┘OU COULD ALSO KEEP A COUNTER FOR THE ╔╥╤ AND DON'T EXECUTE IT
- EVERY 6 INTERRUPT. ╘HIS WILL MAKE IT THE RIGHT SPEED ALTHOUGH THE BEST
- SOLUTION IS FOR MODIFYING THE ├╔┴ TO 50╚Z LIKE HE MENTIONS ABOVE.]
-
- ╚OW THE MUSIC DATA IS ARRANGED:
- ******************************
-
- 1. ╘HE MUSIC 'MODULE' CONTAINS ONE OR MORE SONGS.
-
- ┼ACH ╥╚ MUSIC IS MADE UP OF A 'BUNCH' OF SONGS IN A SINGLE MODULE. ╘HUS
- THE 'MODULE' CAN HAVE THE TITLE MUSIC, IN-GAME MUSIC, AND THE GAME-OVER MUSIC
- ALL USING THE SAME PLAYROUTINE (AND EVEN THE SAME INSTRUMENTS :). ╘HE SOURCE
- THAT APPEARS BELOW ONLY HAS THE ONE SONG IN IT, AND THE MUSIC NUMBER IS
- AUTOMATICALLY SET TO 0 AS A RESULT (LINE 20). ╘HE LABEL 'SONGS' IS WHERE YOU
- WANT TO LOOK FOR THE POINTERS TO THE SONGS IF YOU WANT TO CHANGE THIS.
-
- 2. ┼ACH SONG IS MADE UP OF THREE TRACKS.
-
- ╫E ALL KNOW THAT THERE ARE ONLY 3 CHANNELS ON THE ╙╔─ CHIP, SO THERE ARE
- ALSO 3 TRACKS - ONE FOR EACH CHANNEL. ╫HEN ╔ SAID 'POINTERS TO THE SONGS'
- ABOVE, ╔ WAS THEREFORE REFERRING TO 'POINTERS TO THE THREE TRACKS THAT MAKE UP
- THE SONG'...HENCE WE ARE LOOKING AT THE LABEL 'SONGS' AGAIN. ┼ACH TRACK NEEDS
- A HIGH AND LOW POINTER, SO THERE ARE 6 BYTES NEEDED TO POINT TO A SONG.
-
- 3. ┼ACH TRACK IS MADE UP OF A LIST OF PATTERN NUMBERS
-
- ┼ACH TRACK CONSISTS OF A LIST OF THE PATTERN NUMBERS IN THE ORDER IN WHICH
- THEY ARE TO BE PLAYED. ╚ERE WE ARE LOOKING AT THE LABELS 'MONTYMAINTR1' AND
- 'MONTYMAINTR2'AND 'MONTYMAINTR3'. ╘HEREFORE ╔ CAN TELL YOU THAT THE INITIAL
- PATTERNS PLAYED IN THIS SONG ARE $11, $12 AND $13 ON CHANNELS 1,2 AND 3
- RESPECTIVELY. ╘HE TRACK IS EITHER ENDED WITH A $FF OR $FE BYTE. ┴ $FF MEANS
- THAT THE SONG NEEDS TO BE LOOPED WHEN THE END OF THE TRACK IS REACHED (LIKE
- THE MONTY MAIN TUNE), WHILE A $FE MEANS THAT THE SONG IS ONLY TO BE PLAYED
- ONCE. ╘HE CURRENT OFFSET INTO THE TRACK IS OFTEN CALLED THE CURRENT ╨╧╙╔╘╔╧╬
- FOR THAT TRACK.
-
- 4. ┴ PATTERN CONSISTS OF A SEQUENCE OF NOTES.
-
- ┴ PATTERN CONTAINS THE DATA THAT SAYS WHEN THE NOTES SHOULD BE PLAYED, HOW
- LONG THEY SHOULD BE PLAYED FOR, AT WHAT PITCH, WITH WHAT INSTRUMENT, SHOULD
- THERE BE ┴─╙╥, SHOULD THERE BE BENDING (PORTAMENTO) OF THE NOTES ETC. ┼ACH
- PATTERN IS ENDED WITH A $FF BYTE, AND WHEN THIS IS ENCOUNTERED, THE NEXT
- PATTERN IN THE TRACK WILL BE PLAYED. ┼ACH NOTE HAS UP TO A 4 BYTE
- SPECIFICATION.
-
- - ╘HE FIRST BYTE IS ALWAYS THE LENGTH OF THE NOTE FROM 0-31 OR 0-$1F IN HEX.
- ┘OU WILL NOTICE THAT THE TOP THREE BITS ARE NOT USED FOR THE LENGTH OF THE
- NOTE, SO THEY ARE USED FOR OTHER THINGS.
- - ┬IT#5 SIGNALS NO RELEASE NEEDED. - ┬IT#6 SIGNALS THAT THIS NOTE IS
- APPENDED TO THE LAST ONE (NO ATTACK/ETC). - ┬IT#7 SIGNALS THAT A NEW
- INSTRUMENT OR PORTAMENTO IS COMING UP.
-
- - ╘HE SECOND BYTE IS AN OPTIONAL BYTE, AND IT HOLDS THE INSTUMENT NUMBER TO
- USE OR THE PORTAMENTO VALUE (IE A BENDED NOTE). ╘HIS BYTE WILL BE NEEDED
- ACCORDING TO WHETHER BIT#7 OF THE FIRST BYTE IS SET OR NOT...IE IF THE 1ST
- BYTE WAS NEGATIVE, THEN THIS BYTE IS NEEDED.
- - ╔F THE SECOND BYTE IS POSITIVE, THEN THIS IS THE NEW INSTRUMENT NUMBER.
- - ╔F THE SECOND BYTE IS NEGATIVE, THEN THIS IS A BENDED NOTE (PORTAMENTO).
- AND THE VALUE IS THE SPEED OF THE PORTAMENTO (EXCEPT FOR BITS #7 AND #0)
- ┬IT #0 OF THE PORTAMENTO BYTE DETERMINES THE DIRECTION OF THE BEND.
- - ┬IT#0 = 0 THEN PORTAMENTO IS UP.
- - ┬IT#0 = 1 THEN PORTAMENTO IS DOWN.
-
- - ╘HE THIRD BYTE OF THE SPECIFICATION IS THE PITCH OF THE NOTE. ┴ PITCH OF
- 0 IS THE LOWEST ├ POSSIBLE. ┴ PITCH OF 12 OR $├(HEX) IS THE NEXT HIGHEST
- ├ ABOVE THAT. ╘HESE PITCHES ARE DENOTED FAIRLY UNIVERSALLY AS EG. '├-1' AND
- FOR SHARPS EG. '─#3'. ╬OTICE THAT THIS ROUTINE USES PITCHES OF HIGHER THAN
- 72 ($48) WHICH IS C-6 :-)
-
- - ╘HE FOURTH BYTE IF IT EXISTS WILL DENOTE THE END OF THE PATTERN.
- IE. ╔F THE NEXT BYTE IS A $FF, THEN THIS IS THE END OF THE PATTERN.
-
- ╬╧╘┼: ╔ HAVE LABELLED THE VARIOUS BYTES WITH NUMBERS FOR CONVENIENCE. ┬EAR
- IN MIND THAT SOME OF THESE ARE OPTIONAL, SO IF THE SECOND BYTE IS NOT NEEDED,
- THEN ╔ WILL SAY THAT THE PITCH OF THE NOTE COMING UP IS THE 'THIRD BYTE',
- EVEN THOUGH IT ISN'T REALLY.
-
- ╧KAY, HERE ARE SOME EXAMPLES:
-
- EG. $84,$04,$24 MEANS THAT THE LENGTH OF THE NOTE IS 4 (FROM THE LOWER 5 BITS
- OF THE FIRST BYTE), THAT THE INSTRUMENT TO USE IS INSTRUMENT NUMBER 4
- (THE SECOND BYTE, AS INDICATED BY BIT #7 OF THE FIRST BYTE), AND THAT THE
- PITCH OF THE NOTE IS $24 OR C-3.
- EG. $─6,$98,$25,$╞╞ MEANS THAT THE LENGTH OF THE NOTE IS 22 ($16), THAT THIS
- NOTE SHOULD BE APPENDED TO THE LAST, THAT THE SECOND BYTE IS A PORTAMENTO
- (AS BOTH 1ST AND 2ND BYTES -VE!), THAT THE PORTAMENTO IS GOING UP (AS
- BIT#0 = 0) WITH A SPEED OF 24 ($18), THAT THE PITCH OF THE NOTE IS $25
- OR C#3, AND THAT THIS IS THE END OF THE PATTERN.
-
- ╔T DOESN'T GET ANY HARDER THAN THAT!! ─ID YOU REALISE THAT THIS IS EXACTLY
- THE WAY THAT ╥OB ╚UBBARD MADE THE MUSIC!! ╚E WORKED OUT SOME MUSICAL IDEAS
- ON HIS CHEAP (MUSICAL) KEYBOARD, AND TYPED THE NOTES INTO HIS ASSEMBLER IN
- HEX, JUST LIKE THIS.
-
-
- 5. ╘HE INSTRUMENTS ARE AN 8 BYTE DATA STRUCTURE.
-
- ┘OU ARE LOOKING AT THE LABEL 'INSTR' AT THE BOTTOM OF THE SOURCECODE. ╘HE
- 8 BYTES WHICH COME ALONG FIRST ARE INSTRUMENT NUMNBER 0, THE NEXT 8 DEFINE
- INSTRUMENT NUMBER 1, ETC. ╚ERE ARE THE MEANINGS OF THE BYTES, BUT ╔ SUGGEST
- THAT YOU CHECK OUT YOUR PROGRAMMING MANUALS IF YOU ARE UNFAMILIAR WITH THESE:
-
- - ┬YTE 0 IS THE PULSE WIDTH LOW BYTE, AND
- - ┬YTE 1 IS THE PULSE WIDTH HIGH BYTE. (ALSO SEE BYTE 7).
-
- - ┬YTE 2 IS THE CONTROL REGISTER BYTE.
- ╘HIS SPECIFIES WHICH TYPE OF SOUND SHOULD BE USED; SINE, SAWTOOTH ETC.
-
- - ┬YTE 3 IS THE ATTACK AND DECAY VALUES, AND
- - ┬YTE 4 IS THE SUSTAIN AND RELEASE VALUES.
- ╘HE NOTE'S VOLUME IS ALTERED ACCORDING TO THESE VALUES. ╫HEN THE ATTACK AND
- DECAY ARE OVER, THE VOLUME OF THE NOTE IS HELD AT THE SUSTAIN LEVEL. ╫HEN
- LENGTH OF A NOTE IS OVER, A RELEASE IS DONE THROUGH THE 'GATE' BIT IN ╙╔─.
-
- - ┬YTE 5 IS THE VIBRATO DEPTH FOR THE INSTRUMENT.
-
- - ┬YTE 6 IS THE PULSE SPEED.
- ╘IMBRE IS CREATED BY CHANGING THE SHAPE OF THE WAVEFORM EACH 50TH OF A
- SECOND, AND THIS IS THE MOST COMMON WAY OF ACHIEVING IT. ╘HE SHAPE OF
- THE PULSE WAVEFORM CHANGES FROM SQUARE TO A VERY RECTANGULAR AT A SPEED
- ACCORDING TO THIS BYTE.
- ╬.┬. IF YOU ARE INTERESTED IN HOW THE PULSE VALUE NUMBER WORKS, THEN
- E-MAIL ME SOMETIME, AS ╔ FOUND THIS OUT (EXHAUSTIVELY) A FEW DAYS AGO!
-
- - ┬YTE 7 IS THE INSTRUMENT FX BYTE, AND IS THE MAJOR THING WHICH CHANGES
- BETWEEN DIFFERENT MUSIC ROUTINES. ┼ACH BIT IN THIS BYTE DETERMINES WHETHER
- THIS INSTRUMENT WILL HAVE A CERTAIN EFFECT IN IT.
- - ┬IT#0 SIGNALS THAT THIS IS A DRUM. ─RUMS ARE MADE FROM A NOISE CHANNEL
- AND ALSO A FAST FREQUENCY DOWN, WITH FAST DECAY. ┬ASS DRUMS USE A SQUARE
- WAVE, AND ONLY THE FIRST 50TH OF A SECOND IS A NOISE CHANNEL. ╘HIS IS
- THE TELL-TALE INSTRUMENT THAT GIVES AWAY A ╥OB ╚UBBARD ROUTINE! ╚IHATS
- AND OTHER DRUMS USE NOISE ALL THE TIME.
- - ┬IT#1 SIGNALS A 'SKYDIVE'. ╘HIS IS A SLOWER FREQUENCY DOWN, THAT ╔ THINK
- SOUNDS LIKE SOMEBODY YELLING AS THEY FALL OUT OF A PLANE .. ┴╚╚╚╚HHHHGH..
- ..HENCE ╔ CALL IT A SKYDIVE!!
- - ┬IT#2 SIGNALS AN OCTAVE ARPEGGIO. ╔T'S A VERY LIMITED ARPEGGIO ROUTINE IN
- THIS SONG. ╠ISTEN FOR THE ARPEGGIO AND THE SKYDIVE WHEN COMBINED, WHICH
- IS USED ALOT IN ╚UBBARD SONGS.
- - ┴LL THE OTHER BITS HAVE NO MEANING IN THIS MUSIC, BUT WERE USED ALOT IN
- LATER MUSIC FOR THE FX.
-
- ┴ BIG REASON THAT ╔ PRESENTED THIS EARLY ROUTINE, WAS BECAUSE THERE WAS NOT
- TOO MUCH IN THE WAY OF SPECIAL FX TO CONFUSE YOU. ┴S A RESULT, YOU CAN
- CONCENTRATE ON THE GUTS OF THE CODE INSTEAD OF THE SPECIAL FX :-)
-
-
- ╚OW THE SOURCECODE WORKS:
- ************************
-
- ╘HE ROUTINES AT THE TOP OF THE SOURCECODE ARE CONCERNED WITH TURNING THE
- MUSIC ON AND OFF, AND YOU WILL SEE THAT THIS IS DONE THROUGH A VARIABLE CALLED
- 'MSTATUS' (OR MUSIC STATUS). ╔F MSTATUS IS SET TO $├0, THEN THE MUSIC IS
- TURNED OFF AND ╙╔─ IS QUIETENED, THEREAFTER MSTATUS IS SET TO $80 WHICH MEANS
- THAT THE MUSIC IS STILL OFF, BUT ╙╔─ DOESN'T NEED TO BE QUIETENED AGAIN. ╫HEN
- THE MUSIC IS INITIALIZED, THEN MSTATUS IS GIVEN A VALUE OF $40 WHICH KICKS IN
- THE FURTHER INITIALIZATION STUFF. ╔F MSTATUS IS ANY OTHER VALUE, THEN THE
- MUSIC IS BEING PLAYED. ╞OR ANY OF THE INITIALIZATION STUFF TO HAVE ANY MEANING
- TO YOU, YOU OFCOURSE HAVE TO UNDERSTAND THE REST OF THE PLAYROUTINE :-)
-
- ┴FTER WE HAVE GOT PAST THE ON/OFF/INIT STUFF, WE ARE AT THE LABEL CALLED
- 'CONTPLAY' AT AROUND LINE 100. ╘HE FIRST THING YOU SHOULD NOTICE IS THAT THIS
- IS THE START OF A HUGE LOOP THAT IS DONE *3* TIMES - ONCE FOR EACH CHANNEL.
- ╘HE LOOP REALLY *IS* HUGE, AS IT ENDS RIGHT ON THE LAST FEW LINES OF THE CODE
- :-)
-
- ╬OW THAT WE ARE TALKING ABOUT ROUTINES WITHIN THE LOOP, WE ARE TALKING ABOUT
- THESE ROUTINES BEING APPLIED TO THE CHANNELS INDEPENDANTLY. ╘HERE ARE 2 MAIN
- ROUTINES WITHIN THE LOOP, ONE IS CALLED ╬OTE╫ORK, AND THE OTHER IS CALLED
- ╙OUND╫ORK. ╬OTE╫ORK CHECKS TO SEE WHETHER A NEW NOTE IS NEEDED ON THIS
- CHANNEL, AND IF IT IS, THEN THE NOTEDATA IS FETCHED AND STUFF IS INITIALIZED.
- ╔F NO NOTE IS NEEDED, THEN ╙OUND╫ORK IS CALLED WHICH PROCESSES THE INSTRUMENTS
- AND DOES THE PORTAMENTO.
-
- ╬OTE╫ORK FIRST CHECKS THE SPEED AT WHICH THE NOTES ARE FETCHED. ╔F THE DELAY
- IS STILL OCCURRING, THEN NEW NOTES ARE NOT NEEDED AND SOUNDWORK IS CALLED.
- ╬.┬. THAT THE SPEED FOR ═ONTY ON THE ╥UN IS 1, WHICH MEANS THAT A NOTE OF
- LENGTH $1F WILL LAST FOR 64 CALLS TO THE ROUTINE (IE JUST OVER A SECOND). ╔F
- THE SPEED OF THE SONG IS RESET, THEN ╬OTE╫ORK DECREMENTS THE LENGTH OF THE
- CURRENT NOTE. ╫HEN THE LENGTH OF THE CURRENT NOTE HITS $FF (-1) THEN A NEW
- NOTE IS NEEDED, OTHERWISE ╙OUND╫ORK IS JUMPED TO.
-
- ╘HE DATA FOR A NEW NOTE IS COLLECTED AT THE LABEL 'GETNEWNOTE'. ╔N THE
- SIMPLEST CASE, THIS INVOLVES GETTING THE NEXT BYTES OF DATA FROM THE CURRENT
- PATTERN ON THIS CHANNEL, BUT IF THE END OF THE PATTERN IS REACHED, THEN THE
- NEXT PATTERN NUMBER IS FETCHED BY REFERENCE TO THE CURRENT POSITION WITHIN
- THIS CHANNEL'S TRACK. ╔N AN EVEN MORE COMPLEX SITUATION, THE END OF A TRACK IS
- REACHED, AND THE CURRENT POSITION NEEDS TO BE RESET TO 0 BEFORE THE NEXT
- PATTERN NUMBER CAN BE FOUND.
-
- ┘OU CAN SEE QUITE CLEARLY IN THIS PART OF THE ROUTINE WHERE THE LENGTH OF
- THE NOTE IS COLLECTED, AND IT IS DETERMINED WHETHER A 2ND BYTE IS NEEDED,
- WHERE THE PITCH IS COLLECTED, AND THE END OF THE SONG CHECKED. ┘OU CAN ALSO
- SEE WHERE SOME OF THE DATA IS COLLECTED FROM THE CURRENT INSTRUMENT AND JAMMED
- INTO THE ╙╔─ REGISTERS.
-
- ╙OUND╫ORK IS CALLED IF NO NEW NOTES ARE NEEDED, AND IT PROCESSES THE
- INSTRUMENTS AND DOES THE PORTAMENTO ETC. ╘HIS PART OF THE ROUTINE IS NEATLY
- EXPRESSED IN SECTIONS WHICH ARE REALLY WELL COMMENTED AND QUITE EASY TO
- UNDERSTAND.
-
- - ╘HE FIRST THING THAT OCCURS IN ╙OUND╫ORK IS THAT THE 'GATE BIT' OF ╙╔─ IS
- SET WHEN THE LENGTH OF THE NOTE IS OVER - THIS CAUSES A RELEASE OF THE NOTE.
-
- - ╘HE VIBRATO ROUTINE IS QUITE INEFFICIENT, BUT IT'S PRETTY GOOD FOR 1985!
- ╧FCOURSE VIBRATO IS IMPLEMENTED BY RAISING AND LOWERING THE PITCH OF THE
- NOTE EVER-SO-SLIGHTLY CAUSING THE NOTE TO 'FLOAT'. ╘HE AMOUNT OF THE
- VIBRATO IS DETERMINED IN THE CURRENT INSTRUMENT.
-
- - ╘HE PULSEWORK ROUTINE CHANGES THE PULSEWIDTH BETWEEN SQUARE WAVE AND VERY
- RECTANGULAR WAVE ACCORDING TO THE PULSESPEED IN THE CURRENT INSTRUMENT.
- (IE. IT CHANGES THE SOUND OF THE INSTRUMENT AND THUS ALTERS THE 'TIMBRE')
- ╘HE ROUTINE GOES BACKWARDS AND FORWARDS BETWEEN THE TWO; AND SWITCHES
- WHEN ONE EXTREMITY IS REACHED. ╔T'S INTERESTING TO NOTE THAT THE CURRENT
- VALUES OF THE PULSE WIDTH ARE ACTUALLY STORED IN THE INSTRUMENT :-)
-
- - ╨ORTAMENTO IS ACHIEVED BY ADDING/SUBTRACTING AN AMOUNT OF FREQUENCY TO
- THE CURRENT FREQUENCY EACH TIME THIS PART OF THE ROUTINE IS CALLED.
-
- - ╘HE INSTRUMENT FX ROUTINES ARE ALSO REALLY EASY TO FIGURE OUT, AS THEY ARE
- WELL COMMENTED. ┬OTH THE DRUMS AND THE SKYDIVE DO A VERY FAST FREQUENCY
- DOWN, SO IT IS THE MOST SIGNIFICANT BYTE OF THE FREQUENCY WHICH IS REDUCED
- .. AND NOT 16-BIT MATHS (MATH?!) ╘HE ARPEGGIO IS ONLY AN OCTAVE ARPEGGIO,
- SO FOR THE FIRST 50TH OF A SECOND, THE CURRENT NOTE IS PLAYED, AND FOR
- THE NEXT 50TH OF A SECOND, CURRENT NOTE+12 IS PLAYED, FOLLOWED BY THE
- CURRENT NOTE AGAIN ETC.
- ( ╔F YOU DON'T KNOW WHAT AN ARPEGGIO IS..IT'S GENERALLY WHEN THE NOTES OF )
- ( A CHORD ARE PLAYED INDIVIDUALLY IN A RAPID SUCCESSION. ╔T PRODUCES A )
- ( 'FULL' SOUND DEPENDING ON THE SPEED OF THE ARPEGGIO. ╔N MOST CASES THE )
- ( NOTE IS CHANGED 50 TIMES PER SECOND, WHICH GIVES A VERY NICE SOUND. ╔F )
- ( YOU HAVE LISTENED TO SOME COMPUTER MUSIC, THEN YOU WILL HAVE DEFINATELY )
- ( LISTENED TO AN ARPEGGIOS ALL THE TIME, EVEN IF YOU DON'T REALIZE IT! )
-
-
- ╞INAL ╘HOUGHTS:
- **************
-
- *┬OUNCE* ╔'M FINALLY NEAR THE END OF THIS ARTICLE! ╔T HAS BEEN ALOT OF WORK
- TO TRY TO EXPLAIN THIS ROUTINE, BUT ╔'M GLAD THAT ╔'VE DONE IT *GRIN* ╔F YOU
- HAVE ANY QUESTIONS THEN PLEASE FEEL FREE TO E-MAIL ME, OR EVEN E-MAIL ├RAIG IF
- IT'S AFTER ┴UGUST 1993 AND ╔'LL MAKE SURE THAT ╔ LEAVE A FORWARDING ADDRESS
- WITH HIM. ┴LSO, PLEASE FEEL FREE TO E-MAIL ME AND TELL ME WHAT YOU THINK OF
- THIS ARTICLE. ╔ WILL ONLY BE BOTHERED WRITING MORE OF THE SAME IF ╔ KNOW THAT
- SOMEONE IS FINDING THEM USEFUL/INTERESTING. ┴LSO E-MAIL ME IF YOU ARE
- INTERESTED IN ┴MIGA OR ╙╘ MUSIC TOO, AS ╔'VE DONE ALOT ON BOTH OF THOSE
- MACHINES.
-
- ╔'M NOT SURE WHETHER ├RAIG WILL BE PUTTING THE ACTUAL SOURCECODE BELOW THIS
- TEXT, OR IN SOME KIND OF ┴PPENDIX. ╔N EITHER CASE, ╔ ╙╚┴╠╠ TAKE ALL LEGAL
- RESPONSIBILTY FOR PUBLISHING ╥OB ╚UBBARD'S ROUTINE. ├RAIG WAS QUITE RELUCTANT
- TO PUBLISH THE ROUTINE IN HIS NET-MAG BECAUSE OF COPYRIGHT REASONS. ┴S A
- POST-GRADUATE LAW STUDENT THAT WILL BE WORKING AS A COMMERCIAL LAWYER
- (ATTOURNEY FOR ┴MERICANS :) SPECIALIZING IN COPYRIGHT/PATENTS FOR COMPUTER
- SOFTWARE/HARDWARE STARTING ┴UGUST THIS YEAR, ╔ DON'T BELIEVE THAT THERE ARE
- ANY PRACTICAL LEGAL CONSEQUENCES FOR ME.
-
- ╔ WOULD HAVE GIVEN AN ARM OR A LEG FOR A COMMENTED ╥OB ╚UBBARD SOURCECODE IN
- THE PAST, SO ╔ HOPE YOU ENJOY THIS VALUABLE OFFERING.
- -----------------------------------------------------------------------------
- ;ROB HUBBARD
- ;MONTY ON THE RUN MUSIC DRIVER
-
- ;THIS PLAYER WAS USED (WITH SMALL MODS)
- ;FOR HIS FIRST APPROX 30 MUSIX
-
- .ORG $8000
- .OBJ MOTR
-
- JMP INITMUSIC
- JMP PLAYMUSIC
- JMP MUSICOFF
-
-
- ;====================================
- ;INIT MUSIC
-
- INITMUSIC =*
-
- LDA #$00 ;MUSIC NUM
- LDY #$00
- ASL
- STA TEMPSTORE
- ASL
- CLC
- ADC TEMPSTORE ;NOW MUSIC NUM*6
- TAX
-
- - LDA SONGS,X ;COPY PTRS TO THIS
- STA CURRTRKHI,Y ;MUSIC'S TRACKS TO
- INX ;CURRENT TRACKS
- INY
- CPY #$06
- BNE -
-
- LDA #$00 ;CLEAR CONTROL REGS
- STA $D404
- STA $D40B
- STA $D412
- STA $D417
-
- LDA #$0F ;FULL VOLUME
- STA $D418
-
- LDA #$40 ;FLAG INIT MUSIC
- STA MSTATUS
-
- RTS
-
-
- ;====================================
- ;MUSIC OFF
-
- MUSICOFF =*
-
- LDA #$C0 ;FLAG MUSIC OFF
- STA MSTATUS
- RTS
-
-
- ;====================================
- ;PLAY MUSIC
-
- PLAYMUSIC =*
-
- INC COUNTER
-
- BIT MSTATUS ;TEST MUSIC STATUS
- BMI MOFF ;$80 AND $C0 IS OFF
- BVC CONTPLAY ;$40 INIT, ELSE PLAY
-
-
- ;==========
- ;INIT THE SONG (MSTATUS $40)
-
- LDA #$00 ;INIT COUNTER
- STA COUNTER
-
- LDX #3-1
- - STA POSOFFSET,X ;INIT POS OFFSETS
- STA PATOFFSET,X ;INIT PAT OFFSETS
- STA LENGTHLEFT,X ;GET NOTE RIGHT AWAY
- STA NOTENUM,X
- DEX
- BPL -
-
- STA MSTATUS ;SIGNAL MUSIC PLAY
- JMP CONTPLAY
-
-
- ;==========
- ;MUSIC IS OFF (MSTATUS $80 OR $C0)
-
- MOFF =*
-
- BVC + ;IF MSTATUS $C0 THEN
- LDA #$00
- STA $D404 ;KILL VOICE 1,2,3
- STA $D40B ;CONTROL REGISTERS
- STA $D412
-
- LDA #$0F ;FULL VOLUME STILL
- STA $D418
-
- LDA #$80 ;FLAG NO NEED TO KILL
- STA MSTATUS ;SOUND NEXT TIME
-
- + JMP MUSICEND ;END
-
-
- ;==========
- ;MUSIC IS PLAYING (MSTATUS OTHERWISE)
-
- CONTPLAY =*
-
- LDX #3-1 ;NUMBER OF CHANELS
-
- DEC SPEED ;CHECK THE SPEED
- BPL MAINLOOP
-
- LDA RESETSPD ;RESET SPEED IF NEEDED
- STA SPEED
-
-
- MAINLOOP =*
-
- LDA REGOFFSETS,X ;SAVE OFFSET TO REGS
- STA TMPREGOFST ;FOR THIS CHANNEL
- TAY
-
-
- ;CHECK WHETHER A NEW NOTE IS NEEDED
-
- LDA SPEED ;IF SPEED NOT RESET
- CMP RESETSPD ;THEN SKIP NOTEWORK
- BEQ CHECKNEWNOTE
- JMP VIBRATO
-
- CHECKNEWNOTE =*
-
- LDA CURRTRKHI,X ;PUT BASE ADDR.W OF
- STA $02 ;THIS TRACK IN $2
- LDA CURRTRKLO,X
- STA $03
-
- DEC LENGTHLEFT,X ;CHECK WHETHER A NEW
- BMI GETNEWNOTE ;NOTE IS NEEDED
-
- JMP SOUNDWORK ;NO NEW NOTE NEEDED
-
-
- ;==========
- ;NOTEWORK
- ;A NEW NOTE IS NEEDED. GET THE PATTERN
- ;NUMBER/CC FROM THIS POSITION
-
- GETNEWNOTE =*
-
- LDY POSOFFSET,X ;GET THE DATA FROM
- LDA ($02),Y ;THE CURRENT POSITION
-
- CMP #$FF ;POS $FF RESTARTS
- BEQ RESTART
-
- CMP #$FE ;POS $FE STOPS MUSIC
- BNE GETNOTEDATA ;ON ALL CHANNELS
- JMP MUSICEND
-
- ;CC OF $FF RESTARTS THIS TRACK FROM THE
- ;FIRST POSITION
-
- RESTART =*
-
- LDA #$00 ;GET NOTE IMMEDIATELY
- STA LENGTHLEFT,X ;AND RESET PAT,POS
- STA POSOFFSET,X
- STA PATOFFSET,X
- JMP GETNEWNOTE
-
-
- ;GET THE NOTE DATA FROM THIS PATTERN
-
- GETNOTEDATA =*
-
- TAY
- LDA PATPTL,Y ;PUT BASE ADDR.W OF
- STA $04 ;THE PATTERN IN $4
- LDA PATPTH,Y
- STA $05
-
- LDA #$00 ;DEFAULT NO PORTAMENTO
- STA PORTAVAL,X
-
- LDY PATOFFSET,X ;GET OFFSET INTO PTN
-
- LDA #$FF ;DEFAULT NO APPEND
- STA APPENDFL
-
- ;1ST BYTE IS THE LENGTH OF THE NOTE 0-31
- ;BIT5 SIGNALS NO RELEASE (SEE SNDWORK)
- ;BIT6 SIGNALS APPENDED NOTE
- ;BIT7 SIGNALS A NEW INSTRUMENT
- ; OR PORTAMENTO COMING UP
-
- LDA ($04),Y ;GET LENGTH OF NOTE
- STA SAVELNTHCC,X
- STA TEMPLNTHCC
- AND #$1F
- STA LENGTHLEFT,X
-
- BIT TEMPLNTHCC ;TEST FOR APPEND
- BVS APPENDNOTE
-
- INC PATOFFSET,X ;PT TO NEXT DATA
-
- LDA TEMPLNTHCC ;2ND BYTE NEEDED?
- BPL GETPITCH
-
- ;2ND BYTE NEEDED AS 1ST BYTE NEGATIVE
- ;2ND BYTE IS THE INSTRUMENT NUMBER(+VE)
- ;OR PORTAMENTO SPEED(-VE)
-
- INY
- LDA ($04),Y ;GET INSTR/PORTAMENTO
- BPL +
-
- STA PORTAVAL,X ;SAVE PORTAMENTO VAL
- JMP ++
-
- + STA INSTRNR,X ;SAVE INSTR NR
-
- + INC PATOFFSET,X
-
- ;3RD BYTE IS THE PITCH OF THE NOTE
- ;GET THE 'BASE FREQUENCY' HERE
-
- GETPITCH =*
-
- INY
- LDA ($04),Y ;GET PITCH OF NOTE
- STA NOTENUM,X
- ASL ;PITCH*2
- TAY
- LDA FREQUENZLO,Y ;SAVE THE APPROPRIATE
- STA TEMPFREQ ;BASE FREQUENCY
- LDA FREQUENZHI,Y
- LDY TMPREGOFST
- STA $D401,Y
- STA SAVEFREQHI,X
- LDA TEMPFREQ
- STA $D400,Y
- STA SAVEFREQLO,X
- JMP +
-
- APPENDNOTE =*
-
- DEC APPENDFL ;CLEVER EH?
-
-
- ;FETCH ALL THE INITIAL VALUES FROM THE
- ;INSTRUMENT DATA STRUCTURE
-
- + LDY TMPREGOFST
- LDA INSTRNR,X ;INSTR NUM
- STX TEMPSTORE
- ASL ;INSTR NUM*8
- ASL
- ASL
- TAX
-
- LDA INSTR+2,X ;GET CONTROL REG VAL
- STA TEMPCTRL
- LDA INSTR+2,X
- AND APPENDFL ;IMPLEMENT APPEND
- STA $D404,Y
-
- LDA INSTR+0,X ;GET PULSE WIDTH LO
- STA $D402,Y
-
- LDA INSTR+1,X ;GET PULSE WIDTH HI
- STA $D403,Y
-
- LDA INSTR+3,X ;GET ATTACK/DECAY
- STA $D405,Y
-
- LDA INSTR+4,X ;GET SUSTAIN/RELEASE
- STA $D406,Y
-
- LDX TEMPSTORE ;SAVE CONTROL REG VAL
- LDA TEMPCTRL
- STA VOICECTRL,X
-
-
- ;4TH BYTE CHECKS FOR THE END OF PATTERN
- ;IF EOP FOUND, INC THE POSITION AND
- ;RESET PATOFFSET FOR NEW PATTERN
-
- INC PATOFFSET,X ;PREVIEW 4TH BYTE
- LDY PATOFFSET,X
- LDA ($04),Y
-
- CMP #$FF ;CHECK FOR EOP
- BNE +
-
- LDA #$00 ;END OF PAT REACHED
- STA PATOFFSET,X ;INC POSITION FOR
- INC POSOFFSET,X ;THE NEXT TIME
-
- + JMP LOOPCONT
-
-
- ;==========
- ;SOUNDWORK
- ;THE INSTRUMENT AND EFFECTS PROCESSING
- ;ROUTINE WHEN NO NEW NOTE WAS NEEDED
-
- SOUNDWORK =*
-
- ;RELEASE ROUTINE
- ;SET OFF A RELEASE WHEN THE LENGTH OF
- ;THE NOTE IS EXCEEDED
- ;BIT4 OF THE 1ST NOTE-BYTE CAN SPECIFY
- ;FOR NO RELEASE
-
- LDY TMPREGOFST
-
- LDA SAVELNTHCC,X ;CHECK FOR NO RELEASE
- AND #$20 ;SPECIFIED
- BNE VIBRATO
-
- LDA LENGTHLEFT,X ;CHECK FOR LENGTH OF
- BNE VIBRATO ;EXCEEDED
-
- LDA VOICECTRL,X ;LENGTH EXCEEDED SO
- AND #$FE ;START THE RELEASE
- STA $D404,Y ;AND KILL ADSR
- LDA #$00
- STA $D405,Y
- STA $D406,Y
-
-
- ;VIBRATO ROUTINE
- ;(DOES ALOT OF WORK)
-
- VIBRATO =*
-
- LDA INSTRNR,X ;INSTR NUM
- ASL
- ASL
- ASL ;INSTR NUM*8
- TAY
- STY INSTNUMBY8 ;SAVE INSTR NUM*8
-
- LDA INSTR+7,Y ;GET INSTR FX BYTE
- STA INSTRFX
-
- LDA INSTR+6,Y ;GET PULSE SPEED
- STA PULSEVALUE
-
- LDA INSTR+5,Y ;GET VIBRATO DEPTH
- STA VIBRDEPTH
- BEQ PULSEWORK ;CHECK FOR NO VIBRATO
-
- LDA COUNTER ;THIS IS CLEVER!!
- AND #7 ;THE COUNTER'S TURNED
- CMP #4 ;INTO AN OSCILLATING
- BCC + ;VALUE (01233210)
- EOR #7
- + STA OSCILATVAL
-
- LDA NOTENUM,X ;GET BASE NOTE
- ASL ;NOTE*2
- TAY ;GET DIFF BTW NOTE
- SEC ;AND NOTE+1 FREQUENCY
- LDA FREQUENZLO+2,Y
- SBC FREQUENZLO,Y
- STA TMPVDIFLO
- LDA FREQUENZHI+2,Y
- SBC FREQUENZHI,Y
-
- - LSR ;DIVIDE DIFFERENCE BY
- ROR TMPVDIFLO ;2 FOR EACH VIBRDEPTH
- DEC VIBRDEPTH
- BPL -
- STA TMPVDIFHI
-
- LDA FREQUENZLO,Y ;SAVE NOTE FREQUENCY
- STA TMPVFRQLO
- LDA FREQUENZHI,Y
- STA TMPVFRQHI
-
- LDA SAVELNTHCC,X ;NO VIBRATO IF NOTE
- AND #$1F ;LENGTH LESS THAN 8
- CMP #8
- BCC +
-
- LDY OSCILATVAL
-
- - DEY ;DEPENDING ON THE OSC
- BMI + ;VALUE, ADD THE VIBR
- CLC ;FREQ THAT MANY TIMES
- LDA TMPVFRQLO ;TO THE BASE FREQ
- ADC TMPVDIFLO
- STA TMPVFRQLO
- LDA TMPVFRQHI
- ADC TMPVDIFHI
- STA TMPVFRQHI
- JMP -
-
- + LDY TMPREGOFST ;SAVE THE FINAL
- LDA TMPVFRQLO ;FREQUENCIES
- STA $D400,Y
- LDA TMPVFRQHI
- STA $D401,Y
-
-
- ;PULSE-WIDTH TIMBRE ROUTINE
- ;DEPENDING ON THE CONTROL/SPEED BYTE IN
- ;THE INSTRUMENT DATASTRUCTURE, THE PULSE
- ;WIDTH IS OF COURSE INC/DECREMENTED TO
- ;PRODUCE TIMBRE
-
- ;STRANGELY THE DELAY VALUE IS ALSO THE
- ;SIZE OF THE INC/DECREMENTS
-
- PULSEWORK =*
-
- LDA PULSEVALUE ;CHECK FOR PULSEWORK
- BEQ PORTAMENTO ;NEEDED THIS INSTR
-
- LDY INSTNUMBY8
- AND #$1F
- DEC PULSEDELAY,X ;PULSEDELAY-1
- BPL PORTAMENTO
-
- STA PULSEDELAY,X ;RESET PULSEDELAY
-
- LDA PULSEVALUE ;RESTRICT PULSE SPEED
- AND #$E0 ;FROM $00-$1F
- STA PULSESPEED
-
- LDA PULSEDIR,X ;PULSEDIR 0 IS UP AND
- BNE PULSEDOWN ;1 IS DOWN
-
- LDA PULSESPEED ;PULSE WIDTH UP
- CLC
- ADC INSTR+0,Y ;ADD THE PULSESPEED
- PHA ;TO THE PULSE WIDTH
- LDA INSTR+1,Y
- ADC #$00
- AND #$0F
- PHA
- CMP #$0E ;GO PULSEDOWN WHEN
- BNE DUMPULSE ;THE PULSE VALUE
- INC PULSEDIR,X ;REACHES MAX ($0EXX)
- JMP DUMPULSE
-
- PULSEDOWN =*
-
- SEC ;PULSE WIDTH DOWN
- LDA INSTR+0,Y
- SBC PULSESPEED ;SUB THE PULSESPEED
- PHA ;FROM THE PULSE WIDTH
- LDA INSTR+1,Y
- SBC #$00
- AND #$0F
- PHA
- CMP #$08 ;GO PULSEUP WHEN
- BNE DUMPULSE ;THE PULSE VALUE
- DEC PULSEDIR,X ;REACHES MIN ($08XX)
-
- DUMPULSE =*
-
- STX TEMPSTORE ;DUMP PULSE WIDTH TO
- LDX TMPREGOFST ;CHIP AND BACK INTO
- PLA ;THE INSTR DATA STR
- STA INSTR+1,Y
- STA $D403,X
- PLA
- STA INSTR+0,Y
- STA $D402,X
- LDX TEMPSTORE
-
-
- ;PORTAMENTO ROUTINE
- ;PORTAMENTO COMES FROM THE SECOND BYTE
- ;IF IT'S A NEGATIVE VALUE
-
- PORTAMENTO =*
-