Sona 0.50 Source

Sona 0.50/src-z80/fm_restore.z80

;****************************************************************************
; RestoreFm
; Restores a FM channel after a SFX stream is over.
;----------------------------------------------------------------------------
; input a ... channel ID (0,1,2,4,5,6)
;----------------------------------------------------------------------------
; modifies ... a,iyl,a'
;****************************************************************************

RestoreFm:
    push    bc                          ; Save registers
    push    de
    push    hl
    
    push    af
    
    add     a, BgmFmVol&$FF             ; Copy volume from BGM to the
    ld      h, BgmFmVol>>8              ; "current" volume we're trying to
    ld      l, a                        ; output in that channel
    add     a, RealFmVol-BgmFmVol
    ld      d, h
    ld      e, a
    ld      a, (hl)
    ld      (de), a
    
    PollPcm
    
    ld      a, e                            ; Compute offset to the byte
    add     a, (BgmFmParam-RealFmVol)&$FF   ; that holds the pan/PMS/AMS
    ld      (RestorePanAddr), a             ; setting for this channel and
                                            ; save it for later
    
    sub     BgmFmParam&$FF              ; Determine which register number
    ld      b, a                        ; to write to restore pan/PMS/AMS
    and     $03                         ;
    add     a, YMREG_PAN                ; ch1/ch4 = YMREG_PAN+0
    ld      (RestorePanReg), a          ; ch2/ch5 = YMREG_PAN+1
                                        ; ch3/ch6 = YMREG_PAN+2
    
    ld      a, b                        ; Determine which port to write to
    and     $04                         ; restore pan/PMS/AMS
    rrca                                ;
    ld      iyl, a                      ; ch1~ch3 = YmAddr1
                                        ; ch4~ch6 = YmAddr2
    
    PollPcm
    pop     af
    
    ld      e, a                        ; Mute the FM channel
    call    StopFmChannel
    ld      a, e
    
    add     a, a                        ; Z80 has bitmask instructions but
    add     a, a                        ; only for hardcoded bit numbers, we
    add     a, a                        ; work around this by generarting
    or      Z80OPCB_SET_0_iHL           ; the relevant instruction instead
    ld      (RestoreFmMaskSet), a       ; (i.e. self-modification)
    
    ld      hl, FmChanToReload          ; Set the relevant bit in the mask
RestoreFmMaskSet: equ $+1               ; of FM channels to restore later
    set     0, (hl)
    
    PollPcm
    
    ld      (iy+0), YMREG_PAN           ; Restore pan/PMS/AMS setting for
RestorePanReg: equ $-1                  ; this FM channel now that it's
RestorePanAddr: equ $+1                 ; mute and won't cause any weirdness
    ld      de, BgmFmParam              ;
    ld      a, (de)                     ; The OR mask is the same as for
RestorePanOrMask: equ $+1               ; SetPan (it's used to override
    or      $00                         ; stereo when forcing mono mode)
    ld      (iy+1), a
    
    pop     hl                          ; Restore registers
    pop     de
    pop     bc
    
    ret                                 ; End of subroutine