diff options
author | pfero <ohpee@loves.dicksinhisan.us> | 2018-06-04 03:35:28 +0200 |
---|---|---|
committer | pfero <ohpee@loves.dicksinhisan.us> | 2018-06-04 03:35:28 +0200 |
commit | 1bd0b22baf383dc171e5ce3c708746ba9aff86d6 (patch) | |
tree | 0ff0a58c153df11108d2055b00e81256cb20a7dc | |
parent | 9bfd7f3cbe0aae80bab93ed715c8c88cfa7241c1 (diff) |
Small dent into the audio engine
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | audio/engine.asm | 548 | ||||
-rw-r--r-- | constants/audio_constants.asm | 100 | ||||
-rw-r--r-- | home/audio.asm | 2 | ||||
-rw-r--r-- | macros/wram.asm | 6 | ||||
-rw-r--r-- | shim.sym | 7 | ||||
-rw-r--r-- | wram.asm | 43 |
7 files changed, 530 insertions, 177 deletions
@@ -22,6 +22,7 @@ shim.asm *.exe tools/scan_includes tools/pkmncompress +tools/make_shim tools/gfx *.pyc build/ 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" diff --git a/constants/audio_constants.asm b/constants/audio_constants.asm index 8d25540..b9e8594 100644 --- a/constants/audio_constants.asm +++ b/constants/audio_constants.asm @@ -12,33 +12,87 @@ NUM_NOISE_CHANS EQU const_value const CHAN8 NUM_CHANNELS EQU const_value +; channel_struct members (see macros/wram.asm) +CHANNEL_MUSIC_ID EQUS "(wChannel1MusicID - wChannel1)" +CHANNEL_MUSIC_BANK EQUS "(wChannelMusicBank - wChannel1)" +CHANNEL_FLAGS1 EQUS "(wChannel1Flags1 - wChannel1)" +CHANNEL_FLAGS2 EQUS "(wChannel1Flags2 - wChannel1)" +CHANNEL_FLAGS3 EQUS "(wChannel1Flags3 - wChannel1)" +CHANNEL_MUSIC_ADDRESS EQUS "(wChannel1MusicAddress - wChannel1)" +CHANNEL_LAST_MUSIC_ADDRESS EQUS "(wChannel1LastMusicAddress - wChannel1)" +CHANNEL_NOTE_FLAGS EQUS "(wChannel1NoteFlags - wChannel1)" +CHANNEL_CONDITION EQUS "(wChannel1Condition - wChannel1)" +CHANNEL_DUTY_CYCLE EQUS "(wChannel1DutyCycle - wChannel1)" +CHANNEL_INTENSITY EQUS "(wChannel1Intensity - wChannel1)" +CHANNEL_FREQUENCY EQUS "(wChannel1Frequency - wChannel1)" +CHANNEL_PITCH EQUS "(wChannel1Pitch - wChannel1)" +CHANNEL_OCTAVE EQUS "(wChannelOctave - wChannel1)" +CHANNEL_PITCH_OFFSET EQUS "(wChannelPitchOffset - wChannel1)" +CHANNEL_NOTE_DURATION EQUS "(wChannel1NoteDuration - wChannel1)" +CHANNEL_FIELD16 EQUS "(wChannel1Field16 - wChannel1)" +CHANNEL_LOOP_COUNT EQUS "(wChannel1LoopCount - wChannel1)" +CHANNEL_TEMPO EQUS "(wChannel1Tempo - wChannel1)" +CHANNEL_TRACKS EQUS "(wChannel1Tracks - wChannel1)" +CHANNEL_SFX_DUTY_LOOP EQUS "(wChannel1SFXDutyLoop - wChannel1)" +CHANNEL_VIBRATO_DELAY_COUNT EQUS "(wChannel1VibratoDelayCount - wChannel1)" +CHANNEL_VIBRATO_DELAY EQUS "(wChannel1VibratoDelay - wChannel1)" +CHANNEL_VIBRATO_EXTENT EQUS "(wChannel1VibratoExtent - wChannel1)" +CHANNEL_VIBRATO_RATE EQUS "(wChannel1VibratoRate - wChannel1)" +CHANNEL_PITCH_WHEEL_TARGET EQUS "(wChannel1PitchWheelTarget - wChannel1)" +CHANNEL_PITCH_WHEEL_AMOUNT EQUS "(wChannel1PitchWheelAmount - wChannel1)" +CHANNEL_PITCH_WHEEL_AMOUNT_FRACTION EQUS "(wChannel1PitchWheelAmountFraction - wChannel1)" +CHANNEL_FIELD25 EQUS "(wChannel1Field25 - wChannel1)" +CHANNEL_CRY_PITCH EQUS "(wChannel1CryPitch - wChannel1)" +CHANNEL_FIELD29 EQUS "(wChannel1Field29 - wChannel1)" +CHANNEL_FIELD2A EQUS "(wChannel1Field2a - wChannel1)" +CHANNEL_FIELD2C EQUS "(wChannel1Field2c - wChannel1)" +CHANNEL_NOTE_LENGTH EQUS "(wChannel1NoteLength - wChannel1)" +CHANNEL_FIELD2E EQUS "(wChannel1Field2e - wChannel1)" +CHANNEL_FIELD2F EQUS "(wChannel1Field2f - wChannel1)" +CHANNEL_FIELD30 EQUS "(wChannel1Field30 - wChannel1)" +CHANNEL_STRUCT_LENGTH EQUS "(wChannel2 - wChannel1)" + ; Flags1 -SOUND_CHANNEL_ON EQU 0 -SOUND_SUBROUTINE EQU 1 -SOUND_LOOPING EQU 2 -SOUND_SFX EQU 3 -SOUND_NOISE EQU 4 -SOUND_REST EQU 5 + const_def + const SOUND_CHANNEL_ON ; 0 + const SOUND_SUBROUTINE ; 1 + const SOUND_LOOPING ; 2 + const SOUND_SFX ; 3 + const SOUND_NOISE ; 4 + const SOUND_REST ; 5 ; Flags2 - -SOUND_VIBRATO EQU 0 -SOUND_PITCH_WHEEL EQU 1 -SOUND_DUTY EQU 2 -SOUND_UNKN_0B EQU 3 -SOUND_CRY_PITCH EQU 4 -SOUND_UNKN_0D EQU 5 -SOUND_UNKN_0E EQU 6 -SOUND_UNKN_0F EQU 7 + const_def + const SOUND_VIBRATO ; 0 + const SOUND_PITCH_WHEEL ; 1 + const SOUND_DUTY ; 2 + const SOUND_UNKN_0B ; 3 + const SOUND_CRY_PITCH ; 4 + const SOUND_UNKN_0D ; 5 + const SOUND_UNKN_0E ; 6 + const SOUND_UNKN_0F ; 7 ; Flags3 -SOUND_VIBRATO_DIR EQU 0 -SOUND_PITCH_WHEEL_DIR EQU 1 + const_def + const SOUND_VIBRATO_DIR ; 0 + const SOUND_PITCH_WHEEL_DIR ; 1 ; NoteFlags -NOTE_UNKN_0 EQU 0 -NOTE_UNKN_1 EQU 1 -NOTE_UNKN_3 EQU 3 -NOTE_UNKN_4 EQU 4 -NOTE_REST EQU 5 -NOTE_UNKN_6 EQU 6 + const_def + const NOTE_DUTY_OVERRIDE ; 0 + const NOTE_FREQ_OVERRIDE ; 1 + const NOTE_UNUSED ; 2 + const NOTE_UNKN_3 ; 3 + const NOTE_NOISE_SAMPLING ; 4 + const NOTE_REST ; 5 + const NOTE_VIBRATO_OVERRIDE ; 6 + +; wVolume +VOLUME_SO1_F EQU 3 +VOLUME_SO2_F EQU 7 +VOLUME_SO1_LEVEL EQU %00000111 +VOLUME_SO2_LEVEL EQU %01110000 +MAX_VOLUME EQU $77 + +; wMusicFade +MUSIC_FADE_IN_F EQU 7 diff --git a/home/audio.asm b/home/audio.asm index bf3a6c5..03a0990 100644 --- a/home/audio.asm +++ b/home/audio.asm @@ -109,7 +109,7 @@ endr ld [MBC3RomBank], a ; Unsafe ldh [hROMBank], a call _PlayCryHeader - + pop af ld [MBC3RomBank], a ; Unsafe ldh [hROMBank], a diff --git a/macros/wram.asm b/macros/wram.asm index dd9b76b..c598245 100644 --- a/macros/wram.asm +++ b/macros/wram.asm @@ -119,7 +119,7 @@ channel_struct: MACRO ; Addreses are Channel1 (c101). \1MusicID:: dw \1MusicBank:: db -\1Flags:: db ; 0:on/off 1:subroutine 3:sfx 4:noise 5:rest +\1Flags1:: db ; 0:on/off 1:subroutine 3:sfx 4:noise 5:rest \1Flags2:: db ; 0:vibrato on/off 2:duty 4:cry pitch \1Flags3:: db ; 0:vibrato up/down \1MusicAddress:: dw @@ -129,9 +129,7 @@ channel_struct: MACRO \1Condition:: db ; conditional jumps \1DutyCycle:: db ; bits 6-7 (0:12.5% 1:25% 2:50% 3:75%) \1Intensity:: db ; hi:pressure lo:velocity -\1Frequency:: ; 11 bits -\1FrequencyLo:: db -\1FrequencyHi:: db +\1Frequency:: dw ; 11 bits \1Pitch:: db ; 0:rest 1-c:note \1Octave:: db ; 7-0 (0 is highest) \1StartingOctave:: db ; raises existing octaves (to repeat phrases) @@ -150,6 +150,13 @@ 33:4000 Function_cc000 33:4000 Function_cc000_2 33:4001 Function_cc001 +3A:4307 Function_e8307 +3A:4352 Function_e8352 +3A:441D Function_e841d +3A:45D8 Function_e85d8 +3A:47F9 Function_e87f9 +3A:4839 Function_e8839 +3A:484F Function_e884f 3A:4D9D _PlayCryHeader 3A:4E22 _PlaySFX 3A:4F11 LoadChannel @@ -17,36 +17,43 @@ wChannel6:: channel_struct wChannel6 ; c0fa wChannel7:: channel_struct wChannel7 ; c12c wChannel8:: channel_struct wChannel8 ; c15e - ds 8 ; TODO + ds 1 ; c190 -wCurChannel:: ; c198 - db +wCurTrackDuty:: db ; c191 +wCurTrackIntensity:: db ; c192 +wCurTrackFrequency:: dw ; c193 +wc195:: db ; c195 -wVolume:: ; c199 - db + ds 2 ; TODO - ds 2 ; TODO +wCurChannel:: db ; c198 +wVolume:: db ; c199 +wSoundOutput:: db ; c19a -wMusicID:: ; c19c - dw + ds 1 ; TODO -wMusicBank:: ; c19e - db +wMusicID:: dw ; c19c +wMusicBank:: db ; c19e - ds 14 ; TODO + ds 6 ; TODO -wMapMusic:: ; c1ad - db +wMusicFade:: ; c1a5 +; fades volume over x frames +; bit 7: fade in/out +; bit 0-6: number of frames for each volume level +; $00 = none (default) + db +wMusicFadeCount:: db ; c1a6 +wMusicFadeID:: dw ; c1a7 -wCryPitch:: ; c1ae - dw + ds 4 ; TODO -wCryLength:: ; c1b0 - dw +wMapMusic:: db ; c1ad +wCryPitch:: dw ; c1ae +wCryLength:: dw ; c1b0 ds 10 ; TODO - ; either wChannelsEnd or wMusicEnd, unsure wMusicInitEnd:: ; c1bc |