;----------------------------------------------------------------------------; ; ; ; D.THOMPSON '88 Soundtrack ; ; ; ; Orchestration, blood, sweat & tears by Jonathan Dunn ; ; ; ; Oh wow (paroxism!) programming by Paul Hughes ; ; ; ; (c) Copyright Ocean Software / Imagine Software / Paul Hughes 1988 ; ; ; ; Ported to DASM 10/11/2004 by Paulie. ; ;----------------------------------------------------------------------------; processor 6502 seg code NUM_OF_TUNES EQU 6 TOPLAY EQU 6-1 ALLOCATION EQU 5*1024+512 DRIVER.LEN EQU DRIVER.END-DRIVER.START DATA.LEN EQU DATA.END-DATA.START PROGRAM.LEN EQU PROG.END-DRIVER.START TOGO EQU ALLOCATION-PROGRAM.LEN BARS EQU $44 ; Bars to skip BARLENGTH EQU 96 ; Beats per bar ; ; ZP - All zero page usage for speed, although only the PC's require ZP ; ZP EQU $20 IA EQU ZP IX EQU ZP+1 IY EQU ZP+2 PC.A EQU ZP+4 PC.B EQU ZP+6 PC.C EQU ZP+8 READ_A EQU ZP+10 READ_B EQU ZP+12 READ_C EQU ZP+14 FROM EQU ZP+16 FRM EQU ZP+18 ; USED BY TESTER TO EQU ZP+20 TO2 EQU ZP+22 SA EQU ZP+24 SX EQU ZP+25 SY EQU ZP+26 ; ------------------------------------ AT EQU $80 FIN EQU 0 ; ; To play the music " JSR REFRESH " every frame ; ; To select a tune " LDX #TUNE_NUMBER " ; " JSR TUNE " ;TUNE_NUMBER:- Load X with... ; 0 = DISQUALIFIED ; 1 = SUCCESS ; 2 = FAIL ; 3 = NEXT EVENT ; 4 = TITLE MUSIC ; 5 = QUALIFY ; ; Music Driver development framework... ; ORG $4000 ; ENT START SEI ; Bin the interrupts LDA #$35 ; ROMS out STA 1 LDA #0 ; Screen & Border black STA $D020 STA $D021 STA $D015 ; Sprites off LDA #$C0 ; Bank 0 STA $DD02 LDA #$15 ; ROM charset STA $D018 LDA #R0 STA $FFFF LDA #0 ; Bar counter variables STA BARCOUNT STA CURRENTBAR LDA #BARS ; Number of beats per bar STA BAR_TEMP LDA #$7F ; Raster interrupts enabled AND $D011 STA $D011 STA $DC0D ; Spurious interrupts cleared LDA $DC0D LDA #1 ; Acknowledge any interrupts STA $D019 STA $D01A LDA #$A0 ; Refresh raster position STA $D012 LDA #$1B ; Screen on, Y centered STA $D011 LDA #$C8 ; X centered STA $D016 LDX #TOPLAY ; Tune to fire up with STX TUNE_NUM JSR TUNE ; Initialise the tune CLI ; Let the interrupts rip LDX #0 CLS LDA #$20 ; Clear the screen STA $0400,X STA $0500,X STA $0600,X STA $0700,X LDA #1 ; White colour RAM STA $D800,X STA $D900,X STA $DA00,X STA $DB00,X INX BNE CLS LDA #50 ; 50hz counter STA FIFTIES LDX #TEXT1 JSR SPRINT LDX #13 ; All this bunf updates the front LDY #24 LDA #>PROGRAM.LEN ; panel JSR HEX INX INX LDA #ALLOCATION JSR HEX INX INX LDA #TOGO JSR HEX INX INX LDA #DATA.LEN JSR HEX INX INX LDA #DRUM_TEXT STA FRM+1 RTS NOTECALC LDY #0 STY TEMP ASL ROL TEMP ASL ROL TEMP CLC ADC #NOTES STA FRM+1 RTS DRUM_TEXT dc.b "DRUM" ; ; KEYSCAN - Entered with desired key in A CARRY SET if key pressed (Debounced) ; KEYSCAN STA KEYTEMP JSR KEYIN BCC NOKEY DEBOUNCE LDA KEYTEMP JSR KEYIN BCS DEBOUNCE SEC NOKEY RTS KEYTEMP dc.b 0 KEYIN STY KEYT PHA LSR LSR LSR TAY LDA COL,Y STA $DC00 PLA AND #7 TAY LDA $DC01 AND ROW,Y BNE NOTPRESS LDA #$FF STA $DC00 LDA $DC01 AND ROW,Y BEQ NOTPRESS SEC JMP GOTKEY NOTPRESS CLC GOTKEY LDY KEYT LDA #$7F STA $DC00 LDA #$FF STA $DC01 RTS KEYT dc.b 0 COL dc.b $FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F ROW dc.b 1,2,4,8,16,32,64,128 S EQU $0400 YTAB dc.w S+[0*40],S+[1*40],S+[2*40],S+[3*40],S+[4*40] dc.w S+[5*40],S+[6*40],S+[7*40],S+[8*40],S+[9*40] dc.w S+[10*40],S+[11*40],S+[12*40],S+[13*40],S+[14*40] dc.w S+[15*40],S+[16*40],S+[17*40],S+[18*40],S+[19*40] dc.w S+[20*40],S+[21*40],S+[22*40],S+[23*40],S+[24*40] CULA dc.b 0 TEMP dc.b 0 RTIME dc.b 0 MAXTIME dc.b 0 TUNE_NUM dc.b 0 DIGITS dc.b "0123456789ABCDEF" FIFTIES dc.b 0 BARCOUNT dc.b 0 CURRENTBAR dc.b 0 BAR_TEMP dc.b 0 NOTES dc.b "C 0C# 0D 0D# 0E 0F 0F# 0G 0G# 0A 0A# 0B 0" dc.b "C 1C# 1D 1D# 1E 1F 1F# 1G 1G# 1A 1A# 1B 1" dc.b "C 2C# 2D 2D# 2E 2F 2F# 2G 2G# 2A 2A# 2B 2" dc.b "C 3C# 3D 3D# 3E 3F 3F# 3G 3G# 3A 3A# 3B 3" dc.b "C 4C# 4D 4D# 4E 4F 4F# 4G 4G# 4A 4A# 4B 4" dc.b "C 5C# 5D 5D# 5E 5F 5F# 5G 5G# 5A 5A# 5B 5" dc.b "C 6C# 6D 6D# 6E 6F 6F# 6G 6G# 6A 6A# 6B 6" dc.b "C 7C# 7D 7D# 7E 7F 7F# 7G 7G# 7A 7REST" ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ; Paste in the driver code here. ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ DRIVER.START EQU . ; ; TUNE - Initialises a tune, entered with tune number in X ; TUNE LDY #0 LDA #0 CLR_VAR STA VAR_START,Y ; Reset all variables to zero INY CPY #VAR_END-VAR_START BNE CLR_VAR LDY #$16 CLRSID LDA #8 ; Set SID test bit so there's no STA SID,Y LDA #0 ; grotty clicking STA SID,Y DEY BPL CLRSID STY MODEBYTE_A ; Reset any non-zero variables ($FF) STY MODEBYTE_B STY MODEBYTE_C LDY #1 STY DURCOUNT.A ; $01 STY DURCOUNT.B STY DURCOUNT.C STY DURATIONON_A STY DURATIONON_B STY DURATIONON_C STY MFL_A STY MFL_B STY MFL_C STY MOD_OFF_A STY MOD_OFF_B STY MOD_OFF_C LDA TUNETABLE.A.L,X ; Initialise the addresses STA PC.A LDA TUNETABLE.A.H,X ; of the tunes into each STA PC.A+1 LDA TUNETABLE.B.L,X ; individual program counter STA PC.B LDA TUNETABLE.B.H,X STA PC.B+1 LDA TUNETABLE.C.L,X STA PC.C LDA TUNETABLE.C.H,X STA PC.C+1 LDA #$0F ; Volume on STA $D418 RTS ; Finito ; ; REFRESH - Called by interrupt, plays the music ; REFRESH LDA MFL_A ; Check if channel A is playing BEQ NOMUSIC_A JSR MUSICA ; Play it NOMUSIC_A LDA MFL_B ; Check if channel B is playing BEQ NOMUSIC_B JSR MUSICB ; Play it NOMUSIC_B LDA MFL_C ; Check if channel C is playing BEQ NOMUSIC_C JSR MUSICC ; Play it NOMUSIC_C LDA #READ_C ; Set up the channel C indirect STA MOD_1+1 ; address for the arpeggio LDA #2 ; Start modulation from channel C STA VOICE_NUM LDX VOICE_NUM NEXT_VOICE LDA MOD_OFF_A,X ; See if modulators are required BNE NOPUL_A LDA drumFLAG,X ; If a drum is playing don't do any BNE NOPUL_A ; modulators LDA ARPFLAG_A,X ; Is the arpeggio active on this BEQ NOAR_A ; Voice JSR DO_ARP_A ; Yes, process the arpeggio NOAR_A LDA PULSEFLAG_A,X ; Is the pulse width active on this BEQ NOPUL_A ; voice JSR DOPULSE_A ; Yes, process the pulse width NOPUL_A DEC MOD_1+1 ; Modify the indirect arpeggio address DEC MOD_1+1 DEX STX VOICE_NUM ; Do the next voice BPL NEXT_VOICE NOPUL_C JMP DRUMMER ; Process DunnyDrums (tm) ; ; MUSICTEST - Tests to see if music is playing ; MUSICTEST LDA MFL_A ; ORA all the flags together ORA MFL_B ; if zero is the result then the ORA MFL_C ; tune is complete RTS ; ; MUSICA - Handles all music to channel A ; MUSICA DEC DURCOUNT.A ; Note duration over ? BEQ READBYTE.A ; Yup, get a new byte LDA DURCOUNT.A CMP #1 BNE NO_SHUT_A STA MOD_OFF_A ; Shut off modulation for this frame NO_SHUT_A DEC RELEASE_A ; Has the note release finished BNE NO_RELEASE_A ; No, modulate channel A LDA EFFECTFLAG_A ; Effect mode active ? BEQ NOEFFECT_A ; No LDX REAL_NOTE_A ; Get the real unmauled note LDA LOWFREQ,X STA FREQ.LOW.A ; expand out into a frequency LDA HIFREQ,X STA FREQ.HI.A NOEFFECT_A LDA MODEBYTE_A ; Should the gate get set AND #1 BEQ NO_RELEASE_A ; No way jose LDA GATEOFF.A ; Set the gate bit STA $D404 NO_RELEASE_A LDX #0 JMP MODULATE ; Modulate channel A READBYTE.A LDA SUSTAIN_A ; Reset the note's release period STA RELEASE_A LDY #0 ; Shut down any drum on this channel STY MOD_OFF_A STY drumFLAG+0 LDA (PC.A),Y ; Get next byte from the data BPL NOCONTROL_A TAX LDA JUMPVECL.A-128,X ; the control code vectors STA JUMPVEC.A+1 LDA JUMPVECH.A-128,X STA JUMPVEC.A+2 INY JUMPVEC.A JMP $FFFF ; Self modified jump address NOCONTROL_A CMP #REST ; Is it a rest BNE NOREST_A JMP REST_A ; Yes process a rest NOREST_A CLC ADC TRANSVAL_A ; Add any transpose value to the base STA NOTE_A ; note, and store it STA REAL_NOTE_A LDX EFFECTFLAG_A ; Is effect mode enabled BEQ NOFX_A ; No, thank God ! LDA MODEBYTE_A ; Is it an emulated plucked note (!) AND #8 BNE PLUCK ; Yessum boss LDA EFFECT_NOTE_A ; Use the effect note for the freq JMP NOFX_A PLUCK LDA REAL_NOTE_A ; Otherwise get the base note and CLC ADC EFFECT_NOTE_A ; add the effect note on NOFX_A TAX ; Expand the note into a frequency LDA LOWFREQ,X STA FREQ.LOW.A ; Maulable frequencys LDA HIFREQ,X STA FREQ.HI.A DOREST_A LDA PULSEFLAG_A ; Pulse mode enabled ? BEQ NOPULSE_A ; No LDA MODEBYTE_A ; Should the pulse be retriggered AND #2 BEQ NOPULSE_A ; No LDA PWL2_A ; Reset all pulse width variables STA PWL_A LDA PWH2_A STA PWH_A LDA #0 STA PULSEDIR_A ; Pulse direction LDA CUP2_A ; Counts up STA CUP_A LDA CDOWN2_A ; Counts down STA CDOWN_A NOPULSE_A LDA VIBFLAG_A ; Is the vibrato active BEQ NOV_A ; No LDA VIBDELAY2_A ; Reset the vibrato delay STA VIBDELAY_A LDA VIBDEPTH_A ; Get the vibrato depth LSR STA VIBDEPTH2_A ; Divide it by 2 for other direction LDA #0 ; Reset the Vib direction variable STA VIB_DIR_A NOV_A LDA MODEBYTE_A ; Should the gate get set AND #1 BEQ REST_A ; No LDA GATE.A ; Set the gate bit STA $D404 REST_A LDA DURATIONON_A ; Automatic duration mode ? BNE PICK_UP_A ; No LDA DURATION_A ; Reset the note duration STA DURCOUNT.A LDX GAPFLAG_A ; Gap mode active BEQ NOGAP2_A ; no SEC SBC SUSTAIN_A ; Subtact the sustain from the STA RELEASE_A ; duration to give a release value NOGAP2_A INC PC.A ; Increment the music PC BNE COMEOUT.A INC PC.A+1 COMEOUT.A JMP NO_RELEASE_A ; Do the modulators for channel A PICK_UP_A INY ; Manual duration mode LDA (PC.A),Y STA DURCOUNT.A ; Get the duration of the note LDX GAPFLAG_A ; Gap mode active BEQ NOGAP_A ; No SEC SBC SUSTAIN_A ; Subtact the sustain from the STA RELEASE_A ; duration to give a release value NOGAP_A LDA PC.A ; Add 2 to the music PC CLC ADC #2 STA PC.A BCC SKIPIT_A INC PC.A+1 SKIPIT_A JMP NO_RELEASE_A ; Do the modulators for channel A ; ; MODULATE - Handles all modulation requirements for Channels A,B & C ; MODULATE LDA MOD_OFF_A,X ; Check if modulators are required BNE NOVIB_A LDA ARPFLAG_A,X ; Is arpeggio processing BEQ NOARP_A RTS ; Yes, don't bother with other stuff NOARP_A LDA PORTFLAG.A,X ; Pitch bender on ? BEQ NOBEND.A ; No JSR DO.BEND.A ; Set up a pitch bend NOBEND.A LDA VIBFLAG_A,X ; Is the vibrato active ? BEQ NOVIB_A ; No JSR DOVIB_A ; Process the vibrato NOVIB_A JMP DUMP ; Dump the final frequency to SID ; ; DO.BEND.A - Processes all pitchbending to all channels ; DO.BEND.A BMI SET.BEND.A ; Bendflag minus = init bend DEC BENDLENGTH.A,X ; See if bend complete BEQ BEND.DONE.A ; Exit if so PROC.BEND.A LDA BEND.DIR.A,X ; Otherwise get bend direction BMI BEND.DOWN.A ; Minus = downwards bend LDA FREQ.LOW.A,X ; Get frequency and add the bend CLC ADC BENDSTEP.A,X STA FREQ.LOW.A,X ; additive BCC NOCHANGE1.A INC FREQ.HI.A,X NOCHANGE1.A RTS ; Exit BEND.DOWN.A LDA FREQ.LOW.A,X ; Get frequency and subtract the bend SEC SBC BENDSTEP.A,X STA FREQ.LOW.A,X ; subtractive BCS NOCHANGE2.A DEC FREQ.HI.A,X NOCHANGE2.A RTS ; Exit BEND.DONE.A LDA #0 ; Terminate the pitchbend STA PORTFLAG.A,X RTS ; Exit SET.BEND.A LDA #1 ; Do bend but don't re-initialise STA PORTFLAG.A,X LDY WORD_OFFSET,X LDA BEND.DIR.A,X ; Get the bend direction BMI SET.DOWN.A LDA FREQ.LOW.A,X ; Subract the offset from the base SEC SBC OFFSET.A,Y STA FREQ.LOW.A,X ; frequency (bend up to a note) LDA FREQ.HI.A,X SBC OFFSET.A+1,Y STA FREQ.HI.A,X JMP PROC.BEND.A ; Process the bend SET.DOWN.A LDA FREQ.LOW.A,X ; Add the offset from the base CLC ADC OFFSET.A,Y STA FREQ.LOW.A,X ; frequency (bend down to a note) LDA FREQ.HI.A,X ADC OFFSET.A+1,Y STA FREQ.HI.A,X JMP PROC.BEND.A ; Process the bend ; ; DOVIB_A - Suprisingly enuf this handles the vibrato ; DOVIB_A LDA VIBDELAY_A,X ; Time to activate the vibrato BEQ DELAYOFF_A DEC VIBDELAY_A,X ; No, not yet RTS DELAYOFF_A DEC VIBDEPTH2_A,X ; Decrement the vib direction counter BEQ CHANGEDIR_A ; Zero = change the direction LDA VIB_DIR_A,X ; Get the vibrato direction BNE VIB_DOWN_A LDA FREQ.LOW.A,X ; Get the base frequency CLC ADC VIBRATE_A,X ; Add the vibrato add rate STA FREQ.LOW.A,X BCC NOADD_A INC FREQ.HI.A,X NOADD_A RTS ; Exit VIB_DOWN_A LDA FREQ.LOW.A,X ; Get the base frequency SEC SBC VIBRATE_A,X ; Subtract the vibrato subtract rate STA FREQ.LOW.A,X BCS NOADD2_A DEC FREQ.HI.A,X NOADD2_A RTS ; Exit CHANGEDIR_A LDA VIB_DIR_A,X ; Flip the vibrato direction EOR #1 STA VIB_DIR_A,X LDA VIBDEPTH_A,X ; Reset the depth counter STA VIBDEPTH2_A,X JMP DELAYOFF_A ; Back to processing the vibrato ; ; TRANS_A - Constant transpose value initialise ; TRANS_A LDA (PC.A),Y ; Pull in the transpose value STA TRANSVAL_A ; Store it LDA #2 JMP ADD_PC_A ; Bump the PC ; ; TRANS_B - Constant transpose value initialise ; TRANS_B ; Ditto LDA (PC.B),Y STA TRANSVAL_B LDA #2 JMP ADD_PC_B ; ; TRANS_C - Constant transpose value initialise ; TRANS_C ; Ditto LDA (PC.C),Y STA TRANSVAL_C LDA #2 JMP ADD_PC_C ; ; CT_A - Call a routine transposed ; CT_A LDA (PC.A),Y ; Pull in the transpose value STA TRANSVAL_A ; Store INC PC.A ; Bump the PC BNE SKPCT_A INC PC.A+1 SKPCT_A JMP CALL.A ; Cheap n nasty go to the CALL routine ; ; CT_B - Call a routine transposed ; CT_B ; Ditto LDA (PC.B),Y STA TRANSVAL_B INC PC.B BNE SKPCT_B INC PC.B+1 SKPCT_B JMP CALL.B ; ; CT_C - Call a routine transposed ; CT_C ; Ditto LDA (PC.C),Y STA TRANSVAL_C INC PC.C BNE SKPCT_C INC PC.C+1 SKPCT_C JMP CALL.C ; ; LENGTH_A - Determines the duration of the notes ; LENGTH_A LDA (PC.A),Y ; Pull in the constant duration value STA DURATION_A LDA #0 STA DURATIONON_A ; Signal this mode LDA #2 JMP ADD_PC_A ; Bump the PC ; ; DO_ARP_A - Processes the arpeggiator on A,B & C ; DO_ARP_A DEC NEXTDELAY_A,X ; Time to read the next byte yet ? BEQ GO_ARP_A RTS ; No GO_ARP_A LDA NEXTDELAY2_A,X ; Reset the read period STA NEXTDELAY_A,X LDY ARPEGIND_A,X ; Get the index within the table MOD_1 LDA (READ_A),Y ; plus the indirect address LDY SID_OFFSETS,X CLC ADC NOTE_A,X ; add this value to the base note TAX LDA LOWFREQ,X ; Expand out into a frequency STA $D400,Y LDA HIFREQ,X STA $D401,Y LDX VOICE_NUM INC ARPEGIND_A,X ; Increment the index within the table LDA ARPEGIND_A,X CMP ARPEGLEN_A,X ; Reached the end of the table yet ? BNE RESETARP_A LDA #2 ; Yes reset the index to 2 STA ARPEGIND_A,X RESETARP_A RTS ; Exit ; ; DOPULSE_A - Process pwm on A,B & C ; DOPULSE_A LDA PULSEDIR_A,X ; Get the pulse direction BNE PULSEDOWN_A PULSEUP_A DEC CUP_A,X ; Decrement the pulse up counter BEQ NEWDIR_A ; zero, do the other direction LDY SID_OFFSETS,X LDA PWL_A,X ; Add the rate up to the CLC ADC RATEUP_A,X STA PWL_A,X ; pulse width STA $D402,Y LDA PWH_A,X ADC #0 STA PWH_A,X STA $D403,Y RTS ; Exit PULSEDOWN_A DEC CDOWN_A,X ; Decrement the pulse down counter BEQ NEWDIR2_A ; Zero, do the other direction LDY SID_OFFSETS,X LDA PWL_A,X ; Subtract the pulse down counter SEC SBC RATEUP_A,X STA PWL_A,X ; to the pulse width STA $D402,Y LDA PWH_A,X SBC #0 STA PWH_A,X STA $D403,Y RTS ; Exit NEWDIR_A LDA CUP2_A,X ; Reset the count up STA CUP_A,X LDA #1 ; Set the new direction STA PULSEDIR_A,X JMP PULSEDOWN_A ; Process it NEWDIR2_A LDA CDOWN2_A,X ; Reset the count down STA CDOWN_A,X LDA #0 ; Set the new direction STA PULSEDIR_A,X JMP PULSEUP_A ; Process it ; ; DUMP - Dumps frequencies to SID channel A,B & C ; DUMP LDY SID_OFFSETS,X LDA FREQ.LOW.A,X ; Get the final mauled frequency STA $D400,Y LDA FREQ.HI.A,X ; and send it to SID STA $D401,Y RTS ; ; ADD_PC_A - Adds a value in A to PC.A ; ADD_PC_A CLC ADC PC.A ; Add PC to the value in the STA PC.A BCC SKP_A ; accumulator INC PC.A+1 SKP_A JMP READBYTE.A ; and back to the sequencer ; ; DUR_ON_A - Acctivates manual duration mode ; DUR_ON_A LDA #1 ; Set the manual duration flag STA DURATIONON_A INC PC.A ; Bump PC BNE SKIP_A INC PC.A+1 SKIP_A JMP READBYTE.A ; Back to the sequencer ; ; PULSEON_A - Switches pulse width modulation on ! ; PULSEON_A LDA #0 STA FROM+1 ; Zero FROM+1 LDA (PC.A),Y ; Get the pulse patch number ASL ASL CLC ADC (PC.A),Y ; *5 ADC #PWM_START ; plus PWM table base address STA FROM+1 DEY ; Y=0 LDA (FROM),Y STA RATEUP_A ; Get the rate on the upward sweep INY ; Y=1 STY PULSEFLAG_A ; Pulse enabled STY PULSEDIR_A ; Set the initial direction LDA (FROM),Y STA CUP_A ; Get the additive count STA CUP2_A INY LDA (FROM),Y STA CDOWN_A ; Get the subtractive count STA CDOWN2_A INY ; Y=2 LDA (FROM),Y ; Initial pulse width LOW STA PWL2_A INY ; Y=3 LDA (FROM),Y STA PWH2_A ; Initial pulse width HIGH LDA #2 ; Bump PC JMP ADD_PC_A ; ; MUSICB - Handles all music to channel B ; MUSICB DEC DURCOUNT.B BEQ READBYTE.B LDA DURCOUNT.B CMP #1 BNE NO_SHUT_B STA MOD_OFF_B NO_SHUT_B DEC RELEASE_B BNE NO_RELEASE_B LDA EFFECTFLAG_B BEQ NOEFFECT_B LDX REAL_NOTE_B LDA LOWFREQ,X STA FREQ.LOW.B LDA HIFREQ,X STA FREQ.HI.B NOEFFECT_B LDA MODEBYTE_B AND #1 BEQ NO_RELEASE_B LDA GATEOFF.B STA $D404+7 NO_RELEASE_B LDX #1 JMP MODULATE ; Modulate channel B READBYTE.B LDA SUSTAIN_B STA RELEASE_B LDY #0 STY MOD_OFF_B STY drumFLAG+1 LDA (PC.B),Y BPL NOCONTROL_B TAX LDA JUMPVECL.B-128,X STA JUMPVEC.B+1 LDA JUMPVECH.B-128,X STA JUMPVEC.B+2 INY JUMPVEC.B JMP $FFFF NOCONTROL_B CMP #REST BNE NOREST_B JMP REST_B NOREST_B CLC ADC TRANSVAL_B STA NOTE_B STA REAL_NOTE_B LDX EFFECTFLAG_B BEQ NOFX_B LDA MODEBYTE_B AND #8 BNE PLUCK_B LDA EFFECT_NOTE_A JMP NOFX_B PLUCK_B LDA REAL_NOTE_B CLC ADC EFFECT_NOTE_B NOFX_B TAX LDA LOWFREQ,X STA FREQ.LOW.B ; Maulable frequencys LDA HIFREQ,X STA FREQ.HI.B LDA PULSEFLAG_B BEQ NOPULSE_B LDA MODEBYTE_B AND #2 BEQ NOPULSE_B LDA PWL2_B STA PWL_B LDA PWH2_B STA PWH_B LDA #0 STA PULSEDIR_B LDA CUP2_B STA CUP_B LDA CDOWN2_B STA CDOWN_B NOPULSE_B LDA VIBFLAG_B BEQ NOV_B LDA VIBDELAY2_B STA VIBDELAY_B LDA VIBDEPTH_B LSR STA VIBDEPTH2_B LDA #0 STA VIB_DIR_B NOV_B LDA MODEBYTE_B AND #1 BEQ REST_B LDA GATE.B STA $D404+7 REST_B LDA DURATIONON_B BNE PICK_UP_B LDA DURATION_B STA DURCOUNT.B LDX GAPFLAG_B BEQ NOGAP2_B SEC SBC SUSTAIN_B STA RELEASE_B NOGAP2_B INC PC.B BNE COMEOUT.B INC PC.B+1 COMEOUT.B JMP NO_RELEASE_B PICK_UP_B INY LDA (PC.B),Y STA DURCOUNT.B LDX GAPFLAG_B BEQ NOGAP_B SEC SBC SUSTAIN_B STA RELEASE_B NOGAP_B LDA PC.B CLC ADC #2 STA PC.B BCC SKIPIT_B INC PC.B+1 SKIPIT_B JMP NO_RELEASE_B ; ; ADD_PC_B - Adds a value in A to PC.B ; ADD_PC_B CLC ADC PC.B STA PC.B BCC SKP_B INC PC.B+1 SKP_B JMP READBYTE.B ; ; LENGTH_B - Determines the duration of the notes ; LENGTH_B LDA (PC.B),Y STA DURATION_B LDA #0 STA DURATIONON_B LDA #2 JMP ADD_PC_B ; ; DUR_ON_B - Acctivates manual duration mode ; DUR_ON_B LDA #1 STA DURATIONON_B INC PC.B BNE SKIP_B INC PC.B+1 SKIP_B JMP READBYTE.B ; ; PULSEON_B - Switches pulse width modulation on ! ; PULSEON_B LDA #0 STA FROM+1 LDA (PC.B),Y ASL ASL CLC ADC (PC.B),Y ADC #PWM_START STA FROM+1 DEY LDA (FROM),Y STA RATEUP_B INY STY PULSEFLAG_B STY PULSEDIR_B LDA (FROM),Y STA CUP_B STA CUP2_B INY LDA (FROM),Y STA CDOWN_B STA CDOWN2_B INY LDA (FROM),Y STA PWL2_B INY LDA (FROM),Y STA PWH2_B LDA #2 JMP ADD_PC_B ; ; MUSICC - Handles all music to channel C ; MUSICC DEC DURCOUNT.C BEQ READBYTE.C LDA DURCOUNT.C CMP #1 BNE NO_SHUT_C STA MOD_OFF_C NO_SHUT_C DEC RELEASE_C BNE NO_RELEASE_C LDA EFFECTFLAG_C BEQ NOEFFECT_C LDX REAL_NOTE_C LDA LOWFREQ,X STA FREQ.LOW.C LDA HIFREQ,X STA FREQ.HI.C NOEFFECT_C LDA MODEBYTE_C AND #1 BEQ NO_RELEASE_C LDA GATEOFF.C STA $D404+14 NO_RELEASE_C LDA drumFLAG+2 ; No modulation during drums BEQ DO_MODULATE RTS DO_MODULATE LDX #2 JMP MODULATE ; Modulate channel C READBYTE.C LDA SUSTAIN_C STA RELEASE_C LDA drumFLAG+2 BEQ DONTOFF_C LDA #0 STA drumFLAG+2 STA DRUMx+2 STA $D404+14 LDA SUSTEMP+2 STA $D406+14 LDA ADTEMP+2 STA $D405+14 DONTOFF_C LDY #0 STY MOD_OFF_C LDA (PC.C),Y BPL NOCONTROL_C ; Found a control byte TAX LDA JUMPVECL.C-128,X STA JUMPVEC.C+1 LDA JUMPVECH.C-128,X STA JUMPVEC.C+2 INY JUMPVEC.C JMP $FFFF NOCONTROL_C CMP #REST BNE NOREST_C JMP REST_C NOREST_C CLC ADC TRANSVAL_C STA NOTE_C STA REAL_NOTE_C LDX EFFECTFLAG_C BEQ NOFX_C LDA MODEBYTE_C AND #8 BNE PLUCK_C LDA EFFECT_NOTE_C JMP NOFX_C PLUCK_C LDA REAL_NOTE_C CLC ADC EFFECT_NOTE_C NOFX_C TAX LDA LOWFREQ,X STA FREQ.LOW.C ; Maulable frequencys LDA HIFREQ,X STA FREQ.HI.C DOREST_C LDA PULSEFLAG_C BEQ NOPULSE_C LDA MODEBYTE_C AND #2 BEQ NOPULSE_C LDA PWL2_C STA PWL_C LDA PWH2_C STA PWH_C LDA #0 STA PULSEDIR_C LDA CUP2_C STA CUP_C LDA CDOWN2_C STA CDOWN_C NOPULSE_C LDA VIBFLAG_C BEQ NOV_C LDA VIBDELAY2_C STA VIBDELAY_C LDA VIBDEPTH_C LSR STA VIBDEPTH2_C LDA #0 STA VIB_DIR_C NOV_C LDA MODEBYTE_C AND #1 BEQ REST_C LDA GATE.C STA $D404+14 REST_C LDA DURATIONON_C BNE PICK_UP_C LDA DURATION_C STA DURCOUNT.C LDX GAPFLAG_C BEQ NOGAP2_C SEC SBC SUSTAIN_C STA RELEASE_C NOGAP2_C INC PC.C BNE COMEOUT.C INC PC.C+1 COMEOUT.C JMP NO_RELEASE_C PICK_UP_C INY LDA (PC.C),Y STA DURCOUNT.C LDX GAPFLAG_C BEQ NOGAP_C SEC SBC SUSTAIN_C STA RELEASE_C NOGAP_C LDA PC.C CLC ADC #2 STA PC.C BCC SKIPIT_C INC PC.C+1 SKIPIT_C JMP NO_RELEASE_C ; ; LENGTH_C - Determines the duration of the notes ; LENGTH_C LDA (PC.C),Y STA DURATION_C LDA #0 STA DURATIONON_C LDA #2 JMP ADD_PC_C ; ; DUR_ON_C - Acctivates manual duration mode ; DUR_ON_C LDA #1 STA DURATIONON_C INC PC.C BNE SKIP_C INC PC.C+1 SKIP_C JMP READBYTE.C ; ; ADD_PC_C - Adds a value in A to PC.C ; ADD_PC_C CLC ADC PC.C STA PC.C BCC SKP_C INC PC.C+1 SKP_C JMP READBYTE.C ; ; PULSEON_C - Switches pulse width modulation on ! ; PULSEON_C LDA #0 STA FROM+1 LDA (PC.C),Y ASL ASL CLC ADC (PC.C),Y ADC #PWM_START STA FROM+1 DEY LDA (FROM),Y STA RATEUP_C INY STY PULSEFLAG_C STY PULSEDIR_C LDA (FROM),Y STA CUP_C STA CUP2_C INY LDA (FROM),Y STA CDOWN_C STA CDOWN2_C INY LDA (FROM),Y STA PWL2_C INY LDA (FROM),Y STA PWH2_C LDA #2 JMP ADD_PC_C ; ; Music control routines follow ...... ; ; ; JUMP.A - Jumps to a new sequence of notes ; JUMP.A LDA (PC.A),Y STA TEMP.PC ; Preserve the LOW byte new address INY LDA (PC.A),Y STA PC.A+1 ; New high byte into PC+1 LDA TEMP.PC STA PC.A ; Low byte in PC JMP READBYTE.A ; Back to sequencer ; ; CALL.A - Same as JSR, goes to a new sequence and returns on finding a RET ; CALL.A LDX SP.A ; Stack pointer, channel A LDA (PC.A),Y STA TEMP.PC ; TEMP.PC contains CALL address INY LDA (PC.A),Y STA TEMP.PC+1 LDA PC.A CLC ADC #3 STA STACK.A.L,X ; Preserve current PC low byte LDA PC.A+1 ADC #0 STA STACK.A.H,X ; Preserve current PC high byte LDA TEMP.PC ; Set PC to CALL address STA PC.A LDA TEMP.PC+1 STA PC.A+1 INC SP.A ; Increment channel A stack pointer JMP READBYTE.A ; ; RET.A - Returns the last stacked PC value ; RET.A DEC SP.A ; Decrement channel A stack pointer LDX SP.A LDA STACK.A.L,X ; Retrieve Program counter low byte STA PC.A LDA STACK.A.H,X ; Retrieve Program counter high byte STA PC.A+1 LDA #0 STA TRANSVAL_A ; Reset the transpose value JMP READBYTE.A ; ; FOR.HANDLE.A - Handles the stacking of FOR instructions ; FOR.HANDLE.A LDX SP.A LDA (PC.A),Y STA FOR.COUNTS.A,X ; Store number of channel A FOR loops LDA PC.A ; Bump PC, and stack it's new value CLC ADC #2 STA PC.A STA STACK.A.L,X BCC NOCARRY.A INC PC.A+1 NOCARRY.A LDA PC.A+1 STA STACK.A.H,X INC SP.A ; Bump channel A stack pointer JMP READBYTE.A ; ; NEXT.HANDLE.A - Handles unstacking PC and decrementing the FOR counters ; NEXT.HANDLE.A LDX SP.A ; SP.A only gets stored in LAST.NEXT DEX ; to preserve the FOR address DEC FOR.COUNTS.A,X BEQ LAST.NEXT.A LDA STACK.A.L,X ; Get back old for address STA PC.A LDA STACK.A.H,X STA PC.A+1 JMP READBYTE.A LAST.NEXT.A STX SP.A ; Decremented SP.A is now stored INC PC.A BNE NOCARRY2.A INC PC.A+1 NOCARRY2.A JMP READBYTE.A ; Back to sequencer ; ; JUMP.B - Jumps to a new sequence of notes ; JUMP.B ; Ditto LDA (PC.B),Y STA TEMP.PC INY LDA (PC.B),Y STA PC.B+1 LDA TEMP.PC STA PC.B JMP READBYTE.B ; ; CALL.B - Same as JSR, goes to a new sequence and returns on finding a RET ; CALL.B LDX SP.B ; Ditto LDA (PC.B),Y STA TEMP.PC INY LDA (PC.B),Y STA TEMP.PC+1 LDA PC.B CLC ADC #3 STA STACK.B.L,X LDA PC.B+1 ADC #0 STA STACK.B.H,X LDA TEMP.PC STA PC.B LDA TEMP.PC+1 STA PC.B+1 INC SP.B JMP READBYTE.B ; ; RET.B - Returns the last stacked PC value ; RET.B DEC SP.B ; Ditto LDX SP.B LDA STACK.B.L,X STA PC.B LDA STACK.B.H,X STA PC.B+1 LDA #0 STA TRANSVAL_B JMP READBYTE.B ; ; FOR.HANDLE.B - Handles the stacking of FOR instructions ; FOR.HANDLE.B LDX SP.B ; Ditto LDA (PC.B),Y STA FOR.COUNTS.B,X LDA PC.B CLC ADC #2 STA PC.B STA STACK.B.L,X BCC NOCARRY.B INC PC.B+1 NOCARRY.B LDA PC.B+1 STA STACK.B.H,X INC SP.B JMP READBYTE.B ; ; NEXT.HANDLE.B - Handles unstacking PC and decrementing the FOR counters ; NEXT.HANDLE.B LDX SP.B ; Ditto DEX DEC FOR.COUNTS.B,X BEQ LAST.NEXT.B LDA STACK.B.L,X STA PC.B LDA STACK.B.H,X STA PC.B+1 JMP READBYTE.B LAST.NEXT.B STX SP.B INC PC.B BNE NOCARRY2.B INC PC.B+1 NOCARRY2.B JMP READBYTE.B ; ; JUMP.C - Jumps to a new sequence of notes ; JUMP.C ; Ditto LDA (PC.C),Y STA TEMP.PC INY LDA (PC.C),Y STA PC.C+1 LDA TEMP.PC STA PC.C JMP READBYTE.C ; ; CALL.C - Same as JSR, goes to a new sequence and returns on finding a RET ; CALL.C LDX SP.C ; Ditto LDA (PC.C),Y STA TEMP.PC INY LDA (PC.C),Y STA TEMP.PC+1 LDA PC.C CLC ADC #3 STA STACK.C.L,X LDA PC.C+1 ADC #0 STA STACK.C.H,X LDA TEMP.PC STA PC.C LDA TEMP.PC+1 STA PC.C+1 INC SP.C JMP READBYTE.C ; ; RET.C - Returns the last stacked PC value ; RET.C DEC SP.C ; Ditto LDX SP.C LDA STACK.C.L,X STA PC.C LDA STACK.C.H,X STA PC.C+1 LDA #0 STA TRANSVAL_C JMP READBYTE.C ; ; FOR.HANDLE.C - Handles the stacking of FOR instructions ; FOR.HANDLE.C LDX SP.C ; Ditto LDA (PC.C),Y STA FOR.COUNTS.C,X LDA PC.C CLC ADC #2 STA PC.C STA STACK.C.L,X BCC NOCARRY.C INC PC.C+1 NOCARRY.C LDA PC.C+1 STA STACK.C.H,X INC SP.C JMP READBYTE.C ; ; NEXT.HANDLE.C - Handles unstacking PC and decrementing the FOR counters ; NEXT.HANDLE.C LDX SP.C ; Ditto DEX DEC FOR.COUNTS.C,X BEQ LAST.NEXT.C LDA STACK.C.L,X STA PC.C LDA STACK.C.H,X STA PC.C+1 JMP READBYTE.C LAST.NEXT.C STX SP.C INC PC.C BNE NOCARRY2.C INC PC.C+1 NOCARRY2.C JMP READBYTE.C ; ; VIBON_A - Acctivates the vibrato ; VIBON_A LDA (PC.A),Y STA VIBDELAY2_A ; Permenant vib delay INY LDA (PC.A),Y STA VIBRATE_A ; additive/subtractive rate INY LDA (PC.A),Y STA VIBDEPTH_A ; Variable vib depth LSR STA VIBDEPTH2_A ; Permenant vib depth LDX #1 STX VIBFLAG_A ; Signal vibrato is on DEX STX VIB_DIR_A ; Set the initial vibrato direction STX ARPFLAG_A ; Cancel arpeggio (if it is running) LDA #4 ; Bump the PC JMP ADD_PC_A ; ; VIBOFF_A - Guess moron ! ; VIBOFF_A LDA #0 ; Shut down the vibrato STA VIBFLAG_A INC PC.A ; Bump PC BNE SKIP2_A INC PC.A+1 SKIP2_A JMP READBYTE.A ; Back to the sequencer ; ; VIBON_B - Acctivates the vibrato ; VIBON_B ; Ditto LDA (PC.B),Y STA VIBDELAY2_B ; Permenant vib delay INY LDA (PC.B),Y STA VIBRATE_B INY LDA (PC.B),Y STA VIBDEPTH_B LSR STA VIBDEPTH2_B ; " " " " " depth LDX #1 STX VIBFLAG_B DEX STX VIB_DIR_B STX ARPFLAG_B LDA #4 JMP ADD_PC_B ; ; VIBOFF_B - Guess moron ! ; VIBOFF_B LDA #0 ; Ditto STA VIBFLAG_B INC PC.B BNE SKIP2_B INC PC.B+1 SKIP2_B JMP READBYTE.B ; ; VIBON_C - Acctivates the vibrato ; VIBON_C ; Ditto LDA (PC.C),Y STA VIBDELAY2_C ; Permenant vib delay INY LDA (PC.C),Y STA VIBRATE_C INY LDA (PC.C),Y STA VIBDEPTH_C LSR STA VIBDEPTH2_C ; " " " " " depth LDX #1 STX VIBFLAG_C DEX STX VIB_DIR_C STX ARPFLAG_C LDA #4 JMP ADD_PC_C ; ; VIBOFF_C - Guess moron ! ; VIBOFF_C LDA #0 ; Ditto STA VIBFLAG_C INC PC.C BNE SKIP2_C INC PC.C+1 SKIP2_C JMP READBYTE.C ; ; ARPON_A - Acctivates the arpeggiator ; ARPON_A LDA (PC.A),Y STA READ_A ; Get the address of the arpeggio INY LDA (PC.A),Y ; table STA READ_A+1 LDY #0 ; STY VIBFLAG_A LDA (READ_A),Y STA NEXTDELAY2_A ; Get the delay between reading bytes INY STY ARPFLAG_A ; Trigger the arpeggiator STY NEXTDELAY_A LDA (READ_A),Y CLC ADC #2 STA ARPEGLEN_A ; Set the length of the arpeggio table INY STY ARPEGIND_A ; Set the index into the table LDA #3 ; Bump the PC JMP ADD_PC_A ; ; ARPOFF_A - No prizes dickhead ! ; ARPOFF_A LDA #0 ; Shut down the arpeggiator STA ARPFLAG_A INC PC.A ; Bump the PC BNE SKIP4_A INC PC.A+1 SKIP4_A JMP READBYTE.A ; Back to the sequencer ; ; ARPON_B - Acctivates the arpeggiator ; ARPON_B ; Ditto LDA (PC.B),Y STA READ_B INY LDA (PC.B),Y STA READ_B+1 LDY #0 ; STY VIBFLAG_B LDA (READ_B),Y STA NEXTDELAY2_B INY STY ARPFLAG_B STY NEXTDELAY_B LDA (READ_B),Y CLC ADC #2 STA ARPEGLEN_B INY STY ARPEGIND_B LDA #3 JMP ADD_PC_B ; ; ARPOFF_B - No prizes dickhead ! ; ARPOFF_B LDA #0 ; Ditto STA ARPFLAG_B INC PC.B BNE SKIP4_B INC PC.B+1 SKIP4_B JMP READBYTE.B ; ; ARPON_C - Acctivates the arpeggiator ; ARPON_C ; Ditto LDA (PC.C),Y STA READ_C INY LDA (PC.C),Y STA READ_C+1 LDY #0 ; STY VIBFLAG_C LDA (READ_C),Y STA NEXTDELAY2_C INY STY ARPFLAG_C STY NEXTDELAY_C LDA (READ_C),Y CLC ADC #2 STA ARPEGLEN_C INY STY ARPEGIND_C LDA #3 JMP ADD_PC_C ; ; ARPOFF_C - No prizes dickhead ! ; ARPOFF_C LDA #0 ; Ditto STA ARPFLAG_C INC PC.C BNE SKIP4_C INC PC.C+1 SKIP4_C JMP READBYTE.C ; ; MODE_A - Sets triggering mode, i'll be buggered if i know what this does ! ; MODE_A LDA (PC.A),Y BMI SETEM_A EOR #$FF AND MODEBYTE_A STA MODEBYTE_A LDA #2 JMP ADD_PC_A SETEM_A ORA MODEBYTE_A STA MODEBYTE_A LDA #2 JMP ADD_PC_A ; ; MODE_B - Sets triggering mode ; MODE_B LDA (PC.B),Y BMI SETEM_B EOR #$FF AND MODEBYTE_B STA MODEBYTE_B LDA #2 JMP ADD_PC_B SETEM_B ORA MODEBYTE_B STA MODEBYTE_B LDA #2 JMP ADD_PC_B ; ; MODE_C - Sets triggering mode ; MODE_C LDA (PC.C),Y BMI SETEM_C EOR #$FF AND MODEBYTE_C STA MODEBYTE_C LDA #2 JMP ADD_PC_C SETEM_C ORA MODEBYTE_C STA MODEBYTE_C LDA #2 JMP ADD_PC_C ; ; PORT_A - Sends 1 byte of data to an offset of the SID chip ; PORT_A LDA (PC.A),Y STA TEMP_VAL ; Store byte to be send to SID INY LDA (PC.A),Y ; Get sid offset TAX LDA TEMP_VAL ; Send value to SID STA $D400,X LDA #3 ; Bump the PC JMP ADD_PC_A PORT_B ; Ditto LDA (PC.B),Y STA TEMP_VAL INY LDA (PC.B),Y TAX LDA TEMP_VAL STA $D400,X LDA #3 JMP ADD_PC_B PORT_C ; Ditto LDA (PC.C),Y STA TEMP_VAL INY LDA (PC.C),Y TAX LDA TEMP_VAL STA $D400,X LDA #3 JMP ADD_PC_C ; ; CODE_A - Jumps to a machine code segment ; CODE_A LDA (PC.A),Y STA JUMP_MOD_A+1 ; Get the address of the code INY LDA (PC.A),Y ; to be JSR'd to STA JUMP_MOD_A+2 JUMP_MOD_A JSR $AAAA ; Self modified LDA #3 ; Bump the PC JMP ADD_PC_A CODE_B ; Ditto LDA (PC.B),Y STA JUMP_MOD_B+1 INY LDA (PC.B),Y STA JUMP_MOD_B+2 JUMP_MOD_B JSR $AAAA ; Self modified LDA #3 JMP ADD_PC_B CODE_C ; Ditto LDA (PC.C),Y STA JUMP_MOD_C+1 INY LDA (PC.C),Y STA JUMP_MOD_C+2 JUMP_MOD_C JSR $AAAA ; Self modified LDA #3 JMP ADD_PC_C ; ; EFFECT_A - Sets up effect mode ; ;EFFECT_A ; LDA (PC.A),Y ; STA EFFECT_NOTE_A ; STY EFFECTFLAG_A ; ; LDA #2 ; JMP ADD_PC_A ; ;EFFECT_B ; LDA (PC.B),Y ; STA EFFECT_NOTE_B ; STY EFFECTFLAG_B ; ; LDA #2 ; JMP ADD_PC_B EFFECT_C LDA (PC.C),Y STA EFFECT_NOTE_C STY EFFECTFLAG_C LDA #2 JMP ADD_PC_C ; ; BEND.ON.A - Acctivates the Pitchbender & sets up the pitchbend data ; BEND.ON.A LDA #$81 ; Bend on+minus = initialise bend STA PORTFLAG.A LDA (PC.A),Y STA BEND.DIR.A ; Get the bend direction INY LDA (PC.A),Y STA BENDSTEP.A ; Get the steps INY LDA (PC.A),Y STA BENDLENGTH.A ; and the length INY LDA (PC.A),Y ; Bend offset (Rate x Duration) STA OFFSET.A INY LDA (PC.A),Y STA OFFSET.A+1 LDA #6 ; Bump the PC JMP ADD_PC_A ; ; BEND.ON.B - Acctivates the Pitchbender & sets up the pitchbend data ; ;BEND.ON.B LDA #$81 ; Bend on. Minus = init bend ; STA PORTFLAG.B ; LDA (PC.B),Y ; STA BEND.DIR.B ; Pitchbend direction ; INY ; LDA (PC.B),Y ; STA BENDSTEP.B ; Bend steps ; INY ; LDA (PC.B),Y ; STA BENDLENGTH.B ; INY ; LDA (PC.B),Y ; Bend offset (Rate x Duration) ; STA OFFSET.B ; INY ; LDA (PC.B),Y ; STA OFFSET.B+1 ; ; LDA #6 ; JMP ADD_PC_B ; ; BEND.ON.C - Acctivates the Pitchbender & sets up the pitchbend data ; ;BEND.ON.C LDA #$81 ; Bend on. Minus = init bend ; STA PORTFLAG.C ; LDA (PC.C),Y ; STA BEND.DIR.C ; Pitchbend direction ; INY ; LDA (PC.C),Y ; STA BENDSTEP.C ; Bend steps ; INY ; LDA (PC.C),Y ; STA BENDLENGTH.C ; INY ; LDA (PC.C),Y ; Bend offset (Rate x Duration) ; STA OFFSET.C ; INY ; LDA (PC.C),Y ; STA OFFSET.C+1 ; ; LDA #6 ; JMP ADD_PC_C ; ; PATCH.A - Pokes sound patch into SID chip Channel A ; PATCH.A LDA #0 STA FROM+1 ; Zeroise FROM+1 LDA (PC.A),Y ; Get patch number ASL ASL CLC ADC (PC.A),Y ; *5 ADC #PATCH_START STA FROM+1 LDY #4 LDA (FROM),Y STA GATEOFF.A ; Get the gateoff value DEY LDX #0 LDA (FROM),Y ; Minus = gap mode BPL NO_GAP_A INX NO_GAP_A AND #$7F ; Get rid of bit 7 STA SUSTAIN_A STX GAPFLAG_A ; Set the gap flag (nonzero) DEY LDA (FROM),Y ; Get SR period STA $D406 STA SUSTEMP+0 ; Preserve this DEY LDA (FROM),Y STA $D405 ; Get the AD period STA ADTEMP+0 ; Preserve this DEY LDA (FROM),Y STA GATE.A ; Get the gateon value LDA #2 ; Bump the PC JMP ADD_PC_A ; ; PATCH.B - Pokes sound patch into SID chip Channel B ; PATCH.B LDA #0 ; Ditto STA FROM+1 LDA (PC.B),Y ASL ASL CLC ADC (PC.B),Y ADC #PATCH_START STA FROM+1 LDY #4 LDA (FROM),Y STA GATEOFF.B DEY LDX #0 LDA (FROM),Y BPL NO_GAP_B INX NO_GAP_B AND #$7F STA SUSTAIN_B STX GAPFLAG_B DEY LDA (FROM),Y STA $D406+7 STA SUSTEMP+1 DEY LDA (FROM),Y STA $D405+7 STA ADTEMP+1 DEY LDA (FROM),Y STA GATE.B LDA #2 JMP ADD_PC_B ; ; PATCH.C - Pokes sound patch into SID chip Channel C ; PATCH.C LDA #0 STA FROM+1 LDA (PC.C),Y ASL ASL CLC ADC (PC.C),Y ADC #PATCH_START STA FROM+1 LDY #4 LDA (FROM),Y STA GATEOFF.C DEY LDX #0 LDA (FROM),Y BPL NO_GAP_C INX NO_GAP_C AND #$7F STA SUSTAIN_C STX GAPFLAG_C DEY LDA (FROM),Y STA $D406+14 STA SUSTEMP+2 DEY LDA (FROM),Y STA $D405+14 STA ADTEMP+2 DEY LDA (FROM),Y STA GATE.C LDA #2 JMP ADD_PC_C ; ; DRUM_C - Gets new drum table pointers (DunnyDrums tm) ; DRUM_C LDA (PC.C),Y STA DRUMadd ASL CLC ADC DRUMadd ASL ADC DRUMadd TAX LDA DRUMTABLE,X ;GET LO & HI BYTE OF WVFORM TABLE STA WAVES_L+2 ; LDA DRUMTABLE+1,X ; STA WAVES_H+2 ; LDA DRUMTABLE+2,X ;" "" " "" " FREQUENCY TABLE STA FREQS_L+2 ; LDA DRUMTABLE+3,X ; STA FREQS_H+2 ; LDA DRUMTABLE+4,X ;GET LENGTH OF DRUM TABLE STA DRUMlength+2 ; LDA DRUMTABLE+5,X ;GET VOLUME (SUTAIAN/RELEASE) STA drumFLAG+2 ; STA $D406+14 ; LDA DRUMTABLE+6,X ;GET PULSE WIDTH STA $D403+14 LDA #$00 ;ATTACK/DECAY STA $D405+14 ;FOR DRUMSOUND INY LDA (PC.C),Y STA DRUMtr+2 LDA DURATIONON_C BNE GRAB_DUR_C LDA DURATION_C STA DURCOUNT.C LDA #3 ADD_N_FALL_C CLC ADC PC.C STA PC.C BCC NOLOW_C INC PC.C+1 NOLOW_C RTS GRAB_DUR_C INY LDA (PC.C),Y STA DURCOUNT.C LDA #4 JMP ADD_N_FALL_C ;----------DRUM PROGRAM-------------------- DRUMMER LDX #2 NEXT_DRUM LDA drumFLAG,X BEQ QUITDRUM LDA DRUMx,X CMP DRUMlength,X BNE DRUMcont LDA #0 STA $D417 STA DRUMx,X STA drumFLAG,X LDY SID_OFFSETS,X ; LDA SUSTEMP,X ; STA $D406,Y ; LDA ADTEMP,X ; STA $D405,Y ; LDA #0 STA $D404,Y QUITDRUM DEX BPL NEXT_DRUM RTS DRUMcont STX TEMPX ; TEMPX+0 = Drum Number STA TEMPX+1 ; TEMPX+1 = Drum's position in table LDA FREQS_L,X STA DRUMFQ+1 LDA FREQS_H,X STA DRUMFQ+2 LDA WAVES_L,X STA DRUMWV+1 LDA WAVES_H,X STA DRUMWV+2 LDY SID_OFFSETS,X LDX TEMPX+1 ;GET CURRENT VOICE DRUMFQ LDA $DDDD,X ; LOAD FREQUENCY FROM TABLE (S/M/C) LDX TEMPX CLC ADC DRUMtr,X ; ADD TRANSPOSE BYTE LDX TEMPX+1 STA $D401,Y ; STORE IN SID FRQ HI DRUMWV LDA $DDDD,X ; LOAD WAVEFORM FROM TABLE (S/M/C) STA $D404,Y ; STORE IN SID WAVEFORM LDX TEMPX INC DRUMx,X DEX BMI DRUMS_DONE JMP NEXT_DRUM DRUMS_DONE RTS BITABLE dc.b 1,2,4 ; ; END_A - Terminates the tune on that voice ; END_A LDA #0 STA MFL_A STA PORTFLAG.A STA VIBFLAG_A STA ARPFLAG_A STA PULSEFLAG_A RTS END_B LDA #0 STA MFL_B STA PORTFLAG.B STA VIBFLAG_B STA ARPFLAG_B STA PULSEFLAG_B RTS END_C LDA #0 STA MFL_C STA PORTFLAG.C STA VIBFLAG_C STA ARPFLAG_C STA PULSEFLAG_C RTS DRUM_A DRUM_B BEND.ON.B BEND.ON.C EFFECT_A EFFECT_B NOTHING RTS ; ; FINITO ; ; ; Control tables... ; JUMPVECL.A dc.b JUMP.A,>CALL.A,>RET.A,>FOR.HANDLE.A,>NEXT.HANDLE.A dc.b >BEND.ON.A,>PATCH.A,>LENGTH_A,>VIBON_A,>VIBOFF_A dc.b >ARPON_A,>ARPOFF_A,>DUR_ON_A,>PULSEON_A,>NOTHING dc.b >END_A,TRANS_A,>CT_A,NOTHING,>MODE_A,>DRUM_A dc.b >PORT_A,>CODE_A,>EFFECT_A JUMPVECL.B dc.b JUMP.B,>CALL.B,>RET.B,>FOR.HANDLE.B,>NEXT.HANDLE.B dc.b >BEND.ON.B,>PATCH.B,>LENGTH_B,>VIBON_B,>VIBOFF_B dc.b >ARPON_B,>ARPOFF_B,>DUR_ON_B,>PULSEON_B,>NOTHING dc.b >END_B,>TRANS_B,>CT_B,>NOTHING,>MODE_B,>DRUM_B dc.b >PORT_B,>CODE_B,>EFFECT_B JUMPVECL.C dc.b JUMP.C,>CALL.C,>RET.C,>FOR.HANDLE.C,>NEXT.HANDLE.C dc.b >BEND.ON.C,>PATCH.C,>LENGTH_C,>VIBON_C,>VIBOFF_C dc.b >ARPON_C,>ARPOFF_C,>DUR_ON_C,>PULSEON_C,>NOTHING dc.b >END_C,>TRANS_C,>CT_C,>NOTHING,>MODE_C,>DRUM_C dc.b >PORT_C,>CODE_C,>EFFECT_C STACKDEPTH EQU 5 STACK.A.L ds.b STACKDEPTH,0 STACK.B.L ds.b STACKDEPTH,0 STACK.C.L ds.b STACKDEPTH,0 STACK.A.H ds.b STACKDEPTH,0 STACK.B.H ds.b STACKDEPTH,0 STACK.C.H ds.b STACKDEPTH,0 FOR.COUNTS.A ds.b STACKDEPTH,0 FOR.COUNTS.B ds.b STACKDEPTH,0 FOR.COUNTS.C ds.b STACKDEPTH,0 SID_OFFSETS dc.b 0,7,14 WORD_OFFSET dc.b 0,2,4 LOWFREQ dc.b N00,>N01,>N02,>N03,>N04,>N05,>N06,>N07,>N08,>N09 dc.b >N10,>N11,>N12,>N13,>N14,>N15,>N16,>N17,>N18,>N19 dc.b >N20,>N21,>N22,>N23,>N24,>N25,>N26,>N27,>N28,>N29 dc.b >N30,>N31,>N32,>N33,>N34,>N35,>N36,>N37,>N38,>N39 dc.b >N40,>N41,>N42,>N43,>N44,>N45,>N46,>N47,>N48,>N49 dc.b >N50,>N51,>N52,>N53,>N54,>N55,>N56,>N57,>N58,>N59 dc.b >N60,>N61,>N62,>N63,>N64,>N65,>N66,>N67,>N68,>N69 dc.b >N70,>N71,>N72,>N73,>N74,>N75,>N76,>N77,>N78,>N79 dc.b >N80,>N81,>N82,>N83,>N84,>N85,>N86,>N87,>N88,>N89 dc.b >N90,>N91,>N92,>N93,>0 DRIVER.END EQU . ; ;------------------------------------------------------------------------------ ; MUSIC DATA ;------------------------------------------------------------------------------ ; DATA.START EQU . TUNETABLE.A.L dc.b DITTY1,>SUCCESS1,>FAIL2,>EVENT1,>TITLE1,>QUAL1 TUNETABLE.B.L dc.b DITTY2,>SUCCESS2,>FAIL2,>EVENT2,>TITLE2,>QUAL2 TUNETABLE.C.L dc.b DITTY3,>SUCCESS3,>FAIL3,>EVENT3,>TITLE3,>QUAL3 ;----------------------------------------------------------------------------- TEMPO EQU 5 ; TEMPO CONTROL SQ EQU TEMPO ; SEMI-QUAVER QV EQU SQ*2 ; QUAVER CR EQU QV*2 ; CROTCHET DCR EQU CR+QV MN EQU CR*2 ; MINIM SB EQU MN*2 ; SEMI-BREVE ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- TEMPO2 EQU 6 ; TEMPO CONTROL SQ2 EQU TEMPO2 ; SEMI-QUAVER QV2 EQU SQ2*2 ; QUAVER DQV2 EQU SQ2+QV2 ; QUAVER CR2 EQU QV2*2 ; CROTCHET DCR2 EQU CR2+QV2 MN2 EQU CR2*2 ; MINIM SB2 EQU MN2*2 ; SEMI-BREVE ;----------------------------------------------------------------------------- UP EQU 1 DOWN EQU $80 GAP EQU $80 NO EQU 0 FILTIT EQU 1 REST EQU 94 JUMP EQU $80 CALL EQU $81 RET EQU $82 LOOP EQU $83 NEXT EQU $84 BEND EQU $85 PATCH EQU $86 LENGTH EQU $87 VIBON EQU $88 VIBOFF EQU $89 ARPON EQU $8A ARPOFF EQU $8B MANUAL EQU $8C PWM EQU $8D FILTER EQU $8E END EQU $8F TRANSPOSE EQU $90 CT EQU $91 FILTOFF EQU $92 MODE EQU $93 DRUM EQU $94 PORT EQU $95 CODE EQU $96 EFFECT EQU $97 ;----DISQUALIFIED JINGLE----------------------------------------------------- DITTY2 dc.b PATCH,1,PWM,1 dc.b ARPON dc.w ARP2 dc.b LENGTH,SQ dc.b CALL dc.w MEL1 dc.b CT,-5 dc.w MEL1 dc.b CT,-12 dc.w MEL1 dc.b CT,-17 dc.w MEL1 dc.b D4 dc.b END MEL1 dc.b LOOP,2 dc.b F4,G4,F4,D5 dc.b NEXT dc.b RET DITTY1 dc.b PATCH,0,PWM,0,VIBON,0,7,6 dc.b LOOP,2,D2,CR+QV,D2,CR+QV,D2,CR,NEXT dc.b END DITTY3 dc.b LOOP,2 dc.b DRUM,0,2,SQ dc.b DRUM,2,0,SQ dc.b DRUM,2,0,SQ dc.b DRUM,2,0,SQ dc.b DRUM,1,0,QV dc.b DRUM,2,0,SQ dc.b DRUM,2,0,SQ dc.b DRUM,0,2,SQ dc.b DRUM,2,0,SQ dc.b DRUM,0,2,SQ dc.b DRUM,2,0,SQ dc.b DRUM,1,0,QV dc.b DRUM,2,0,SQ dc.b DRUM,2,0,SQ dc.b NEXT dc.b DRUM,3,0,QV dc.b END ARP1 dc.b 3,4,0,4,7,9 ARP2 dc.b 1,3,24,12,0 ;----------------------------------------------------------------------------- ;----------SUCCESS------------------------------------------------------------ ;----------------------------------------------------------------------------- SUCCESS1 dc.b REST,2 dc.b CALL dc.w FMEL1 dc.b END SUCCESS2 dc.b CALL dc.w FMEL1 dc.b END FMEL1 dc.b PATCH,3,PWM,3 dc.b ARPON dc.w FARP1 dc.b REST,CR2 dc.b FS4,CR2 dc.b ARPON dc.w FARP2 dc.b FS4,CR2 dc.b ARPON dc.w FARP1 dc.b FS4,CR2 dc.b ARPON dc.w FARP2 dc.b FS4,CR2 dc.b ARPON dc.w FARP1 dc.b FS4,CR2 dc.b ARPON dc.w FARP2 dc.b FS4,QV2 dc.b ARPON dc.w FARP3 dc.b FS4,QV2+CR2 dc.b RET ;----------------------------------------------------------------------------- SUCCESS3 dc.b PATCH,2,PWM,2,VIBON,0,7,6 dc.b LOOP,2 dc.b A2,QV2,A2,SQ2,A1,SQ2,DRUM,3,0,QV2,A2,QV2 dc.b NEXT dc.b E2,QV2,E2,SQ2,E3,SQ2,DRUM,3,0,QV2,E2,QV2 dc.b D2,QV2,D2,SQ2,D1,SQ2,DRUM,3,0,QV2 dc.b END FARP1 dc.b 2,4,0,3,7,12 FARP2 dc.b 2,4,0,3,8,12 FARP3 dc.b 2,4,0,3,10,12 ;----------------------------------------------------------------------------- ;-------------FAIL------------------------------------------------------------ ;----------------------------------------------------------------------------- FAIL1 dc.b PATCH,4,PWM,4 dc.b VIBON,6,$20,6 dc.b LENGTH,CR dc.b C5 dc.b MODE,%00000010 dc.b B4,A4,G4,F4,E4,D4,C4,B3 dc.b CODE dc.w TURNOFF dc.b END FAIL2 dc.b REST,QV dc.b PATCH,4,PWM,4 dc.b VIBON,6,$40,6 dc.b LENGTH,CR dc.b F4 dc.b MODE,%00000010 dc.b E4,D4,C4,B3,A3,G3,F3,REST dc.b END FAIL3 dc.b PATCH,5,ARPON dc.w ARP2 dc.b DRUM,4,-9,QV dc.b DRUM,4,-9,QV dc.b DRUM,4,-9,QV dc.b C5,QV dc.b DRUM,3,15,QV dc.b C4,QV,G5,QV dc.b DRUM,4,-9,CR dc.b DRUM,4,-9,QV dc.b DRUM,4,-9,QV dc.b E5,QV dc.b DRUM,3,15,QV dc.b C4,QV,G5,QV dc.b DRUM,4,-9,QV dc.b B4,CR dc.b END ;----------------------------------------------------------------------------- ;------NEXT EVENT------------------------------------------------------------- ;----------------------------------------------------------------------------- EVENT1 dc.b PATCH,6,PWM,5,VIBON,0,7,6 dc.b CODE dc.w RESETVOL dc.b LENGTH,QV2 dc.b LOOP,9 CURRENTVOL dc.b PORT,1,$18 dc.b A2 dc.b CODE dc.w FADEUP dc.b NEXT dc.b REST,REST dc.b CODE dc.w TURNOFF dc.b END EVENT2 dc.b PATCH,7,PWM,6,ARPON dc.w NARP1 dc.b LENGTH,SB2+QV2 dc.b A4 dc.b END EVENT3 dc.b LOOP,16*2 dc.b DRUM,2,-1,SQ2/2 dc.b NEXT dc.b DRUM,3,0,QV2 dc.b END ;----------------------------------------------------------------------------- RESETVOL LDA #3 STA CURRENTVOL+1 RTS FADEUP INC CURRENTVOL+1 RTS NARP1 dc.b 2,5,0,4,7,9,12 ;----------------------------------------------------------------------------- ;-------TITLE MUSIC----------------------------------------------------------- ;----------------------------------------------------------------------------- TITLE1 dc.b PATCH,9,PWM,9 dc.b VIBON,0,$80,6 ;0 dc.b LOOP,4 ; dc.b CS5,SB2 ; dc.b A4,MN2,FS4,MN2 ; dc.b NEXT ;8 dc.b A4,SB2*2 ;10 dc.b REST,SB2*2 dc.b LOOP,2 dc.b PATCH,13,PWM,11 dc.b VIBON,0,$40,6 dc.b CALL dc.w TMEL1 dc.b CALL dc.w TMEL1 dc.b PATCH,14,VIBON,8,$E0,6 dc.b CALL dc.w TMEL2 dc.b CALL dc.w TMEL2 dc.b NEXT ;PLAY VERSE+CHORUS TWICE dc.b PATCH,15,PWM,12 ; dc.b VIBON,8,$20,8 ; MIDDLE 8 dc.b LOOP,2 ; -------- dc.b FS4,MN2,E4,SB2 dc.b CS4,QV2,D4,QV2,CS4,QV2,D4,QV2 dc.b CS4,SB2*2 dc.b NEXT dc.b REST,SB2 dc.b PATCH,17,PWM,4 dc.b ARPON dc.w ARP2 dc.b LENGTH,SQ2 dc.b LOOP,4*2 dc.b E4,FS4,A4,E4,FS4,B4,D4,FS4,A4,D4,E4,CS4,A4,E4,FS4,B4 dc.b NEXT dc.b MANUAL dc.b PATCH,18,PWM,11 dc.b VIBON,$10,$1A,8 dc.b CT,-12 dc.w TMEL1 dc.b CT,-12 dc.w TMEL1 dc.b PATCH,14,VIBON,8,$E0,6 dc.b CALL dc.w TMEL2 dc.b CALL dc.w TMEL2 dc.b LOOP,4,REST,SB2*2,NEXT; LET BASS + BACK TAKE OVER dc.b PATCH,14,VIBON,8,$E0,6 dc.b CODE dc.w RESETFADE dc.b LOOP,8 FADEPOS dc.b PORT,$0F,$18 dc.b E5,QV2,FS5,QV2,A5,QV2 dc.b BEND,UP,$80,11 dc.w $80*11 dc.b B5,CR2,A5,CR2+QV2+SB2 dc.b CODE dc.w TFADEAWAY dc.b NEXT dc.b PORT,$00,$18 dc.b REST,SB*2 dc.b REST,SB*2 dc.b PORT,$0F,$18 dc.b JUMP dc.w TITLE1 TFADEAWAY LDA FADEPOS+1 CMP #1 BEQ MISSFADE DEC FADEPOS+1 DEC FADEPOS+1 MISSFADE RTS RESETFADE LDA #$0F STA FADEPOS+1 RTS ;----------------------------------------------------------------------------- TITLE2 dc.b PATCH,10,PWM,3 dc.b LOOP,5 dc.b CALL dc.w TBACK1 dc.b NEXT dc.b PATCH,12 dc.b LOOP,1+4+4+4+4 dc.b CALL dc.w TBACK1 dc.b NEXT dc.b ARPON dc.w TARP4 ; MIDDLE 8 dc.b PATCH,16 ; ======== dc.b LOOP,4 ; dc.b CALL dc.w TBACK2 dc.b NEXT dc.b REST,SB2 dc.b PATCH,12 dc.b LOOP,4+4+4 dc.b CALL dc.w TBACK1 dc.b NEXT dc.b ARPON dc.w TARP4 ; MIDDLE 8 dc.b PATCH,16 ; ======== dc.b LOOP,4 ; dc.b CALL dc.w TBACK2 dc.b NEXT dc.b PATCH,12 ; dc.b LOOP,8 ; REPEAT TO FADE dc.b CALL dc.w TBACK1 ; dc.b NEXT ; dc.b REST,SB*2 dc.b REST,SB*2 dc.b JUMP dc.w TITLE2 ;----------------------------------------------------------------------------- TITLE3 dc.b PATCH,9,PWM,9 dc.b VIBON,0,$80,6 ;0 dc.b LOOP,4 ; dc.b A4,SB2 ; dc.b E4,MN2,D4,MN2 ; dc.b NEXT ;8 dc.b E4,SB2*2 ;10 dc.b PATCH,11,PWM,10 dc.b EFFECT,C7,MODE,%00001000 dc.b VIBON,0,7,6 dc.b LOOP,1+4+4+4+4 dc.b CALL dc.w TBASS1 dc.b NEXT dc.b LOOP,4 ; dc.b CALL dc.w TBASS2 ;MIDDLE8 dc.b CT,-2 dc.w TBASS2 ; dc.b NEXT ; dc.b FS2,QV2,G2,QV2 dc.b DRUM,3,0,CR2 dc.b CODE dc.w RESTOREPOS DRUMPOS dc.b LOOP,16,DRUM,2,-9,SQ2/2,CODE dc.w UPDRUM dc.b NEXT dc.b LOOP,4+4+4 dc.b CALL dc.w TBASS1 dc.b NEXT dc.b LOOP,3 dc.b CALL dc.w TBASS3 dc.b CT,-2 dc.w TBASS3 dc.b NEXT dc.b CALL dc.w TBASS3 dc.b CALL dc.w TBASS4 dc.b DRUM,3,3,QV2 dc.b DRUM,3,3,QV2 dc.b LOOP,4 dc.b DRUM,3,3,SQ2 dc.b NEXT dc.b LOOP,8 ; dc.b CALL dc.w TBASS1 ; REPEAT TO FADE dc.b NEXT ; dc.b CODE dc.w EFFECTOFF_C dc.b REST,SB*2 dc.b REST,SB*2 dc.b JUMP dc.w TITLE3 ;----------------------------------------------------------------------------- UPDRUM INC DRUMPOS+4 RTS RESTOREPOS LDA #-9 STA DRUMPOS+4 RTS EFFECTOFF_C LDA #0 STA EFFECTFLAG_C RTS EFFECTON_C LDA #1 STA EFFECTFLAG_C RTS ;----------------------------------------------------------------------------- TBACK1 dc.b ARPON dc.w TARP1 dc.b REST,CR2 dc.b FS4,CR2 dc.b ARPON dc.w TARP2 dc.b FS4,CR2 dc.b ARPON dc.w TARP1 dc.b FS4,CR2 dc.b ARPON dc.w TARP2 dc.b FS4,CR2 dc.b ARPON dc.w TARP1 dc.b FS4,CR2 dc.b ARPON dc.w TARP2 dc.b FS4,QV2 dc.b ARPON dc.w TARP3 dc.b FS4,QV2+CR2 dc.b RET TBACK2 dc.b CS4,CR2,CS4,QV2,CS4,QV2,CS4,CR2,CS4,QV2,CS4,QV2 dc.b CS4,QV2,REST,QV2,CS4,QV2,CS4,CR2,CS4,QV2,CS4,CR2 dc.b RET TBASS1 dc.b A2,SQ2,A2,SQ2,A2,QV2,DRUM,3,0,QV2,A2,QV2 dc.b A2,QV2,A2,SQ2,A1,SQ2,DRUM,3,3,QV2,DRUM,3,3,SQ2 dc.b A2,SQ2 dc.b E2,QV2,E3,SQ2,E2,SQ2,DRUM,3,0,QV2,E2,QV2 dc.b D2,QV2,D3,SQ2,D2,SQ2,DRUM,3,3,QV2,DRUM,3,3,SQ2,D3,SQ2 dc.b RET TBASS2 dc.b FS2,SQ2,FS2,SQ2,FS2,QV2,DRUM,3,0,QV2,FS2,QV2 dc.b FS2,QV2,FS2,SQ2,FS1,SQ2,DRUM,3,3,QV2,DRUM,3,3,SQ2 dc.b FS2,SQ2 dc.b RET TBASS3 dc.b FS2,SQ2,FS2,SQ2,FS2,QV2,FS3,QV2,FS2,QV2 TBASS4 dc.b FS2,QV2,FS2,SQ2,FS1,SQ2,FS2,QV2,FS3,SQ2 dc.b FS2,SQ2 dc.b RET TMEL1 dc.b FS5,MN2,E5,SB2 dc.b CS5,QV2,D5,QV2,CS5,QV2,D5,QV2,CS5,QV2 dc.b A4,CR2,E4,MN2+QV2+SB2 dc.b RET TMEL2 dc.b E5,QV2,FS5,QV2,A5,QV2 dc.b BEND,UP,$80,11 dc.w $80*11 dc.b B5,CR2,A5,CR2+QV2+SB2 TMEL22 dc.b E5,QV2,FS5,QV2,A5,QV2 dc.b BEND,UP,$80,11 dc.w $80*11 dc.b B5,CR2,A5,CR2+QV2,B5,CR2 dc.b BEND,UP,$90,11 dc.w $90*11 dc.b CS6,CR2,B5,QV2,A5,CR2+QV2 dc.b RET TARP1 dc.b 2,3,0,3,7 TARP2 dc.b 2,3,0,3,8 TARP3 dc.b 2,3,0,3,10 TARP4 dc.b 1,3,0,3,5 ;----------------------------------------------------------------------------- QUAL1 dc.b PATCH,18,PWM,11 dc.b VIBON,$04,$1A,6 dc.b BEND,UP,$50,8 dc.w $50*8 dc.b C5,DQV2,G4,DQV2,C4,QV2 dc.b VIBON,$0E,$20,8 dc.b BEND,UP,$50,11 dc.w $50*11 dc.b DS4,MN2,F4,MN2,G4,SB2 dc.b END QUAL2 dc.b PATCH,18,PWM,11 dc.b VIBON,$0E,$20,8 dc.b REST,3 dc.b C5,DQV2,G4,DQV2,C4,QV2-3 dc.b AS4,MN2,A4,MN2,B4,SB2 dc.b CODE dc.w TURNOFF dc.b END QUAL3 dc.b REST,MN2 dc.b VIBON,0,7,6 dc.b PWM,10 dc.b EFFECT,C7,MODE,%00001000 dc.b CALL dc.w QBASS1 dc.b CT,2 dc.w QBASS1 dc.b CT,4 dc.w QBASS1 dc.b CT,4 dc.w QBASS1 dc.b END QBASS1 dc.b PATCH,11 dc.b DS2,SQ2,DS3,SQ2 dc.b PATCH,13 dc.b CODE dc.w EFFECTOFF_C dc.b DS5,SQ2,DS5,SQ2,DRUM,3,5,QV2 dc.b CODE dc.w EFFECTON_C dc.b PATCH,11,DS1,QV2 dc.b RET ;---PATCH TABLE--------------------------------------------------------------- PATCH_START dc.b $51,$00,$C8,3,$40 ; 00 dc.b $01,$00,$88,2,$42 ; 01 dc.b $55,$00,$99,3,$40 ; 02 dc.b $41,$00,$88,QV2+GAP,$10; 03 dc.b $55,$00,$A9,3,$40 ; 04 dc.b $81,$00,$A8,3,$10 ; 05 dc.b $41,$00,$99,3,$40 ; 06 dc.b $41,$00,$59,9+GAP,$40; 07 dc.b $41,$00,$6A,6+GAP,$10; 08 dc.b $11,$AA,$79,QV2+SQ2+GAP,$10; 09 dc.b $41,$00,$89,QV2+GAP,$20; 10 dc.b $81,$00,$99,2,$40 ; 11 dc.b $41,$00,$89,QV2+GAP,$10; 12 dc.b $41,$00,$88,4+GAP,$14; 13 dc.b $11,$00,$A8,4+GAP,$10; 14 dc.b $41,$00,$69,6+GAP,$20; 15 dc.b $41,$00,$69,5+GAP,$10; 16 dc.b $41,$00,$48,3+GAP,$10; 17 dc.b $41,$00,$68,4+GAP,$14; 18 ;---PWM TABLE----------------------------------------------------------------- PWM_START dc.b $80,$00,$02 dc.w $0F50; 00 dc.b $70,$10,$08 dc.w $0000; 01 dc.b $40,$05,$05 dc.w $0100; 02 dc.b $30,$00,$02 dc.w $0000; 03 dc.b $F0,$04,$04 dc.w $0800; 04 dc.b $50,$05,$05 dc.w $0200; 05 dc.b $08,$00,$02 dc.w $0000; 06 dc.b $08,$00,$02 dc.w $0000; 07 dc.b $4F,$04,$04 dc.w $0600; 08 dc.b $08,$03,$03 dc.w $0800; 09 dc.b $30,$04,$02 dc.w $0100; 10 dc.b $50,$06,$04 dc.w $0000; 11 dc.b $20,$08,$07 dc.w $0100; 12 dc.b $50,$10,$0E dc.w $0000; 13 ;-----DRUM TABLE & DATA--------------------- DRUMTABLE dc.w DRUM1V,DRUM1F dc.b 4,$D8,$08 dc.w DRUM2V,DRUM2F dc.b 13,$D9,$07 dc.w DRUM3V,DRUM3F dc.b 5,$95,$02 dc.w DRUM4V,DRUM4F dc.b 15,$F8,$02 dc.w DRUM3V,DRUM3F dc.b 5,$F5,$02 ;-----BASS DRUM------ DRUM1V dc.b $41,$41,$10,$80 DRUM1F dc.b $0E,$06,$0F,$10 ;-----SNARE---------- DRUM2V dc.b $41,$41,$40,$80,$80,$80,$10,$80,$10,$80,$80,$10,$80 DRUM2F dc.b $11,$0C,$08,$70,$70,$2F,$0C,$2E,$0C,$2D,$BC,$0C,$2B ;-----HI-HAT--------- DRUM3V dc.b $11,$11,$80,$80,$80 DRUM3F dc.b $10,$10,$70,$20,$30 ;-----SNARE 2-------- DRUM4V dc.b $11,$11,$80,$10,$80,$10,$80,$10,$80,$10,$80,$10,$80,$10,$80 DRUM4F dc.b $10,$10,$70,$0B,$24,$0B,$23,$0B,$22,$0B,$21,$0B,$20,$0B,$20 TURNOFF LDA #8 STA $D404 STA $D404+7 STA $D404+14 LDA #0 STA $D404 STA $D404+7 STA $D404+14 RTS DATA.END EQU . ;------------------------------------------------------------------------------ VAR_START FILT_TOGGLE dc.b 0 FILT_TOGFLAG dc.b 0 DURCOUNT.A dc.b 0 DURCOUNT.B dc.b 0 DURCOUNT.C dc.b 0 TEMP.PC dc.b 0,0 ; 2 bytes GATE.A dc.b 0 GATE.B dc.b 0 GATE.C dc.b 0 SP.A dc.b 0 SP.B dc.b 0 SP.C dc.b 0 PORTFLAG.A dc.b 0 PORTFLAG.B dc.b 0 PORTFLAG.C dc.b 0 BEND.DIR.A dc.b 0 BEND.DIR.B dc.b 0 BEND.DIR.C dc.b 0 BENDSTEP.A dc.b 0 BENDSTEP.B dc.b 0 BENDSTEP.C dc.b 0 FREQ.LOW.A dc.b 0 FREQ.LOW.B dc.b 0 FREQ.LOW.C dc.b 0 FREQ.HI.A dc.b 0 FREQ.HI.B dc.b 0 FREQ.HI.C dc.b 0 OFFSET.A dc.b 0,0 ; 2 bytes OFFSET.B dc.b 0,0 ; 2 bytes OFFSET.C dc.b 0,0 ; 2 bytes BENDLENGTH.A dc.b 0 BENDLENGTH.B dc.b 0 BENDLENGTH.C dc.b 0 RELEASE_A dc.b 0 RELEASE_B dc.b 0 RELEASE_C dc.b 0 SUSTAIN_A dc.b 0 SUSTAIN_B dc.b 0 SUSTAIN_C dc.b 0 DURATION_A dc.b 0 DURATION_B dc.b 0 DURATION_C dc.b 0 VIBFLAG_A dc.b 0 VIBFLAG_B dc.b 0 VIBFLAG_C dc.b 0 VIBDELAY_A dc.b 0 VIBDELAY_B dc.b 0 VIBDELAY_C dc.b 0 VIBDELAY2_A dc.b 0 VIBDELAY2_B dc.b 0 VIBDELAY2_C dc.b 0 VIBDEPTH_A dc.b 0 VIBDEPTH_B dc.b 0 VIBDEPTH_C dc.b 0 VIBDEPTH2_A dc.b 0 VIBDEPTH2_B dc.b 0 VIBDEPTH2_C dc.b 0 VIBRATE_A dc.b 0 VIBRATE_B dc.b 0 VIBRATE_C dc.b 0 VIB_DIR_A dc.b 0 VIB_DIR_B dc.b 0 VIB_DIR_C dc.b 0 NEXTDELAY_A dc.b 0 NEXTDELAY_B dc.b 0 NEXTDELAY_C dc.b 0 NEXTDELAY2_A dc.b 0 NEXTDELAY2_B dc.b 0 NEXTDELAY2_C dc.b 0 ARPEGLEN_A dc.b 0 ARPEGLEN_B dc.b 0 ARPEGLEN_C dc.b 0 ARPEGIND_A dc.b 0 ARPEGIND_B dc.b 0 ARPEGIND_C dc.b 0 ARPFLAG_A dc.b 0 ARPFLAG_B dc.b 0 ARPFLAG_C dc.b 0 GATEOFF.A dc.b 0 GATEOFF.B dc.b 0 GATEOFF.C dc.b 0 NOTE_A dc.b 0 NOTE_B dc.b 0 NOTE_C dc.b 0 DURATIONON_A dc.b 0 DURATIONON_B dc.b 0 DURATIONON_C dc.b 0 PULSEDIR_A dc.b 0 PULSEDIR_B dc.b 0 PULSEDIR_C dc.b 0 RATEUP_A dc.b 0 RATEUP_B dc.b 0 RATEUP_C dc.b 0 RATEDOWN_A dc.b 0 RATEDOWN_B dc.b 0 RATEDOWN_C dc.b 0 CUP_A dc.b 0 CUP_B dc.b 0 CUP_C dc.b 0 CUP2_A dc.b 0 CUP2_B dc.b 0 CUP2_C dc.b 0 CDOWN_A dc.b 0 CDOWN_B dc.b 0 CDOWN_C dc.b 0 CDOWN2_A dc.b 0 CDOWN2_B dc.b 0 CDOWN2_C dc.b 0 PWL_A dc.b 0 PWL_B dc.b 0 PWL_C dc.b 0 PWL2_A dc.b 0 PWL2_B dc.b 0 PWL2_C dc.b 0 PWH_A dc.b 0 PWH_B dc.b 0 PWH_C dc.b 0 PWH2_A dc.b 0 PWH2_B dc.b 0 PWH2_C dc.b 0 PULSEFLAG_A dc.b 0 PULSEFLAG_B dc.b 0 PULSEFLAG_C dc.b 0 GAPFLAG_A dc.b 0 GAPFLAG_B dc.b 0 GAPFLAG_C dc.b 0 MFL_A dc.b 0 MFL_B dc.b 0 MFL_C dc.b 0 TRANSVAL_A dc.b 0 TRANSVAL_B dc.b 0 TRANSVAL_C dc.b 0 MODEBYTE_A dc.b 0 MODEBYTE_B dc.b 0 MODEBYTE_C dc.b 0 VOICE_NUM dc.b 0 DRUMadd dc.b 0 DRUMx ds.b 3,0 drumFLAG ds.b 3,0 DRUMtr ds.b 3,0 DRUMlength ds.b 3,0 WAVES_L ds.b 3,0 WAVES_H ds.b 3,0 FREQS_L ds.b 3,0 FREQS_H ds.b 3,0 VOLUMES ds.b 3,0 RELEASE.TEMP dc.b 0 ATTACK.TEMP dc.b 0 TEMP_VAL dc.b 0 EFFECTFLAG_A dc.b 0 EFFECTFLAG_B dc.b 0 EFFECTFLAG_C dc.b 0 EFFECT_NOTE_A dc.b 0 EFFECT_NOTE_B dc.b 0 EFFECT_NOTE_C dc.b 0 REAL_NOTE_A dc.b 0 REAL_NOTE_B dc.b 0 REAL_NOTE_C dc.b 0 TEMPX dc.b 0,0 ; 2 Bytes SUSTEMP ds.b 3,0 ADTEMP ds.b 3,0 MOD_OFF_A dc.b 0 MOD_OFF_B dc.b 0 MOD_OFF_C dc.b 0 VAR_END EQU . PROG.END EQU . ;------------------------------------------------------------------------------ SID EQU $D400 ; PAL Note frequency table N00 EQU 279 N01 EQU 296 N02 EQU 314 N03 EQU 332 N04 EQU 352 N05 EQU 373 N06 EQU 395 N07 EQU 419 N08 EQU 444 N09 EQU 470 N10 EQU 498 N11 EQU 528 N12 EQU 559 N13 EQU 592 N14 EQU 627 N15 EQU 665 N16 EQU 704 N17 EQU 746 N18 EQU 790 N19 EQU 837 N20 EQU 887 N21 EQU 940 N22 EQU 996 N23 EQU 1055 N24 EQU 1118 N25 EQU 1184 N26 EQU 1255 N27 EQU 1330 N28 EQU 1408 N29 EQU 1492 N30 EQU 1581 N31 EQU 1675 N32 EQU 1774 N33 EQU 1880 N34 EQU 1992 N35 EQU 2110 N36 EQU 2236 N37 EQU 2369 N38 EQU 2509 N39 EQU 2659 N40 EQU 2817 N41 EQU 2984 N42 EQU 3162 N43 EQU 3350 N44 EQU 3549 N45 EQU 3760 N46 EQU 3984 N47 EQU 4220 N48 EQU 4471 N49 EQU 4737 N50 EQU 5019 N51 EQU 5317 N52 EQU 5634 N53 EQU 5969 N54 EQU 6324 N55 EQU 6700 N56 EQU 7098 N57 EQU 7520 N58 EQU 7967 N59 EQU 8441 N60 EQU 8943 N61 EQU 9475 N62 EQU 10038 N63 EQU 10635 N64 EQU 11267 N65 EQU 11937 N66 EQU 12647 N67 EQU 13399 N68 EQU 14195 N69 EQU 15040 N70 EQU 15934 N71 EQU 16881 N72 EQU 17886 N73 EQU 18949 N74 EQU 20076 N75 EQU 21270 N76 EQU 22534 N77 EQU 23875 N78 EQU 25294 N79 EQU 26798 N80 EQU 28391 N81 EQU 30080 N82 EQU 31869 N83 EQU 33764 N84 EQU 35771 N85 EQU 37898 N86 EQU 40151 N87 EQU 42540 N88 EQU 45069 N89 EQU 47749 N90 EQU 50588 N91 EQU 53596 N92 EQU 56783 N93 EQU 60160 C0 EQU 0 CS0 EQU 1 D0 EQU 2 DS0 EQU 3 E0 EQU 4 F0 EQU 5 FS0 EQU 6 G0 EQU 7 GS0 EQU 8 A0 EQU 9 AS0 EQU 10 B0 EQU 11 C1 EQU 12 CS1 EQU 13 D1 EQU 14 DS1 EQU 15 E1 EQU 16 F1 EQU 17 FS1 EQU 18 G1 EQU 19 GS1 EQU 20 A1 EQU 21 AS1 EQU 22 B1 EQU 23 C2 EQU 24 CS2 EQU 25 D2 EQU 26 DS2 EQU 27 E2 EQU 28 F2 EQU 29 FS2 EQU 30 G2 EQU 31 GS2 EQU 32 A2 EQU 33 AS2 EQU 34 B2 EQU 35 C3 EQU 36 CS3 EQU 37 D3 EQU 38 DS3 EQU 39 E3 EQU 40 F3 EQU 41 FS3 EQU 42 G3 EQU 43 GS3 EQU 44 A3 EQU 45 AS3 EQU 46 B3 EQU 47 C4 EQU 48 CS4 EQU 49 D4 EQU 50 DS4 EQU 51 E4 EQU 52 F4 EQU 53 FS4 EQU 54 G4 EQU 55 GS4 EQU 56 A4 EQU 57 AS4 EQU 58 B4 EQU 59 C5 EQU 60 CS5 EQU 61 D5 EQU 62 DS5 EQU 63 E5 EQU 64 F5 EQU 65 FS5 EQU 66 G5 EQU 67 GS5 EQU 68 A5 EQU 69 AS5 EQU 70 B5 EQU 71 C6 EQU 72 CS6 EQU 73 D6 EQU 74 DS6 EQU 75 E6 EQU 76 F6 EQU 77 FS6 EQU 78 G6 EQU 79 GS6 EQU 80 A6 EQU 81 AS6 EQU 82 B6 EQU 83 C7 EQU 84 CS7 EQU 85 D7 EQU 86 DS7 EQU 87 E7 EQU 88 F7 EQU 89 FS7 EQU 90 G7 EQU 91 GS7 EQU 92 A7 EQU 93 AS7 EQU 94 B7 EQU 95