;****************************************************************************
; 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