Sona 0.50 Source

Sona 0.50/src-z80/psg_load.z80

;****************************************************************************
; LoadPsgOp [SONAOP_LOAD_PSG1,PSG2,PSG3,PSG4]
; Processes the stream opcode for loading a PSG instrument.
;----------------------------------------------------------------------------
; input b ..... channel ID (bits 1-0 only)
; input c ..... current stream bank
; input hl .... current stream address
;----------------------------------------------------------------------------
; output c .... new stream bank
; output hl ... new stream address
;----------------------------------------------------------------------------
; modifies .... a,bc,de,hl,a'
;****************************************************************************

LoadPsgOp:
    PollPcm
    CheckOwner
    
    ld      a, b                        ; Get channel ID
    and     $03
    ld      e, a
    ex      af, af'
    
    call    ReadInstrumentId            ; Get instrument ID
    
    JumpIfSfx LoadPsgNotBgm             ; If it's a BGM keep track of the
    ld      a, e                        ; instrument ID in case we need to
    ld      d, BgmPsgInstr>>8           ; restore it after a SFX stomps on
    add     a, BgmPsgInstr&$FF          ; the channel
    ld      e, a
    ld      a, b
    ld      (de), a
LoadPsgNotBgm:
    
    RetIfNotOwner                       ; Don't touch the ADSR envelope if
                                        ; we haven't reserved this channel
                                        ; (or if it was taken away, in the
                                        ; case of BGM)
    
    ex      af, af'
    ; fallthrough to LoadPsgInstr...

;****************************************************************************
; LoadPsgInstr
; Loads a PSG instrument.
;----------------------------------------------------------------------------
; input a .... channel ID (0..3)
; input b .... instrument ID (0..255)
;----------------------------------------------------------------------------
; modifies ... a,de,a'
;****************************************************************************

LoadPsgInstr:
    add     a, a                        ; Get pointer to the ADSR envelope
    add     a, a                        ; we're about to load into
    add     a, a
    add     a, PsgAdsr_Psg1&$FF
    ld      (LoadPsgOp_AdsrAddrLo), a
    
    PollPcm
    
    push    bc                          ; Save registers
    push    hl
    
    ld      h, InstrList>>8             ; Retrieve instrument addr+bank
    ld      l, b
    ld      e, (hl)
    inc     h
    ld      d, (hl)
    inc     h
    ld      c, (hl)
    
    PollPcm
    
LoadPsgOp_AdsrAddrLo: equ $+1           ; Get proper pointer to
LoadPsgOp_AdsrAddrHi: equ $+2           ; ADSR envelope state now
    ld      hl, PsgAdsr_Psg1
    
    ld      (hl), $00                   ; Set up ADSR level and phase so it
    inc     l                           ; doesn't output sound regardless of
    ld      (hl), PSGPHASE_RELEASE      ; whatever ends up loaded into it
    inc     l
    
    ld      a, 6                        ; Load ADSR envelope
    ex      de, hl                      ;
LoadPsgOp_AdsrLoop:                     ; A = loop counter (yes, really)
    ex      af, af'                     ; B = byte being read
    ReadRomByte                         ; C = ADSR data bank
    ld      a, b                        ; HL = ADSR data address
    ld      (de), a                     ; DE = pointer to envelope
    ex      af, af'
    inc     e
    dec     a
    jr      nz, LoadPsgOp_AdsrLoop
    
    pop     hl                          ; Restore registers
    pop     bc
    
    ret                                 ; End of subroutine