;****************************************************************************
; OutputPcm [RST $30]
; Called regularly to output PCM samples.
;----------------------------------------------------------------------------
; input carry ... set if timer A fired
; input hl' ..... must be YmAddr1
; input de' ..... must be YmData1
; input bc' ..... pointer to PCM sample to output
;----------------------------------------------------------------------------
; output bc' .... pointer to next PCM sample to output
;----------------------------------------------------------------------------
; breaks ........ a
;****************************************************************************
OutputPcm:
ret ; This instruction becomes LD A,(NNN)
dw YmAddr1 ; when PCM playback is enabled. Load
rra ; the timer A flag into carry.
ret nc ; Return if timer A didn't fire
exx ; Switch to alternate register set
TimerAAck: equ $+1
ld a, YMACK_TIMERA ; Acknowledge timer A
ld (hl), YMREG_MODE ; Note that the YMACK_TIMERA will be
ld (de), a ; overwritten when ch3 mode changes
ld a, (bc) ; Retrieve PCM sample
inc c ; Advance PCM pointer
ld (hl), YMREG_DAC ; Output PCM sample
ld (de), a
jr z, OutputPcmEnd ; End of buffer?
exx ; Switch to normal register set
ret ; End of subroutine
;----------------------------------------------------------------------------
OutputPcmEnd:
ld a, b ; Flip to the other PCM buffer (the
ld (OutputPcmOutBuf), a ; XOR trickery is to quickly change
xor (PcmBuffer1^PcmBuffer2)>>8 ; between both addresses)
ld b, a
ld c, PcmBuffer1&$FF
exx ; Switch to normal register set
; Calling PollPcm recursively now
; is safe (it'll play back the
; samples from the new buffer half)
PollPcm
push bc ; Save all registers
push de ; We don't know what the main thread
push hl ; may have been executing (this is
; effectively like an "interrupt")
; so we can't change anything except
; A (which is already expected to be
; clobbered by PollPcm)
PollPcm
OutputPcmOutBuf: equ $+2
ld de, PcmBuffer1&$FF ; Get the address of the buffer to
; render new samples into. The high
; byte comes from the write we did
; when we flipped buffers earlier.
OutputPcmCall: equ $+1
call PcmRender0ch ; Call the render function
; The called address gets overwritten
; as different PCM chanenls play.
PollPcm
pop hl ; Restore all registers
pop de
pop bc
PollPcm
ret ; End of subroutine