;****************************************************************************
; PsgSetVolume [SONAOP_VOLUME_PSG1..PSG4]
; Handles volume events for PSG channels.
;----------------------------------------------------------------------------
; input b ..... channel ID (bits 1~0 only)
; input c ..... current bank
; input hl .... current address
;----------------------------------------------------------------------------
; output c .... new bank
; output hl ... new address
;----------------------------------------------------------------------------
; modifies .... a,bc,de,hl,a'
;****************************************************************************
PsgSetVolume:
PollPcm
CheckOwner
ld a, b ; Isolate channel ID
and $03
ld b, a
add a, RealPsgVol&$FF ; Compute pointer to where the final
ld (PsgSetVolume_RealPtr), a ; PSG volume (what the hardware will
; see) will be stored later
ld a, i ; Get pointer to where channel
and SfxPsgVol-BgmPsgVol ; volume is stored
add a, b
add a, BgmPsgVol&$FF
ld d, BgmPsgVol>>8
ld e, a
call ReadVolArg ; Read volume value
RetIfNotOwner ; Don't touch the PSG hardware volume
; if we don't own this channel
; fallthrough to RawPsgSetVolume...
;****************************************************************************
; RawPsgSetVolume
;
; The piece of code that takes the SonaStream-formatted PSG volume and
; converts it to what the PSG actually takes and stores it so the update
; code can do its thing properly.
;
; Isolated into its own subroutine since it's used by RestorePsg too.
;----------------------------------------------------------------------------
; input de ... pointer to volume
;----------------------------------------------------------------------------
; modifies .... a,b,de
;----------------------------------------------------------------------------
; Before calling PsgSetVolume_RealPtr must be overwritten to point to where
; to write the result (the postprocessed PSG volume).
;****************************************************************************
RawPsgSetVolume:
PollPcm
ld a, (de) ; Check if volume would be too quiet
cp 40 ; for the PSG and clamp it if so (it
jr c, PsgSetVolume_NotMute ; prevents overflow issues below)
ld a, 40
PsgSetVolume_NotMute:
ld b, a ; Volume is given in YM2612 units
add a, b ; (-0.75dB per step) but PSG uses
add a, b ; different units (-2dB per step)
rrca ; so convert the value accordingly
rrca
rrca
and $0F
PsgSetVolume_RealPtr: equ $+1
ld e, 0 ; Store new precomputed value
ld (de), a
ret ; End of subroutine