dmgtris/src/sfx.asm

527 lines
11 KiB
NASM
Raw Normal View History

2023-10-21 15:28:38 +00:00
; DMGTRIS
; Copyright (C) 2023 - Randy Thiemann <randy.thiemann@gmail.com>
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <https://www.gnu.org/licenses/>.
2023-10-16 11:27:08 +00:00
IF !DEF(SFX_ASM)
DEF SFX_ASM EQU 1
2023-10-17 05:41:11 +00:00
DEF REG_NR10_CH1_SWEEP EQU $10
DEF REG_NR11_CH1_LENDT EQU $11
DEF REG_NR12_CH1_VOLEV EQU $12
DEF REG_NR13_CH1_FRQLO EQU $13
DEF REG_NR14_CH1_FRQHI EQU $14
DEF REG_NR21_CH2_LENDT EQU $16
DEF REG_NR22_CH2_VOLEV EQU $17
DEF REG_NR23_CH2_FRQLO EQU $18
DEF REG_NR24_CH2_FRQHI EQU $19
DEF REG_NR30_CH3_DACEN EQU $1A
DEF REG_NR31_CH3_LENGT EQU $1B
DEF REG_NR32_CH3_VOLUM EQU $1C
DEF REG_NR33_CH3_FRQLO EQU $1D
DEF REG_NR34_CH3_FRQHI EQU $1E
DEF REG_NR41_CH4_LENGT EQU $20
DEF REG_NR42_CH4_VOLEV EQU $21
DEF REG_NR43_CH4_FQRND EQU $22
DEF REG_NR44_CH4_CNTRL EQU $23
DEF REG_NR50_MVOLVINPN EQU $24
DEF REG_NR51_MASTERPAN EQU $25
DEF REG_NR52_MASTERCTL EQU $26
DEF REG_WAVE_PATTERN_0 EQU $30
DEF REG_WAVE_PATTERN_1 EQU $31
DEF REG_WAVE_PATTERN_2 EQU $32
DEF REG_WAVE_PATTERN_3 EQU $33
DEF REG_WAVE_PATTERN_4 EQU $34
DEF REG_WAVE_PATTERN_5 EQU $35
DEF REG_WAVE_PATTERN_6 EQU $36
DEF REG_WAVE_PATTERN_7 EQU $37
DEF REG_WAVE_PATTERN_8 EQU $38
DEF REG_WAVE_PATTERN_9 EQU $39
DEF REG_WAVE_PATTERN_A EQU $3A
DEF REG_WAVE_PATTERN_B EQU $3B
DEF REG_WAVE_PATTERN_C EQU $3C
DEF REG_WAVE_PATTERN_D EQU $3D
DEF REG_WAVE_PATTERN_E EQU $3E
DEF REG_WAVE_PATTERN_F EQU $3F
2023-10-25 07:21:06 +00:00
INCLUDE "globals.asm"
INCLUDE "res/sfx_data.inc"
INCLUDE "res/music_data.inc"
2023-10-16 11:27:08 +00:00
2023-10-21 18:49:52 +00:00
SECTION "High SFX Variables", HRAM
2023-10-16 11:27:08 +00:00
hPlayhead:: ds 2
2023-10-17 05:41:11 +00:00
hPlayQueue:: ds 4
2023-10-27 10:20:33 +00:00
hNoisePlayhead:: ds 2
2023-10-16 11:27:08 +00:00
SECTION "SFX Functions", ROM0
; Audio on, volume on, and enable all channels.
2023-10-27 19:37:32 +00:00
; Zeroes out all playheads and the queue.
SFXInit::
2023-10-16 11:27:08 +00:00
ld a, $80
ldh [rNR52], a
ld a, $FF
ldh [rNR51], a
ld a, $77
ldh [rNR50], a
2023-10-17 05:41:11 +00:00
ld a, $FF
ldh [hPlayQueue], a
ldh [hPlayQueue+1], a
ldh [hPlayQueue+2], a
ldh [hPlayQueue+3], a
xor a, a
ldh [hPlayhead], a
ldh [hPlayhead+1], a
2023-10-27 10:20:33 +00:00
ldh [hNoisePlayhead], a
ldh [hNoisePlayhead+1], a
2023-10-17 05:41:11 +00:00
ret
; Pop the head of the queue into A, the tail of the queue will be set to $FF.
2023-10-27 19:37:32 +00:00
SFXPopQueue:
2023-10-17 05:41:11 +00:00
ldh a, [hPlayQueue]
ld b, a
ldh a, [hPlayQueue+1]
ldh [hPlayQueue], a
ldh a, [hPlayQueue+2]
ldh [hPlayQueue+1], a
ldh a, [hPlayQueue+3]
ldh [hPlayQueue+2], a
ld a, $FF
ldh [hPlayQueue+3], a
ld a, b
ret
; Push A onto the tail of the queue, the head of the queue will be pushed off.
2023-10-27 19:37:32 +00:00
SFXPushQueue:
2023-10-17 05:41:11 +00:00
ld b, a
ldh a, [hPlayQueue+1]
ldh [hPlayQueue], a
ldh a, [hPlayQueue+2]
ldh [hPlayQueue+1], a
ldh a, [hPlayQueue+3]
ldh [hPlayQueue+2], a
ld a, b
ldh [hPlayQueue+3], a
ret
2023-10-16 11:27:08 +00:00
2023-10-27 19:37:32 +00:00
; Process the queue, if there's more to play, it will do so.
2023-10-17 05:41:11 +00:00
SFXProcessQueue:
; Clear the playhead.
xor a, a
2023-10-16 11:27:08 +00:00
ldh [hPlayhead], a
ldh [hPlayhead+1], a
2023-10-17 05:41:11 +00:00
2023-10-27 19:37:32 +00:00
; Music will just repeat.
2023-10-25 07:21:06 +00:00
ldh a, [hPlayQueue]
cp a, MUSIC_MENU
jr nz, :+
2023-10-27 19:37:32 +00:00
jr SFXEnqueue
2023-10-25 07:21:06 +00:00
2023-10-17 05:41:11 +00:00
; Try 4 times to pop a sound effect off the queue.
2023-10-25 07:21:06 +00:00
: call SFXPopQueue
2023-10-17 05:41:11 +00:00
cp a, $FF
jr nz, :+
call SFXPopQueue
cp a, $FF
jr nz, :+
call SFXPopQueue
cp a, $FF
jr nz, :+
call SFXPopQueue
cp a, $FF
ret z
; If we got a valid sound effect, then play it.
2023-10-27 19:37:32 +00:00
jr SFXEnqueue
2023-10-16 11:27:08 +00:00
2023-10-27 19:37:32 +00:00
; Noise effects use their own playhead that can play at the same time as the normal queue.
2023-10-27 10:20:33 +00:00
SFXTriggerNoise::
cp a, SFX_LINE_CLEAR
jr nz, :+
ld a, LOW(sSFXLineClear)
ldh [hNoisePlayhead], a
ld a, HIGH(sSFXLineClear)
ldh [hNoisePlayhead+1], a
ret
: cp a, SFX_LAND
jr nz, :+
ld a, LOW(sSFXLand)
ldh [hNoisePlayhead], a
ld a, HIGH(sSFXLand)
ldh [hNoisePlayhead+1], a
ret
: cp a, SFX_LOCK
ret nz
ld a, LOW(sSFXLock)
ldh [hNoisePlayhead], a
ld a, HIGH(sSFXLock)
ldh [hNoisePlayhead+1], a
ret
2023-10-17 05:41:11 +00:00
; Attempt to play the sound effect in A. Will enqueue the sound effect if the play routine is currently busy.
SFXEnqueue::
; If the playhead isn't null, then we're already playing something.
ld b, a
ldh a, [hPlayhead]
ld l, a
ldh a, [hPlayhead+1]
ld h, a
or a, l
jr z, :+
ld a, b
2023-10-27 19:37:32 +00:00
jr SFXPushQueue
2023-10-17 05:41:11 +00:00
2023-10-25 07:21:06 +00:00
; Menu music
: ld a, b
cp a, MUSIC_MENU
jr nz, :+
ldh [hPlayQueue], a
ld a, LOW(sMusicMenu)
ldh [hPlayhead], a
ld a, HIGH(sMusicMenu)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-25 07:21:06 +00:00
2023-10-24 11:35:51 +00:00
; Piece jingles.
2023-10-17 05:41:11 +00:00
: ld a, b
cp a, PIECE_I
jr nz, :+
ld a, LOW(sSFXPieceI)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceI)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_I | SFX_IRS
jr nz, :+
ld a, LOW(sSFXPieceIRSI)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceIRSI)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_S
2023-10-17 05:41:11 +00:00
jr nz, :+
ld a, LOW(sSFXPieceS)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceS)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_S | SFX_IRS
jr nz, :+
ld a, LOW(sSFXPieceIRSS)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceIRSS)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_Z
2023-10-17 05:41:11 +00:00
jr nz, :+
ld a, LOW(sSFXPieceZ)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceZ)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_Z | SFX_IRS
jr nz, :+
ld a, LOW(sSFXPieceIRSZ)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceIRSZ)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_J
2023-10-17 05:41:11 +00:00
jr nz, :+
ld a, LOW(sSFXPieceJ)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceJ)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_J | SFX_IRS
jr nz, :+
ld a, LOW(sSFXPieceIRSJ)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceIRSJ)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_L
2023-10-17 05:41:11 +00:00
jr nz, :+
ld a, LOW(sSFXPieceL)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceL)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_L | SFX_IRS
jr nz, :+
ld a, LOW(sSFXPieceIRSL)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceIRSL)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_O
2023-10-17 05:41:11 +00:00
jr nz, :+
ld a, LOW(sSFXPieceO)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceO)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_O | SFX_IRS
jr nz, :+
ld a, LOW(sSFXPieceIRSO)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceIRSO)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_T
2023-10-17 05:41:11 +00:00
jr nz, :+
ld a, LOW(sSFXPieceT)
ldh [hPlayhead], a
ld a, HIGH(sSFXPieceT)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: ld a, b
cp a, PIECE_T | SFX_IRS
2023-10-17 05:41:11 +00:00
jr nz, :+
2023-10-24 11:35:51 +00:00
ld a, LOW(sSFXPieceIRST)
2023-10-17 05:41:11 +00:00
ldh [hPlayhead], a
2023-10-24 11:35:51 +00:00
ld a, HIGH(sSFXPieceIRST)
2023-10-17 05:41:11 +00:00
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
; IRS
: cp a, SFX_IHS
2023-10-17 05:41:11 +00:00
jr nz, :+
2023-10-24 11:35:51 +00:00
ld a, LOW(sSFXIHS)
2023-10-17 05:41:11 +00:00
ldh [hPlayhead], a
2023-10-24 11:35:51 +00:00
ld a, HIGH(sSFXIHS)
2023-10-17 05:41:11 +00:00
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-24 11:35:51 +00:00
: cp a, SFX_IHS | SFX_IRS
2023-10-17 05:41:11 +00:00
jr nz, :+
2023-10-24 11:35:51 +00:00
ld a, LOW(sSFXIHSIRS)
2023-10-17 05:41:11 +00:00
ldh [hPlayhead], a
2023-10-24 11:35:51 +00:00
ld a, HIGH(sSFXIHSIRS)
2023-10-17 05:41:11 +00:00
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp SFXPlay
2023-10-24 11:35:51 +00:00
; Leveling
: cp a, SFX_LEVELLOCK
jr nz, :+
ld a, LOW(sSFXLevelLock)
ldh [hPlayhead], a
ld a, HIGH(sSFXLevelLock)
2023-10-18 07:31:08 +00:00
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jr SFXPlay
2023-10-18 07:31:08 +00:00
2023-10-24 11:35:51 +00:00
: cp a, SFX_LEVELUP
2023-10-20 09:45:41 +00:00
jr nz, :+
2023-10-18 07:31:08 +00:00
ld a, LOW(sSFXLevelUp)
ldh [hPlayhead], a
ld a, HIGH(sSFXLevelUp)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jr SFXPlay
2023-10-21 17:42:33 +00:00
2023-10-24 11:35:51 +00:00
; Other
: cp a, SFX_RANKUP
2023-10-21 17:42:33 +00:00
jr nz, :+
2023-10-24 11:35:51 +00:00
ld a, LOW(sSFXRankUp)
2023-10-20 09:45:41 +00:00
ldh [hPlayhead], a
2023-10-24 11:35:51 +00:00
ld a, HIGH(sSFXRankUp)
2023-10-20 09:45:41 +00:00
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jr SFXPlay
2023-10-20 09:45:41 +00:00
2023-10-24 11:35:51 +00:00
: cp a, SFX_READYGO
2023-10-21 17:42:33 +00:00
ret nz
ld a, LOW(sSFXReadyGo)
ldh [hPlayhead], a
ld a, HIGH(sSFXReadyGo)
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jr SFXPlay
2023-10-17 05:41:11 +00:00
2023-10-27 19:37:32 +00:00
; Kill the non-noise sound and clear the queue.
2023-10-20 14:28:11 +00:00
SFXKill::
2023-10-21 13:25:02 +00:00
; Kill all sound without pops.
ld a, %00111111
ldh [rNR11], a
ldh [rNR21], a
ld a, $FF
ldh [rNR31], a
ld a, %01000000
ldh [rNR14], a
ldh [rNR24], a
ldh [rNR34], a
; Clear the queue.
2023-10-20 14:28:11 +00:00
ld a, $FF
ldh [hPlayQueue], a
ldh [hPlayQueue+1], a
ldh [hPlayQueue+2], a
ldh [hPlayQueue+3], a
xor a, a
ldh [hPlayhead], a
ldh [hPlayhead+1], a
ret
2023-10-27 19:37:32 +00:00
; Play routine for the noise channel.
; Must be called every frame.
2023-10-27 10:20:33 +00:00
SFXPlayNoise::
; Get the noise playhead.
ldh a, [hNoisePlayhead]
ld l, a
ldh a, [hNoisePlayhead+1]
ld h, a
or a, l
; Bail if it's null
ret z
2023-10-28 17:04:55 +00:00
; Bank to sound effects.
ld b, BANK_SFX
2023-10-27 10:20:33 +00:00
rst RSTSwitchBank
; Get the register to write to
.noisereg
ld a, [hl]
inc hl
; If it's $FE, then we're done.
cp a, $FE
jr nz, :+
rst RSTRestoreBank
xor a, a
ldh [hNoisePlayhead], a
ldh [hNoisePlayhead+1], a
ret
; If it's $FF, then we're done for this frame.
: cp a, $FF
jr z, .savenoiseplayhead
; Otherwise, put the register in C.
ld c, a
; Get the value to write.
ld a, [hl]
inc hl
; Write it and loop.
ldh [$ff00+c], a
jr .noisereg
; Save the playhead position.
.savenoiseplayhead
ld a, l
ldh [hNoisePlayhead], a
ld a, h
ldh [hNoisePlayhead+1], a
2023-10-27 19:37:32 +00:00
jp RSTRestoreBank
2023-10-27 10:20:33 +00:00
2023-10-27 19:37:32 +00:00
; Play routine for the regular sfx channels.
; Must be called every frame.
2023-10-16 11:27:08 +00:00
SFXPlay::
2023-10-25 07:21:06 +00:00
; Bank to correct bank.
ldh a, [hPlayQueue]
cp a, MUSIC_MENU
jr nz, :+
2023-10-28 17:04:55 +00:00
ld b, BANK_MUSIC
2023-10-25 07:21:06 +00:00
rst RSTSwitchBank
jr .play
2023-10-28 17:04:55 +00:00
: ld b, BANK_SFX
2023-10-25 05:21:48 +00:00
rst RSTSwitchBank
2023-10-25 04:40:08 +00:00
2023-10-16 11:27:08 +00:00
; Load the playhead position into HL.
2023-10-25 07:21:06 +00:00
.play
2023-10-16 11:27:08 +00:00
ldh a, [hPlayhead]
ld l, a
ldh a, [hPlayhead+1]
ld h, a
; Nothing to do if it's a null ptr.
or a, l
2023-10-25 04:40:08 +00:00
jr nz, .getRegister
2023-10-27 19:37:32 +00:00
jp RSTRestoreBank
2023-10-16 11:27:08 +00:00
; Otherwise, get the register to write to.
.getRegister
ld a, [hl]
inc hl
2023-10-17 05:41:11 +00:00
; If it's $FE, then we're done. Check if there's more for us in the queue.
2023-10-16 11:27:08 +00:00
cp a, $FE
jr nz, :+
2023-10-25 05:21:48 +00:00
rst RSTRestoreBank
2023-10-27 19:37:32 +00:00
jp SFXProcessQueue
2023-10-16 11:27:08 +00:00
; If it's $FF, then we're done for this frame.
: cp a, $FF
jr z, .savePlayhead
; Otherwise, put the register in C.
ld c, a
; Get the value to write.
ld a, [hl]
inc hl
; Write it and loop.
ldh [$ff00+c], a
jr .getRegister
2023-10-17 05:41:11 +00:00
; Save the playhead position.
2023-10-16 11:27:08 +00:00
.savePlayhead
ld a, l
ldh [hPlayhead], a
ld a, h
ldh [hPlayhead+1], a
2023-10-27 19:37:32 +00:00
jp RSTRestoreBank
2023-10-16 11:27:08 +00:00
ENDC