Sona 0.50 Source

Sona 0.50/src-z80/stream_stop.z80

;****************************************************************************
; StopBgmCmd [CMD_STOPBGM]
; Stops playing new music on 68000's request.
;----------------------------------------------------------------------------
; continues in EndOfCommand
;****************************************************************************

StopBgmCmd:
    call    StopAllSound                ; Call the actual routine
    jp      EndOfCommand                ; Pop command off the queue

;****************************************************************************
; StopStream [SONAOP_END]
; Ends the current stream's playback.
;----------------------------------------------------------------------------
; modifies .... a,bc,de,hl,a'
;----------------------------------------------------------------------------
; notes: it won't return back to the caller, but to the caller's caller (this
; is meant to be called from the stream update routine which never returns on
; its own, so we're acting as a return point instead)
;****************************************************************************

StopStream:
    PollPcm
    
    ld      hl, (StreamPtr)             ; Set the stream's stack level to
    ld      (hl), -1                    ; -1 to signal that playback is over
    
    ld      a, (StreamNum)              ; Is it a SFX? (and get the SFX
    sub     FIRST_SFXSTREAM             ; stream ID in the process)
    call    nc, FreeSfxStream
    
    pop     de                          ; Quit the processing loop
    ret                                 ; End of subroutine

;****************************************************************************
; FreeSfxStream
; Deallocates the resources used up by a SFX stream.
;----------------------------------------------------------------------------
; input a .... SFX stream ID (0..2)
;----------------------------------------------------------------------------
; modifies ... a,bc,de,hl,iy,a'
;****************************************************************************

FreeSfxStream:
    ld      b, 7                        ; Loop through every FM channel
    ld      hl, ChanOwner_Fm1
    ld      de, ChanPriority_Fm1
ClearSfxFmLoop:
    
    cp      (hl)                        ; Does this SFX stream control
    jr      nz, NoClearSfxFm            ; this FM channel?
    
    push    af
    
    ld      (hl), $FF                   ; Free up the FM channel
    ex      de, hl
    ld      (hl), $00
    ex      de, hl
    
    ld      a, l                        ; Restore the FM channel
    call    RestoreFm
    
    pop     af
    
NoClearSfxFm:
    inc     l                           ; Go check next FM channel
    inc     e
    djnz    ClearSfxFmLoop

;----------------------------------------------------------------------------

    ld      b, 4                        ; Loop through every PSG channel
    ld      l, ChanOwner_Psg1&$FF
    ld      e, ChanPriority_Psg1&$FF
ClearPsgSfxLoop:
    cp      (hl)                        ; Does this SFX stream control
    jr      nz, NoClearSfxPsg           ; this PSG channel?
    
    push    af
    
    ld      (hl), $FF                   ; Free up the PSG channel
    ex      de, hl
    ld      (hl), $00
    ex      de, hl
    
    ld      a, l                        ; Restore the PSG channel
    sub     ChanOwner_Psg1&$FF
    call    RestorePsg
    
    pop     af
    
NoClearSfxPsg:
    inc     l                           ; Go check next PSG channel
    inc     e
    djnz    ClearPsgSfxLoop

;----------------------------------------------------------------------------

    ld      bc, $0201                   ; Loop through every PCM channel
    ld      l, ChanOwner_Pcm1&$FF
    ld      e, ChanPriority_Pcm1&$FF
ClearSfxPcmLoop:
    
    cp      (hl)                        ; Does this SFX stream control
    jr      nz, NoClearSfxPcm           ; this PCM channel?
    
    ex      af, af'
    
    ld      (hl), $FF                   ; Free up the PCM channel
    ex      de, hl
    ld      (hl), $00
    ex      de, hl
    
    push    bc                          ; Stop the PCM channel if the SFX
    push    de                          ; stream was using it
    push    hl                          ;
                                        ; StopPcm wants a bitmask for the
    ld      b, c                        ; channel ID, which means $01 for
    call    StopPcm                     ; ch1 and $02 for ch2. This is held
                                        ; in the C register in this loop.
    pop     hl
    pop     de
    pop     bc
    
    ex      af, af'
    
NoClearSfxPcm:
    inc     l                           ; Go check next PCM channel
    inc     e
    inc     c
    djnz    ClearSfxPcmLoop
    
FreeSfxStream_Skip:
    ld      h, SfxPriority>>8           ; Reset the priority of this SFX
    add     a, SfxPriority&$FF          ; stream so any SFX can override it
    ld      l, a                        ; next time one wants to play
    ld      (hl), $00
    
    ret                                 ; End of subroutine

;****************************************************************************
; StopAllSound
; Stops playing everything.
;----------------------------------------------------------------------------
; modifies ... a,bc,de,hl,a'
;****************************************************************************

StopAllSound:
    call    StopAllFm                   ; Stop all FM channels
    call    StopAllPsg                  ; Stop all PSG channels
    call    StopAllPcm                  ; Stop PCM playback
    
    ld      bc, (NUM_STREAMS<<8)|$FF    ; Loop through all streams and
    ld      h, StreamState>>8           ; mark them as not playing
    ld      a, StreamState&$FF          ;
StopAllSound_StreamLoop:                ; HL = pointer to stream state
    ld      l, a                        ; A = mirror of L (to do ADD 8)
    ld      (hl), c                     ; B = loop counter
    add     a, 8                        ; C = -1 (used to mark the streams
    djnz    StopAllSound_StreamLoop     ;        as not playing currently)
    
    xor     a                           ; Loop through all channels and
    ld      hl, ChanOwner               ; reset their owner and priority to
    ld      de, ChanPriority            ; the defaults used when there's no
    ld      b, 16                       ; SFX playing.
StopAllSound_OwnerLoop:                 ;
    ld      (hl), c                     ; DE = pointer to owner
    ld      (de), a                     ; HL = pointer to priority
    inc     e                           ; C = $FF (default owner)
    inc     l                           ; A = $00 (default priority)
    djnz    StopAllSound_OwnerLoop      ; B = loop counter
    
    ld      c, a                        ; Reset the priorities of all
    ld      (SfxPriority), bc           ; sound effects since none are
    ld      (SfxPriority+2), a          ; playing now
    
    ret                                 ; End of subroutine