Sona 0.50 Source

Sona 0.50/src-z80/lock.z80

;****************************************************************************
; LockChannel [SONAOP_LOCK_*]
; Locks the requested channel for the current stream.
;----------------------------------------------------------------------------
; input b .... opcode
;----------------------------------------------------------------------------
; modifies ... a,b,de,a'
;----------------------------------------------------------------------------
; continues in ProcessStreamLoop
;****************************************************************************

LockChannel:
    PollPcm
    
    ld      a, b                        ; Isolate channel ID
    and     $0F
    
    ld      b, a
    
    cp      $03                         ; Check in case somebody decided
    jr      nz, LockChannelNoCh3        ; to use FM3 special (which should
    dec     a                           ; behave like normal FM3 instead)
LockChannelNoCh3:
    
    add     a, ChanPriority&$FF         ; Get current channel priority
    ld      d, ChanPriority>>8
    ld      e, a
    
    PollPcm
    
ThisPriority: equ $+1
    ld      a, $00                      ; Check if our priority is higher
    ex      de, hl                      ; than the channel's current one,
    cp      (hl)                        ; and proceed only if it isn't lower
    ex      de, hl
    ret     c
    ld      (de), a
    
    PollPcm
    
    ld      a, e                        ; Store the new owner for this
    sub     ChanPriority-ChanOwner      ; channel
    ld      e, a
    ld      a, (ThisOwner)
    ld      (de), a
    
    ld      a, b                        ; Are we locking a FM channel?
    cp      $08
    ret     nc
    
    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_RES_0_iHL           ; the relevant instruction instead
    ld      (LockFmMaskClear), a        ; (i.e. self-modification)
    
    PollPcm
    
    ex      de, hl                      ; Clear the relevant bit in the mask
    ld      hl, FmChanToReload          ; of FM channels to restore later (in
LockFmMaskClear: equ $+1                ; case it wasn't already clear)
    res     0, (hl)                     ;
    ex      de, hl                      ; The reason we need to do this is
                                        ; that it's possible for a SFX to
                                        ; restore its channel then another
                                        ; SFX to try to claim it back before
                                        ; BGM is processed (e.g. when a SFX
                                        ; is overriden by another one using
                                        ; the same resources)
    
    ret                                 ; End of subroutine