summaryrefslogtreecommitdiff
path: root/audio/engine.asm
diff options
context:
space:
mode:
Diffstat (limited to 'audio/engine.asm')
-rw-r--r--audio/engine.asm548
1 files changed, 417 insertions, 131 deletions
diff --git a/audio/engine.asm b/audio/engine.asm
index f7a9974..3e590f6 100644
--- a/audio/engine.asm
+++ b/audio/engine.asm
@@ -3,169 +3,455 @@ INCLUDE "constants.asm"
SECTION "Audio", ROMX[$4000], BANK[$3A]
_DisableAudio:: ; 3a:4000
- push hl
- push de
- push bc
- push af
- ld hl, rNR50
- xor a
- ld [hli], a
- ld [hli], a
- ld a, $80
- ld [hli], a
- ld hl, rNR10
- ld e, 4
+ push hl
+ push de
+ push bc
+ push af
+ ld hl, rNR50
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld a, $80
+ ld [hli], a
+ ld hl, rNR10
+ ld e, 4
.init_channel
- xor a
- ld [hli], a
- ld [hli], a
- ld a, 8
- ld [hli], a
- xor a
- ld [hli], a
- ld a, $80
- ld [hli], a
- dec e
- jr nz, .init_channel
-
- ld hl, wMusic
- ld de, wMusicInitEnd - wMusic
-.clear
- xor a
- ld [hli], a
- dec de
- ld a, e
- or d
- jr nz, .clear
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld a, 8
+ ld [hli], a
+ xor a
+ ld [hli], a
+ ld a, $80
+ ld [hli], a
+ dec e
+ jr nz, .init_channel
- ld a, $77
- ld [wVolume], a
+ ld hl, wMusic
+ ld de, wMusicInitEnd - wMusic
+.clear
+ xor a
+ ld [hli], a
+ dec de
+ ld a, e
+ or d
+ jr nz, .clear
- pop af
- pop bc
- pop de
- pop hl
- ret
+ ld a, $77
+ ld [wVolume], a
+ pop af
+ pop bc
+ pop de
+ pop hl
+ ret
_UpdateSound:: ; 3a:4037
- xor a
- ; So, I'm being told I need to disassemble this...
- ; OH HELL NO
+; Called once per frame
+ xor a
+ ld [wCurChannel], a
+ ld [wSoundOutput], a
+ ld bc, wChannel1
+
+.loop
+ ld hl, CHANNEL_FLAGS1
+ add hl, bc
+ bit SOUND_CHANNEL_ON, [hl]
+ jr z, .nextchannel
+
+ call UpdateChannel
+
+.nextchannel
+ ; Next channel
+ ld hl, CHANNEL_STRUCT_LENGTH
+ add hl, bc
+ ld c, l
+ ld b, h
+ ld a, [wCurChannel]
+ inc a
+ ld [wCurChannel], a
+ cp NUM_CHANNELS
+ jr nz, .loop
+
+ call Function_e82f0
+ ret
+
+UpdateChannel: ; 3a:4061
+ ; Get the note's duration
+ ld hl, CHANNEL_NOTE_DURATION
+ add hl, bc
+ ld a, [hl]
+
+ ; Check if this is the last frame
+ cp 1
+ jr z, .noteover
+ and a
+ jr z, .noteover
+
+ dec [hl]
+ jr .continue_sound_update
+
+.noteover
+ call DisablePitchWheel
+ call Function_e884f
+
+.continue_sound_update
+ call Function_e80b6
+ ret
+
+DisablePitchWheel: ; 3a:4061
+ ld hl, CHANNEL_FLAGS2
+ add hl, bc
+ res SOUND_PITCH_WHEEL, [hl]
+ ret
+
+Unreferenced_Function_e8081: ; 3a:4081
+ ld a, [wMapMusic]
+ bit 0, a
+ jr nz, .disable_music
+
+ bit 1, a
+ jr nz, .disable_sfx
+
+.fail
+ and a
+ ret
+
+.disable_music
+ call _DisableAudio
+ jr .done
+
+.disable_sfx
+ call IsChannelSFXOn
+ jr c, .fail
+
+ ; Clear the registers of the channel
+ call GetChannelRegisters
+ ld e, rNR20 - rNR10
+ xor a
+
+.clear_loop
+ ld [hli], a
+ dec e
+ jr nz, .clear_loop
+
+.done
+ scf
+ ret
+
+GetChannelRegisters: ; 3a:40a4
+ ld a, [wCurChannel]
+ ld e, a
+ ld d, $00
+ ld hl, .registers
+ add hl, de
+ ld l, [hl]
+ ld h, $ff ; HIGH(rNR10, rNR20, rNR30, rNR40)
+ ret
+
+.registers
+ db LOW(rNR10), LOW(rNR20), LOW(rNR30), LOW(rNR40)
+
+Function_e80b6: ; 3a:40b6
+ ld hl, CHANNEL_DUTY_CYCLE
+ add hl, bc
+ ld a, [hl]
+ ld [wCurTrackDuty], a
+
+ ld hl, CHANNEL_INTENSITY
+ add hl, bc
+ ld a, [hl]
+ ld [wCurTrackIntensity], a
+
+ ld hl, CHANNEL_FREQUENCY
+ add hl, bc
+ ld a, [hli]
+ ld [wCurTrackFrequency], a
+ ld a, [hl]
+ ld [wCurTrackFrequency + 1], a
+ ld a, $3f
+ ld [wc195], a
+ call Function_e85d8
+ call Function_e87f9
+ call Function_e8839
+ call IsChannelSFXOn
+ jr nc, .end
+
+ call Function_e80fa
+ ld hl, CHANNEL_TRACKS
+ add hl, bc
+ ld a, [wSoundOutput]
+ or [hl]
+ ld [wSoundOutput], a
+
+.end
+ ld hl, CHANNEL_NOTE_FLAGS
+ add hl, bc
+ xor a
+ ld [hl], a
+ ret
+
+Function_e80fa: ; 3a:40fa
+ ld hl, .jumptable
+ ld a, [wCurChannel]
+ maskbits NUM_CHANNELS
+ add a
+ ld e, a
+ ld d, 0
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.jumptable
+ ; TODO
+
+SECTION "IsChannelSFXOn", ROMX[$42bd], BANK[$3a]
+IsChannelSFXOn: ; 3a:42bd
+ ; If it's not a valid channel, return
+ ld a, [wCurChannel]
+ cp NUM_MUSIC_CHANS
+ jr nc, .off
+
+ ; Check if the corresponding SFX channel is on
+ ld hl, CHANNEL_STRUCT_LENGTH * NUM_MUSIC_CHANS + CHANNEL_FLAGS1
+ add hl, bc
+ bit SOUND_CHANNEL_ON, [hl]
+ jr z, .off
+
+ and a
+ ret
+
+.off
+ scf
+ ret
+
+IsAnySFXOn: ; 3a:42d0
+ ld hl, wChannel5Flags1
+ bit SOUND_CHANNEL_ON, [hl]
+ jr nz, .on
+ ld hl, wChannel6Flags1
+ bit SOUND_CHANNEL_ON, [hl]
+ jr nz, .on
+ ld hl, wChannel7Flags1
+ bit SOUND_CHANNEL_ON, [hl]
+ jr nz, .on
+ ld hl, wChannel8Flags1
+ bit SOUND_CHANNEL_ON, [hl]
+ jr nz, .on
+
+ and a
+ ret
+
+.on
+ scf
+ ret
+
+SECTION "Function_e82f0", ROMX[$42f0], BANK[$3a]
+Function_e82f0: ; 3a:42f0
+ call Function_e8352
+ call Function_e8307
+ call FadeMusic
+ call Function_e841d
+ ld a, [wVolume]
+ ld [rNR50], a
+ ld a, [wSoundOutput]
+ ld [rNR51], a
+ ret
+
+SECTION "FadeMusic", ROMX[$43ce], BANK[$3a]
+FadeMusic: ; 3a:43ce
+; Fade music if applicable
+; usage:
+; write to wMusicFade
+; song fades out at the given rate
+; load song id in wMusicFadeID
+; fade new song in
+; notes:
+; max # frames per volume level is $7f
+
+ ; Exit early if not fading
+ ld a, [wMusicFade]
+ and a
+ ret z
+
+ ; If it doesn't have a count, assign it
+ ld a, [wMusicFadeCount]
+ and a
+ jr z, .update
+
+ ; Count down
+ dec a
+ ld [wMusicFadeCount], a
+ ret
+
+.update
+ ld a, [wMusicFade]
+ ld d, a
+
+ ; Get new count
+ and $7f
+ ld [wMusicFadeCount], a
+
+ ; Get SO1 volume
+ ld a, [wVolume]
+ and VOLUME_SO1_LEVEL
+
+ ; Which way are we fading?
+ bit MUSIC_FADE_IN_F, d
+ jr nz, .fadein
+
+ ; Decrement volume
+ and a
+ jr z, .novolume
+ dec a
+ jr .updatevolume
+
+.novolume
+ ; Fade in new song
+ ld a, [wMusicFadeID]
+ ld e, a
+ ld a, [wMusicFadeID + 1]
+ ld d, a
+ push bc
+ call _PlayMusic
+ pop bc
+ ld hl, wMusicFade
+ set 7, [hl]
+ ret
- ; ... TODO :/
+.fadein
+ ; Increment volume
+ cp MAX_VOLUME & $f
+ jr nc, .maxvolume
+ inc a
+ jr .updatevolume
+.maxvolume
+ ; Clear wMusicFade
+ xor a
+ ld [wMusicFade], a
+ ret
+.updatevolume
+ ; Set the current volume for both speakers
+ ld d, a
+ swap a
+ or d
+ ld [wVolume], a
+ ret
SECTION "Audio engine, part 2", ROMX[$4CEE],BANK[$3A] ; TODO: disassemble what's above (gulp) and remove this
SetGlobalTempo: ; 3a:4cee
- push bc
- ld a, [wCurChannel]
- cp CHAN5
- jr nc, .sfxchannels
- ld bc, wChannel1
- call Tempo
- ld bc, wChannel2
- call Tempo
- ld bc, wChannel3
- call Tempo
- ld bc, wChannel4
- call Tempo
- jr .end
+ push bc
+ ld a, [wCurChannel]
+ cp CHAN5
+ jr nc, .sfxchannels
+ ld bc, wChannel1
+ call Tempo
+ ld bc, wChannel2
+ call Tempo
+ ld bc, wChannel3
+ call Tempo
+ ld bc, wChannel4
+ call Tempo
+ jr .end
.sfxchannels
- ld bc, wChannel5
- call Tempo
- ld bc, wChannel6
- call Tempo
- ld bc, wChannel7
- call Tempo
- ld bc, wChannel8
- call Tempo
+ ld bc, wChannel5
+ call Tempo
+ ld bc, wChannel6
+ call Tempo
+ ld bc, wChannel7
+ call Tempo
+ ld bc, wChannel8
+ call Tempo
.end
- pop bc
- ret
+ pop bc
+ ret
Tempo: ; 3a:4d2a
- ld hl, wChannel1Tempo - wChannel1
- add hl, bc
- ld [hl], e
- inc hl
- ld [hl], d
- xor a
- ld hl, wChannel1Field16 - wChannel1
- add hl, bc
- ld [hl], a
- ret
+ ld hl, CHANNEL_TEMPO
+ add hl, bc
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ xor a
+ ld hl, CHANNEL_FIELD16
+ add hl, bc
+ ld [hl], a
+ ret
StartChannel: ; 3a:4d38
- call SetLRTracks
- ld hl, wChannel1Flags - wChannel1
- add hl, bc
- set SOUND_CHANNEL_ON, [hl]
- ret
+ call SetLRTracks
+ ld hl, CHANNEL_FLAGS1
+ add hl, bc
+ set SOUND_CHANNEL_ON, [hl]
+ ret
StopChannel: ; 3a:4d42
- ld hl, wChannel1Flags - wChannel1
- add hl, bc
- res SOUND_CHANNEL_ON, [hl]
- ld hl, wChannel1MusicID - wChannel1
- add hl, bc
- xor a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ret
+ ld hl, CHANNEL_FLAGS1
+ add hl, bc
+ res SOUND_CHANNEL_ON, [hl]
+ ld hl, CHANNEL_MUSIC_ID
+ add hl, bc
+ xor a
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ret
SetLRTracks: ; 3a:4d51
- push de
- ld a, [wCurChannel]
- maskbits NUM_MUSIC_CHANS
- ld e, a
- ld d, 0
- ld hl, $52B3 ; FIXME
- add hl, de
- ld a, [hl]
- ld hl, wChannel1Tracks - wChannel1
- add hl, bc
- ld [hl], a
- pop de
- ret
+ push de
+ ld a, [wCurChannel]
+ maskbits NUM_MUSIC_CHANS
+ ld e, a
+ ld d, 0
+ ld hl, $52B3 ; FIXME
+ add hl, de
+ ld a, [hl]
+ ld hl, CHANNEL_TRACKS
+ add hl, bc
+ ld [hl], a
+ pop de
+ ret
_PlayMusic:: ; 3a:4d66
- ld hl, wMusicID
- ld [hl], e
- inc hl
- ld [hl], d
- ld hl, Music
- add hl, de
- add hl, de
- add hl, de
- ld a, [hli]
- ld [wMusicBank], a
- ld e, [hl]
- inc hl
- ld d, [hl]
- call LoadMusicByte
- rlca
- rlca
- maskbits NUM_MUSIC_CHANS
- inc a
+ ld hl, wMusicID
+ ld [hl], e
+ inc hl
+ ld [hl], d
+ ld hl, Music
+ add hl, de
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld [wMusicBank], a
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ call LoadMusicByte
+ rlca
+ rlca
+ maskbits NUM_MUSIC_CHANS
+ inc a
.loop
- push af
- call LoadChannel
- call StartChannel
- pop af
- dec a
- jr nz, .loop
- xor a
- ; TODO
+ push af
+ call LoadChannel
+ call StartChannel
+ pop af
+ dec a
+ jr nz, .loop
+ xor a
+ ; TODO
SECTION "Song Header Pointers", ROMX[$52C7], BANK[$3A]
INCLUDE "audio/song_header_pointers.inc"