8bitworkshop/presets/vcs/vcslib/sound.ca65

80 lines
1.4 KiB
Plaintext

.include "vcs-ca65.inc"
.export _sound_update
.export _sound_play
.import _sound_duration
.import _sound_data
.zeropage
_sndchan_sfx: .res 2
_sndchan_timer: .res 2
.exportzp _sndchan_sfx
.exportzp _sndchan_timer
.importzp ptr3
sounddata = ptr3
.segment "ROM3"
; 00-1F: set frequency
; 81-9F odd: set volume
; 80-9E even: set control register
.proc _sound_update
ldx #0
jsr _sound_update_channel
ldx #1
.endproc
.proc _sound_update_channel
; decrement timer
lda _sndchan_timer,x
beq @done
dec _sndchan_timer,x
beq @killsound
; get sound data address
lda _sndchan_sfx,x
asl
tay
lda _sound_data+0,y
sta sounddata+0
lda _sound_data+1,y
sta sounddata+1
; get next sound data byte
ldy _sndchan_timer,x
lda (sounddata),y ; get sound data
bpl @setfreq ; hi bit clear = just freq
lsr ; right shift (/ 2)
bcs @setvol ; lo bit set = volume
sta AUDC0,x ; lo bit clear = control
lsr ; also set freq (/ 2)
@setfreq:
sta AUDF0,x ; set frequency
rts
@killsound:
lda #0
@setvol:
sta AUDV0,x ; set volume
@done:
rts
.endproc
.proc _sound_play
; but which channel to use?
; whichever has the lower timer counter
ldx #0
ldy _sndchan_timer+0
cpy _sndchan_timer+1
bcc @Chan0Free ; timer0 < timer 1?
inx
@Chan0Free:
sta _sndchan_sfx,x
tay
lda _sound_duration,y
sta _sndchan_timer,x
rts
.endproc