From 178968cc2fc4c32fb918ebb4ccd24d78b64cd73f Mon Sep 17 00:00:00 2001 From: Javier Degirolmo Date: Fri, 7 Oct 2011 12:17:54 -0300 Subject: Initial upload, Echo 0.8 UNSTABLE VERSION --- src-z80/player/psg.z80 | 667 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 667 insertions(+) create mode 100644 src-z80/player/psg.z80 (limited to 'src-z80/player/psg.z80') diff --git a/src-z80/player/psg.z80 b/src-z80/player/psg.z80 new file mode 100644 index 0000000..46df82a --- /dev/null +++ b/src-z80/player/psg.z80 @@ -0,0 +1,667 @@ +;**************************************************************************** +; UpdatePSG +; Updates PSG output +;**************************************************************************** + +UpdatePSG: + ld hl, RAM_PSGData+48 ; PSG envelope data of *last* channel + ld b, 3 ; Go through all channels +.loop: + push bc + + ld a, (hl) ; Get channel volume + bit 7, a + jr nz, .noskip + ld b, $0F + inc l + jp .skip +.noskip: + and $7F + ld b, a + + inc l ; Add global volume + ld a, (hl) + add b + ld b, a + + PollPCM + push bc + + inc l ; Get current address of envelope + ld c, (hl) + inc l + ld e, (hl) + inc l + ld d, (hl) + ex de, hl + +.readenv: + PollPCM + call GetParam ; Get next byte + PollPCM + + ld a, b + cp $FE ; Set loop point? + jp z, .envsetloop + cp $FF ; Loop envelope? + jp z, .envloop + + ld iyl, b ; Keep byte safe somewhere... + PollPCM + + ex de, hl ; Store new address + ld (hl), d + dec l + ld (hl), e + dec l + ld (hl), c + dec l + + pop bc + PollPCM + + db $FD,$7D ; ld a, iyl ; Mix envelope with volume + add b + ld b, a + + cp $10 ; Check for overflow + jr c, .notmute + ld b, $0F +.notmute: + +.skip: + PollPCM + + ld a, b ; Set PSG channel volume + rlca + rlca + rlca + pop bc + or b + rrca + rrca + rrca + or $90 + ld ($7F11), a + + ld a, l ; Go for next channel + sub 16+1 + ld l, a + PollPCM + dec b + jp p, .loop + + jp DoTick_PSGSkip ; End of subroutine + +.envsetloop: + PollPCM + inc e ; Where we store the loop point + + ex de, hl ; Store loop point + ld (hl), c + inc l + ld (hl), e + inc l + ld (hl), d + ex de, hl + + dec e ; Back to where we were... + dec e + dec e + jp .readenv ; Go for next byte + +.envloop: + PollPCM + inc e ; Where we store the loop point + + ex de, hl ; Retrieve loop point + ld c, (hl) + inc l + ld e, (hl) + inc l + ld d, (hl) + ex de, hl + + dec e ; Back to where we were... + dec e + dec e + jp .readenv ; Go for next byte + +;**************************************************************************** +; NoteOnPSG* +; Does a "note on" for a PSG channel +;**************************************************************************** + +NoteOnPSGSFX: + call NoteOnPSG ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +NoteOnPSGBGM: + ld b, a + PollPCM + ld a, b + + push hl + and $03 ; Check if channel is free + ld hl, RAM_Locked+8 + add l + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip1 ; Don't play if locked + + ld a, b + call NoteOnPSG ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +NoteOnPSG: + and $03 + ld b, a + ;push af + ex af, af' + PollPCM + + push hl ; Set channel volume + ld h, RAM_PSGData>>8 + ld a, b + rrca + rrca + rrca + rrca + ld l, a + ld a, (hl) + or $80 + ld (hl), a + + PollPCM + push de + + inc l ; Now we'll reset the envelope address... + inc l + ld d, h + ld a, l + add 6 + ld e, a + + PollPCM + + ld a, (de) ; Reset envelope address + 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 + pop hl + + PollPCM + call GetParam ; Get note + PollPCM + + ;pop af + ex af, af' + push hl + push de + ld h, PSGFreqTable>>8 ; Get address of frequency data + ld l, b + ld de, $7F11 + + rrca ; Set new frequency + rrca + rrca + ld b, (hl) + or b + ld (de), a + inc l + ld a, (hl) + ld (de), a + pop de + pop hl + + ret ; End of subroutine + +;**************************************************************************** +; NoteOnNoise* +; Does a "note on" for the noise PSG channel +;**************************************************************************** + +NoteOnNoiseSFX: + call NoteOnNoise ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +NoteOnNoiseBGM: + ld a, (RAM_Locked+11) ; Check if channel is free + or a + jp nz, ProcessBGMSkip1 ; Don't play if locked + + call NoteOnNoise ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +NoteOnNoise: + PollPCM + push hl + + ld hl, RAM_PSGData+48 ; Set channel volume + ld a, (hl) + or $80 + ld (hl), a + + PollPCM + push de + + inc l ; Now we'll reset the envelope address... + inc l + ld d, h + ld a, l + add 6 + ld e, a + + PollPCM + + ld a, (de) ; Reset envelope address + 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 + pop hl + +SetNoteNoise: + PollPCM + call GetParam ; Get noise type + PollPCM + + ld a, $E0 ; Set new noise type + or b + ld ($7F11), a + + ret ; End of subroutine + +;**************************************************************************** +; NoteOffPSG* +; Does a "note off" for a PSG channel +;**************************************************************************** + +NoteOffPSGSFX: + call NoteOffPSG ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +NoteOffPSGBGM: + ld b, a + PollPCM + ld a, b + + push hl + and $03 ; Check if channel is free + ld hl, RAM_Locked+8 + add l + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMRun ; Don't stop if locked + + ld a, b + call NoteOffPSG ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +NoteOffPSG: + and $03 + ld b, a + PollPCM + + push hl ; Mark channel as not playing + ld h, RAM_PSGData>>8 + ld a, b + rrca + rrca + rrca + rrca + ld l, a + ld a, (hl) + and $7F + ld (hl), a + pop hl + + ret ; End of subroutine + +;**************************************************************************** +; SetPSGVol* +; Sets the volume of a PSG channel +;**************************************************************************** + +SetPSGVolSFX: + and $03 ; Get channel ID + + ex af, af' + PollPCM + call GetParam ; Get volume + PollPCM + ex af, af' + + push hl + ld h, RAM_PSGData>>8 ; Set new volume + rrca + rrca + rrca + rrca + ld l, a + ld a, (hl) + and $80 + or b + ld (hl), a + pop hl + + jp ProcessSFXRun ; End of subroutine + +SetPSGVolBGM: + and $03 ; Get channel ID + + ex af, af' + PollPCM + call GetParam ; Get volume + PollPCM + ex af, af' + + push de + push hl + + push af + ld de, RAM_Locked+8 ; Check if channel is locked + add e ; Keep results for later + ld e, a + ld a, (de) + ld e, a + + PollPCM + pop af + + ld h, RAM_PSGData>>8 ; Store new volume + rrca + rrca + rrca + rrca + add 15 + ld l, a + ld (hl), b + + PollPCM + + ld a, e ; Is channel locked? + or a + jr nz, .nosetvol + + ld a, l ; Set new volume + sub 15 + ld l, a + ld a, (hl) + and $80 + or b + ld (hl), a + + PollPCM + +.nosetvol: + pop hl + pop de + + jp ProcessBGMRun ; End of subroutine + +;**************************************************************************** +; LoadPSG* +; Loads a PSG instrument +;**************************************************************************** + +LoadPSGSFX: + and $03 ; Get channel number + + ex af, af' + PollPCM + call GetParam ; Get instrument ID + PollPCM + ex af, af' + + push de + push hl + + ld d, RAM_PointerList>>8 ; Get position in pointer list + ld e, b + + ld h, RAM_PSGData>>8 ; Where to store address + rrca + rrca + rrca + rrca + add 8+2+(RAM_PSGData&$FF) + ld l, a + + PollPCM + + ld a, (de) ; Store PSG envelope start address + ld (hl), a + inc d + dec l + ld a, (de) + ld (hl), a + inc d + dec l + ld a, (de) + ld (hl), a + + PollPCM + + ld a, l ; Reset volume + sub 8 + ld l, a + ld (hl), $00 + + pop hl + pop de + jp ProcessSFXRun ; End of subroutine + +;---------------------------------------------------------------------------- + +LoadPSGBGM: + and $03 ; Get channel number + + ex af, af' + PollPCM + call GetParam ; Get instrument ID + PollPCM + ex af, af' + + push de + push hl + + ld d, RAM_PointerList>>8 ; Get position in pointer list + ld e, b + + ld hl, RAM_Locked+8 ; Get if channel is locked + push af + add l + ld l, a + pop af + ld b, (hl) + + ld h, RAM_PSGData>>8 ; Where to store BGM instrument data + rrca + rrca + rrca + rrca + add 15 + ld l, a + + PollPCM + + ld (hl), a ; Reset volume for BGM + dec l + + ld a, (de) ; Store PSG envelope address for BGM + ld (hl), a + inc d + dec l + ld a, (de) + ld (hl), a + inc d + dec l + ld a, (de) + ld (hl), a + + PollPCM + + ld a, b ; Don't set PSG envelope if locked + or a + jp z, .noloadlocked + pop hl + pop de + jp ProcessBGMRun +.noloadlocked: + PollPCM + + ld d, h ; Set PSG envelope + ld a, l + sub 12-8 + ld e, a + + ld a, (hl) + ld (de), a + inc l + inc e + ld a, (hl) + ld (de), a + inc l + inc e + ld a, (hl) + ld (de), a + + PollPCM + + ld a, l ; Reset volume + sub 8 + ld l, a + ld (hl), $00 + + pop hl + pop de + jp ProcessBGMRun ; End of subroutine + +;**************************************************************************** +; SetNotePSG* +; Sets the note of a PSG channel without "note on" +;**************************************************************************** + +SetNotePSGSFX: + call SetNotePSG ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +SetNotePSGBGM: + ld b, a + PollPCM + ld a, b + + push hl + and $0F ; Check if channel is free + ;ld hl, RAM_Locked + ;add l + ld h, RAM_Locked>>8 + add RAM_Locked&$FF + ld l, a + ld a, (hl) + pop hl + or a + jp nz, ProcessBGMSkip2 ; Don't play if locked + + ld a, b + call SetNotePSG ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +SetNotePSG: + and $03 ; Get channel number + + ex af, af' + PollPCM + call GetParam ; Get first byte + PollPCM + ex af, af' + + push de ; PSG port address + ld de, $7F11 + + rrca ; Set first frequency byte + rrca + rrca + or b + or $80 + ld (de), a + + PollPCM + call GetParam ; Get second byte + PollPCM + + ex de, hl + ld (hl), b ; Set second frequency byte + ex de, hl + pop de + + ret ; End of subroutine + +;**************************************************************************** +; SetNoteNoise* +; Sets the note of the noise PSG channel without "note on" +;**************************************************************************** + +SetNoteNoiseSFX: + call SetNoteNoise ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +SetNoteNoiseBGM: + ld a, (RAM_Locked+11) ; Check if channel is free + or a + jp nz, ProcessBGMSkip1 ; Don't play if locked + + call SetNoteNoise ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +;**************************************************************************** +; LockChannelPSG [events $E8-$EB] +; Locks a PSG channel +;**************************************************************************** + +LockChannelPSG: + ld b, a + PollPCM + push hl + + ld h, RAM_Locked>>8 ; Get address of channel to lock + ld a, b + and $0F + add RAM_Locked&$FF + ld l, a + + ld (hl), $01 ; Lock channel + + PollPCM + + ld a, b ; Stop channel + rrca + rrca + rrca + rrca + ld l, a + ld h, RAM_PSGData>>8 + ld (hl), $00 + + pop hl + jp ProcessSFXRun ; End of subroutine -- cgit v1.2.3