From 3aacf3d2cedfdeca49ceb57533389870bfc688a9 Mon Sep 17 00:00:00 2001 From: sik Date: Sun, 23 Jul 2017 03:20:35 -0300 Subject: Now with pausing and other niceties --- src-z80/core/bgm.z80 | 185 ++++++++++++++++++++++++++++++------------------- src-z80/core/macro.z80 | 41 +++++++++++ src-z80/core/main.z80 | 113 +++++++++++++----------------- src-z80/core/sfx.z80 | 48 ++++++++++--- src-z80/core/vars.z80 | 18 ++++- 5 files changed, 260 insertions(+), 145 deletions(-) create mode 100644 src-z80/core/macro.z80 (limited to 'src-z80/core') diff --git a/src-z80/core/bgm.z80 b/src-z80/core/bgm.z80 index 338a7a6..b48d87a 100644 --- a/src-z80/core/bgm.z80 +++ b/src-z80/core/bgm.z80 @@ -25,13 +25,14 @@ PlayBGM: PollPCM - xor a ; Command parsed - ld (RAM_Command), a + xor a ; Playing a BGM immediately unpauses playback + ld (RAM_Paused), a + inc a ld hl, RAM_BGMData ; Set BGM as playing - ld (hl), $01 + ld (hl), a inc l ; No delays! - ld (hl), $01 + ld (hl), a inc l ; Store BGM start bank ld (hl), c inc l ; Store BGM start address (low) @@ -44,55 +45,111 @@ PlayBGM: ld hl, ProcessBGM ; Tell Echo to process BGM ld (DoTick_BGM+1), hl - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine ;**************************************************************************** -; ResumeBGM [command $06] -; Resumes a stopped BGM +; PauseBGM [command $08] +; Pauses a playing BGM ;---------------------------------------------------------------------------- ; breaks: all ;**************************************************************************** -ResumeBGM: - xor a ; Command parsed - ld (RAM_Command), a +PauseBGM: + ld a, (RAM_BGMPlaying) ; Is BGM even playing? + or a + jp z, EndOfCommand + + ld a, 1 ; Halt BGM playback + ld (RAM_Paused), a ;---------------------------------------------------------------------------- - - ld b, 8 ; Restore all FM channels - ld de, RAM_Locked+7 -.restorefm: + ld b, $7F ; Mute all FM channels + ld c, 7 + ld hl, RAM_Locked+7 +.mutefm: PollPCM - - ld a, (de) ; Check if this channel is locked + ld a, (hl) or a - jp nz, .fmlocked - + jr nz, .nofmmute + ld a, c + call SetFMVolTempLoad +.nofmmute: PollPCM + dec l + dec c + jp p, .mutefm - dec b ; Restore FM channel - call RestoreFM - inc b - -.fmlocked: - dec e ; Go for next channel to restore - dec b - jp nz, .restorefm + ld b, 4 ; Mute all PSG channels + ld c, $0F + ld de, RAM_Locked+8 + ld hl, RAM_PSGData +.mutepsg: + PollPCM + ld a, (de) + or a + jr nz, .nopsgmute + ld a, (hl) + and $80 + or c, + ld (hl), a +.nopsgmute: + PollPCM + ld a, l + add 16 + ld l, a + inc e + djnz .mutepsg ;---------------------------------------------------------------------------- - ld a, (RAM_Status) ; Show BGM playback in Echo's status - or $02 - ld (RAM_Status), a + ld a, (RAM_Locked+6) ; Mute PCM channel + or a + call z, StopPCM - ld hl, RAM_BGMData ; Set BGM as playing - ld (hl), $01 +;---------------------------------------------------------------------------- + + jp EndOfCommand ; End of subroutine + +;**************************************************************************** +; ResumeBGM [command $06] +; Resumes a stopped BGM +;---------------------------------------------------------------------------- +; breaks: all +;**************************************************************************** + +ResumeBGM: + ld a, (RAM_BGMPlaying) ; Was BGM even playing? + or a + jp z, EndOfCommand - ld hl, ProcessBGM ; Tell Echo to process BGM - ld (DoTick_BGM+1), hl + xor a + ld (RAM_Paused), a ; Resume BGM playback - jp IdleLoop ; End of subroutine + ld b, 4 ; Restore PSG channels + ld de, RAM_Locked+11 + ld hl, RAM_PSGData+63 +.resumepsg: + PollPCM + ld c, (hl) + ld a, l + sub 15 + ld l, a + ld a, (de) + or a + jr nz, .nopsgresume + ld a, (hl) + and $80 + or c + ld (hl), a +.nopsgresume: + PollPCM + dec l + dec e + djnz .resumepsg + + call RefreshVolume ; Restore remaining channels + jp EndOfCommand ; End of subroutine ;**************************************************************************** ; ProcessBGM @@ -197,6 +254,9 @@ ProcessBGMEventFF: jp c, SetFMParamBGM cp $FA ; Events $F8-$F9: set FM register jp c, SetFMRegBGM + jp z, SetFlagsBGM ; Events $FA-$FB: set/clear flags + cp $FB + jp z, ClearFlagsBGM PollPCM ; FFFFFFFFF bad event >:( ProcessBGMEnd: @@ -234,10 +294,8 @@ StopBGMEvent: jp DoTick_BGMSkip ; End of subroutine StopBGMCmd: - xor a ; Command parsed - ld (RAM_Command), a call StopBGM ; We're just a wrapper - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine StopBGM: ld a, (RAM_Status) ; Hide BGM playback in Echo's status @@ -271,7 +329,7 @@ ClearBGM: ld b, 4 ; Reset all PSG channels ld de, RAM_PSGData+48+15 ld hl, RAM_Locked+11 -.mutepsg: +.killpsg: PollPCM ld (hl), $00 ; Reset BGM volume @@ -282,22 +340,22 @@ ClearBGM: ld a, (hl) ; Mute PSG channel if it isn't locked or a - jr nz, .nopsgmute + jr nz, .nopsgkill xor a ld (de), a -.nopsgmute: +.nopsgkill: PollPCM dec e dec l - djnz .mutepsg + djnz .killpsg ;---------------------------------------------------------------------------- ld b, 8 ; Reset all FM channels ld de, RAM_BGMFMVol+7 -.resetfm: +.killfm: PollPCM ld a, $7F ; Reset BGM volume @@ -328,10 +386,10 @@ ClearBGM: inc b .nofmkill: dec l - djnz .resetfm + djnz .killfm ;---------------------------------------------------------------------------- - + ld hl, RAM_BGMFMPan ; Reset panning status (for restoring) ld a, $C0 ld b, 8 @@ -339,6 +397,9 @@ ClearBGM: ld (hl), a inc l djnz .initpanstat + + xor a ; Reset flags + ld (RAM_Flags), a ret ; End of subroutine @@ -349,19 +410,11 @@ ClearBGM: LoopBGM: PollPCM - - ex de, hl ; Get looping address - inc l - ld c, (hl) - inc l - ld e, (hl) - inc l - ld d, (hl) - dec l - dec l - dec l - ex de, hl - + + ld hl, (RAM_BGMLoopPoint+1) ; Get looping address + ld a, (RAM_BGMLoopPoint) + ld c, a + jp ProcessBGMRun ; End of subroutine ;**************************************************************************** @@ -371,17 +424,9 @@ LoopBGM: SetLoopBGM: PollPCM - - ex de, hl - inc l ; Store loop point address - ld (hl), c - inc l - ld (hl), e - inc l - ld (hl), d - dec l - dec l - dec l - ex de, hl - + + ld a, c ; Store loop point address + ld (RAM_BGMLoopPoint), a + ld (RAM_BGMLoopPoint+1), hl + jp ProcessBGMRun ; End of subroutine diff --git a/src-z80/core/macro.z80 b/src-z80/core/macro.z80 new file mode 100644 index 0000000..eedd527 --- /dev/null +++ b/src-z80/core/macro.z80 @@ -0,0 +1,41 @@ +;**************************************************************************** +; PollPCM +; Used to update PCM while not idle +;---------------------------------------------------------------------------- +; breaks: af +;**************************************************************************** + +PollPCM: macro + ld a, ($4000) + rrca + rst $08 + endm + +;**************************************************************************** +; BankSwitch +; Switches into a new bank (won't update player status!) +;---------------------------------------------------------------------------- +; input A .... New bank to switch into +; input HL ... Must be $60xx +;---------------------------------------------------------------------------- +; breaks ..... AF +;**************************************************************************** + +BankSwitch: macro + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + ld (hl), h + rrca + ld (hl), a + endm diff --git a/src-z80/core/main.z80 b/src-z80/core/main.z80 index 4eb6e5a..387b879 100644 --- a/src-z80/core/main.z80 +++ b/src-z80/core/main.z80 @@ -4,10 +4,11 @@ ;**************************************************************************** EntryPoint: - ld sp, RAM_Stack ; Init stack + xor a ; Reset Echo status (we don't clear + ld (RAM_Status), a ; RAM_Command since Echo_Init fills in values + ld (RAM_Command2), a ; before Echo gets to run!) - xor a ; Reset Echo status - ld (RAM_Status), a + ld sp, RAM_Stack ; Init stack ld hl, $7F11 ; Mute PSG ld (hl), $9F @@ -87,23 +88,12 @@ EntryPoint: jp IdleLoop ; Go into idle loop -;**************************************************************************** -; PollPCM -; Used to update PCM while not idle -;---------------------------------------------------------------------------- -; breaks: af -;**************************************************************************** - -PollPCM: macro - ld a, ($4000) - rrca - call c, UpdatePCM - endm - ;**************************************************************************** ; RunCommand ; Checks which command to run ;---------------------------------------------------------------------------- +; notes: doesn't return +;---------------------------------------------------------------------------- ; To-do: replace with pointer list? ;**************************************************************************** @@ -122,17 +112,36 @@ RunCommand: jp z, ResumeBGM dec a ; Command $07: set PCM rate jp z, SetPCMRate + dec a ; Command $08: pause BGM + jp z, PauseBGM PollPCM - xor a ; Bad command, ignore >:( - ld (RAM_Command), a + ; Bad command, ignore >:( + +;**************************************************************************** +; EndOfCommand +; Cleans up when a command finishes +;---------------------------------------------------------------------------- +; notes: doesn't return +;**************************************************************************** +EndOfCommand: + ld hl, ($1FF8) ; Copy second slot into first + ld ($1FFC), hl + ld hl, ($1FFA) + ld ($1FFE), hl + + xor a ; Free up second slot + ld (RAM_Command2), a + PollPCM ;**************************************************************************** ; IdleLoop ; Loop that runs when not processing SFX or BGM +;---------------------------------------------------------------------------- +; notes: doesn't return (d'oh) ;**************************************************************************** IdleLoop: @@ -153,13 +162,11 @@ IdleLoop: ;**************************************************************************** ; DoTick ; Called whenever a new tick triggers +;---------------------------------------------------------------------------- +; notes: doesn't return ;**************************************************************************** DoTick: -; ld a, (ix+0) -; bit 0, a -; call nz, UpdatePCM - PollPCM ld (ix+0), $27 ; Retrigger the timer @@ -181,6 +188,9 @@ DoTick_SFXSkip: PollPCM + ld a, (RAM_Paused) ; BGMs are paused? + or a + jr nz, DoTick_BGMSkip DoTick_BGM: ; Process BGMs jp DoTick_BGMSkip DoTick_BGMSkip: @@ -194,58 +204,31 @@ DoTick_PSGSkip: jp IdleLoop ; End of subroutine -;**************************************************************************** -; BankSwitch -; Switches into a new bank (won't update player status!) -; -; input A .... New bank to switch into -; input HL ... Must be $6000 -; breaks ..... AF -;**************************************************************************** - -BankSwitch: macro - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - ld (hl), h - rrca - ld (hl), a - endm - ;**************************************************************************** ; LoadList [command $01] ; Loads the pointer list ;**************************************************************************** LoadList: - ld hl, RAM_ComBank ; Get command parameters - ld c, (hl) - inc l - ld e, (hl) - inc l - ld d, (hl) - ex de, hl - - xor a ; Command parsed - ld (RAM_Command), a +; ld hl, RAM_ComBank ; Get command parameters +; ld c, (hl) +; inc l +; ld e, (hl) +; inc l +; ld d, (hl) +; ex de, hl + + ld hl, (RAM_ComAddr) ; Get command parameters + ld a, (RAM_ComBank) + ld c, a ld de, RAM_PointerList ; Where the pointer list starts -.loop: +.loadloop: call GetParam ; Get high byte address ld a, b ; Is it the end of the list? or a - jp z, .end + jp z, .loadend ld (de), a ; Store high byte address inc d @@ -261,10 +244,10 @@ LoadList: dec d ; Go for next byte dec d inc e - jp .loop + jp .loadloop -.end: - jp IdleLoop ; End of subroutine +.loadend: + jp EndOfCommand ; End of subroutine ;**************************************************************************** ; GetParam diff --git a/src-z80/core/sfx.z80 b/src-z80/core/sfx.z80 index 4bca4c7..8c5e7dd 100644 --- a/src-z80/core/sfx.z80 +++ b/src-z80/core/sfx.z80 @@ -25,9 +25,6 @@ PlaySFX: PollPCM - xor a ; Command parsed - ld (RAM_Command), a - ld hl, RAM_SFXData ; Set SFX as playing ld (hl), $01 inc l ; No delays! @@ -45,7 +42,7 @@ PlaySFX: ld (DoTick_SFX+1), hl PollPCM - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine ;**************************************************************************** ; ProcessSFX @@ -153,6 +150,14 @@ ProcessSFXRun: jp c, SetFMParamSFX cp $FA ; Events $F8-$F9: set FM register jp c, SetFMRegSFX + jp z, SetFlagsSFX ; Events $FA-$FB: set/clear flags + cp $FB + jp z, ClearFlagsSFX + + cp $FC + jp z, LoopSFX ; Event $FC: loop SFX + cp $FD + jp z, SetLoopSFX ; Event $FD: set loop point ;**************************************************************************** ; StopSFX* [command $03, event $FF] @@ -166,10 +171,8 @@ StopSFXEvent: 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 + jp EndOfCommand ; End of subroutine StopSFX: PollPCM @@ -283,9 +286,36 @@ ClearSFX: .fmfree: dec e ; Go for next FM channel to unlock - dec b - jp nz, .unlockfm + djnz .unlockfm ;---------------------------------------------------------------------------- ret ; End of subroutine + +;**************************************************************************** +; LoopSFX [event $FC] +; Makes a SFX loop +;**************************************************************************** + +LoopSFX: + PollPCM + + ld hl, (RAM_SFXLoopPoint+1) ; Get looping address + ld a, (RAM_SFXLoopPoint) + ld c, a + + jp ProcessSFXRun ; End of subroutine + +;**************************************************************************** +; SetLoopSFX [event $FD] +; Sets the SFX loop point +;**************************************************************************** + +SetLoopSFX: + PollPCM + + ld a, c ; Store loop point address + ld (RAM_SFXLoopPoint), a + ld (RAM_SFXLoopPoint+1), hl + + jp ProcessSFXRun ; End of subroutine diff --git a/src-z80/core/vars.z80 b/src-z80/core/vars.z80 index cd7162d..79e4a1d 100644 --- a/src-z80/core/vars.z80 +++ b/src-z80/core/vars.z80 @@ -42,13 +42,23 @@ RAM_SFXPlaying: ds 1 ; Set if a SFX is playing RAM_SFXDelay: ds 1 ; How many ticks to wait RAM_SFXBank: ds 1 ; Current SFX bank RAM_SFXAddress: ds 2 ; Current SFX address +RAM_SFXLoopPoint: ds 3 ; SFX loop point + +RAM_Paused: ds 1 ; Set if BGM stream is paused + +RAM_PCMBank1: db 1 ; (not implemented yet) +RAM_PCMAddr1: dw 1 ; (not implemented yet) +RAM_PCMBank2: db 1 ; (not implemented yet) +RAM_PCMAddr2: dw 1 ; (not implemented yet) RAM_Scratch: ds 32 ; Scratch bytes, may be useful when ; buffering to speed up to avoid bank ; switching conflicts ds $F0-($&$FF), $FF -RAM_PCMBuffer: ds 16 ; PCM buffer +RAM_PCMBuffer: ds 0 ; PCM buffer +RAM_PCMBuffer1: ds 8 ; (not implemented yet) +RAM_PCMBuffer2: ds 8 ; (not implemented yet) ;**************************************************************************** ; Pointer list starts being stored from here @@ -71,6 +81,12 @@ RAM_Stack: equ $1FE0 ; Where stack starts RAM_GlobalVol: equ $1FE0 ; Global volume for all channels RAM_Status: equ $1FF0 ; Current playback status RAM_RefreshVol: equ $1FF1 ; Set to refresh all volumes +RAM_Flags: equ $1FF2 ; Track flags + RAM_Command: equ $1FFF ; Command type RAM_ComAddr: equ $1FFD ; Command address parameter RAM_ComBank: equ $1FFC ; Command bank parameter + +RAM_Command2: equ $1FFB ; (second slot for all the above) +RAM_ComAddr2: equ $1FF9 +RAM_ComBank2: equ $1FF8 -- cgit v1.2.3