;This is a somewhat modified version of Paul Slocum's music player ;Specifically, it has been made to not use any stack ;It also loops back to measure INTROLENGTH, not zero bitMaskArray byte #%10000000 byte #%01000000 byte #%00100000 byte #%00010000 byte #%00001000 byte #%00000100 byte #%00000010 byte #%00000001 ;-------------------------------------------------------------------------- ; playPattern ;-------------------------------------------------------------------------- ; Plays a pattern ; ; - ACC should contain the offset in the patternArray of the pattern to play ; - X should contain the oscillator to be used (0 or 1) ; ;-------------------------------------------------------------------------- playPattern ; save unaltered patternArray offset sta temp16L ; save patternArray offset asl asl asl sta temp ; custom code to allow 1 quarter note per measure (Thrust): ; use beat to determine extra offset within patternArray lda beat and #%00011000 lsr lsr ; add in original offset adc temp ; save osc number stx temp tax ; Get address of selected pattern lda patternArrayH,x ldy patternArrayH+1,x sta temp16L sty temp16H ; The variable, beat, contains the 32nd note ; that the beat is currently on. lda beat ; modification for 1 quarter per measure (Thrust) and #%00000111 tay ; Get sound/note data lda (temp16L),y eor #255 beq muteNote eor #255 ;-------------------------------------------------------------------------- ; Extract Pattern Data ;-------------------------------------------------------------------------- ; Each byte of pattern data contains the frequency and ; sound type data. This function separates and decodes them. ; ; The encoding is: the 3 high bits contain the encoded sound ; type and the lower 5 bits contain the freq data. ; ; - ACC must contain pattern byte ; ; = ACC will return the freq ; = X will return the sound type ; ; changes ACC,X ;-------------------------------------------------------------------------- tax ; Extract freq data and push it and #%00011111 sta temp+3 txa lsr lsr lsr lsr lsr tax ;----------------------- lda soundVolArray,x sec sbc atten bpl GotVolume lda #0 GotVolume sta temp+4 ;----------------------- lda soundTypeArray,x ;-------------------------------------------------------------------------- ; Get the osc number again ldx temp ; bne noPhase ; sta AUDF0 ; nop ; nop ; nop ; nop noPhase #if SONGDBG ; REMOVE IN FINAL VERSION sta sound1,x #endif sta AUDC0,x lda temp+3 sta AUDF0,x #if SONGDBG ; REMOVE IN FINAL VERSION sta note1,x #endif ; restore beat & #%111 tya tax ;-------------------------------------------------------------------------- ; Accent Reader ;-------------------------------------------------------------------------- ; Each set of pattern data is followed by 4 accept bytes. ; Each bit in order represents the accent (on or off) ; of its corresponding 32nd note. This function ; returns the attenuation of a note in a pattern. ; ; - temp16 must contain an indirect pointer to the pattern data ; - X must contain the beat && %00000111 ; ; = will return the volume in ACC ; ; changes X,Y,ACC ;-------------------------------------------------------------------------- ; Accent offset is always 8 for Thrust mod ldy #8 lda (temp16L),y and bitMaskArray,x beq noAccent ;accent -> reset volume lda temp+4 jmp StoreNote noAccent ;trail off ldy temp lda vol1,Y sec sbc #1 bpl StoreNote2 lda #0 muteNote StoreNote ldy temp ; Get the osc number again StoreNote2 sta AUDV0,y sta vol1,y ;-------------------------------------------------------------------------- ; Super High Hat (TM) ;-------------------------------------------------------------------------- ; This plays the high hat sound on the first frame of each beat indicated ; in hatPattern ;-------------------------------------------------------------------------- ldy temp beq noHat ; Reat high hat pattern lda measure cmp #HATSTART bmi noHat lda beat and #%00000111 tax lda beat lsr lsr lsr tay lda hatPattern,y and bitMaskArray,x beq noHat ; Only play had on first frame lda tempoCount bpl noHat ; Play hat lda #HATPITCH sta AUDF0+HATCHAN lda #HATSOUND sta AUDC0+HATCHAN lda atten lsr ;makes hat linger a bit sta temp+4 lda #HATVOLUME sec sbc temp+4 bpl SetHatVolume lda #0 SetHatVolume sta AUDV0+HATCHAN noHat ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; Percussion cutter ;-------------------------------------------------------------------------- ; This code cuts off the sound for better percussive sounds. You ; can set it to start working at a certain measure. ;-------------------------------------------------------------------------- ; lda measure ; cmp #111 ; start measure ; bmi noCut ; lda tempoCount ; and #%11111110 ; beq noCut ; lda #0 ; sta AUDV0 noCut ;figure out where we should return to ;spaghettified to save RAM lda temp beq PlayPattern1 jmp SongPlayerRet ;-------------------------------------------------------------------------- ; songPlayer ;-------------------------------------------------------------------------- ; Plays up to two pre-programmed patterns simlutaneously. ; ; Call this once per screen-draw. ;-------------------------------------------------------------------------- songPlayer lda tempoCount and #$7F clc adc #TEMPO sta tempoCount bpl quitTempo inc beat lda beat eor #32 bne quitTempo sta beat inc measure lda measure cmp #INTROLENGTH bcc quitTempo inc atten quitTempo ;-------------------------------------------------------------------------- ; set the volume to zero ldx #0 #if SONGDBG stx vol1 stx vol2 #endif ldy measure lda song1,y ; Check to see if the end of the song was reached cmp #255 bne notEndOfSong ; Go back to just after the intro lda #INTROLENGTH sta measure lda song1,x notEndOfSong jmp playPattern PlayPattern1 ldy measure lda song2,y ldx #1 jmp playPattern ; songPlayer ;--------------------------------------------------------------------------