;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 ;-------------------------------------------------------------------------- ; 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 ;this works because bit 5-7 are always masked away further down bne quitTempo sta beat inc measure #if FADEOUT ldy measure cpy #INTROLENGTH bcc quitTempoHaveY inc atten #endif quitTempo ldy measure quitTempoHaveY cpy #SONGEND bcc MeasureOK ldy #INTROLENGTH sty measure MeasureOK ldx #0 lda song1,y ;-------------------------------------------------------------------------- ; 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 osc number stx temp beq muteNote ;hard code pattern zero = mute ; save patternArray offset sta temp+1 ; custom code to allow 1 quarter note per measure (Thrust): ; use beat to determine extra offset within patternArray lda beat asr #%00011000 lsr ; add in original offset adc temp+1 tax ; Get address of selected pattern lda patternArray-8,x ldy patternArray-7,x sta temp+1 sty temp+2 ; 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 (temp+1),y ;-------------------------------------------------------------------------- ; 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 #if FADEOUT sec sbc atten bpl GotVolume lda #0 GotVolume #endif sta temp+4 ;----------------------- lda soundTypeArray,x ;-------------------------------------------------------------------------- ; Get the osc number again ldx temp #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 (temp+1),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 ;-------------------------------------------------------------------------- lda temp bne DonePlayer ; Reat high hat pattern #if HATSTART lda measure cmp #HATSTART bmi noHat #endif lda beat and #%00000111 tax lda beat lsr lsr lsr tay #if HATSTATIC lda #HATPATTRN #else lda hatPattern,y #endif and bitMaskArray,x beq noHat ; Only play had on first frame lda tempoCount bpl noHat ; Play hat lda #HATPITCH sta AUDF0 lda #HATSOUND sta AUDC0 #if FADEOUT lda atten lsr ;makes hat linger a bit sta temp+4 lda #HATVOLUME sec sbc temp+4 bpl SetHatVolume lda #0 SetHatVolume #else lda #HATVOLUME #endif sta AUDV0 noHat ldy measure ldx #1 lda song2,y jmp playPattern DonePlayer ;fall through back into main.asm