.include "vcs-ca65.inc" .export _music_update .exportzp _music_ptr .import _sound_duration .import _sound_play .zeropage _music_ptr: .res 2 _music_timer: .res 1 .importzp _sndchan_sfx .importzp _sndchan_timer .importzp ptr3 musicdata = ptr3 .segment "ROM3" ; 00-3f: play note ; 40-7f: play sound effect ; 80-fe: set duration until next note ; ff: stop music .proc _music_update ; is music timer up? lda _music_timer bmi @Done beq @NextData dec _music_timer jmp @Done ; Timer ran out, so fetch next note @NextData: ldx #0 lda (_music_ptr,x) bmi @LoadDuration ; >= $40, play sound effect cmp #$40 bcs @PlaySound ; < $80, play next note ; but which channel to use? ; whichever has the lower timer counter tay ldx #0 ldy _sndchan_timer+0 cpy _sndchan_timer+1 bcc @Chan0Free ; timer0 < timer 1? inx @Chan0Free: ; set the sound channels tay lda FREQZ,y sta AUDF0,x lda TONEZ,y sta AUDC0,x ; set the sound channel lda #0 sta _sndchan_sfx,x ; sound 0 = envelope lda _sound_duration+0 sta _sndchan_timer,x ; set channel timer jmp @IncMusic @LoadDuration: cmp #$ff beq @Done ; end of sound and #$7f sta _music_timer ; set music timer @IncMusic: inc _music_ptr bne @Done inc _music_ptr+1 @Done: rts @PlaySound: sec sbc #$40 jsr _sound_play jmp @IncMusic .endproc ; Table of AUDF base values for each note FREQZ: .byte 31, 31, 31, 31, 30, 28, 27, 25, 24, 22, 21, 20, 19, 17, 17, 15, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 31, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 12, 11, 10, 31, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15 ; Table of AUDC values for each note TONEZ: .byte 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4