;****************************************************************************
; PlaySFX [command $02]
; Plays a SFX
;****************************************************************************

PlaySFX:
    PollPCM
    call ClearSFX               ; Clear SFX resources
    PollPCM

    ld a, (RAM_Status)          ; Show SFX playback in Echo's status
    or $01
    ld (RAM_Status), a

    PollPCM

    ld hl, RAM_ComBank          ; Get command parameters
    ld c, (hl)
    inc l
    ld e, (hl)
    inc l
    ld d, (hl)

    PollPCM

    xor a                       ; Command parsed
    ld (RAM_Command), a

    ld hl, RAM_SFXData          ; Set SFX as playing
    ld (hl), $01
    inc l                       ; No delays!
    ld (hl), $01
    inc l                       ; Store SFX start bank
    ld (hl), c
    inc l                       ; Store SFX start address (low)
    ld (hl), e
    inc l                       ; Store SFX start address (high)
    ld (hl), d

    PollPCM

    ld hl, ProcessSFX           ; Tell Echo to process SFX
    ld (DoTick_SFX+1), hl

    PollPCM
    jp IdleLoop                 ; End of subroutine

;****************************************************************************
; ProcessSFX
; Processes a tick for a SFX
;****************************************************************************

ProcessSFX:
    PollPCM

    ld hl, RAM_SFXData+1        ; SFX data address

    ld a, (hl)                  ; Delaying?
    dec a
    jp z, .nodelay
    ld (hl), a

    jp DoTick_SFXSkip           ; End of subroutine

.nodelay:
    PollPCM

    inc l                       ; Get current address
    ld c, (hl)
    inc l
    ld e, (hl)
    inc l
    ld d, (hl)
    ex de, hl

ProcessSFXRun:
    PollPCM                     ; Fetch next event
    call GetParam
    PollPCM

    ld a, b                     ; Parse byte

    cp $08
    jp c, NoteOnFMSFX           ; Events $00-$07: note on FM
    cp $0B
    jp c, NoteOnPSGSFX          ; Events $08-$0A: note on PSG (square)
    jp z, NoteOnNoiseSFX        ; Event $0B: note on PSG (noise)
    cp $0C
    jp z, PlayPCMSFX            ; Event $0C: note on PCM

    PollPCM
    ld a, b

    cp $18
    jp c, NoteOffFMSFX          ; Events $10-$17: note off FM
    cp $1C
    jp c, NoteOffPSGSFX         ; Events $18-$1B: note off PSG
    jp z, StopPCMSFX            ; Event $1C: note off PCM

    PollPCM
    ld a, b

    cp $FE
    jp z, SetDelaySFX           ; Event $FE: set delay
    cp $FF
    jp z, StopSFXEvent          ; Event $FF: stop SFX

    PollPCM
    ld a, b

    cp $28
    jp c, SetFMVolSFX           ; Events $28-$2B: set FM volume
    cp $2C
    jp c, SetPSGVolSFX          ; Events $28-$2B: set PSG volume

    PollPCM
    ld a, b

    cp $38
    jp c, SetNoteFMSFX          ; Events $30-$37: set FM note
    cp $3B
    jp c, SetNotePSGSFX         ; Events $38-$3A: set PSG note (square)
    jp z, SetNoteNoiseSFX       ; Event $3B: set PSG note (noise)

    PollPCM
    ld a, b

    cp $48
    jp c, LoadFMSFX             ; Events $40-$47: load FM instrument
    cp $4C
    jp c, LoadPSGSFX            ; Events $48-$4B: load PSG instrument

    PollPCM
    ld a, b

    cp $E8
    jp c, LockChannelFM         ; Events $E0-$E7: lock FM channel
    cp $EC
    jp c, LockChannelPSG        ; Events $E8-$EB: lock PSG channel
    jp z, LockChannelPCM        ; Event $EC: lock PCM channel

    PollPCM
    ld a, b

    cp $F8                      ; Events $F0-$F7: set FM parameters
    jp c, SetFMParamSFX

;****************************************************************************
; StopSFX* [command $03, event $FF]
; Stops SFX playback
;****************************************************************************

StopSFXEvent:
    call StopSFX                ; We're just a wrapper
    jp DoTick_SFXSkip           ; End of subroutine

StopSFXCmd:
    xor a                       ; Command parsed
    ld (RAM_Command), a
    call StopSFX                ; We're just a wrapper
    jp IdleLoop                 ; End of subroutine

StopSFX:
    PollPCM

    ld a, (RAM_Status)          ; Hide SFX playback in Echo's status
    and $FE
    ld (RAM_Status), a

    PollPCM

    xor a                       ; Stop playback
    ld (RAM_SFXPlaying), a
    ld hl, DoTick_SFXSkip
    ld (DoTick_SFX+1), hl

    PollPCM
    call ClearSFX               ; Clear SFX resources

    PollPCM
    ret                         ; End of subroutine

;****************************************************************************
; ClearSFX
; Clears SFX resources
;****************************************************************************

ClearSFX:
    ld a, (RAM_Locked+6)        ; Stop PCM playback if needed
    or a
    call nz, StopPCM

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

    ld b, 4                     ; Look for locked PSG channels
    ld de, RAM_Locked+11
.unlockpsg:

    PollPCM

    ld a, (de)                    ; Check if this channel needs unlocking
    or a
    jr z, .psgfree
    xor a
    ld (de), a

    PollPCM

    ld a, b                       ; Restore BGM volume
    rrca
    rrca
    rrca
    rrca
    dec a
    ld h, RAM_PSGData>>8
    ld l, a
    ld c, (hl)
    sub 15
    ld l, a
    ld (hl), c

    PollPCM
    push de

    ld a, l                       ; Restore BGM envelope
    add 8
    ld l, a
    add 12-8
    ld e, a
    ld d, h
    
    PollPCM

    ld a, (de)
    ld (hl), a
    inc l
    inc e
    ld a, (de)
    ld (hl), a
    inc l
    inc e
    ld a, (de)
    ld (hl), a

    pop de
    PollPCM

.psgfree:
    dec e                         ; Go for next PSG channel to unlock
    djnz .unlockpsg

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

    ld b, 8                     ; Look for locked FM channels
.unlockfm:

    PollPCM

    ld a, (de)                    ; Check if this channel needs unlocking
    or a
    jp z, .fmfree
    xor a
    ld (de), a

    PollPCM
    
    dec b                         ; Restore FM channel
    call RestoreFM
    inc b
    
.fmfree:
    dec e                         ; Go for next FM channel to unlock
    dec b
    jp nz, .unlockfm

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

    ret                         ; End of subroutine
