diff --git a/MBMlib/MBMlib.rel b/MBMlib/MBMlib.rel index 2cbc11f..81e2c66 100644 --- a/MBMlib/MBMlib.rel +++ b/MBMlib/MBMlib.rel @@ -1,12 +1,18 @@ XL2 -H 9 areas 26 global symbols +H 9 areas 32 global symbols M MBMlib O -mz80 S _SMS_Port3EBIOSvalue Ref0000 S .__.ABS. Def0000 -A _CODE size 7CB flags 0 addr 0 +A _CODE size 8AB flags 0 addr 0 +S _MBMSFXPlay Def07CB +S _MBMSFXCancelLoop Def07FA +S _MBMSFXGetStatus Def0848 S _MBMPlay Def0000 +S _MBMSFXStop Def0800 +S _MBMSFXFrame Def0850 S _MBMCancelLoop Def0153 +S _MBMSFXPlayLoop Def07F1 S _MBMGetStatus Def01B2 S _SMS_GetFMAudioCapabilities Def0770 S _MBMStop Def0169 @@ -18,19 +24,24 @@ S _MBMFreqencyLUT Def01BA S _MBMPlayNoRepeat Def0159 S _MBMDrumReg Def027A S _MBMModVal Def0283 -A _DATA size A8 flags 0 addr 0 +A _DATA size B1 flags 0 addr 0 S _MBMChannelInfo Def00A4 +S _MBMSFXLoopFlag Def00AF S _MBMFading Def001F S _MBMStart Def0001 S _MBMFadeCounter Def0020 S _MBMSpeedCounter Def0018 +S _MBMSFXDelayIVR Def00B0 +S _MBMSFXPointer Def00AA S _MBMChannelBuffer Def0021 S _MBMPosition Def0003 +S _MBMSFXLoopPoint Def00AC S _MBMStatusByte Def0005 S _MBMStep Def0004 S _MBMPatternAddress Def0019 S _MBMLoopPoint Def00A5 S _MBMPAT Def001D +S _MBMSFXSkipFrames Def00AE S _MBMSpeed Def0017 S _MBMFrequency Def0015 S _MBMSFXStatus Def00A7 @@ -40,6 +51,7 @@ S _MBMSongLength Def00A3 S _MBMTransposeValue Def0016 S _MBMDrumBlockAddr Def00A1 S _MBMPatternPointer Def001B +S _MBMSFXStart Def00A8 S _MBMLastCustInstr Def00A6 S _MBMStatus Def0000 A _INITIALIZED size 0 flags 0 addr 0 @@ -141,6 +153,30 @@ T A7 00 R 00 00 01 00 T A7 00 R 00 00 01 00 +T A8 00 +R 00 00 01 00 +T A8 00 +R 00 00 01 00 +T AA 00 +R 00 00 01 00 +T AA 00 +R 00 00 01 00 +T AC 00 +R 00 00 01 00 +T AC 00 +R 00 00 01 00 +T AE 00 +R 00 00 01 00 +T AE 00 +R 00 00 01 00 +T AF 00 +R 00 00 01 00 +T AF 00 +R 00 00 01 00 +T B0 00 +R 00 00 01 00 +T B0 00 +R 00 00 01 00 T 00 00 R 00 00 00 00 T 00 00 FD 21 01 00 FD 75 00 FD 74 01 DD E5 3A @@ -721,3 +757,77 @@ T BB 07 3A 00 00 F6 04 D3 3E 7D D3 F2 3A 00 00 D3 R 00 00 00 00 02 03 00 00 02 0D 00 00 T C9 07 3E C9 R 00 00 00 00 +T CB 07 +R 00 00 00 00 +T CB 07 FD 21 A8 00 FD 75 00 FD 74 01 AF 32 AF 00 +R 00 00 00 00 00 04 01 00 00 0E 01 00 +T D9 07 CD 33 08 3C 32 A7 00 32 AE 00 2A +R 00 00 00 00 00 03 00 00 00 07 01 00 00 0A 01 00 +T E4 07 A8 00 22 AA 00 22 AC 00 AF 32 +R 00 00 00 00 00 02 01 00 00 05 01 00 00 08 01 00 +T EE 07 B0 00 C9 +R 00 00 00 00 00 02 01 00 +T F1 07 +R 00 00 00 00 +T F1 07 CD CB 07 21 AF 00 36 01 C9 +R 00 00 00 00 00 03 00 00 00 06 01 00 +T FA 07 +R 00 00 00 00 +T FA 07 21 AF 00 36 00 C9 +R 00 00 00 00 00 03 01 00 +T 00 08 +R 00 00 00 00 +T 00 08 3E 16 32 B0 00 C3 33 08 +R 00 00 00 00 00 05 01 00 00 08 00 00 +T 08 08 +R 00 00 00 00 +T 08 08 AF 32 A7 00 32 B0 00 3A 27 00 3D 06 00 87 +R 00 00 00 00 00 04 01 00 00 07 01 00 00 0A 01 00 +T 16 08 4F 2A 9F 00 09 7E FE 10 38 01 AF +R 00 00 00 00 00 04 01 00 +T 21 08 +R 00 00 00 00 +T 21 08 07 07 07 07 47 3A 2E 00 CB 3F CB 3F A8 0E +R 00 00 00 00 00 08 01 00 +T 2F 08 30 C3 68 07 +R 00 00 00 00 00 04 00 00 +T 33 08 +R 00 00 00 00 +T 33 08 AF 0E 10 CD 68 07 00 00 00 00 00 00 D6 00 +R 00 00 00 00 00 06 00 00 +T 41 08 D6 00 0E 20 C3 68 07 +R 00 00 00 00 00 07 00 00 +T 48 08 +R 00 00 00 00 +T 48 08 FD 21 A7 00 FD 6E 00 C9 +R 00 00 00 00 00 04 01 00 +T 50 08 +R 00 00 00 00 +T 50 08 3A A7 00 B7 C8 3A B0 00 FE 01 DA 65 08 CA +R 00 00 00 00 00 03 01 00 00 08 01 00 00 0D 00 00 +T 5E 08 08 08 3D 32 B0 00 C9 +R 00 00 00 00 00 02 00 00 00 06 01 00 +T 65 08 +R 00 00 00 00 +T 65 08 3A AE 00 3D 32 AE 00 C0 2A AA 00 +R 00 00 00 00 00 03 01 00 00 07 01 00 00 0B 01 00 +T 70 08 +R 00 00 00 00 +T 70 08 7E FE 10 DA 8C 08 FE FF C2 82 08 23 22 +R 00 00 00 00 00 06 00 00 00 0B 00 00 +T 7D 08 AC 00 C3 70 08 +R 00 00 00 00 00 02 01 00 00 05 00 00 +T 82 08 +R 00 00 00 00 +T 82 08 4F 23 7E CD 68 07 23 C3 70 08 +R 00 00 00 00 00 06 00 00 00 0A 00 00 +T 8C 08 +R 00 00 00 00 +T 8C 08 B7 CA 98 08 32 AE 00 23 22 AA 00 C9 +R 00 00 00 00 00 04 00 00 00 07 01 00 00 0B 01 00 +T 98 08 +R 00 00 00 00 +T 98 08 3A AF 00 B7 CA 00 08 3E 01 32 AE 00 2A +R 00 00 00 00 00 03 01 00 00 07 00 00 00 0C 01 00 +T A5 08 AC 00 22 AA 00 C9 +R 00 00 00 00 00 02 01 00 00 05 01 00 diff --git a/MBMlib/src/MBMlib.c b/MBMlib/src/MBMlib.c index 310d31b..bc717c0 100644 --- a/MBMlib/src/MBMlib.c +++ b/MBMlib/src/MBMlib.c @@ -1,7 +1,7 @@ /* ************************************************** MBMlib - C programming library for Moonblaster modules replay ( part of devkitSMS - github.com/sverx/devkitSMS ) - code: Kagesan, sverx + code: 'Remco Schrijvers / MoonSoft', Kagesan, sverx ************************************************** */ #define MBMIVLIST_OFFSET #0x00A3 @@ -65,7 +65,14 @@ unsigned char MBMLoopPoint; // loop position unsigned char MBMLastCustInstr; // last programmed custom instrument -unsigned char MBMSFXStatus; // SFX status (TO DO) +// SFX variables +unsigned char MBMSFXStatus; // SFX status +void* MBMSFXStart; // ROM address of SFX +void* MBMSFXPointer; // current address +void* MBMSFXLoopPoint; // the pointer to the loop begin +unsigned char MBMSFXSkipFrames; // wait counter for empty frames +unsigned char MBMSFXLoopFlag; // looping? 1= yes, 0 = no +unsigned char MBMSFXDelayIVR; // delay until instrument and volume are restored void MBMPlay (void *module) __z88dk_fastcall __naked { @@ -1295,3 +1302,148 @@ void SMS_EnableAudio (unsigned char chips) __z88dk_fastcall __naked { __endasm; } #pragma restore + +// SFX + +void MBMSFXPlay (void *sound_effect) __z88dk_fastcall __naked { + + MBMSFXStart=sound_effect; + + __asm + xor a ; SFX is _NOT_ a looping one + ld (_MBMSFXLoopFlag),a + call MBMSFXSilence ; stop any sfx that might be playing + inc a + ld (_MBMSFXStatus), a ; set status to "playing" + ld (_MBMSFXSkipFrames), a ; next frame follows immediately + ld hl,(_MBMSFXStart) ; set pointer to start of sfx data + ld (_MBMSFXPointer), hl + ld (_MBMSFXLoopPoint), hl ; loop pointer also points at the start for now + xor a + ld (_MBMSFXDelayIVR), a + ret + __endasm; +} + +void MBMSFXPlayLoop (void *sound_effect) __z88dk_fastcall { + MBMSFXPlay (sound_effect); + MBMSFXLoopFlag=1; +} + +void MBMSFXCancelLoop (void) { + MBMSFXLoopFlag=0; +} + +void MBMSFXStop (void) __naked { + __asm + ld a, #22 ; set number of frames until I/V restore + ld (_MBMSFXDelayIVR), a + jp MBMSFXSilence ; zero frequency + +MBMSFXRestoreInstrVol: + xor a + ld (_MBMSFXStatus), a ; reset status to "not playing" + ld (_MBMSFXDelayIVR), a ; reset delay timer + ld a, (_MBMChannelBuffer+6) ; get instrument number + dec a + ld b, #0 + add a, a + ld c, a + ld hl,(_MBMIVListAddr) + add hl, bc + ld a, (hl) ; get instrument from list + cp #16 + jr c, _is_not_custom + xor a +_is_not_custom: + rlca ; move instrument into upper nibble + rlca + rlca + rlca + ld b, a + ld a, (_MBMChannelBuffer+13) ; get volume + srl a + srl a + xor b ; combine volume with instrument + ld c, #0x30 + jp FMOut ; restore instrument and volume, return + +MBMSFXSilence: + xor a + ld c, #0x10 ; set frequency to zero, key off + call FMOut + nop ;* + nop ;* + nop ;* + nop ;* + nop ;* + nop ;* + sub #0 ;* + sub #0 ;* + ld c, #0x20 + jp FMOut + __endasm; +} + +unsigned char MBMSFXGetStatus (void) { + return MBMSFXStatus; +} + +void MBMSFXFrame (void) __naked { + __asm + ld a, (_MBMSFXStatus) ; check if sfx is playing + or a ; no? + ret z ; then just return + + ld a, (_MBMSFXDelayIVR) ; check if inside delay period + cp #1 + jp c, _proceed ; if not, proceed with sfx + jp z, MBMSFXRestoreInstrVol ; if end of delay, restore instrument/volume, end sfx + dec a ; else reduce timer + ld (_MBMSFXDelayIVR), a ; store new value + ret + +_proceed: + ld a, (_MBMSFXSkipFrames) ; check if there are empty frames to skip + dec a + ld (_MBMSFXSkipFrames), a + ret nz + + ld hl, (_MBMSFXPointer) +_sfx_loop: + ld a, (hl) ; read command / register + cp #16 + jp c, _EndFrame + cp #255 ; check if loop point + jp nz, _loop_point + inc hl + ld (_MBMSFXLoopPoint), hl ; set loop point + jp _sfx_loop + +_loop_point: + ld c, a ; if a > 15, then it is a register number + inc hl ; move to data byte + ld a, (hl) ; read data byte + call FMOut + inc hl ; move to next command / register byte + jp _sfx_loop ; repeat until frame ends + +_EndFrame: + or a ; check if end of sfx + jp z, _EndSFX + ld (_MBMSFXSkipFrames), a ; store wait frames + inc hl + ld (_MBMSFXPointer), hl + ret + +_EndSFX: + ld a, (_MBMSFXLoopFlag) ; check if sfx is looping + or a ; no? + jp z, _MBMSFXStop ; then stop sfx, restore instrument and volume + ld a, #1 + ld (_MBMSFXSkipFrames), a ; next frame follows immediately + ld hl, (_MBMSFXLoopPoint) ; set pointer back to loop point + ld (_MBMSFXPointer), hl + ret + __endasm; +} diff --git a/MBMlib/src/MBMlib.h b/MBMlib/src/MBMlib.h index b32a129..4902de3 100644 --- a/MBMlib/src/MBMlib.h +++ b/MBMlib/src/MBMlib.h @@ -1,7 +1,7 @@ /* ************************************************** MBMlib - C programming library for Moonblaster modules replay ( part of devkitSMS - github.com/sverx/devkitSMS ) - code: Kagesan, sverx + code: 'Remco Schrijvers / MoonSoft', Kagesan, sverx ************************************************** */ #define MBM_STOPPED 0 @@ -34,3 +34,18 @@ unsigned char SMS_GetFMAudioCapabilities (void) __naked; #define SMS_ENABLE_AUDIO_NONE 0x02 void SMS_EnableAudio (unsigned char chips) __z88dk_fastcall __naked; + +/* SFX */ + +#define MBMSFX_STOPPED 0 +#define MBMSFX_PLAYING 1 + +void MBMSFXPlay (void *sound_effect) __z88dk_fastcall __naked; +void MBMSFXPlayLoop (void *sound_effect) __z88dk_fastcall; +void MBMSFXCancelLoop (void); + +void MBMSFXStop (void) __naked; + +unsigned char MBMSFXGetStatus (void); + +void MBMSFXFrame (void) __naked;