;----------------------------------------------------------------------------;
;                                                                            ;
;                         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                  ; Music refresh interrupt
               STA $FFFE
               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               ; Print the front end
               LDY #>TEXT1
               JSR SPRINT

               LDX #13                  ; All this bunf updates the front
               LDY #24
               LDA #>PROGRAM.LEN         ; panel
               JSR HEX
               INX
	       INX
               LDA #<PROGRAM.LEN
               JSR HEX

               LDX #13
               LDY #23
               LDA #>ALLOCATION
               JSR HEX
               INX
	       INX
               LDA #<ALLOCATION
               JSR HEX

               LDX #36
               LDA #>TOGO
               JSR HEX
               INX
	       INX
               LDA #<TOGO
               JSR HEX

               LDX #36
               LDY #24
               LDA #>DATA.LEN
               JSR HEX

               INX
	       INX
               LDA #<DATA.LEN
               JSR HEX

; this is the main loop of the framework

PRINT_STUFF    LDX #13
               LDY #3
               LDA TUNE_NUM
	       CLC
               ADC #1
               JSR HEX


               LDX #13
               LDY #4
               LDA CURRENTBAR
               JSR HEX

MISSBAR        LDX #17
               LDY #5
               LDA PC.A+1
               JSR HEX
               INX
	       INX
               LDA PC.A
               JSR HEX

               LDX #23
               LDA PC.B+1
               JSR HEX
               INX
	       INX
               LDA PC.B
               JSR HEX

               LDX #29
               LDA PC.C+1
               JSR HEX
               INX
	       INX
               LDA PC.C
               JSR HEX

               LDY #7
               LDX #17
               LDA PWH_A
               JSR HEX
               INX
	       INX
               LDA PWL_A
               JSR HEX

               LDY #7
               LDX #23
               LDA PWH_B
               JSR HEX
               INX
	       INX
               LDA PWL_B
               JSR HEX

               LDY #7
               LDX #29
               LDA PWH_C
               JSR HEX
               INX
	       INX
               LDA PWL_C
               JSR HEX

               LDX #18
               LDY #8
               LDA VIBDEPTH2_A
               JSR HEX

               LDX #24
               LDY #8
               LDA VIBDEPTH2_B
               JSR HEX

               LDX #30
               LDY #8
               LDA VIBDEPTH2_C
               JSR HEX

               LDY ARPEGIND_A
               LDA (READ_A),Y
               LDX #18
               LDY #9
               JSR HEX

               LDY ARPEGIND_B
               LDA (READ_B),Y
               LDX #24
               LDY #9
               JSR HEX

               LDY ARPEGIND_C
               LDA (READ_C),Y
               LDX #30
               LDY #9
               JSR HEX

               LDX #17
               LDY #10
               LDA READ_A+1
               JSR HEX
               INX
	       INX
               LDA READ_A
               JSR HEX

               LDX #23
               LDA READ_B+1
               JSR HEX
               INX
	       INX
               LDA READ_B
               JSR HEX

               LDX #29
               LDA READ_C+1
               JSR HEX
               INX
	       INX
               LDA READ_C
               JSR HEX

               LDX #17
               LDY #6
               LDA FREQ.HI.A
               JSR HEX
               INX
	       INX
               LDA FREQ.LOW.A
               JSR HEX

               LDX #23
               LDY #6
               LDA FREQ.HI.B
               JSR HEX
               INX
	       INX
               LDA FREQ.LOW.B
               JSR HEX

               LDX #29
               LDY #6
               LDA FREQ.HI.C
               JSR HEX
               INX
	       INX
               LDA FREQ.LOW.C
               JSR HEX

               LDX #18
               LDY #11
               LDA RELEASE_A
               JSR HEX

               LDX #24
               LDY #11
               LDA RELEASE_B
               JSR HEX

               LDX #30
               LDY #11
               LDA RELEASE_C
               JSR HEX

               LDA NOTE_A
               JSR NOTECALC
               LDY #3
PRIN_A         LDA (FRM),Y
               AND #$3F
               STA S+[12*40]+17,Y
               DEY
               BPL PRIN_A

               LDA NOTE_B
               JSR NOTECALC
               LDY #3
PRIN_B         LDA (FRM),Y
               AND #$3F
               STA S+[12*40]+23,Y
               DEY
               BPL PRIN_B

               LDA NOTE_C
               JSR NOTECALC_C           ; Calc note, & see if drum is playing
               LDY #3
PRIN_C         LDA (FRM),Y
               AND #$3F
               STA S+[12*40]+29,Y
               DEY
               BPL PRIN_C

               LDY #0
               LDX #38
               LDA RTIME
               JSR HEX

               LDY #1
               LDA MAXTIME
               JSR HEX

               LDA DURATIONON_A
               ASL
	       ASL
               TAY
               LDX #0
MODE_A1        LDA MODETEXT,Y
               AND #$3F
               STA S+[13*40]+17,X
               INY
               INX
               CPX #4
               BNE MODE_A1

               LDA DURATIONON_B
               ASL
	       ASL
               TAY
               LDX #0
MODE_B1        LDA MODETEXT,Y
               AND #$3F
               STA S+[13*40]+23,X
               INY
               INX
               CPX #4
               BNE MODE_B1

               LDA DURATIONON_C
               ASL
	       ASL
               TAY
               LDX #0
MODE_C1        LDA MODETEXT,Y
               AND #$3F
               STA S+[13*40]+29,X
               INY
               INX
               CPX #4
               BNE MODE_C1

               LDX #18
               LDY #14
               LDA GATE.A
               JSR HEX

               LDX #24
               LDY #14
               LDA GATE.B
               JSR HEX

               LDX #30
               LDY #14
               LDA GATE.C
               JSR HEX

               INY
               LDX #18
               LDA GATEOFF.A
               JSR HEX

               LDX #24
               LDA GATEOFF.B
               JSR HEX

               LDX #30
               LDA GATEOFF.C
               JSR HEX

               LDX #18
               LDY #18
               LDA BENDLENGTH.A
               JSR HEX

               LDX #24
               LDA BENDLENGTH.B
               JSR HEX

               LDX #30
               LDA BENDLENGTH.C
               JSR HEX

               LDA GAPFLAG_A
               ASL
               ASL
               TAY
               LDX #0
PRGAP_A        LDA GAPTEXT,Y
               AND #$3F
               STA S+[16*40]+17,X
               INY
               INX
               CPX #4
               BNE PRGAP_A

               LDA GAPFLAG_B
               ASL
               ASL
               TAY
               LDX #0
PRGAP_B        LDA GAPTEXT,Y
               AND #$3F
               STA S+[16*40]+23,X
               INY
               INX
               CPX #4
               BNE PRGAP_B

               LDA GAPFLAG_C
               ASL
               ASL
               TAY
               LDX #0
PRGAP_C        LDA GAPTEXT,Y
               AND #$3F
               STA S+[16*40]+29,X
               INY
               INX
               CPX #4
               BNE PRGAP_C

OUT            LDX #18
               LDY #19
               LDA TRANSVAL_A
               JSR HEX
               LDX #24
               LDA TRANSVAL_B
               JSR HEX
               LDX #30
               LDA TRANSVAL_C
               JSR HEX

               LDX #21
               LDY #1
               LDA BAR_TEMP
               JSR HEX

               LDX #12
               LDY #20
               LDA MODEBYTE_A
               JSR BINARY
               LDX #21
               LDA MODEBYTE_B
               JSR BINARY
               LDX #30
               LDA MODEBYTE_C
               JSR BINARY

               LDA #12                  ; All keychecks done from here
               JSR KEYSCAN
               BCC NOPAUSE

               LDA SKIP_FLAG
               EOR #1
               STA SKIP_FLAG

NOPAUSE        LDA #40
               JSR KEYSCAN
               BCC NO_PLUS

               INC BAR_TEMP
               JMP PRINT_STUFF

NO_PLUS        LDA #43
               JSR KEYSCAN
               BCC CHECK_TUNES

               DEC BAR_TEMP

               JMP PRINT_STUFF

CHECK_TUNES    LDX #0                   ; Trigger a different tune
NEXT_SCAN      LDA KEYS,X
               JSR KEYSCAN
               BCS GOT_TUNE
               INX
               CPX #NUM_OF_TUNES
               BNE NEXT_SCAN
               JMP TEST_STOP

GOT_TUNE       STX TUNE_NUM
               JSR TUNE

               LDA #0
               STA CURRENTBAR
               STA BARCOUNT
               STA MAXTIME
               LDA #"0"
               STA S+[1*40]+0
               STA S+[1*40]+1
               STA S+[1*40]+3
               STA S+[1*40]+4
               LDA #50
               STA FIFTIES

TEST_STOP      LDA #60
               JSR KEYSCAN
               BCS STOP_TUNE

               LDA #4                   ; Bar skip
               JSR KEYSCAN
               BCS SKIP
               JMP PRINT_STUFF

SKIP           LDY BAR_TEMP
               STY YTMP
               LDX #BARLENGTH
               STX XTMP
               LDA #1
               STA SKIP_FLAG
JUMP_LOTS      JSR REFRESH
               JSR DOBARS
               JSR CLOCK
               DEC XTMP
               BNE JUMP_LOTS
               LDA #BARLENGTH
               STA XTMP
               DEC YTMP
               BNE JUMP_LOTS
               LDA #0
               STA SKIP_FLAG
               JMP PRINT_STUFF

XTMP           dc.b 0
YTMP           dc.b 0
SKIP_FLAG      dc.b 0

STOP_TUNE      LDA #0                   ; Halts a tune
               STA MFL_A
               STA MFL_B
               STA MFL_C
               STA PORTFLAG.A
               STA PORTFLAG.B
               STA PORTFLAG.C
               STA VIBFLAG_A
               STA VIBFLAG_B
               STA VIBFLAG_C
               STA ARPFLAG_A
               STA ARPFLAG_B
               STA ARPFLAG_C
               STA PULSEFLAG_A
               STA PULSEFLAG_B
               STA PULSEFLAG_C
               STA $D418
               JMP PRINT_STUFF

TEST_FF        LDA #47
               JSR KEYIN
               BCS FAST1
               LDA #44
               JSR KEYIN
               BCS FAST2
               RTS

FAST1          JSR REFRESH
               JSR DOBARS
               JSR MUSICTEST
               BEQ NOCLOCK1
               JSR CLOCK
NOCLOCK1       RTS

FAST2          JSR REFRESH
               JSR DOBARS
               JSR REFRESH
               JSR DOBARS
               JSR REFRESH
               JSR DOBARS
               JSR MUSICTEST
               BEQ NOCLOCK2
               JSR CLOCK
               JSR CLOCK
               JSR CLOCK
NOCLOCK2       RTS

TEXT1          dc.b AT,0,0,14, "DRIVER V1.4 BY P.HUGHES"
               dc.b AT,1,3,3, "TUNE NUMBER"
               dc.b AT,18,3,1, "C1    C2    C3"
               dc.b AT,0,5,7, "PC ADDRESS"
               dc.b AT,0,6,7, "FREQUENCIES"
               dc.b AT,0,7,7, "PULSE WIDTH"
               dc.b AT,0,8,7, "VIBRATO"
               dc.b AT,0,9,7, "ARPEGGIO OFFSET"
               dc.b AT,0,10,7, "ARPEGGIO ADDR"
               dc.b AT,0,11,7, "SUSTAIN COUNT"
               dc.b AT,0,12,7, "NOTE"
               dc.b AT,0,13,7, "LENGTH MODE"
               dc.b AT,0,14,7, "WAVEFORM ON"
               dc.b AT,0,15,7, "WAVEFORM OFF"
               dc.b AT,0,16,7, "GAP MODE"
               dc.b AT,0,17,7, "FUTURE EXPANSION"
               dc.b AT,0,18,7, "PORTAMENTO"
      	       dc.b AT,0,19,7, "TRANSPOSE"
               dc.b AT,0,20,7, "MODE BYTE"
               dc.b AT,0,23,7, "ALLOCATION"
               dc.b AT,25,23,7, "FREE SPACE"
               dc.b AT,0,24,7, "TOTAL LENGTH"
               dc.b AT,24,24,7, "DATA LENGTH"
               dc.b AT,25,0,7, "RASTER TIME"
               dc.b AT,25,1,7, "MAXIMUM TIME"
               dc.b AT,0,21,14
	       ds.b 40,"-"
               dc.b AT,0,22,1, "-----D.T.'88-MUSIC-BY-JONATHAN-DUNN-----"
               dc.b AT,0,1,8, "00-00"
               dc.b AT,1,4,5, "CURRENT BAR"
               dc.b AT,7,1,4, "BARS TO SKIP $00"
               dc.b FIN

MODETEXT       dc.b "AUTOMAN "
GAPTEXT        dc.b "OFF ON  "

KEYS           dc.b 10,28,20,18,14,21,26,29,33,34,37,42,36,39,38,41,62,17
               dc.b 13,22,30,31,9,23,25,12

DOBARS         INC BARCOUNT
               LDA BARCOUNT
               CMP #BARLENGTH
               BNE NOBAR
               INC CURRENTBAR
               LDA #0
               STA BARCOUNT
NOBAR          RTS

;
;
;

R0             STA IA
               STX IX
               STY IY
               CLD
               DEC $D019                ; Acknowledge interrupt

               LDA #2                   ; Border RED
               STA $D020

               LDA SKIP_FLAG
               BNE NO_RAST

               JSR REFRESH              ; Refresh music

               JSR MUSICTEST
               BEQ NO_RAST
               JSR DOBARS

NO_RAST        LDA #0                   ; Border black
               STA $D020

               LDA $D012                ; Work out the raster time used
	       SEC
               SBC #$A2
               STA RTIME
               CMP MAXTIME
               BCC NOT_HIGHER
               STA MAXTIME

NOT_HIGHER     JSR MUSICTEST
               BEQ NOCLOCK
               JSR CLOCK                ; Update 50Hz clock

NOCLOCK        JSR TEST_FF              ; Test for Fast Forward

               LDA IA
               LDX IX
               LDY IY
               RTI                      ; Interrupt over and done with

;
; SPRINT - Print text pointed to by X & Y in single or double height
;

SPRINT         STX FRM
               STY FRM+1

               LDY #0
GET            LDA (FRM),Y
               BMI GETCOORD
               BNE TEXT
               JMP DONE

TEXT           AND #$3F
               STA (TO),Y
               LDA CULA
               STA (TO2),Y

               INC TO
               BNE NOC2
               INC TO+1
NOC2           INC TO2
               BNE NOC3
               INC TO2+1
NOC3           INC FRM
               BNE GET
               INC FRM+1
               JMP GET

GETCOORD
               INY                      ; Get data; X coord, Y coord, colour
               LDA (FRM),Y
               STA TEMP
               INY
               LDA (FRM),Y
               ASL
               TAX
               LDA TEMP
	       CLC
               ADC YTAB,X
               STA TO
               STA TO2
               LDA YTAB+1,X
               ADC #0
               STA TO+1
               ADC #$D4
               STA TO2+1
               INY
               LDA (FRM),Y
               STA CULA

               LDA FRM
	       CLC
               ADC #4
               STA FRM
               BCC NOC
               INC FRM+1

NOC            LDY #0
               JMP GET

DONE           RTS

;
; HEX - Print a hex number in A at X,Y
;

HEX            STX SX
               STY SY
               STA SA
               TYA
               ASL
               TAY
               LDA YTAB,Y
               STA TO
               LDA YTAB+1,Y
               STA TO+1
               TXA
               TAY
               LDA SA
               LSR
               LSR
               LSR
               LSR
               TAX
               LDA DIGITS,X
               AND #$3F
               STA (TO),Y
               LDA SA
               AND #$0F
               TAX
               LDA DIGITS,X
               AND #$3F
               INY
               STA (TO),Y
               LDA SA
               LDX SX
               LDY SY
               RTS

;
; BINARY - Print a number in A at X,Y in Binary
;

BINARY         STA SA
               STX SX
               STY SY
               TYA
               ASL
               TAY
               LDA YTAB,Y
               STA TO
               LDA YTAB+1,Y
               STA TO+1
               TXA
               TAY
               LDX #0
BIN_LOOP       LDA SA
               AND MASK,X
               BNE PRINTIT
               LDA #"0"
               JMP DUMPBIN
PRINTIT        LDA #"1"
DUMPBIN        STA (TO),Y
               INY
               INX
               CPX #8
               BNE BIN_LOOP
               LDA SA
               LDX SX
               LDY SY
               RTS

MASK           dc.b 128,64,32,16,8,4,2,1

;
; CLOCK - Processes and prints a clock running at 50Hz
;

CLOCK          DEC FIFTIES
               BEQ BUMP_1
               RTS

BUMP_1         LDA #50
               STA FIFTIES
               LDA S+1*40+4
               CMP #"9"
               BEQ BUMP_2
               INC S+1*40+4
               RTS

BUMP_2         LDA #"0"
               STA S+1*40+4
               LDA S+1*40+3
               CMP #"5"
               BEQ BUMP_3
               INC S+1*40+3
               RTS

BUMP_3         LDA #"0"
               STA S+1*40+3
               LDA S+1*40+1
               CMP #"9"
               BEQ BUMP_4
               INC S+1*40+1
               RTS

BUMP_4         LDA #"0"
               STA S+1*40+1
               INC S+1*40+0
               RTS

;
; NOTECALC - Calculates what note is being played
;

NOTECALC_C     LDX drumFLAG+2           ; Only called by channel C
               BEQ NOTECALC
               LDA #<DRUM_TEXT
               STA FRM
               LDA #>DRUM_TEXT
               STA FRM+1
               RTS

NOTECALC       LDY #0
               STY TEMP
               ASL
               ROL TEMP
               ASL
               ROL TEMP
	       CLC
               ADC #<NOTES
               STA FRM
               LDA TEMP
               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
               STA FROM
               LDA FROM+1
               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
               LDA FROM+1
               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
               LDA FROM+1
               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
               LDA FROM+1               ; Plus patch base address
               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
               LDA FROM+1
               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
               LDA FROM+1
               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

JUMPVECH.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

JUMPVECH.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

JUMPVECH.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

HIFREQ         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,<FAIL1,<EVENT1,<TITLE1,<QUAL1
TUNETABLE.A.H  dc.b >DITTY1,>SUCCESS1,>FAIL2,>EVENT1,>TITLE1,>QUAL1

TUNETABLE.B.L  dc.b <DITTY2,<SUCCESS2,<FAIL2,<EVENT2,<TITLE2,<QUAL2
TUNETABLE.B.H  dc.b >DITTY2,>SUCCESS2,>FAIL2,>EVENT2,>TITLE2,>QUAL2

TUNETABLE.C.L  dc.b <DITTY3,<SUCCESS3,<FAIL3,<EVENT3,<TITLE3,<QUAL3
TUNETABLE.C.H  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





