*-------------------------------
*
* music.s
*
* Or, to be more precise, Prelude #2 from The Well-
* Tempered Klavier, by J.S. Bach.
*
* This is the main music routine for the 4k demo.
* The music is driven by an interrupt generated by
* VIC.  A simple countdown timer is decremented
* until zero is reached, at which point the next
* note is played, and if necessary the next note
* (or notes) are read in.  For more details, see the
* code!
*
* Stephen L. Judd  6/27/96  <--- (Down to the wire, eh?)
*
         DSK "music"      
                          
         REL              
                          
*
* Variables
*
COUNTER  EQU $03          ;Duration countdown
INDEX    EQU $04          ;Index into note table (not freq)
VOICES   EQU $05          ;Tells which voices are active
NUMNOTES EQU $06          ;Number of notes read in at a time
NOTEPTR  EQU $07          ;2-byte pointer to music data
DURATION EQU $09          ;Duration of each note
VOLUME   EQU $0A          ;Duh
GATE1    EQU $0B          ;Value to gate/ungate voice 1 with
GATE2    EQU $0C          ;Same for voice 2
GATE3    EQU $0D          ;Same for voice 3
                          
*
* Some awesome-possum constants
*
VOICE1   EQU $C200        ;Current notes for voice 1
VOICE2   EQU $C210        ;Current notes for voice 2
VOICE3   EQU $C220        ;Hmmmm...
FREQLO   EQU $C300        ;Frequency table
FREQHI   EQU $C380        
                          
REST     EQU 00           ;Treat note zero as a rest
                          ;(which just un-gates the voice)
                          
RESTART  EQU $80          ;Special music-data token
SETDUR   EQU $81          ;Set-duration token
SETVOL   EQU $82          ;Set-volume token
SETNUM   EQU $83          ;Set number of notes token
SETV1    EQU $84          ;Voice-1 only token
SETV12   EQU $85          ;Voice 1 and 2
SETV123  EQU $86          
                          
EIGHTH   EQU 7            ;Duration of a sixteenth note :)
PRESTO   EQU 5            ;16th note in Presto section
ADAGIO   EQU 18           ;16th note in Adagio section
F        EQU 12           ;Forte
SF       EQU 14           ;"Sfortzando"
FF       EQU 15           ;Double-forte
P        EQU 8            ;Piano
                          
*
* Some handy-dandy C64-related constants
*
                          
SID      EQU $D400        
V1       EQU SID          
V2       EQU SID+7        
V3       EQU V2+7         
                          
* Kernal
                          
SCNKEY   EQU $EA87        
GETIN    EQU $F13E        
CHROUT   EQU $FFD2        
                          
*-------------------------------
*===============================
* Not assembled
         DO 0             ;Don't assemble
         SEI              
         JSR MUSINIT      
         CLI              
:TEST    JSR SCNKEY       ;Just test if we are calling
         JSR GETIN        ;interrupt correctly, etc.
         CMP #00          
         BEQ :TEST        
         JSR CHROUT       
         JMP :TEST        
         FIN              
*===============================
                          
*-------------------------------
*
* Initialize interrupt routine
*
* Note that calling routine must SEI/CLI !!!
*
                          
MUSINIT  ENT              ;Set up interrupt
                          
         LDX #11          ;Set up note frequency tables
                          ;Since I screwed up and made
                          ;everything an octave too high,
                          ;I compensate here in the table
                          ;setup via an LSR/ROR
                          ;Or, if you like, it sounds better
                          ;an octave lower with this instrument
:L1      LDA HITAB,X      
         LSR              
         STA FREQHI+84,X  ;Store at top of table
         LDA LOTAB,X      
         ROR              
         STA FREQLO+84,X  
         DEX              
         BPL :L1          
         LDX #83          ;Now extend the table
:L2      LDA FREQHI+12,X  ;downwards, dividing by
         LSR              ;two to get octaves
         STA FREQHI,X     
         LDA FREQLO+12,X  
         ROR              
         STA FREQLO,X     
         DEX              
         BPL :L2          ;That ought to do it!
                          
NOTEINIT                  
         LDX #20          ;Initialize SID
:LOOP    LDA SIDINIT,X    
         STA SID,X        
         DEX              
         BPL :LOOP        
                          
         LDA #16          
         STA NUMNOTES     ;Read in 16 notes at a time
                          ;initially
         STA INDEX        
         LDA #00          
         STA VOLUME       
         LDA SIDINIT+4    
         STA GATE1        
         LDA SIDINIT+11   
         STA GATE2        
         LDA SIDINIT+18   
         STA GATE3        
                          
*===============================
         DO 0             ;Don't assemble
         LDA #15          
         STA SID+24       
         LDA GATE1        
         STA V1+4         
         LDX #00          ;Test the note table
         STX COUNTER      
:L3      LDA FREQLO,X     
         STA V1           
         LDA FREQHI,X     
         STA V1+1         
         LDY #10          
:L4      DEC COUNTER      ;delay loop
         BNE :L4          
         DEY              
         BNE :L4          
         INX              
         CPX #96          
         BNE :L3          
         LDA GATE1        
         AND #$FE         
         STA V1+4         
         FIN              
*===============================
                          
         LDA #<NOTEDATA   
         STA NOTEPTR      ;Pointer into note data
         LDA #>NOTEDATA   
         STA NOTEPTR+1    
                          
         LDA #<MUSPLAY    
         STA $0314        ;Set location of interrupt
         LDA #>MUSPLAY    
         STA $0315        
                          
         LDA #$00         
         STA $DC0E        ;Kill CIA interrupt
                          
         LDA #$01         
         STA COUNTER      
         STA DURATION     
         STA $D01A        ;Enable raster interrupt
         STA $D019        ;Raster compare
         STA $D012        ;Set line to interrupt at
                          ;(line 1 or line 257 is ok)
* LDA $D011
* AND #$7F ;Zap upper VIC bit
* STA $D011
         RTS              
                          
*-------------------------------
*
* Some initialization data for SID and note frequency
* table.
*
* Just a boring ol sawtooth.
*
SIDINIT  HEX 000000002128A8 ;Voice 1 lo hi plo phi gate adsr
         HEX 00000000212AAD ;Voice 2
         HEX 00000000202AAD ;Voice 3
                          
* These are frequencies out of PRG for equal tempered
* scale.  Equal tempered is a drag but it ought to work OK.
                          
LOTAB    DFB 30,24,139,126,250,6,172,243,230,143,248,46
                          
HITAB    DFB 134,142,150,159,168,179,189,200,212,225,238,253
                          
*-------------------------------
*
* The main music player routine.
*
                          
*
* First, a few nifty-spiffty macros
*
                          
* PLAYNOTE does what it says.  Three variables are passed
* in: the first is VOICE1 VOICE2 or VOICE3, and is
* the next note to be played.  The second is V1 V2 V3
* which are the appropriate SID locations to store stuff.
* The third is GATE1, etc., which essentially tells whether
* to gate or ungate a note.
                          
PLAYNOTE MAC              
         LDA ]1,X         ;VOICE3 etc. contains index into
         TAY              ;note frequency table
         LDA FREQLO,Y     
         STA ]2           ;Store it in SID
         LDA FREQHI,Y     ;Lo/Hi frequency
         STA ]2+1         
         LDA ]3           ;Gate/ungate note
         STA ]2+4         
         <<<              
                          
* It is simpler to put the end at the beginning :)
                          
ALLDONE  STX INDEX        
         PLA              
         TAY              ;Restore registers
         PLA              
         TAX              
         PLA              
         RTI              
*
* Now the main player routine
*
MUSPLAY                   
         LDA $D019        
         STA $D019        ;Clear interrupt flag
         LDX INDEX        ;Index into note table
         DEC COUNTER      
         BNE ALLDONE      
         LDA DURATION     ;Reset counter
         STA COUNTER      
         BIT VOICES       ;Which voices are "active"?
         BPL PLAY2        ;bit7=>voice3 bit6=>voice2
                          
PLAY3    >>> PLAYNOTE,VOICE3;V3;GATE3
PLAY2    BVC PLAY1        
         >>> PLAYNOTE,VOICE2;V2;GATE2
PLAY1    >>> PLAYNOTE,VOICE1;V1;GATE1
         LDA VOLUME       
         STA SID+24       
                          
         INX              
         CPX NUMNOTES     ;Either 16 or 1
         BMI ALLDONE      
                          
* Main parser routine.  Data is either an index into
* the note frequency table (thus, a note) or else a
* special character.  Special characters have the
* high bit set and have the following meanings:
*    - Restart music
*    - Every note after this has duration xx
*    - Set volume to xx
*    - Voice 1 only (No data for voice 2 or 3)
*    - Voice1 and 2 only
*    - Voice 1 2 and 3
*    - Notes are read in one at a time from now on
*
* First all dynamics e.g. special characters are read in,
* then the next notes are read in.  These values will be
* updated into SID the NEXT time around.
                          
PARSE                     
         LDY #00          
:LOOP    LDA (NOTEPTR),Y  
         BPL READNOTE     ;High bit clear means note data
                          
         CMP #RESTART     
         BNE :DUR         
         JSR NOTEINIT     ;Reinitialize, skipping tables
         LDX #00          
         JMP ALLDONE      
:DUR     CMP #SETDUR      ;Change duration
         BNE :VOL         
         INY              
         LDA (NOTEPTR),Y  ;Get durations of following notes
         STA DURATION     
         BNE :DONE        
:VOL     CMP #SETVOL      ;Set new volume
         BNE :V1          
         INY              ;Get volume to set to
         LDA (NOTEPTR),Y  
         STA VOLUME       
         BNE :DONE        
:V1      CMP #SETV1       ;Voice 1 only
         BNE :V2          
         LDA #00          
         STA VOICES       
         BEQ :DONE        ;(really don't need these branches)
:V2      CMP #SETV12      
         BNE :V3          
         LDA #$40         ;Set bit six
         STA VOICES       
         BNE :DONE        
:V3      CMP #SETV123     
         BNE :NEWNUM      
         LDA #$C0         ;Bit six and seven
         STA VOICES       
         BNE :DONE        
:NEWNUM  LDA #01          ;If we got here then this is
         STA NUMNOTES     ;the only one left!
:DONE    INY              ;That was so much fun...
         BNE :LOOP        ;let's do it again.
                          
READNOTE                  ;Now read in note data
         LDX NUMNOTES     
         CPX #16          
         BEQ READ16       ;Routine to read 16 notes at a time
                          ;Otherwise, read one note at a time
READ1    CMP #REST        
         BNE :V1          
         LDA GATE1        ;REST will mean ungate note
         AND #$FE         
         STA GATE1        
         BNE :V2          
:V1      STA VOICE1       
         LDA GATE1        
         ORA #$01         
         STA GATE1        
:V2      BIT VOICES       ;Any voice 2 data to read in?
         BVC NOTEDONE     ;No voice 2 means no voice 3
         INY              
         LDA (NOTEPTR),Y  ;Otherwise, read in note
         CMP #REST        
         BNE :NOPE2       
         LDA GATE2        
         AND #$FE         
         STA GATE2        
         BNE :V3          
:NOPE2                    
         STA VOICE2       
         LDA GATE2        
         ORA #$01         
         STA GATE2        
:V3      BIT VOICES       ;Read in voice 3 data?
         BPL NOTEDONE     
         INY              
         LDA (NOTEPTR),Y  
         CMP #REST        
         BNE :NOPE3       
         LDA GATE3        
         AND #$FE         
         STA GATE3        
         BNE NOTEDONE     
:NOPE3                    
         STA VOICE3       
         LDA GATE3        
         ORA #$01         
         STA GATE3        
                          
NOTEDONE INY              ;Point to next piece of data
         TYA              ;and update note pointer
         CLC              
         ADC NOTEPTR      
         STA NOTEPTR      
         BCC :CONT        
         INC NOTEPTR+1    
:CONT    LDX #00          ;Reset index
         JMP ALLDONE      ;And get the heck out of here!
*
* Much of the piece consists of broken 4-note chords,
* broken across four sets of four notes each.  Thus
* sixteen notes can be specified at a time with
* just four data values, and this routine handles
* this case.
*
READ16                    
         STA VOICE1       ;First note of chord goes to
                          ;notes 1 and 9
         INY              
         LDA (NOTEPTR),Y  
         STA VOICE1+1     
         STA VOICE1+3     
         STA VOICE1+5     
         STA VOICE1+7     
         INY              
         LDA (NOTEPTR),Y  
         STA VOICE1+2     
         STA VOICE1+6     
         INY              
         LDA (NOTEPTR),Y  
         STA VOICE1+4     
                          
         INY              ;Now read in voice 2 guys
         LDA (NOTEPTR),Y  
         STA VOICE2       
         INY              
         LDA (NOTEPTR),Y  
         STA VOICE2+1     
         STA VOICE2+3     
         STA VOICE2+5     
         STA VOICE2+7     
         INY              
         LDA (NOTEPTR),Y  
         STA VOICE2+2     
         STA VOICE2+6     
         INY              
         LDA (NOTEPTR),Y  
         STA VOICE2+4     
                          
         LDX #7           ;Now repeat each 8-note set
:LOOP    LDA VOICE1,X     
         STA VOICE1+8,X   
         LDA VOICE2,X     
         STA VOICE2+8,X   
         DEX              
         BPL :LOOP        
         INX              ;X=0 -> INDEX
         JMP NOTEDONE     ;And depart
                          
*-------------------------------
*
* And finally the music data.  The music data is divided
* into two types of data: notes and special actions.
* If the high bit is set, then we undertake a special
* action, otherwise the data is a note.
*
* Each "note" is an index into a table of frequency values
* set up by the initialization routine.
*
* Special actions are described up above in the parser
* routine, and are things like change volume, duration, etc.
* The basic rule is that if any actions (e.g. volume changes)
* are to take place in a measure/on a note, then the data
* corresponding to those actions needs to appear before the
* note data.
*
* The piece is essentially a series of broken chords, and
* the first 24 measures are four-note chords broken into
* a repeated set of eight notes, split into two groups of
* four each.  There is one set for each hand, thus voice 1
* and voice 2 behave similarly.  These are the "16-note"
* measures read in by READ16 above, and they are defined
* by specifying first the four notes for the right hand,
* then the four notes for the left hand.
*
NOTEDATA                  
         DFB SETV12       ;Voices 1 and 2
         DFB SETDUR       
         DFB EIGHTH       ;Note duration
         DFB SETVOL,F     
                          ;Now voice-1 four note chord
                          ;Measure 1
         DFB 72           ;C-6
         DFB 63           ;Eb
         DFB 62           ;D
         DFB 60           ;C-5
                          ;And voice-2 chord
         DFB 48           ;C-4
         DFB 55           ;G-4
         DFB 53           ;F
         DFB 51           ;Eb
                          
                          ;Measure 2
         DFB 68,65,64,60  ;Ab F E C
         DFB 48,56,55,53  ;C Ab G F
                          
                          ;Measure 3
         DFB 71,65,63,62  ;B F Eb D
         DFB 48,56,55,53  ;C Ab G F
                          
         DFB 72,67,65,63  ;C G F Eb
         DFB 48,51,50,55  ;C Eb D G
                          
         DFB SETVOL,SF    
         DFB 75,68,67,63  ;Eb Ab G Eb
         DFB 48,60,58,56  ;C C Bb Ab
                          
         DFB SETVOL,P     ;Piano
         DFB 74,66,64,62  ;D F# E D
         DFB 48,57,55,54  ;C A G F#
                          
         DFB SETVOL,SF    
         DFB 74,67,66,62  ;D G F# D
         DFB 46,58,57,55  ;Bb Bb A G
                          
         DFB SETVOL,P     ;Measure 8
         DFB 72,64,62,60  ;C E D C
         DFB 46,55,53,52  ;Bb G F E
                          
         DFB SETVOL,F     
         DFB 72,65,64,60  ;C F E C
         DFB 44,56,55,53  ;Ab Ab G F
                          
         DFB 70,65,63,62  ;Bb F Eb D
         DFB 44,50,48,53  ;Ab D C F
                          
         DFB SETVOL,F-1   ;Start decrescendo
         DFB 70,67,65,63  ;Bb G F Eb
         DFB 43,51,50,55  ;G Eb D G
                          
         DFB SETVOL,F-2   
         DFB 68,67,65,63  ;Ab G F Eb
         DFB 48,51,50,56  ;C Eb D Ab
                          
         DFB SETVOL,P     ;Measure 13
         DFB 68,62,60,58  ;Ab D C Bb
         DFB 50,53,51,56  ;D F Eb Ab
                          
         DFB 67,58,55,63  ;G Bb Ab Eb
         DFB 51,55,53,56  ;Eb G F Ab
                          
         DFB SETVOL,P+1   ;cresc.
         DFB 65,60,58,57  ;F C Bb A
         DFB 51,57,55,53  ;Eb A G F
                          
         DFB SETVOL,P+2   
         DFB 65,62,60,59  ;F D C B
         DFB 50,53,51,56  ;D F Eb Ab
                          
         DFB SETVOL,P+3   
         DFB 65,62,60,59  ;F D C B
         DFB 48,53,52,56  ;C F E Ab
                          
         DFB SETVOL,P+4   
         DFB 63,60,59,55  ;Eb C B G
         DFB 48,51,50,53  ;C Eb D F
                          
         DFB SETVOL,F     
         DFB 53,63,62,65  ;F Eb D F
         DFB 44,48,47,50  ;Ab C B D
                          
         DFB 54,60,59,63  ;F# C B Eb
         DFB 45,51,50,48  ;A Eb D C
                          
         DFB SETVOL,F+1   
         DFB 63,60,59,55  ;Eb C B G
         DFB 43,51,50,53  ;G Eb D F
                          
         DFB 66,60,59,57  ;F# C B A
         DFB 43,51,50,48  ;G Eb D C
                          
         DFB SETVOL,F+2   
         DFB 67,60,59,62  ;G C B D
         DFB 43,51,50,53  ;G Eb D F
                          
         DFB 68,60,59,62  ;Ab C B D
         DFB 43,51,50,53  ;G Eb D F
                          
         DFB SETNUM       ;Read one at a time from now on
         DFB SETVOL,F+1   ;fz if you will
         DFB SETDUR,EIGHTH+2 ;A self-indulgent hesitation
         DFB 43           
         DFB REST         ;Ungate voice 2
         DFB SETV1        ;Voice 1 only
         DFB 47           
         DFB SETDUR,EIGHTH
         DFB 50,53        
         DFB SETVOL,F     ;Slight decrescendo
         DFB 56,53,52,53  
         DFB 59,53,62,59,56,53,52
         DFB SETDUR,EIGHTH+2
         DFB 53           
                          
* DFB SETDUR,EIGHTH+2
         DFB 43,48        
         DFB SETDUR,EIGHTH
         DFB 51,55        
         DFB 60,55,54,55  
         DFB 63,60,67,63  
         DFB 60,56,55     
         DFB SETDUR,EIGHTH+2
         DFB 56           
                          
* DFB SETDUR,EIGHTH+2
         DFB 43,45        
         DFB SETDUR,EIGHTH
         DFB 53,60        
         DFB 63,60,62,60  
         DFB 66,60,69,66  
         DFB 63,60,62,60  
                          
         DFB SETV12       
         DFB SETVOL,FF    ;Fortissimo!
         DFB REST         
         DFB 43           ;Voice 2 pedal tone
         DFB SETV1        
         DFB SETDUR,PRESTO ;Presto!
         DFB 74,72,74     
         DFB 75,72,71,72  
         DFB 69,72,71,72  
         DFB 74,71,69,71  
                          
         DFB SETV12       
         DFB 67,REST      ;Voice 1, Voice 2
         DFB 71,62        
         DFB 69,60        
         DFB 71,62        
                          
         DFB 72,63        ;C,Eb
         DFB 69,60        ;A,C
         DFB 67,59        ;G,B
         DFB 69,60        ;A,C
                          
         DFB 66,57        ;F#,A
         DFB 69,60        
         DFB 67,59        
         DFB 69,60        
                          
         DFB 71,62        ;B,D
         DFB 67,59        
         DFB 66,57        
         DFB 67,59        
                          
         DFB 62,55        ;Presto, measure 3
         DFB 79,59        
         DFB 77,57        
         DFB 79,59        
                          
         DFB 80,60        
         DFB 77,56        
         DFB 75,55        
         DFB 77,56        
                          
         DFB 74,53        
         DFB 77,57        
         DFB 75,55        
         DFB 77,57        
                          
         DFB 79,59        
         DFB 75,55        
         DFB 74,53        
         DFB 75,55        
                          
         DFB 72,51        ;Presto +4
         DFB 75,67        
         DFB 74,65        
         DFB 75,67        
                          
         DFB 77,68        
         DFB 74,65        
         DFB 72,63        
         DFB 74,65        
                          
         DFB 71,62        
         DFB 74,65        
         DFB 72,63        
         DFB 74,65        
                          
         DFB 75,67        
         DFB 72,63        
         DFB 71,62        
         DFB 72,63        
                          
         DFB 67,60        ;Presto +5
         DFB 72,63        
         DFB 71,62        
         DFB 72,63        
                          
         DFB 69,65        
         DFB 77,62        
         DFB 75,60        
         DFB 77,62        
                          
         DFB 67,63        
         DFB 75,60        
         DFB 74,59        
         DFB 75,60        
                          
         DFB 65,62        
         DFB 74,59        
         DFB 72,57        
         DFB 74,59        
                          
         DFB 63,60        ;Presto +6
         DFB 72,63        
         DFB 71,62        
         DFB 72,63        
                          
         DFB 68,53        
         DFB 65,62        
         DFB 63,60        
         DFB 65,62        
                          
         DFB 67,51        
         DFB 63,60        
         DFB 62,59        
         DFB 63,60        
                          
         DFB 65,50        
         DFB 62,59        
         DFB 60,57        
         DFB 62,59        
                          
         DFB SETV123      ;Formata / chord
         DFB SETDUR,PRESTO+3 ;A little slower
         DFB SETVOL,F     ;And a little softer
         DFB REST,REST,48 
         DFB 55,REST,REST 
         DFB SETV12       
         DFB 55,58        
         DFB 60,REST      
         DFB SETV1        
         DFB SETDUR,EIGHTH*13 ;Hold it out a little while
         DFB 64           
                          
         DFB SETDUR,ADAGIO/2 ;Now the adagio run
         DFB SETVOL,P+2   ;Softer
         DFB 60,62,64     
         DFB SETDUR,ADAGIO/4 ;1/64 notes
         DFB 65,67,68,70,72,70,68,67
         DFB SETDUR,ADAGIO
         DFB 65           
         DFB SETDUR,ADAGIO/2+2
         DFB 67,64        
                          
         DFB SETV123      ;Second formata/chord
         DFB REST,REST,48 
         DFB 53,REST,REST 
         DFB SETV12       
         DFB 53,56        
         DFB 60,REST      
         DFB SETV1        
         DFB SETDUR,EIGHTH*13
         DFB 65           
                          
         DFB SETVOL,P     ;Softer yet
         DFB SETDUR,ADAGIO/2 ;Second Adagio run
         DFB 67,65,64,65,67,68,67
         DFB SETDUR,ADAGIO/4 ;More 1/64 notes
         DFB 65,63,62,63,65,62,63,65
                          
         DFB SETDUR,EIGHTH+1 ;The final Allegro section
         DFB SETVOL,P+2   ;A little louder, I think
         DFB 59           
         DFB SETV123      
         DFB 59,REST,36   
         DFB 59,47,REST   
         DFB SETV12       
         DFB 50,REST      
         DFB SETV1        
         DFB 53,56,55,53,59,53,62,53,59,56,55,53
         DFB SETV123      
         DFB 52,48,36     
         DFB 61,REST,REST 
         DFB SETV1        
         DFB 58,55,60,56,53,56
         DFB 55,58,55,52  
         DFB 56,53,50,53  
         DFB SETDUR,EIGHTH+2
         DFB 52,55,52,48  
         DFB 53,50,47,50  
                          
         DFB SETDUR,EIGHTH+3 ;Lento
         DFB SETV123      
         DFB SETVOL,P+3   
         DFB REST,REST,36 
         DFB REST,43,REST 
         DFB SETV12       
         DFB REST,48      
         DFB 50,REST      
         DFB SETV1        
         DFB 52,55,58,55  
         DFB 56,60,65,62  
         DFB 65,68        
         DFB SETDUR,EIGHTH+4 ;ritard
         DFB 72,71        
         DFB SETDUR,EIGHTH+5 ;ritard
         DFB 72,67        
         DFB SETDUR,EIGHTH+6
         DFB 65,62        
                          
         DFB SETDUR,PRESTO+1
         DFB SETV123      
         DFB REST,REST,55 
         DFB REST,60,55   
         DFB SETDUR,140   
         DFB 64,60,55     
                          
         DFB REST,REST,REST
         DFB REST,REST,REST
                          
         DFB RESTART      ;Ad infinitum
