diff options
author | IIMarckus <iimarckus@gmail.com> | 2019-08-16 01:03:03 -0600 |
---|---|---|
committer | IIMarckus <iimarckus@gmail.com> | 2019-08-16 01:03:03 -0600 |
commit | 2176239aa565126b528facc9041ed3b58eaade90 (patch) | |
tree | 4589377cff104542abb2ee309496b5e4786eb59f | |
parent | 901e6f25deda73fa7053942d7d094108a73e2bea (diff) |
Incorporate the rest of the audio engine.
-rw-r--r-- | audio/cry_pointers.asm | 69 | ||||
-rw-r--r-- | audio/drumkits.asm | 261 | ||||
-rw-r--r-- | audio/engine.asm | 2850 | ||||
-rwxr-xr-x | audio/music_pointers.asm | 189 | ||||
-rw-r--r-- | audio/notes.asm | 26 | ||||
-rw-r--r-- | audio/sfx_pointers.asm | 190 | ||||
-rw-r--r-- | audio/wave_samples.asm | 13 | ||||
-rwxr-xr-x | constants/audio_constants.asm | 163 | ||||
-rw-r--r-- | data/trainers/encounter_music.asm | 75 | ||||
-rwxr-xr-x | engine/events/overworld.asm | 8 | ||||
-rwxr-xr-x | engine/main_menu.asm | 2 | ||||
-rwxr-xr-x | engine/overworld/player_movement.asm | 10 | ||||
-rwxr-xr-x | engine/specials.asm | 2 | ||||
-rwxr-xr-x | engine/variables.asm | 2 | ||||
-rw-r--r-- | home/audio.asm | 58 | ||||
-rw-r--r-- | home/cry.asm | 9 | ||||
-rw-r--r-- | home/init.asm | 4 | ||||
-rw-r--r-- | home/text.asm | 2 | ||||
-rw-r--r-- | home/vblank.asm | 24 | ||||
-rwxr-xr-x | items/item_effects.asm | 8 | ||||
-rw-r--r-- | macros.asm | 51 | ||||
-rw-r--r-- | macros/code.asm | 106 | ||||
-rwxr-xr-x | macros/wram.asm | 24 | ||||
-rw-r--r-- | main.asm | 67 | ||||
-rw-r--r-- | wram.asm | 6 |
25 files changed, 3930 insertions, 289 deletions
diff --git a/audio/cry_pointers.asm b/audio/cry_pointers.asm new file mode 100644 index 00000000..ec6b17e0 --- /dev/null +++ b/audio/cry_pointers.asm @@ -0,0 +1,69 @@ +Cries: + dba Cry_Nidoran_M + dba Cry_Nidoran_F + dba Cry_Slowpoke + dba Cry_Kangaskhan + dba Cry_Charmander + dba Cry_Grimer + dba Cry_Voltorb + dba Cry_Muk + dba Cry_Oddish + dba Cry_Raichu + dba Cry_Nidoqueen + dba Cry_Diglett + dba Cry_Seel + dba Cry_Drowzee + dba Cry_Pidgey + dba Cry_Bulbasaur + dba Cry_Spearow + dba Cry_Rhydon + dba Cry_Golem + dba Cry_Blastoise + dba Cry_Pidgeotto + dba Cry_Weedle + dba Cry_Caterpie + dba Cry_Ekans + dba Cry_Fearow + dba Cry_Clefairy + dba Cry_Venonat + dba Cry_Lapras + dba Cry_Metapod + dba Cry_Squirtle + dba Cry_Paras + dba Cry_Growlithe + dba Cry_Krabby + dba Cry_Psyduck + dba Cry_Rattata + dba Cry_Vileplume + dba Cry_Vulpix + dba Cry_Weepinbell + dba Cry_Marill + dba Cry_Spinarak + dba Cry_Togepi + dba Cry_Girafarig + dba Cry_Raikou + dba Cry_Mareep + dba Cry_Togetic + dba Cry_Hoothoot + dba Cry_Sentret + dba Cry_Slowking + dba Cry_Cyndaquil + dba Cry_Chikorita + dba Cry_Totodile + dba Cry_Gligar + dba Cry_Cleffa + dba Cry_Slugma + dba Cry_Ledyba + dba Cry_Entei + dba Cry_Wooper + dba Cry_Mantine + dba Cry_Typhlosion + dba Cry_Natu + dba Cry_Teddiursa + dba Cry_Sunflora + dba Cry_Ampharos + dba Cry_Magcargo + dba Cry_Pichu + dba Cry_Aipom + dba Cry_Dunsparce + dba Cry_Donphan diff --git a/audio/drumkits.asm b/audio/drumkits.asm new file mode 100644 index 00000000..a4fa4109 --- /dev/null +++ b/audio/drumkits.asm @@ -0,0 +1,261 @@ +Drumkits: + dw Drumkit0 + dw Drumkit1 + dw Drumkit2 + dw Drumkit3 + dw Drumkit4 + dw Drumkit5 + +Drumkit0: + dw Drum00 ; rest + dw Snare1 ; c + dw Snare2 ; c# + dw Snare3 ; d + dw Snare4 ; d# + dw Drum05 ; e + dw Triangle1 ; f + dw Triangle2 ; f# + dw HiHat1 ; g + dw Snare5 ; g# + dw Snare6 ; a + dw Snare7 ; a# + dw HiHat2 ; b +Drumkit1: + dw Drum00 + dw HiHat1 + dw Snare5 + dw Snare6 + dw Snare7 + dw HiHat2 + dw HiHat3 + dw Snare8 + dw Triangle3 + dw Triangle4 + dw Snare9 + dw Snare10 + dw Snare11 +Drumkit2: + dw Drum00 + dw Snare1 + dw Snare9 + dw Snare10 + dw Snare11 + dw Drum05 + dw Triangle1 + dw Triangle2 + dw HiHat1 + dw Snare5 + dw Snare6 + dw Snare7 + dw HiHat2 +Drumkit3: + dw Drum21 + dw Snare12 + dw Snare13 + dw Snare14 + dw Kick1 + dw Triangle5 + dw Drum20 + dw Drum27 + dw Drum28 + dw Drum29 + dw Drum21 + dw Kick2 + dw Crash2 +Drumkit4: + dw Drum21 + dw Drum20 + dw Snare13 + dw Snare14 + dw Kick1 + dw Drum33 + dw Triangle5 + dw Drum35 + dw Drum31 + dw Drum32 + dw Drum36 + dw Kick2 + dw Crash1 +Drumkit5: + dw Drum00 + dw Snare9 + dw Snare10 + dw Snare11 + dw Drum27 + dw Drum28 + dw Drum29 + dw Drum05 + dw Triangle1 + dw Crash1 + dw Snare14 + dw Snare13 + dw Kick2 + +Drum00: +; unused + noise C#, 1, $11, $00 + endchannel + +Snare1: + noise C#, 1, $c1, $33 + endchannel + +Snare2: + noise C#, 1, $b1, $33 + endchannel + +Snare3: + noise C#, 1, $a1, $33 + endchannel + +Snare4: + noise C#, 1, $81, $33 + endchannel + +Drum05: + noise C#, 8, $84, $37 + noise C#, 7, $84, $36 + noise C#, 6, $83, $35 + noise C#, 5, $83, $34 + noise C#, 4, $82, $33 + noise C#, 3, $81, $32 + endchannel + +Triangle1: + noise C#, 1, $51, $2a + endchannel + +Triangle2: + noise C#, 2, $41, $2b + noise C#, 1, $61, $2a + endchannel + +HiHat1: + noise C#, 1, $81, $10 + endchannel + +Snare5: + noise C#, 1, $82, $23 + endchannel + +Snare6: + noise C#, 1, $82, $25 + endchannel + +Snare7: + noise C#, 1, $82, $26 + endchannel + +HiHat2: + noise C#, 1, $a1, $10 + endchannel + +HiHat3: + noise C#, 1, $a2, $11 + endchannel + +Snare8: + noise C#, 1, $a2, $50 + endchannel + +Triangle3: + noise C#, 1, $a1, $18 + noise C#, 1, $31, $33 + endchannel + +Triangle4: + noise C#, 3, $91, $28 + noise C#, 1, $71, $18 + endchannel + +Snare9: + noise C#, 1, $91, $22 + endchannel + +Snare10: + noise C#, 1, $71, $22 + endchannel + +Snare11: + noise C#, 1, $61, $22 + endchannel + +Drum20: + noise C#, 1, $11, $11 + endchannel + +Drum21: + endchannel + +Snare12: + noise C#, 1, $91, $33 + endchannel + +Snare13: + noise C#, 1, $51, $32 + endchannel + +Snare14: + noise C#, 1, $81, $31 + endchannel + +Kick1: + noise C#, 1, $88, $6b + noise C#, 1, $71, $00 + endchannel + +Triangle5: + noise D_, 1, $91, $18 + endchannel + +Drum27: + noise C#, 8, $92, $10 + endchannel + +Drum28: + noise D_, 4, $91, $00 + noise D_, 4, $11, $00 + endchannel + +Drum29: + noise D_, 4, $91, $11 + noise D_, 4, $11, $00 + endchannel + +Crash1: + noise D_, 4, $88, $15 + noise C#, 1, $65, $12 + endchannel + +Drum31: + noise D_, 4, $51, $21 + noise D_, 4, $11, $11 + endchannel + +Drum32: + noise D_, 4, $51, $50 + noise D_, 4, $11, $11 + endchannel + +Drum33: + noise C#, 1, $a1, $31 + endchannel + +Crash2: + noise C#, 1, $84, $12 + endchannel + +Drum35: + noise D_, 4, $81, $00 + noise D_, 4, $11, $00 + endchannel + +Drum36: + noise D_, 4, $81, $21 + noise D_, 4, $11, $11 + endchannel + +Kick2: + noise C#, 1, $a8, $6b + noise C#, 1, $71, $00 + endchannel diff --git a/audio/engine.asm b/audio/engine.asm new file mode 100644 index 00000000..6b0fe1a6 --- /dev/null +++ b/audio/engine.asm @@ -0,0 +1,2850 @@ +; The entire sound engine. Uses section "audio" in WRAM. + +; Interfaces are in bank 0. + +; Notable functions: +; FadeMusic +; PlayStereoSFX + +_MapSetup_Sound_Off:: +; restart sound operation +; clear all relevant hardware registers & wram + push hl + push de + push bc + push af + call MusicOff + ld hl, rNR50 ; channel control registers + xor a + ld [hli], a ; rNR50 ; volume/vin + ld [hli], a ; rNR51 ; sfx channels + ld a, $80 ; all channels on + ld [hli], a ; ff26 ; music channels + + ld hl, rNR10 ; sound channel registers + ld e, NUM_MUSIC_CHANS +.clearsound +; sound channel 1 2 3 4 + xor a + ld [hli], a ; rNR10, rNR20, rNR30, rNR40 ; sweep = 0 + + ld [hli], a ; rNR11, rNR21, rNR31, rNR41 ; length/wavepattern = 0 + ld a, $8 + ld [hli], a ; rNR12, rNR22, rNR32, rNR42 ; envelope = 0 + xor a + ld [hli], a ; rNR13, rNR23, rNR33, rNR43 ; frequency lo = 0 + ld a, $80 + ld [hli], a ; rNR14, rNR24, rNR34, rNR44 ; restart sound (freq hi = 0) + dec e + jr nz, .clearsound + + ld hl, wChannels ; start of channel data + ld de, wChannelsEnd - wChannels ; length of area to clear (entire sound wram area) +.clearchannels + xor a + ld [hli], a + dec de + ld a, e + or d + jr nz, .clearchannels + ld a, MAX_VOLUME + ld [wVolume], a + call MusicOn + pop af + pop bc + pop de + pop hl + ret + +MusicFadeRestart: +; restart but keep the music id to fade in to + ld a, [wMusicFadeID + 1] + push af + ld a, [wMusicFadeID] + push af + call _MapSetup_Sound_Off + pop af + ld [wMusicFadeID], a + pop af + ld [wMusicFadeID + 1], a + ret + +MusicOn: + ld a, 1 + ld [wMusicPlaying], a + ret + +MusicOff: + xor a + ld [wMusicPlaying], a + ret + +_UpdateSound:: +; called once per frame + ; no use updating audio if it's not playing + ld a, [wMusicPlaying] + and a + ret z + ; start at ch1 + xor a + ld [wCurChannel], a ; just + ld [wSoundOutput], a ; off + ld bc, wChannel1 +.loop + ; is the channel active? + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_CHANNEL_ON, [hl] + jp z, .nextchannel + ; check time left in the current note + ld hl, CHANNEL_NOTE_DURATION + add hl, bc + ld a, [hl] + cp $2 ; 1 or 0? + jr c, .noteover + dec [hl] + jr .continue_sound_update + +.noteover + ; reset vibrato delay + ld hl, CHANNEL_VIBRATO_DELAY + add hl, bc + ld a, [hl] + ld hl, CHANNEL_VIBRATO_DELAY_COUNT + add hl, bc + ld [hl], a + ; turn vibrato off for now + ld hl, CHANNEL_FLAGS2 + add hl, bc + res SOUND_PITCH_WHEEL, [hl] + ; get next note + call ParseMusic +.continue_sound_update + call ApplyPitchWheel + ; duty cycle + ld hl, CHANNEL_DUTY_CYCLE + add hl, bc + ld a, [hli] + ld [wCurTrackDuty], a + ; intensity + ld a, [hli] + ld [wCurTrackIntensity], a + ; frequency + ld a, [hli] + ld [wCurTrackFrequency], a + ld a, [hl] + ld [wCurTrackFrequency + 1], a + ; vibrato, noise + call HandleTrackVibrato ; handle vibrato and other things + call HandleNoise + ; turn off music when playing sfx? + ld a, [wSFXPriority] + and a + jr z, .next + ; are we in a sfx channel right now? + ld a, [wCurChannel] + cp NUM_MUSIC_CHANS + jr nc, .next + ; are any sfx channels active? + ; if so, mute + ld hl, wChannel5Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .restnote + ld hl, wChannel6Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .restnote + ld hl, wChannel7Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .restnote + ld hl, wChannel8Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr z, .next +.restnote + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] ; Rest +.next + ; are we in a sfx channel right now? + ld a, [wCurChannel] + cp NUM_MUSIC_CHANS + jr nc, .sfx_channel + ld hl, CHANNEL_STRUCT_LENGTH * NUM_MUSIC_CHANS + CHANNEL_FLAGS1 + add hl, bc + bit SOUND_CHANNEL_ON, [hl] + jr nz, .sound_channel_on +.sfx_channel + call UpdateChannels + ld hl, CHANNEL_TRACKS + add hl, bc + ld a, [wSoundOutput] + or [hl] + ld [wSoundOutput], a +.sound_channel_on + ; clear note flags + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + xor a + ld [hl], a +.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 ; are we done? + jp nz, .loop ; do it all again + + call PlayDanger + ; fade music in/out + call FadeMusic + ; write volume to hardware register + ld a, [wVolume] + ldh [rNR50], a + ; write SO on/off to hardware register + ld a, [wSoundOutput] + ldh [rNR51], a + ret + +UpdateChannels: + ld hl, .ChannelFnPtrs + ld a, [wCurChannel] + and $7 + add a + ld e, a + ld d, 0 + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.ChannelFnPtrs: + dw .Channel1 + dw .Channel2 + dw .Channel3 + dw .Channel4 +; sfx ch ptrs are identical to music chs +; ..except 5 + dw .Channel5 + dw .Channel6 + dw .Channel7 + dw .Channel8 + +.Channel1: + ld a, [wLowHealthAlarm] + bit DANGER_ON_F, a + ret nz +.Channel5: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_UNKN_3, [hl] + jr z, .asm_e8159 + ; + ld a, [wSoundInput] + ldh [rNR10], a +.asm_e8159 + bit NOTE_REST, [hl] ; rest + jr nz, .ch1rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .asm_e81a2 + bit NOTE_FREQ_OVERRIDE, [hl] + jr nz, .frequency_override + bit NOTE_VIBRATO_OVERRIDE, [hl] + jr nz, .asm_e8184 + jr .check_duty_override + +.frequency_override + ld a, [wCurTrackFrequency] + ldh [rNR13], a + ld a, [wCurTrackFrequency + 1] + ldh [rNR14], a +.check_duty_override + bit NOTE_DUTY_OVERRIDE, [hl] + ret z + ld a, [wCurTrackDuty] + ld d, a + ldh a, [rNR11] + and $3f ; sound length + or d + ldh [rNR11], a + ret + +.asm_e8184 + ld a, [wCurTrackDuty] + ld d, a + ldh a, [rNR11] + and $3f ; sound length + or d + ldh [rNR11], a + ld a, [wCurTrackFrequency] + ldh [rNR13], a + ret + +.ch1rest + ldh a, [rNR52] + and %10001110 ; ch1 off + ldh [rNR52], a + ld hl, rNR10 + call ClearChannel + ret + +.asm_e81a2 + ld hl, wCurTrackDuty + ld a, $3f ; sound length + or [hl] + ldh [rNR11], a + ld a, [wCurTrackIntensity] + ldh [rNR12], a + ld a, [wCurTrackFrequency] + ldh [rNR13], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR14], a + ret + +.Channel2: +.Channel6: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_REST, [hl] ; rest + jr nz, .ch2rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .asm_e8204 + bit NOTE_VIBRATO_OVERRIDE, [hl] + jr nz, .asm_e81e6 + bit NOTE_DUTY_OVERRIDE, [hl] + ret z + ld a, [wCurTrackDuty] + ld d, a + ldh a, [rNR21] + and $3f ; sound length + or d + ldh [rNR21], a + ret + +.asm_e81db ; unused + ld a, [wCurTrackFrequency] + ldh [rNR23], a + ld a, [wCurTrackFrequency + 1] + ldh [rNR24], a + ret + +.asm_e81e6 + ld a, [wCurTrackDuty] + ld d, a + ldh a, [rNR21] + and $3f ; sound length + or d + ldh [rNR21], a + ld a, [wCurTrackFrequency] + ldh [rNR23], a + ret + +.ch2rest + ldh a, [rNR52] + and %10001101 ; ch2 off + ldh [rNR52], a + ld hl, rNR20 + call ClearChannel + ret + +.asm_e8204 + ld hl, wCurTrackDuty + ld a, $3f ; sound length + or [hl] + ldh [rNR21], a + ld a, [wCurTrackIntensity] + ldh [rNR22], a + ld a, [wCurTrackFrequency] + ldh [rNR23], a + ld a, [wCurTrackFrequency + 1] + or $80 ; initial (restart) + ldh [rNR24], a + ret + +.Channel3: +.Channel7: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_REST, [hl] ; rest + jr nz, .ch3rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .asm_e824d + bit NOTE_VIBRATO_OVERRIDE, [hl] + jr nz, .asm_e823a + ret + +.asm_e822f ; unused + ld a, [wCurTrackFrequency] + ldh [rNR33], a + ld a, [wCurTrackFrequency + 1] + ldh [rNR34], a + ret + +.asm_e823a + ld a, [wCurTrackFrequency] + ldh [rNR33], a + ret + +.ch3rest + ldh a, [rNR52] + and %10001011 ; ch3 off + ldh [rNR52], a + ld hl, rNR30 + call ClearChannel + ret + +.asm_e824d + ld a, $3f ; sound length + ldh [rNR31], a + xor a + ldh [rNR30], a + call .asm_e8268 + ld a, $80 + ldh [rNR30], a + ld a, [wCurTrackFrequency] + ldh [rNR33], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR34], a + ret + +.asm_e8268 + push hl + ld a, [wCurTrackIntensity] + and $f ; only 0-9 are valid + ld l, a + ld h, 0 + ; hl << 4 + ; each wavepattern is $f bytes long + ; so seeking is done in $10s +rept 4 + add hl, hl +endr + ld de, WaveSamples + add hl, de + ; load wavepattern into rWave_0-rWave_f + ld a, [hli] + ldh [rWave_0], a + ld a, [hli] + ldh [rWave_1], a + ld a, [hli] + ldh [rWave_2], a + ld a, [hli] + ldh [rWave_3], a + ld a, [hli] + ldh [rWave_4], a + ld a, [hli] + ldh [rWave_5], a + ld a, [hli] + ldh [rWave_6], a + ld a, [hli] + ldh [rWave_7], a + ld a, [hli] + ldh [rWave_8], a + ld a, [hli] + ldh [rWave_9], a + ld a, [hli] + ldh [rWave_a], a + ld a, [hli] + ldh [rWave_b], a + ld a, [hli] + ldh [rWave_c], a + ld a, [hli] + ldh [rWave_d], a + ld a, [hli] + ldh [rWave_e], a + ld a, [hli] + ldh [rWave_f], a + pop hl + ld a, [wCurTrackIntensity] + and $f0 + sla a + ldh [rNR32], a + ret + +.Channel4: +.Channel8: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_REST, [hl] ; rest + jr nz, .ch4rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .asm_e82d4 + ret + +.asm_e82c1 ; unused + ld a, [wCurTrackFrequency] + ldh [rNR43], a + ret + +.ch4rest + ldh a, [rNR52] + and %10000111 ; ch4 off + ldh [rNR52], a + ld hl, rNR40 + call ClearChannel + ret + +.asm_e82d4 + ld a, $3f ; sound length + ldh [rNR41], a + ld a, [wCurTrackIntensity] + ldh [rNR42], a + ld a, [wCurTrackFrequency] + ldh [rNR43], a + ld a, $80 + ldh [rNR44], a + ret + +_CheckSFX: +; return carry if any sfx channels are active + ld hl, wChannel5Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .sfxon + ld hl, wChannel6Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .sfxon + ld hl, wChannel7Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .sfxon + ld hl, wChannel8Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr nz, .sfxon + and a + ret + +.sfxon + scf + ret + +PlayDanger: + ld a, [wLowHealthAlarm] + bit DANGER_ON_F, a + ret z + + ; Don't do anything if SFX is being played + and $ff ^ (1 << DANGER_ON_F) + ld d, a + call _CheckSFX + jr c, .increment + + ; Play the high tone + and a + jr z, .begin + + ; Play the low tone + cp 16 + jr z, .halfway + + jr .increment + +.halfway + ld hl, DangerSoundLow + jr .applychannel + +.begin + ld hl, DangerSoundHigh + +.applychannel + xor a + ldh [rNR10], a + ld a, [hli] + ldh [rNR11], a + ld a, [hli] + ldh [rNR12], a + ld a, [hli] + ldh [rNR13], a + ld a, [hli] + ldh [rNR14], a + +.increment + ld a, d + inc a + cp 30 ; Ending frame + jr c, .noreset + xor a +.noreset + ; Make sure the danger sound is kept on + or 1 << DANGER_ON_F + ld [wLowHealthAlarm], a + + ; Enable channel 1 if it's off + ld a, [wSoundOutput] + and $11 + ret nz + ld a, [wSoundOutput] + or $11 + ld [wSoundOutput], a + ret + +DangerSoundHigh: + db $80 ; duty 50% + db $e2 ; volume 14, envelope decrease sweep 2 + db $50 ; frequency: $750 + db $87 ; restart sound + +DangerSoundLow: + db $80 ; duty 50% + db $e2 ; volume 14, envelope decrease sweep 2 + db $ee ; frequency: $6ee + db $86 ; restart sound + +FadeMusic: +; 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 $3f + + ; fading? + ld a, [wMusicFade] + and a + ret z + ; has the count ended? + 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 $3f + 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 + ; fading out + and a + jr z, .novolume + dec a + jr .updatevolume + +.novolume + ; make sure volume is off + xor a + ld [wVolume], a + ; did we just get on a bike? + ld a, [wPlayerState] + cp PLAYER_BIKE + jr z, .bicycle + push bc + ; restart sound + call MusicFadeRestart + ; get new song id + ld a, [wMusicFadeID] + and a + jr z, .quit ; this assumes there are fewer than 256 songs! + ld e, a + ld a, [wMusicFadeID + 1] + ld d, a + ; load new song + call _PlayMusic +.quit + ; cleanup + pop bc + ; stop fading + xor a + ld [wMusicFade], a + ret + +.bicycle + push bc + ; restart sound + call MusicFadeRestart + ; this turns the volume up + ; turn it back down + xor a + ld [wVolume], a + ; get new song id + ld a, [wMusicFadeID] + ld e, a + ld a, [wMusicFadeID + 1] + ld d, a + ; load new song + call _PlayMusic + pop bc + ; fade in + ld hl, wMusicFade + set MUSIC_FADE_IN_F, [hl] + ret + +.fadein + ; are we done? + cp MAX_VOLUME & $f + jr nc, .maxvolume + ; inc volume + inc a + jr .updatevolume + +.maxvolume + ; we're done + xor a + ld [wMusicFade], a + ret + +.updatevolume + ; hi = lo + ld d, a + swap a + or d + ld [wVolume], a + ret + +LoadNote: + ; wait for pitch wheel to finish + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_PITCH_WHEEL, [hl] + ret z + ; get note duration + ld hl, CHANNEL_NOTE_DURATION + add hl, bc + ld a, [hl] + ld hl, wCurNoteDuration + sub [hl] + jr nc, .ok + ld a, 1 +.ok + ld [hl], a + ; get frequency + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; get direction of pitch wheel + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, e + sub [hl] + ld e, a + ld a, d + sbc 0 + ld d, a + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + sub [hl] + jr nc, .greater_than + ld hl, CHANNEL_FLAGS3 + add hl, bc + set SOUND_PITCH_WHEEL_DIR, [hl] + ; get frequency + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; ???? + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, [hl] + sub e + ld e, a + ld a, d + sbc 0 + ld d, a + ; ???? + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld a, [hl] + sub d + ld d, a + jr .resume + +.greater_than + ld hl, CHANNEL_FLAGS3 + add hl, bc + res SOUND_PITCH_WHEEL_DIR, [hl] + ; get frequency + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; get distance from pitch wheel target + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, e + sub [hl] + ld e, a + ld a, d + sbc 0 + ld d, a + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + sub [hl] + ld d, a +.resume + ; de = x * [wCurNoteDuration] + y + ; x + 1 -> d + ; y -> a + push bc + ld hl, wCurNoteDuration + ld b, 0 ; quotient +.loop + inc b + ld a, e + sub [hl] + ld e, a + jr nc, .loop + ld a, d + and a + jr z, .quit + dec d + jr .loop + +.quit + ld a, e ; remainder + add [hl] + ld d, b ; quotient + pop bc + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT + add hl, bc + ld [hl], d ; quotient + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT_FRACTION + add hl, bc + ld [hl], a ; remainder + ld hl, CHANNEL_FIELD25 + add hl, bc + xor a + ld [hl], a + ret + +HandleTrackVibrato: +; handle duty, cry pitch, and vibrato + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_DUTY, [hl] ; duty + jr z, .next + ld hl, CHANNEL_SFX_DUTY_LOOP + add hl, bc + ld a, [hl] + rlca + rlca + ld [hl], a + and $c0 + ld [wCurTrackDuty], a + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_DUTY_OVERRIDE, [hl] +.next + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_CRY_PITCH, [hl] + jr z, .vibrato + ld hl, CHANNEL_CRY_PITCH + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, wCurTrackFrequency + ld a, [hli] + ld h, [hl] + ld l, a + add hl, de + ld e, l + ld d, h + ld hl, wCurTrackFrequency + ld [hl], e + inc hl + ld [hl], d +.vibrato + ; is vibrato on? + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_VIBRATO, [hl] ; vibrato + jr z, .quit + ; is vibrato active for this note yet? + ; is the delay over? + ld hl, CHANNEL_VIBRATO_DELAY_COUNT + add hl, bc + ld a, [hl] + and a + jr nz, .subexit + ; is the extent nonzero? + ld hl, CHANNEL_VIBRATO_EXTENT + add hl, bc + ld a, [hl] + and a + jr z, .quit + ; save it for later + ld d, a + ; is it time to toggle vibrato up/down? + ld hl, CHANNEL_VIBRATO_RATE + add hl, bc + ld a, [hl] + and $f ; count + jr z, .toggle +.subexit + dec [hl] + jr .quit + +.toggle + ; refresh count + ld a, [hl] + swap [hl] + or [hl] + ld [hl], a + ; ???? + ld a, [wCurTrackFrequency] + ld e, a + ; toggle vibrato up/down + ld hl, CHANNEL_FLAGS3 + add hl, bc + bit SOUND_VIBRATO_DIR, [hl] ; vibrato up/down + jr z, .down +; up + ; vibrato down + res SOUND_VIBRATO_DIR, [hl] + ; get the delay + ld a, d + and $f ; lo + ; + ld d, a + ld a, e + sub d + jr nc, .no_carry + ld a, 0 + jr .no_carry + +.down + ; vibrato up + set SOUND_VIBRATO_DIR, [hl] + ; get the delay + ld a, d + and $f0 ; hi + swap a ; move it to lo + ; + add e + jr nc, .no_carry + ld a, $ff +.no_carry + ld [wCurTrackFrequency], a + ; + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_VIBRATO_OVERRIDE, [hl] +.quit + ret + +ApplyPitchWheel: + ; quit if pitch wheel inactive + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_PITCH_WHEEL, [hl] + ret z + ; de = Frequency + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; check whether pitch wheel is going up or down + ld hl, CHANNEL_FLAGS3 + add hl, bc + bit SOUND_PITCH_WHEEL_DIR, [hl] + jr z, .decreasing + ; frequency += [Channel*PitchWheelAmount] + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT + add hl, bc + ld l, [hl] + ld h, 0 + add hl, de + ld d, h + ld e, l + ; [Channel*Field25] += [Channel*PitchWheelAmountFraction] + ; if rollover: Frequency += 1 + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT_FRACTION + add hl, bc + ld a, [hl] + ld hl, CHANNEL_FIELD25 + add hl, bc + add [hl] + ld [hl], a + ld a, 0 + adc e + ld e, a + ld a, 0 + adc d + ld d, a + ; Compare the dw at [Channel*PitchWheelTarget] to de. + ; If frequency is greater, we're finished. + ; Otherwise, load the frequency and set two flags. + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld a, [hl] + cp d + jp c, .finished_pitch_wheel + jr nz, .continue_pitch_wheel + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, [hl] + cp e + jp c, .finished_pitch_wheel + jr .continue_pitch_wheel + +.decreasing + ; frequency -= [Channel*PitchWheelAmount] + ld a, e + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT + add hl, bc + ld e, [hl] + sub e + ld e, a + ld a, d + sbc 0 + ld d, a + ; [Channel*Field25] *= 2 + ; if rollover: Frequency -= 1 + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT_FRACTION + add hl, bc + ld a, [hl] + add a + ld [hl], a + ld a, e + sbc 0 + ld e, a + ld a, d + sbc 0 + ld d, a + ; Compare the dw at [Channel*PitchWheelTarget] to de. + ; If frequency is lower, we're finished. + ; Otherwise, load the frequency and set two flags. + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld a, d + cp [hl] + jr c, .finished_pitch_wheel + jr nz, .continue_pitch_wheel + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, e + cp [hl] + jr nc, .continue_pitch_wheel +.finished_pitch_wheel + ld hl, CHANNEL_FLAGS2 + add hl, bc + res SOUND_PITCH_WHEEL, [hl] + ld hl, CHANNEL_FLAGS3 + add hl, bc + res SOUND_PITCH_WHEEL_DIR, [hl] + ret + +.continue_pitch_wheel + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_FREQ_OVERRIDE, [hl] + set NOTE_DUTY_OVERRIDE, [hl] + ret + +HandleNoise: + ; is noise sampling on? + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_NOISE, [hl] ; noise sampling + ret z + ; are we in a sfx channel? + ld a, [wCurChannel] + bit NOISE_CHAN_F, a + jr nz, .next + ; is ch8 on? (noise) + ld hl, wChannel8Flags1 + bit SOUND_CHANNEL_ON, [hl] ; on? + jr z, .next + ; is ch8 playing noise? + bit SOUND_NOISE, [hl] + ret nz ; quit if so + ; +.next + ld a, [wNoiseSampleDelay] + and a + jr z, ReadNoiseSample + dec a + ld [wNoiseSampleDelay], a + ret + +ReadNoiseSample: +; sample struct: +; [wx] [yy] [zz] +; w: ? either 2 or 3 +; x: duration +; zz: intensity +; yy: frequency + + ; de = [wNoiseSampleAddress] + ld hl, wNoiseSampleAddress + ld e, [hl] + inc hl + ld d, [hl] + + ; is it empty? + ld a, e + or d + jr z, .quit + + ld a, [de] + inc de + + cp endchannel_cmd + jr z, .quit + + and $f + inc a + ld [wNoiseSampleDelay], a + ld a, [de] + inc de + ld [wCurTrackIntensity], a + ld a, [de] + inc de + ld [wCurTrackFrequency], a + xor a + ld [wCurTrackFrequency + 1], a + + ld hl, wNoiseSampleAddress + ld [hl], e + inc hl + ld [hl], d + + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_NOISE_SAMPLING, [hl] + ret + +.quit + ret + +ParseMusic: +; parses until a note is read or the song is ended + call GetMusicByte ; store next byte in a + cp endchannel_cmd + jr z, .endchannel + cp FIRST_MUSIC_CMD + jr c, .readnote + ; then it's a command +.readcommand + call ParseMusicCommand + jr ParseMusic ; start over + +.readnote +; wCurMusicByte contains current note +; special notes + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_SFX, [hl] + jp nz, ParseSFXOrRest + bit SOUND_REST, [hl] ; rest + jp nz, ParseSFXOrRest + bit SOUND_NOISE, [hl] ; noise sample + jp nz, GetNoiseSample +; normal note + ; set note duration (bottom nybble) + ld a, [wCurMusicByte] + and $f + call SetNoteDuration + ; get note pitch (top nybble) + ld a, [wCurMusicByte] + swap a + and $f + jr z, .rest ; pitch 0-> rest + ; update pitch + ld hl, CHANNEL_PITCH + add hl, bc + ld [hl], a + ; store pitch in e + ld e, a + ; store octave in d + ld hl, CHANNEL_OCTAVE + add hl, bc + ld d, [hl] + ; update frequency + call GetFrequency + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ; ???? + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_NOISE_SAMPLING, [hl] + jp LoadNote + +.rest +; note = rest + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] ; Rest + ret + +.endchannel +; $ff is reached in music data + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_SUBROUTINE, [hl] ; in a subroutine? + jr nz, .readcommand ; execute + ld a, [wCurChannel] + cp CHAN5 + jr nc, .chan_5to8 + ; ???? + ld hl, CHANNEL_STRUCT_LENGTH * NUM_MUSIC_CHANS + CHANNEL_FLAGS1 + add hl, bc + bit SOUND_CHANNEL_ON, [hl] + jr nz, .ok +.chan_5to8 + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_REST, [hl] + call nz, RestoreVolume + ; end music + ld a, [wCurChannel] + cp CHAN5 + jr nz, .ok + ; ???? + xor a + ldh [rNR10], a ; sweep = 0 +.ok +; stop playing + ; turn channel off + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_CHANNEL_ON, [hl] + ; note = rest + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] + ; clear music id & bank + ld hl, CHANNEL_MUSIC_ID + add hl, bc + xor a + ld [hli], a ; id hi + ld [hli], a ; id lo + ld [hli], a ; bank + ret + +RestoreVolume: + ; ch5 only + ld a, [wCurChannel] + cp CHAN5 + ret nz + xor a + ld hl, wChannel6CryPitch + ld [hli], a + ld [hl], a + ld hl, wChannel8CryPitch + ld [hli], a + ld [hl], a + ld a, [wLastVolume] + ld [wVolume], a + xor a + ld [wLastVolume], a + ld [wSFXPriority], a + ret + +ParseSFXOrRest: + ; turn noise sampling on + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_NOISE_SAMPLING, [hl] ; noise sample + ; update note duration + ld a, [wCurMusicByte] + call SetNoteDuration ; top nybble doesnt matter? + ; update intensity from next param + call GetMusicByte + ld hl, CHANNEL_INTENSITY + add hl, bc + ld [hl], a + ; update lo frequency from next param + call GetMusicByte + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld [hl], a + ; are we on the last channel? (noise sampling) + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp CHAN4 + ret z + ; update hi frequency from next param + call GetMusicByte + ld hl, CHANNEL_FREQUENCY + 1 + add hl, bc + ld [hl], a + ret + +GetNoiseSample: +; load ptr to sample header in wNoiseSampleAddress + ; are we on the last channel? + ld a, [wCurChannel] + and NUM_MUSIC_CHANS + -1 + cp CHAN4 + ; ret if not + ret nz + ; update note duration + ld a, [wCurMusicByte] + and $f + call SetNoteDuration + ; check current channel + ld a, [wCurChannel] + bit NOISE_CHAN_F, a + jr nz, .sfx + ld hl, wChannel8Flags1 + bit SOUND_CHANNEL_ON, [hl] ; is ch8 on? (noise) + ret nz + ld a, [wMusicNoiseSampleSet] + jr .next + +.sfx + ld a, [wSFXNoiseSampleSet] +.next + ; load noise sample set id into de + ld e, a + ld d, 0 + ; load ptr to noise sample set in hl + ld hl, Drumkits + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ; get pitch + ld a, [wCurMusicByte] + swap a + ; non-rest note? + and $f + ret z + ; use 'pitch' to seek noise sample set + ld e, a + ld d, 0 + add hl, de + add hl, de + ; load sample pointer into wNoiseSampleAddress + ld a, [hli] + ld [wNoiseSampleAddress], a + ld a, [hl] + ld [wNoiseSampleAddress + 1], a + ; clear ???? + xor a + ld [wNoiseSampleDelay], a + ret + +ParseMusicCommand: + ; reload command + ld a, [wCurMusicByte] + ; get command # + sub FIRST_MUSIC_CMD + ld e, a + ld d, 0 + ; seek command pointer + ld hl, MusicCommands + add hl, de + add hl, de + ; jump to the new pointer + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +MusicCommands: +; entries correspond to macros/sound.asm enumeration + dw Music_Octave8 ; octave 8 + dw Music_Octave7 ; octave 7 + dw Music_Octave6 ; octave 6 + dw Music_Octave5 ; octave 5 + dw Music_Octave4 ; octave 4 + dw Music_Octave3 ; octave 3 + dw Music_Octave2 ; octave 2 + dw Music_Octave1 ; octave 1 + dw Music_NoteType ; note length + intensity + dw Music_ForceOctave ; set starting octave + dw Music_Tempo ; tempo + dw Music_DutyCycle ; duty cycle + dw Music_Intensity ; intensity + dw Music_SoundStatus ; update sound status + dw Music_SoundDuty ; sfx duty + dw Music_ToggleSFX ; sound on/off + dw Music_SlidePitchTo ; pitch wheel + dw Music_Vibrato ; vibrato + dw MusicE2 ; unused + dw Music_ToggleNoise ; music noise sampling + dw Music_Panning ; force panning + dw Music_Volume ; volume + dw Music_Tone ; tone + dw MusicE7 ; unused + dw MusicE8 ; unused + dw Music_TempoRelative ; global tempo + dw Music_RestartChannel ; restart current channel from header + dw Music_NewSong ; new song + dw Music_SFXPriorityOn ; sfx priority on + dw Music_SFXPriorityOff ; sfx priority off + dw MusicEE ; unused + dw Music_StereoPanning ; stereo panning + dw Music_SFXToggleNoise ; sfx noise sampling + dw MusicF1 ; nothing + dw MusicF2 ; nothing + dw MusicF3 ; nothing + dw MusicF4 ; nothing + dw MusicF5 ; nothing + dw MusicF6 ; nothing + dw MusicF7 ; nothing + dw MusicF8 ; nothing + dw MusicF9 ; unused + dw Music_SetCondition ; setcondition + dw Music_JumpIf ; jumpif + dw Music_JumpChannel ; jump + dw Music_LoopChannel ; loop + dw Music_CallChannel ; call + dw Music_EndChannel ; return + +MusicF1: +MusicF2: +MusicF3: +MusicF4: +MusicF5: +MusicF6: +MusicF7: +MusicF8: + ret + +Music_EndChannel: +; called when $ff is encountered w/ subroutine flag set +; end music stream +; return to caller of the subroutine + ; reset subroutine flag + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_SUBROUTINE, [hl] + ; copy LastMusicAddress to MusicAddress + ld hl, CHANNEL_LAST_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ret + +Music_CallChannel: +; call music stream (subroutine) +; parameters: ll hh ; pointer to subroutine + ; get pointer from next 2 bytes + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + push de + ; copy MusicAddress to LastMusicAddress + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, CHANNEL_LAST_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ; load pointer into MusicAddress + pop de + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ; set subroutine flag + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_SUBROUTINE, [hl] + ret + +Music_JumpChannel: +; jump +; parameters: ll hh ; pointer + ; get pointer from next 2 bytes + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ret + +Music_LoopChannel: +; loops xx - 1 times +; 00: infinite +; params: 3 +; xx ll hh +; xx : loop count +; ll hh : pointer + + ; get loop count + call GetMusicByte + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_LOOPING, [hl] ; has the loop been initiated? + jr nz, .checkloop + and a ; loop counter 0 = infinite + jr z, .loop + ; initiate loop + dec a + set SOUND_LOOPING, [hl] ; set loop flag + ld hl, CHANNEL_LOOP_COUNT + add hl, bc + ld [hl], a ; store loop counter +.checkloop + ld hl, CHANNEL_LOOP_COUNT + add hl, bc + ld a, [hl] + and a ; are we done? + jr z, .endloop + dec [hl] +.loop + ; get pointer + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + ; load new pointer into MusicAddress + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ret + +.endloop + ; reset loop flag + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_LOOPING, [hl] + ; skip to next command + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + inc de ; skip + inc de ; pointer + ld [hl], d + dec hl + ld [hl], e + ret + +Music_SetCondition: +; set condition for a jump +; used with FB +; params: 1 +; xx ; condition + + ; set condition + call GetMusicByte + ld hl, CHANNEL_CONDITION + add hl, bc + ld [hl], a + ret + +Music_JumpIf: +; conditional jump +; used with FA +; params: 3 +; xx: condition +; ll hh: pointer + +; check condition + ; a = condition + call GetMusicByte + ; if existing condition matches, jump to new address + ld hl, CHANNEL_CONDITION + add hl, bc + cp [hl] + jr z, .jump +; skip to next command + ; get address + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; skip pointer + inc de + inc de + ; update address + ld [hl], d + dec hl + ld [hl], e + ret + +.jump +; jump to the new address + ; get pointer + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + ; update pointer in MusicAddress + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ret + +MusicEE: +; conditional jump +; checks a byte in ram corresponding to the current channel +; doesn't seem to be set by any commands +; params: 2 +; ll hh ; pointer + +; if ????, jump + ; get channel + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + ld e, a + ld d, 0 + ; hl = wChannel1JumpCondition + channel id + ld hl, wChannel1JumpCondition + add hl, de + ; if set, jump + ld a, [hl] + and a + jr nz, .jump +; skip to next command + ; get address + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; skip pointer + inc de + inc de + ; update address + ld [hl], d + dec hl + ld [hl], e + ret + +.jump + ; reset jump flag + ld [hl], 0 + ; de = pointer + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + ; update address + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ret + +MusicF9: +; sets some flag +; seems to be unused +; params: 0 + ld a, TRUE + ld [wUnusedMusicF9Flag], a + ret + +MusicE2: +; seems to have been dummied out +; params: 1 + call GetMusicByte + ld hl, CHANNEL_FIELD2C + add hl, bc + ld [hl], a + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_UNKN_0B, [hl] + ret + +Music_Vibrato: +; vibrato +; params: 2 +; 1: [xx] + ; delay in frames +; 2: [yz] + ; y: extent + ; z: rate (# frames per cycle) + + ; set vibrato flag? + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_VIBRATO, [hl] + ; start at lower frequency (extent is positive) + ld hl, CHANNEL_FLAGS3 + add hl, bc + res SOUND_VIBRATO_DIR, [hl] + ; get delay + call GetMusicByte +; update delay + ld hl, CHANNEL_VIBRATO_DELAY + add hl, bc + ld [hl], a +; update delay count + ld hl, CHANNEL_VIBRATO_DELAY_COUNT + add hl, bc + ld [hl], a +; update extent +; this is split into halves only to get added back together at the last second + ; get extent/rate + call GetMusicByte + ld hl, CHANNEL_VIBRATO_EXTENT + add hl, bc + ld d, a + ; get top nybble + and $f0 + swap a + srl a ; halve + ld e, a + adc 0 ; round up + swap a + or e + ld [hl], a +; update rate + ld hl, CHANNEL_VIBRATO_RATE + add hl, bc + ; get bottom nybble + ld a, d + and $f + ld d, a + swap a + or d + ld [hl], a + ret + +Music_SlidePitchTo: +; set the target for pitch wheel +; params: 2 +; note duration +; target note + call GetMusicByte + ld [wCurNoteDuration], a + + call GetMusicByte + ; pitch in e + ld d, a + and $f + ld e, a + + ; octave in d + ld a, d + swap a + and $f + ld d, a + call GetFrequency + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld [hl], e + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld [hl], d + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_PITCH_WHEEL, [hl] + ret + +Music_Tone: +; tone +; params: 1 (dw) + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_CRY_PITCH, [hl] + ld hl, CHANNEL_CRY_PITCH + 1 + add hl, bc + call GetMusicByte + ld [hld], a + call GetMusicByte + ld [hl], a + ret + +MusicE7: +; unused +; params: 1 + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_UNKN_0E, [hl] + call GetMusicByte + ld hl, CHANNEL_FIELD29 + add hl, bc + ld [hl], a + ret + +Music_SoundDuty: +; sequence of 4 duty cycles to be looped +; params: 1 (4 2-bit duty cycle arguments) + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_DUTY, [hl] ; duty cycle + ; sound duty sequence + call GetMusicByte + rrca + rrca + ld hl, CHANNEL_SFX_DUTY_LOOP + add hl, bc + ld [hl], a + ; update duty cycle + and $c0 ; only uses top 2 bits + ld hl, CHANNEL_DUTY_CYCLE + add hl, bc + ld [hl], a + ret + +MusicE8: +; unused +; params: 1 + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_UNKN_0D, [hl] + call GetMusicByte + ld hl, CHANNEL_FIELD2A + add hl, bc + ld [hl], a + ret + +Music_ToggleSFX: +; toggle something +; params: none + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_SFX, [hl] + jr z, .on + res SOUND_SFX, [hl] + ret + +.on + set SOUND_SFX, [hl] + ret + +Music_ToggleNoise: +; toggle music noise sampling +; can't be used as a straight toggle since the param is not read from on->off +; params: +; noise on: 1 +; noise off: 0 + ; check if noise sampling is on + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_NOISE, [hl] + jr z, .on + ; turn noise sampling off + res SOUND_NOISE, [hl] + ret + +.on + ; turn noise sampling on + set SOUND_NOISE, [hl] + call GetMusicByte + ld [wMusicNoiseSampleSet], a + ret + +Music_SFXToggleNoise: +; toggle sfx noise sampling +; params: +; on: 1 +; off: 0 + ; check if noise sampling is on + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_NOISE, [hl] + jr z, .on + ; turn noise sampling off + res SOUND_NOISE, [hl] + ret + +.on + ; turn noise sampling on + set SOUND_NOISE, [hl] + call GetMusicByte + ld [wSFXNoiseSampleSet], a + ret + +Music_NoteType: +; note length +; # frames per 16th note +; intensity: see Music_Intensity +; params: 2 + ; note length + call GetMusicByte + ld hl, CHANNEL_NOTE_LENGTH + add hl, bc + ld [hl], a + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp CHAN4 + ret z + ; intensity + call Music_Intensity + ret + +Music_SoundStatus: +; update sound status +; params: 1 + call GetMusicByte + ld [wSoundInput], a + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_UNKN_3, [hl] + ret + +Music_DutyCycle: +; duty cycle +; params: 1 + call GetMusicByte + rrca + rrca + and $c0 + ld hl, CHANNEL_DUTY_CYCLE + add hl, bc + ld [hl], a + ret + +Music_Intensity: +; intensity +; params: 1 +; hi: pressure +; lo: velocity + call GetMusicByte + ld hl, CHANNEL_INTENSITY + add hl, bc + ld [hl], a + ret + +Music_Tempo: +; global tempo +; params: 2 +; de: tempo + call GetMusicByte + ld d, a + call GetMusicByte + ld e, a + call SetGlobalTempo + ret + +Music_Octave8: +Music_Octave7: +Music_Octave6: +Music_Octave5: +Music_Octave4: +Music_Octave3: +Music_Octave2: +Music_Octave1: +; set octave based on lo nybble of the command + ld hl, CHANNEL_OCTAVE + add hl, bc + ld a, [wCurMusicByte] + and 7 + ld [hl], a + ret + +Music_ForceOctave: +; set starting octave +; this forces all notes up by the starting octave +; params: 1 + call GetMusicByte + ld hl, CHANNEL_PITCH_OFFSET + add hl, bc + ld [hl], a + ret + +Music_StereoPanning: +; stereo panning +; params: 1 + ; stereo on? + ld a, [wOptions] + bit STEREO, a + jr nz, Music_Panning + ; skip param + call GetMusicByte + ret + +Music_Panning: +; force panning +; params: 1 + call SetLRTracks + call GetMusicByte + ld hl, CHANNEL_TRACKS + add hl, bc + and [hl] + ld [hl], a + ret + +Music_Volume: +; set volume +; params: 1 +; see Volume + ; read param even if it's not used + call GetMusicByte + ; is the song fading? + ld a, [wMusicFade] + and a + ret nz + ; reload param + ld a, [wCurMusicByte] + ; set volume + ld [wVolume], a + ret + +Music_TempoRelative: +; set global tempo to current channel tempo +/- param +; params: 1 signed + call GetMusicByte + ld e, a + ; check sign + cp $80 + jr nc, .negative +;positive + ld d, 0 + jr .ok + +.negative + ld d, -1 +.ok + ld hl, CHANNEL_TEMPO + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + add hl, de + ld e, l + ld d, h + call SetGlobalTempo + ret + +Music_SFXPriorityOn: +; turn sfx priority on +; params: none + ld a, 1 + ld [wSFXPriority], a + ret + +Music_SFXPriorityOff: +; turn sfx priority off +; params: none + xor a + ld [wSFXPriority], a + ret + +Music_RestartChannel: +; restart current channel from channel header (same bank) +; params: 2 (5) +; ll hh: pointer to new channel header +; header format: 0x yy zz +; x: channel # (0-3) +; zzyy: pointer to new music data + + ; update music id + ld hl, CHANNEL_MUSIC_ID + add hl, bc + ld a, [hli] + ld [wMusicID], a + ld a, [hl] + ld [wMusicID + 1], a + ; update music bank + ld hl, CHANNEL_MUSIC_BANK + add hl, bc + ld a, [hl] + ld [wMusicBank], a + ; get pointer to new channel header + call GetMusicByte + ld l, a + call GetMusicByte + ld h, a + ld e, [hl] + inc hl + ld d, [hl] + push bc ; save current channel + call LoadChannel + call StartChannel + pop bc ; restore current channel + ret + +Music_NewSong: +; new song +; params: 2 +; de: song id + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + push bc + call _PlayMusic + pop bc + ret + +GetMusicByte: +; returns byte from current address in a +; advances to next byte in music data +; input: bc = start of current channel + push hl + push de + ; load address into de + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld a, [hli] + ld e, a + ld d, [hl] + ; load bank into a + ld hl, CHANNEL_MUSIC_BANK + add hl, bc + ld a, [hl] + ; get byte + call _LoadMusicByte ; load data into wCurMusicByte + inc de ; advance to next byte for next time this is called + ; update channeldata address + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld a, e + ld [hli], a + ld [hl], d + ; cleanup + pop de + pop hl + ; store channeldata in a + ld a, [wCurMusicByte] + ret + +GetFrequency: +; generate frequency +; input: +; d: octave +; e: pitch +; output: +; de: frequency + +; get octave + ; get starting octave + ld hl, CHANNEL_PITCH_OFFSET + add hl, bc + ld a, [hl] + swap a ; hi nybble + and $f + ; add current octave + add d + push af ; we'll use this later + ; get starting octave + ld hl, CHANNEL_PITCH_OFFSET + add hl, bc + ld a, [hl] + and $f ; lo nybble + ld l, a ; ok + ld d, 0 + ld h, d + add hl, de ; add current pitch + add hl, hl ; skip 2 bytes for each + ld de, FrequencyTable + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ; get our octave + pop af + ; shift right by [7 - octave] bits +.loop + ; [7 - octave] loops + cp $7 + jr nc, .ok + ; sra de + sra d + rr e + inc a + jr .loop + +.ok + ld a, d + and $7 ; top 3 bits for frequency (11 total) + ld d, a + ret + +SetNoteDuration: +; input: a = note duration in 16ths + ; store delay units in de + inc a + ld e, a + ld d, 0 + ; store NoteLength in a + ld hl, CHANNEL_NOTE_LENGTH + add hl, bc + ld a, [hl] + ; multiply NoteLength by delay units + ld l, 0 ; just multiply + call .Multiply + ld a, l ; low + ; store Tempo in de + ld hl, CHANNEL_TEMPO + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ; add ???? to the next result + ld hl, CHANNEL_FIELD16 + add hl, bc + ld l, [hl] + ; multiply Tempo by last result (NoteLength * LOW(delay)) + call .Multiply + ; copy result to de + ld e, l + ld d, h + ; store result in ???? + ld hl, CHANNEL_FIELD16 + add hl, bc + ld [hl], e + ; store result in NoteDuration + ld hl, CHANNEL_NOTE_DURATION + add hl, bc + ld [hl], d + ret + +.Multiply: +; multiplies a and de +; adds the result to l +; stores the result in hl + ld h, 0 +.loop + ; halve a + srl a + ; is there a remainder? + jr nc, .skip + ; add it to the result + add hl, de +.skip + ; add de, de + sla e + rl d + ; are we done? + and a + jr nz, .loop + ret + +SetGlobalTempo: + push bc ; save current channel + ; are we dealing with music or sfx? + 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 +.end + pop bc ; restore current channel + ret + +Tempo: +; input: +; de: note length + ; update Tempo + ld hl, CHANNEL_TEMPO + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ; clear ???? + xor a + ld hl, CHANNEL_FIELD16 + add hl, bc + ld [hl], a + ret + +StartChannel: + call SetLRTracks + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_CHANNEL_ON, [hl] ; turn channel on + ret + +SetLRTracks: +; set tracks for a the current channel to default +; seems to be redundant since this is overwritten by stereo data later + push de + ; store current channel in de + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + ld e, a + ld d, 0 + ; get this channel's lr tracks + call GetLRTracks + add hl, de ; de = channel 0-3 + ld a, [hl] + ; load lr tracks into Tracks + ld hl, CHANNEL_TRACKS + add hl, bc + ld [hl], a + pop de + ret + +_PlayMusic:: +; load music + call MusicOff + ld hl, wMusicID + ld [hl], e ; song number + inc hl + ld [hl], d ; (always 0) + ld hl, Music + add hl, de ; three + add hl, de ; byte + add hl, de ; pointer + ld a, [hli] + ld [wMusicBank], a + ld e, [hl] + inc hl + ld d, [hl] ; music header address + call LoadMusicByte ; store first byte of music header in a + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a +.loop +; start playing channels + push af + call LoadChannel + call StartChannel + pop af + dec a + jr nz, .loop + xor a + ld [wUnusedMusicF9Flag], a + ld [wChannel1JumpCondition], a + ld [wChannel2JumpCondition], a + ld [wChannel3JumpCondition], a + ld [wChannel4JumpCondition], a + ld [wNoiseSampleAddress], a + ld [wNoiseSampleAddress + 1], a + ld [wNoiseSampleDelay], a + ld [wMusicNoiseSampleSet], a + call MusicOn + ret + +_PlayCry:: +; Play cry de using parameters: +; wCryPitch +; wCryLength + + call MusicOff + +; Overload the music id with the cry id + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + +; 3-byte pointers (bank, address) + ld hl, Cries + add hl, de + add hl, de + add hl, de + + ld a, [hli] + ld [wMusicBank], a + + ld e, [hl] + inc hl + ld d, [hl] + +; Read the cry's sound header + call LoadMusicByte + ; Top 2 bits contain the number of channels + rlca + rlca + maskbits NUM_MUSIC_CHANS + +; For each channel: + inc a +.loop + push af + call LoadChannel + + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_REST, [hl] + + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_CRY_PITCH, [hl] + + ld hl, CHANNEL_CRY_PITCH + add hl, bc + ld a, [wCryPitch] + ld [hli], a + ld a, [wCryPitch + 1] + ld [hl], a + +; No tempo for channel 4 + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp CHAN4 + jr nc, .start + +; Tempo is effectively length + ld hl, CHANNEL_TEMPO + add hl, bc + ld a, [wCryLength] + ld [hli], a + ld a, [wCryLength + 1] + ld [hl], a +.start + call StartChannel + ld a, [wStereoPanningMask] + and a + jr z, .next + +; Stereo only: Play cry from the monster's side. +; This only applies in-battle. + + ld a, [wOptions] + bit STEREO, a + jr z, .next + +; [Tracks] &= [wCryTracks] + ld hl, CHANNEL_TRACKS + add hl, bc + ld a, [hl] + ld hl, wCryTracks + and [hl] + ld hl, CHANNEL_TRACKS + add hl, bc + ld [hl], a + +.next + pop af + dec a + jr nz, .loop + +; Cries play at max volume, so we save the current volume for later. + ld a, [wLastVolume] + and a + jr nz, .end + + ld a, [wVolume] + ld [wLastVolume], a + ld a, MAX_VOLUME + ld [wVolume], a + +.end + ld a, 1 ; stop playing music + ld [wSFXPriority], a + call MusicOn + ret + +_PlaySFX:: +; clear channels if they aren't already + call MusicOff + ld hl, wChannel5Flags1 + bit SOUND_CHANNEL_ON, [hl] ; ch5 on? + jr z, .ch6 + res SOUND_CHANNEL_ON, [hl] ; turn it off + xor a + ldh [rNR11], a ; length/wavepattern = 0 + ld a, $8 + ldh [rNR12], a ; envelope = 0 + xor a + ldh [rNR13], a ; frequency lo = 0 + ld a, $80 + ldh [rNR14], a ; restart sound (freq hi = 0) + xor a + ld [wSoundInput], a ; global sound off + ldh [rNR10], a ; sweep = 0 +.ch6 + ld hl, wChannel6Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr z, .ch7 + res SOUND_CHANNEL_ON, [hl] ; turn it off + xor a + ldh [rNR21], a ; length/wavepattern = 0 + ld a, $8 + ldh [rNR22], a ; envelope = 0 + xor a + ldh [rNR23], a ; frequency lo = 0 + ld a, $80 + ldh [rNR24], a ; restart sound (freq hi = 0) +.ch7 + ld hl, wChannel7Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr z, .ch8 + res SOUND_CHANNEL_ON, [hl] ; turn it off + xor a + ldh [rNR30], a ; sound mode #3 off + ldh [rNR31], a ; length/wavepattern = 0 + ld a, $8 + ldh [rNR32], a ; envelope = 0 + xor a + ldh [rNR33], a ; frequency lo = 0 + ld a, $80 + ldh [rNR34], a ; restart sound (freq hi = 0) +.ch8 + ld hl, wChannel8Flags1 + bit SOUND_CHANNEL_ON, [hl] + jr z, .chscleared + res SOUND_CHANNEL_ON, [hl] ; turn it off + xor a + ldh [rNR41], a ; length/wavepattern = 0 + ld a, $8 + ldh [rNR42], a ; envelope = 0 + xor a + ldh [rNR43], a ; frequency lo = 0 + ld a, $80 + ldh [rNR44], a ; restart sound (freq hi = 0) + xor a + ld [wNoiseSampleAddress], a + ld [wNoiseSampleAddress + 1], a +.chscleared +; start reading sfx header for # chs + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + ld hl, SFX + add hl, de ; three + add hl, de ; byte + add hl, de ; pointers + ; get bank + ld a, [hli] + ld [wMusicBank], a + ; get address + ld e, [hl] + inc hl + ld d, [hl] + ; get # channels + call LoadMusicByte + rlca ; top 2 + rlca ; bits + maskbits NUM_MUSIC_CHANS + inc a ; # channels -> # loops +.startchannels + push af + call LoadChannel ; bc = current channel + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_SFX, [hl] + call StartChannel + pop af + dec a + jr nz, .startchannels + call MusicOn + xor a + ld [wSFXPriority], a + ret + +PlayStereoSFX:: +; play sfx de + + call MusicOff + +; standard procedure if stereo's off + ld a, [wOptions] + bit STEREO, a + jp z, _PlaySFX + +; else, let's go ahead with this + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + +; get sfx ptr + ld hl, SFX + add hl, de + add hl, de + add hl, de + +; bank + ld a, [hli] + ld [wMusicBank], a +; address + ld e, [hl] + inc hl + ld d, [hl] + +; bit 2-3 + call LoadMusicByte + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a + +.loop + push af + call LoadChannel + + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_SFX, [hl] + + push de + ; get tracks for this channel + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + ld e, a + ld d, 0 + call GetLRTracks + add hl, de + ld a, [hl] + ld hl, wStereoPanningMask + and [hl] + + ld hl, CHANNEL_TRACKS + add hl, bc + ld [hl], a + + ld hl, CHANNEL_FIELD30 + add hl, bc + ld [hl], a + + ld a, [wCryTracks] + cp 2 ; ch 1-2 + jr c, .skip + +; ch3-4 + ld a, [wSFXDuration] + + ld hl, CHANNEL_FIELD2E + add hl, bc + ld [hl], a + + ld hl, CHANNEL_FIELD2F + add hl, bc + ld [hl], a + + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_UNKN_0F, [hl] + +.skip + pop de + +; turn channel on + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_CHANNEL_ON, [hl] ; on + +; done? + pop af + dec a + jr nz, .loop + +; we're done + call MusicOn + ret + +LoadChannel: +; prep channel for use +; input: +; de: + ; get pointer to current channel + call LoadMusicByte + inc de + and $7 ; bit 0-2 (current channel) + ld [wCurChannel], a + ld c, a + ld b, 0 + ld hl, ChannelPointers + add hl, bc + add hl, bc + ld c, [hl] + inc hl + ld b, [hl] ; bc = channel pointer + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_CHANNEL_ON, [hl] ; channel off + call ChannelInit + ; load music pointer + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + call LoadMusicByte + ld [hli], a + inc de + call LoadMusicByte + ld [hl], a + inc de + ; load music id + ld hl, CHANNEL_MUSIC_ID + add hl, bc + ld a, [wMusicID] + ld [hli], a + ld a, [wMusicID + 1] + ld [hl], a + ; load music bank + ld hl, CHANNEL_MUSIC_BANK + add hl, bc + ld a, [wMusicBank] + ld [hl], a + ret + +ChannelInit: +; make sure channel is cleared +; set default tempo and note length in case nothing is loaded +; input: +; bc = channel struct pointer + push de + xor a + ; get channel struct location and length + ld hl, CHANNEL_MUSIC_ID ; start + add hl, bc + ld e, CHANNEL_STRUCT_LENGTH ; channel struct length + ; clear channel +.loop + ld [hli], a + dec e + jr nz, .loop + ; set tempo to default ($100) + ld hl, CHANNEL_TEMPO + add hl, bc + xor a + ld [hli], a + inc a + ld [hl], a + ; set note length to default ($1) (fast) + ld hl, CHANNEL_NOTE_LENGTH + add hl, bc + ld [hl], a + pop de + ret + +LoadMusicByte:: +; input: +; de = current music address +; output: +; a = wCurMusicByte + ld a, [wMusicBank] + call _LoadMusicByte + ld a, [wCurMusicByte] + ret + +INCLUDE "audio/notes.asm" + +INCLUDE "audio/wave_samples.asm" + +INCLUDE "audio/drumkits.asm" + +GetLRTracks: +; gets the default sound l/r channels +; stores mono/stereo table in hl + ld a, [wOptions] + bit STEREO, a + ; made redundant, could have had a purpose in gold + jr nz, .stereo + ld hl, MonoTracks + ret + +.stereo + ld hl, StereoTracks + ret + +MonoTracks: +; bit corresponds to track # +; hi: left channel +; lo: right channel + db $11, $22, $44, $88 + +StereoTracks: +; made redundant +; seems to be modified on a per-song basis + db $11, $22, $44, $88 + +ChannelPointers: +; music channels + dw wChannel1 + dw wChannel2 + dw wChannel3 + dw wChannel4 +; sfx channels + dw wChannel5 + dw wChannel6 + dw wChannel7 + dw wChannel8 + +ClearChannels:: +; runs ClearChannel for all 4 channels +; doesn't seem to be used, but functionally identical to MapSetup_Sound_Off + ld hl, rNR50 + xor a + ld [hli], a + ld [hli], a + ld a, $80 + ld [hli], a + ld hl, rNR10 + ld e, NUM_MUSIC_CHANS +.loop + call ClearChannel + dec e + jr nz, .loop + ret + +ClearChannel: +; input: hl = beginning hw sound register (rNR10, rNR20, rNR30, rNR40) +; output: 00 00 80 00 80 + +; sound channel 1 2 3 4 + xor a + ld [hli], a ; rNR10, rNR20, rNR30, rNR40 ; sweep = 0 + + ld [hli], a ; rNR11, rNR21, rNR31, rNR41 ; length/wavepattern = 0 + ld a, $8 + ld [hli], a ; rNR12, rNR22, rNR32, rNR42 ; envelope = 0 + xor a + ld [hli], a ; rNR13, rNR23, rNR33, rNR43 ; frequency lo = 0 + ld a, $80 + ld [hli], a ; rNR14, rNR24, rNR34, rNR44 ; restart sound (freq hi = 0) + ret + +PlayTrainerEncounterMusic:: +; input: e = trainer type + ; turn fade off + xor a + ld [wMusicFade], a + ; play nothing for one frame + push de + ld de, MUSIC_NONE + call PlayMusic + call DelayFrame + ; play new song + call MaxVolume + pop de + ld d, $00 + ld hl, TrainerEncounterMusic + add hl, de + ld e, [hl] + call PlayMusic + ret diff --git a/audio/music_pointers.asm b/audio/music_pointers.asm index b72aa344..2e467c0d 100755 --- a/audio/music_pointers.asm +++ b/audio/music_pointers.asm @@ -1,94 +1,97 @@ +; See song sections in audio.asm. + Music: - dba Music_None - dba Music_Title - dba Music_Route1 - dba Music_Route3 - dba Music_Route12 - dba Music_MagnetTrain - dba Music_KantoGymLeaderBattle - dba Music_KantoTrainerBattle - dba Music_KantoWildBattle - dba Music_PokemonCenter - dba Music_HikerEncounter - dba Music_LassEncounter - dba Music_OfficerEncounter - dba Music_Heal - dba Music_LavenderTown - dba Music_Route2 - dba Music_MtMoon - dba Music_ShowMeAround - dba Music_GameCorner - dba Music_Bicycle - dba Music_HallOfFame - dba Music_ViridianCity - dba Music_CeladonCity - dba Music_TrainerVictory - dba Music_WildVictory - dba Music_GymVictory - dba Music_MtMoonSquare - dba Music_Gym - dba Music_PalletTown - dba Music_PokemonTalk - dba Music_ProfOak - dba Music_RivalEncounter - dba Music_RivalAfter - dba Music_Surf - dba Music_Evolution - dba Music_NationalPark - dba Music_Credits - dba Music_AzaleaTown - dba Music_CherrygroveCity - dba Music_KimonoEncounter - dba Music_UnionCave - dba Music_JohtoWildBattle - dba Music_JohtoTrainerBattle - dba Music_Route30 - dba Music_EcruteakCity - dba Music_VioletCity - dba Music_JohtoGymLeaderBattle - dba Music_ChampionBattle - dba Music_RivalBattle - dba Music_RocketBattle - dba Music_ProfElm - dba Music_DarkCave - dba Music_Route29 - dba Music_Route36 - dba Music_SsAqua - dba Music_YoungsterEncounter - dba Music_BeautyEncounter - dba Music_RocketEncounter - dba Music_PokemaniacEncounter - dba Music_SageEncounter - dba Music_NewBarkTown - dba Music_GoldenrodCity - dba Music_VermilionCity - dba Music_PokemonChannel - dba Music_PokeFluteChannel - dba Music_TinTower - dba Music_SproutTower - dba Music_BurnedTower - dba Music_Lighthouse - dba Music_LakeOfRage - dba Music_IndigoPlateau - dba Music_Route37 - dba Music_RocketHideout - dba Music_DragonsDen - dba Music_JohtoWildBattleNight - dba Music_RuinsOfAlphRadio - dba Music_Capture - dba Music_Route26 - dba Music_Mom - dba Music_VictoryRoad - dba Music_PokemonLullaby - dba Music_PokemonMarch - dba Music_GsOpening - dba Music_GsOpening2 - dba Music_MainMenu - dba Music_RuinsOfAlphInterior - dba Music_RocketOverture - dba Music_DancingHall - dba Music_BugCatchingContestRanking - dba Music_BugCatchingContest - dba Music_LakeOfRageRocketRadio - dba Music_Printer - dba Music_PostCredits +; entries correspond to MUSIC_* constants + dba Music_Nothing + dba Music_TitleScreen + dba Music_Route1 + dba Music_Route3 + dba Music_Route12 + dba Music_MagnetTrain + dba Music_KantoGymBattle + dba Music_KantoTrainerBattle + dba Music_KantoWildBattle + dba Music_PokemonCenter + dba Music_LookHiker + dba Music_LookLass + dba Music_LookOfficer + dba Music_HealPokemon + dba Music_LavenderTown + dba Music_Route2 + dba Music_MtMoon + dba Music_ShowMeAround + dba Music_GameCorner + dba Music_Bicycle + dba Music_HallOfFame + dba Music_ViridianCity + dba Music_CeladonCity + dba Music_TrainerVictory + dba Music_WildPokemonVictory + dba Music_GymLeaderVictory + dba Music_MtMoonSquare + dba Music_Gym + dba Music_PalletTown + dba Music_ProfOaksPokemonTalk + dba Music_ProfOak + dba Music_LookRival + dba Music_AfterTheRivalFight + dba Music_Surf + dba Music_Evolution + dba Music_NationalPark + dba Music_Credits + dba Music_AzaleaTown + dba Music_CherrygroveCity + dba Music_LookKimonoGirl + dba Music_UnionCave + dba Music_JohtoWildBattle + dba Music_JohtoTrainerBattle + dba Music_Route30 + dba Music_EcruteakCity + dba Music_VioletCity + dba Music_JohtoGymBattle + dba Music_ChampionBattle + dba Music_RivalBattle + dba Music_RocketBattle + dba Music_ElmsLab + dba Music_DarkCave + dba Music_Route29 + dba Music_Route36 + dba Music_SSAqua + dba Music_LookYoungster + dba Music_LookBeauty + dba Music_LookRocket + dba Music_LookPokemaniac + dba Music_LookSage + dba Music_NewBarkTown + dba Music_GoldenrodCity + dba Music_VermilionCity + dba Music_PokemonChannel + dba Music_PokeFluteChannel + dba Music_TinTower + dba Music_SproutTower + dba Music_BurnedTower + dba Music_Lighthouse + dba Music_LakeOfRage + dba Music_IndigoPlateau + dba Music_Route37 + dba Music_RocketHideout + dba Music_DragonsDen + dba Music_JohtoWildBattleNight + dba Music_RuinsOfAlphRadio + dba Music_SuccessfulCapture + dba Music_Route26 + dba Music_Mom + dba Music_VictoryRoad + dba Music_PokemonLullaby + dba Music_PokemonMarch + dba Music_GoldSilverOpening + dba Music_GoldSilverOpening2 + dba Music_MainMenu + dba Music_RuinsOfAlphInterior + dba Music_RocketTheme + dba Music_DancingHall + dba Music_ContestResults + dba Music_BugCatchingContest + dba Music_LakeOfRageRocketRadio + dba Music_Printer + dba Music_PostCredits diff --git a/audio/notes.asm b/audio/notes.asm new file mode 100644 index 00000000..eeb84959 --- /dev/null +++ b/audio/notes.asm @@ -0,0 +1,26 @@ +FrequencyTable: + dw 0 ; __ + dw $f82c ; C_ + dw $f89d ; C# + dw $f907 ; D_ + dw $f96b ; D# + dw $f9ca ; E_ + dw $fa23 ; F_ + dw $fa77 ; F# + dw $fac7 ; G_ + dw $fb12 ; G# + dw $fb58 ; A_ + dw $fb9b ; A# + dw $fbda ; B_ + dw $fc16 ; C_ + dw $fc4e ; C# + dw $fc83 ; D_ + dw $fcb5 ; D# + dw $fce5 ; E_ + dw $fd11 ; F_ + dw $fd3b ; F# + dw $fd63 ; G_ + dw $fd89 ; G# + dw $fdac ; A_ + dw $fdcd ; A# + dw $fded ; B_ diff --git a/audio/sfx_pointers.asm b/audio/sfx_pointers.asm new file mode 100644 index 00000000..9a8809dc --- /dev/null +++ b/audio/sfx_pointers.asm @@ -0,0 +1,190 @@ +SFX: +; entries correspond to SFX_* constants + dba Sfx_DexFanfare5079 + dba Sfx_Item + dba Sfx_CaughtMon + dba Sfx_PokeballsPlacedOnTable + dba Sfx_Potion + dba Sfx_FullHeal + dba Sfx_Menu + dba Sfx_ReadText + dba Sfx_ReadText2 + dba Sfx_DexFanfare2049 + dba Sfx_DexFanfare80109 + dba Sfx_Poison + dba Sfx_GotSafariBalls + dba Sfx_BootPc + dba Sfx_ShutDownPc + dba Sfx_ChoosePcOption + dba Sfx_EscapeRope + dba Sfx_PushButton + dba Sfx_SecondPartOfItemfinder + dba Sfx_WarpTo + dba Sfx_WarpFrom + dba Sfx_ChangeDexMode + dba Sfx_JumpOverLedge + dba Sfx_GrassRustle + dba Sfx_Fly + dba Sfx_Wrong + dba Sfx_Squeak + dba Sfx_Strength + dba Sfx_Boat + dba Sfx_WallOpen + dba Sfx_PlacePuzzlePieceDown + dba Sfx_EnterDoor + dba Sfx_SwitchPokemon + dba Sfx_Tally + dba Sfx_Transaction + dba Sfx_ExitBuilding + dba Sfx_Bump + dba Sfx_Save + dba Sfx_Pokeflute + dba Sfx_ElevatorEnd + dba Sfx_ThrowBall + dba Sfx_BallPoof + dba Sfx_Unknown3A + dba Sfx_Run + dba Sfx_SlotMachineStart + dba Sfx_Fanfare + dba Sfx_Peck + dba Sfx_Kinesis + dba Sfx_Lick + dba Sfx_Pound + dba Sfx_MovePuzzlePiece + dba Sfx_CometPunch + dba Sfx_MegaPunch + dba Sfx_Scratch + dba Sfx_Vicegrip + dba Sfx_RazorWind + dba Sfx_Cut + dba Sfx_WingAttack + dba Sfx_Whirlwind + dba Sfx_Bind + dba Sfx_VineWhip + dba Sfx_DoubleKick + dba Sfx_MegaKick + dba Sfx_Headbutt + dba Sfx_HornAttack + dba Sfx_Tackle + dba Sfx_PoisonSting + dba Sfx_Powder + dba Sfx_Doubleslap + dba Sfx_Bite + dba Sfx_JumpKick + dba Sfx_Stomp + dba Sfx_TailWhip + dba Sfx_KarateChop + dba Sfx_Submission + dba Sfx_WaterGun + dba Sfx_SwordsDance + dba Sfx_Thunder + dba Sfx_Supersonic + dba Sfx_Leer + dba Sfx_Ember + dba Sfx_Bubblebeam + dba Sfx_HydroPump + dba Sfx_Surf + dba Sfx_Psybeam + dba Sfx_Charge + dba Sfx_Thundershock + dba Sfx_Psychic + dba Sfx_Screech + dba Sfx_BoneClub + dba Sfx_Sharpen + dba Sfx_EggBomb + dba Sfx_Sing + dba Sfx_HyperBeam + dba Sfx_Shine + dba Sfx_Unknown5F + dba Sfx_Unknown60 + dba Sfx_Unknown61 + dba Sfx_SwitchPockets + dba Sfx_Unknown63 + dba Sfx_Burn + dba Sfx_TitleScreenEntrance + dba Sfx_Unknown66 + dba Sfx_GetCoinFromSlots + dba Sfx_PayDay + dba Sfx_Metronome + dba Sfx_Call + dba Sfx_HangUp + dba Sfx_NoSignal + dba Sfx_Sandstorm + dba Sfx_Elevator + dba Sfx_Protect + dba Sfx_Sketch + dba Sfx_RainDance + dba Sfx_Aeroblast + dba Sfx_Spark + dba Sfx_Curse + dba Sfx_Rage + dba Sfx_Thief + dba Sfx_Thief2 + dba Sfx_SpiderWeb + dba Sfx_MindReader + dba Sfx_Nightmare + dba Sfx_Snore + dba Sfx_SweetKiss + dba Sfx_SweetKiss2 + dba Sfx_BellyDrum + dba Sfx_Unknown7F + dba Sfx_SludgeBomb + dba Sfx_Foresight + dba Sfx_Spite + dba Sfx_Outrage + dba Sfx_PerishSong + dba Sfx_GigaDrain + dba Sfx_Attract + dba Sfx_Kinesis2 + dba Sfx_ZapCannon + dba Sfx_MeanLook + dba Sfx_HealBell + dba Sfx_Return + dba Sfx_ExpBar + dba Sfx_MilkDrink + dba Sfx_Present + dba Sfx_MorningSun + dba Sfx_LevelUp + dba Sfx_KeyItem + dba Sfx_Fanfare2 + dba Sfx_RegisterPhoneNumber + dba Sfx_3RdPlace + dba Sfx_GetEggFromDayCareMan + dba Sfx_GetEggFromDayCareLady + dba Sfx_MoveDeleted + dba Sfx_2ndPlace + dba Sfx_1stPlace + dba Sfx_ChooseACard + dba Sfx_GetTm + dba Sfx_GetBadge + dba Sfx_QuitSlots + dba Sfx_EggCrack + dba Sfx_DexFanfareLessThan20 + dba Sfx_DexFanfare140169 + dba Sfx_DexFanfare170199 + dba Sfx_DexFanfare200229 + dba Sfx_DexFanfare230Plus + dba Sfx_Evolved + dba Sfx_MasterBall + dba Sfx_EggHatch + dba Sfx_GsIntroCharizardFireball + dba Sfx_GsIntroPokemonAppears + dba Sfx_Flash + dba Sfx_GameFreakLogoGs + dba Sfx_NotVeryEffective + dba Sfx_Damage + dba Sfx_SuperEffective + dba Sfx_BallBounce + dba Sfx_Moonlight + dba Sfx_Encore + dba Sfx_BeatUp + dba Sfx_BatonPass + dba Sfx_BallWobble + dba Sfx_SweetScent + dba Sfx_SweetScent2 + dba Sfx_HitEndOfExpBar + dba Sfx_GiveTrademon + dba Sfx_GetTrademon + dba Sfx_TrainArrived + dba Sfx_StopSlot + dba Sfx_2Boops diff --git a/audio/wave_samples.asm b/audio/wave_samples.asm new file mode 100644 index 00000000..81fee211 --- /dev/null +++ b/audio/wave_samples.asm @@ -0,0 +1,13 @@ +WaveSamples: + ; These are streams of 32 nybbles (4-bit values) used as wave patterns. + ; Plot them as a line chart to see the wave's shape. + dn 0, 2, 4, 6, 8, 10, 12, 14, 15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1 + dn 0, 2, 4, 6, 8, 10, 12, 14, 14, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1 + dn 1, 3, 6, 9, 11, 13, 14, 14, 14, 14, 15, 15, 15, 15, 14, 13, 13, 14, 15, 15, 15, 15, 14, 14, 14, 14, 13, 11, 9, 6, 3, 1 + dn 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 15, 14, 13, 14, 15, 15, 14, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + dn 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 14, 15, 7, 7, 15, 14, 14, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0 + dn 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 2, 2, 1, 1, 15, 15, 14, 14, 12, 12, 10, 10, 8, 8, 10, 10, 12, 12, 14, 14 + dn 0, 2, 4, 6, 8, 10, 12, 14, 12, 11, 10, 9, 8, 7, 6, 5, 15, 15, 15, 14, 14, 13, 13, 12, 4, 4, 3, 3, 2, 2, 1, 1 + dn 12, 0, 10, 9, 8, 7, 15, 5, 15, 15, 15, 14, 14, 13, 13, 12, 4, 4, 3, 3, 2, 2, 15, 1, 0, 2, 4, 6, 8, 10, 12, 14 + dn 4, 4, 3, 3, 2, 2, 1, 15, 0, 0, 4, 6, 8, 10, 12, 14, 15, 8, 15, 14, 14, 13, 13, 12, 12, 11, 10, 9, 8, 7, 6, 5 + dn 1, 1, 0, 0, 0, 0, 0, 8, 0, 0, 1, 3, 5, 7, 9, 10, 11, 4, 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1 diff --git a/constants/audio_constants.asm b/constants/audio_constants.asm index a07887e0..1d092edf 100755 --- a/constants/audio_constants.asm +++ b/constants/audio_constants.asm @@ -1,63 +1,130 @@ - - ; pitch +; FrequencyTable indexes (see audio/notes.asm) const_def - const __ - const C_ - const C# - const D_ - const D# - const E_ - const F_ - const F# - const G_ - const G# - const A_ - const A# - const B_ - const CC + const __ ; 0 + const C_ ; 1 + const C# ; 2 + const D_ ; 3 + const D# ; 4 + const E_ ; 5 + const F_ ; 6 + const F# ; 7 + const G_ ; 8 + const G# ; 9 + const A_ ; a + const A# ; b + const B_ ; c + const CC ; d (used for pitchoffset) ; channel +; ChannelPointers indexes (see audio/engine.asm) const_def - const CHAN1 - const CHAN2 - const CHAN3 - const CHAN4 + const CHAN1 ; 0 + const CHAN2 ; 1 + const CHAN3 ; 2 + const CHAN4 ; 3 NUM_MUSIC_CHANS EQU const_value -NUM_NOISE_CHANS EQU const_value - const CHAN5 - const CHAN6 - const CHAN7 - const CHAN8 + const CHAN5 ; 4 + const CHAN6 ; 5 + const CHAN7 ; 6 + const CHAN8 ; 7 +NUM_NOISE_CHANS EQU const_value - NUM_MUSIC_CHANS NUM_CHANNELS EQU const_value +; channel_struct members (see macros/wram.asm) +CHANNEL_MUSIC_ID EQUS "(wChannel1MusicID - wChannel1)" +CHANNEL_MUSIC_BANK EQUS "(wChannel1MusicBank - 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 "(wChannel1Octave - wChannel1)" +CHANNEL_PITCH_OFFSET EQUS "(wChannel1PitchOffset - 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)" + +NOISE_CHAN_F EQU 2 ; bit set in CHAN5-CHAN7 + ; 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 + +; wSoundInput +SOUND_INPUT_CH1_F EQU 0 +SOUND_INPUT_CH2_F EQU 1 +SOUND_INPUT_CH3_F EQU 2 +SOUND_INPUT_CH4_F EQU 3 +SOUND_INPUT_GLOBAL_F EQU 7 + +; wLowHealthAlarm +DANGER_PITCH_F EQU 4 +DANGER_ON_F EQU 7 + +; wMusicFade +MUSIC_FADE_IN_F EQU 7 diff --git a/data/trainers/encounter_music.asm b/data/trainers/encounter_music.asm new file mode 100644 index 00000000..a64d160f --- /dev/null +++ b/data/trainers/encounter_music.asm @@ -0,0 +1,75 @@ +; What music plays when a trainer notices you + +TrainerEncounterMusic:: +; entries correspond to trainer classes (see constants/trainer_constants.asm) + db MUSIC_HIKER_ENCOUNTER ; none + db MUSIC_YOUNGSTER_ENCOUNTER ; falkner + db MUSIC_LASS_ENCOUNTER ; whitney + db MUSIC_YOUNGSTER_ENCOUNTER ; bugsy + db MUSIC_OFFICER_ENCOUNTER ; morty + db MUSIC_OFFICER_ENCOUNTER ; pryce + db MUSIC_LASS_ENCOUNTER ; jasmine + db MUSIC_OFFICER_ENCOUNTER ; chuck + db MUSIC_BEAUTY_ENCOUNTER ; clair + db MUSIC_RIVAL_ENCOUNTER ; rival1 + db MUSIC_HIKER_ENCOUNTER ; pokemon_prof + db MUSIC_HIKER_ENCOUNTER ; will + db MUSIC_HIKER_ENCOUNTER ; cal + db MUSIC_OFFICER_ENCOUNTER ; bruno + db MUSIC_HIKER_ENCOUNTER ; karen + db MUSIC_HIKER_ENCOUNTER ; koga + db MUSIC_OFFICER_ENCOUNTER ; champion + db MUSIC_YOUNGSTER_ENCOUNTER ; brock + db MUSIC_LASS_ENCOUNTER ; misty + db MUSIC_OFFICER_ENCOUNTER ; lt_surge + db MUSIC_ROCKET_ENCOUNTER ; scientist + db MUSIC_OFFICER_ENCOUNTER ; erika + db MUSIC_YOUNGSTER_ENCOUNTER ; youngster + db MUSIC_YOUNGSTER_ENCOUNTER ; schoolboy + db MUSIC_YOUNGSTER_ENCOUNTER ; bird_keeper + db MUSIC_LASS_ENCOUNTER ; lass + db MUSIC_LASS_ENCOUNTER ; janine + db MUSIC_HIKER_ENCOUNTER ; cooltrainerm + db MUSIC_BEAUTY_ENCOUNTER ; cooltrainerf + db MUSIC_BEAUTY_ENCOUNTER ; beauty + db MUSIC_POKEMANIAC_ENCOUNTER ; pokemaniac + db MUSIC_ROCKET_ENCOUNTER ; gruntm + db MUSIC_HIKER_ENCOUNTER ; gentleman + db MUSIC_BEAUTY_ENCOUNTER ; skier + db MUSIC_BEAUTY_ENCOUNTER ; teacher + db MUSIC_BEAUTY_ENCOUNTER ; sabrina + db MUSIC_YOUNGSTER_ENCOUNTER ; bug_catcher + db MUSIC_HIKER_ENCOUNTER ; fisher + db MUSIC_HIKER_ENCOUNTER ; swimmerm + db MUSIC_BEAUTY_ENCOUNTER ; swimmerf + db MUSIC_HIKER_ENCOUNTER ; sailor + db MUSIC_POKEMANIAC_ENCOUNTER ; super_nerd + db MUSIC_RIVAL_ENCOUNTER ; rival2 + db MUSIC_HIKER_ENCOUNTER ; guitarist + db MUSIC_HIKER_ENCOUNTER ; hiker + db MUSIC_HIKER_ENCOUNTER ; biker + db MUSIC_OFFICER_ENCOUNTER ; blaine + db MUSIC_POKEMANIAC_ENCOUNTER ; burglar + db MUSIC_HIKER_ENCOUNTER ; firebreather + db MUSIC_POKEMANIAC_ENCOUNTER ; juggler + db MUSIC_HIKER_ENCOUNTER ; blackbelt_t + db MUSIC_ROCKET_ENCOUNTER ; executivem + db MUSIC_YOUNGSTER_ENCOUNTER ; psychic_t + db MUSIC_LASS_ENCOUNTER ; picnicker + db MUSIC_YOUNGSTER_ENCOUNTER ; camper + db MUSIC_ROCKET_ENCOUNTER ; executivef + db MUSIC_SAGE_ENCOUNTER ; sage + db MUSIC_SAGE_ENCOUNTER ; medium + db MUSIC_HIKER_ENCOUNTER ; boarder + db MUSIC_HIKER_ENCOUNTER ; pokefanm + db MUSIC_KIMONO_ENCOUNTER ; kimono_girl + db MUSIC_LASS_ENCOUNTER ; twins + db MUSIC_BEAUTY_ENCOUNTER ; pokefanf + db MUSIC_HIKER_ENCOUNTER ; red + db MUSIC_RIVAL_ENCOUNTER ; blue + db MUSIC_HIKER_ENCOUNTER ; officer + db MUSIC_ROCKET_ENCOUNTER ; gruntf + db MUSIC_HIKER_ENCOUNTER ; mysticalman + db MUSIC_HIKER_ENCOUNTER + db MUSIC_HIKER_ENCOUNTER + db MUSIC_HIKER_ENCOUNTER diff --git a/engine/events/overworld.asm b/engine/events/overworld.asm index 68f7dcc3..82981450 100755 --- a/engine/events/overworld.asm +++ b/engine/events/overworld.asm @@ -360,7 +360,7 @@ CheckAbleToSurf: jr c, .asm_c980 CheckFlagHL ENGINE_ALWAYS_ON_BIKE jr nz, .asm_c986 - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp PLAYER_SURF jr z, .asm_c983 cp PLAYER_SURF_PIKA @@ -472,7 +472,7 @@ GetSurfDirection: ; c9ea (3:49ea) db FACE_RIGHT TrySurfOW:: - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp PLAYER_SURF_PIKA jr z, .quit cp PLAYER_SURF @@ -1389,7 +1389,7 @@ FishingRodFunction: ; cf91 dw Fish_NoFish ; 3:5013 Fish_CheckMap: - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp PLAYER_SURF jr z, .asm_cfc7 cp PLAYER_SURF_PIKA @@ -1575,7 +1575,7 @@ BicycleFunction: Functiond0c9: ; d0c9 (3:50c9) call CheckBikePermission jr c, .cant_bike - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp PLAYER_NORMAL jr z, .get_on_bike cp PLAYER_BIKE diff --git a/engine/main_menu.asm b/engine/main_menu.asm index 9a829be9..ff480e37 100755 --- a/engine/main_menu.asm +++ b/engine/main_menu.asm @@ -819,7 +819,7 @@ OakText2: text_jump _OakText2 start_asm ld a, MARILL - call PlayCry + call PlayMonCry call WaitSFX ld hl, OakText3 ; $606c ret diff --git a/engine/overworld/player_movement.asm b/engine/overworld/player_movement.asm index 61b45a72..1fdec4e2 100755 --- a/engine/overworld/player_movement.asm +++ b/engine/overworld/player_movement.asm @@ -24,7 +24,7 @@ Function10017: ; 10017 (4:4017) ret Function1002d: ; 1002d (4:402d) - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp PLAYER_NORMAL jr z, .asm_10044 cp PLAYER_SURF @@ -236,7 +236,7 @@ Function10147: ; 10147 (4:4147) ret Function1016b: ; 1016b (4:416b) - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp $4 jr z, Function101c0 cp $8 @@ -655,7 +655,7 @@ Function103b4: ; 103b4 (4:43b4) ret Function103ca: ; 103ca (4:43ca) - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp $1 ret z cp $2 @@ -699,7 +699,7 @@ Function103ee: ; 103ee (4:43ee) Function103f9: ; 103f9 (4:43f9) push bc ld a, $0 - ld [wPlayerBikeSurfState], a + ld [wPlayerState], a call ReplacePlayerSprite pop bc ret @@ -713,7 +713,7 @@ Function10404: ; 10404 (4:4404) ld a, [wPlayerStandingTile] call CheckIceTile jr nc, .asm_1041e - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp $2 jr nz, .asm_10420 .asm_1041e diff --git a/engine/specials.asm b/engine/specials.asm index 6cd4fa91..b26b6bf1 100755 --- a/engine/specials.asm +++ b/engine/specials.asm @@ -521,7 +521,7 @@ SnorlaxAwake: ; c5d6 (3:45d6) PlayCurMonCry: ; c60b (3:460b) ld a, [wCurPartySpecies] - jp PlayCry + jp PlayMonCry GameboyCheck: ; c611 (3:4611) ld a, [hCGB] diff --git a/engine/variables.asm b/engine/variables.asm index 4d67c2bf..e2a399f0 100755 --- a/engine/variables.asm +++ b/engine/variables.asm @@ -42,7 +42,7 @@ GetVarAction_:: dwb .CountCaughtMons, RETVAR_EXECUTE dwb .CountSeenMons, RETVAR_EXECUTE dwb .CountBadges, RETVAR_EXECUTE - dwb wPlayerBikeSurfState, RETVAR_ADDR_DE + dwb wPlayerState, RETVAR_ADDR_DE dwb .PlayerFacing, RETVAR_EXECUTE dwb hHours, RETVAR_STRBUF2 dwb .DayOfWeek, RETVAR_EXECUTE diff --git a/home/audio.asm b/home/audio.asm index 4e931ab4..bf080550 100644 --- a/home/audio.asm +++ b/home/audio.asm @@ -1,14 +1,14 @@ -DisableAudio:: ; 3d4f (0:3d4f) +MapSetup_Sound_Off:: ; 3d4f (0:3d4f) push hl push de push bc push af ld a, [hROMBank] push af - ld a, BANK(DisableAudio_) + ld a, BANK(_MapSetup_Sound_Off) ld [hROMBank], a ld [MBC3RomBank], a - call DisableAudio_ + call _MapSetup_Sound_Off pop af ld [hROMBank], a ld [MBC3RomBank], a @@ -25,10 +25,10 @@ UpdateSound:: ; 3d6b (0:3d6b) push af ld a, [hROMBank] push af - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) ld [hROMBank], a ld [MBC3RomBank], a - call UpdateSound_ + call _UpdateSound pop af ld [hROMBank], a ld [MBC3RomBank], a @@ -38,13 +38,13 @@ UpdateSound:: ; 3d6b (0:3d6b) pop hl ret -LoadMusicByte_:: +_LoadMusicByte:: ld [hROMBank], a ld [MBC3RomBank], a ld a, [de] ld [wCurMusicByte], a - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) ld [hROMBank], a ld [MBC3RomBank], a @@ -57,17 +57,17 @@ PlayMusic:: ; 3d98 (0:3d98) push af ld a, [hROMBank] push af - ld a, BANK(PlayMusic_) + ld a, BANK(_PlayMusic) ld [hROMBank], a ld [MBC3RomBank], a ld a, e and a jr z, .asm_3daf - call PlayMusic_ ; $4b30 + call _PlayMusic ; $4b30 jr .asm_3db2 .asm_3daf - call DisableAudio_ + call _MapSetup_Sound_Off .asm_3db2 pop af ld [hROMBank], a @@ -85,15 +85,15 @@ PlayMusic2:: push af ld a, [hROMBank] push af - ld a, BANK(PlayMusic_) + ld a, BANK(_PlayMusic) ld [hROMBank], a ld [MBC3RomBank], a push de ld de, MUSIC_NONE - call PlayMusic_ + call _PlayMusic call DelayFrame pop de - call PlayMusic_ + call _PlayMusic pop af ld [hROMBank], a ld [MBC3RomBank], a @@ -103,7 +103,7 @@ PlayMusic2:: pop hl ret -PlayCryHeader:: ; 3de4 (0:3de4) +PlayCry:: ; 3de4 (0:3de4) push hl push de push bc @@ -132,10 +132,10 @@ PlayCryHeader:: ; 3de4 (0:3de4) ld [wCryLength], a ld a, [hl] ld [wCryLength + 1], a - ld a, BANK(PlayCryHeader_) + ld a, BANK(_PlayCry) ld [hROMBank], a ld [MBC3RomBank], a - call PlayCryHeader_ + call _PlayCry pop af ld [hROMBank], a ld [MBC3RomBank], a @@ -158,12 +158,12 @@ PlaySFX:: ; 3e24 (0:3e24) .asm_3e33 ld a, [hROMBank] push af - ld a, BANK(PlaySFX_) ; $3a + ld a, BANK(_PlaySFX) ; $3a ld [hROMBank], a ld [MBC3RomBank], a ld a, e ld [wCurSFX], a - call PlaySFX_ ; $4c04 + call _PlaySFX ; $4c04 pop af ld [hROMBank], a ld [MBC3RomBank], a @@ -182,16 +182,16 @@ WaitPlaySFX:: WaitSFX:: ; 3e56 (0:3e56) push hl .asm_3e57 - ld hl, wChannel5Flags + ld hl, wChannel5Flags1 bit 0, [hl] jr nz, .asm_3e57 - ld hl, wChannel6Flags + ld hl, wChannel6Flags1 bit 0, [hl] jr nz, .asm_3e57 - ld hl, wChannel7Flags + ld hl, wChannel7Flags1 bit 0, [hl] jr nz, .asm_3e57 - ld hl, wChannel8Flags + ld hl, wChannel8Flags1 bit 0, [hl] jr nz, .asm_3e57 pop hl @@ -285,7 +285,7 @@ EnterMapMusic:: xor a ld [wDontPlayMapMusicOnReload], a ld de, MUSIC_BICYCLE - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp $1 jr z, .asm_3ef6 call GetMapMusic @@ -336,7 +336,7 @@ RestartMapMusic:: ret SpecialMapMusic:: ; 3f40 (0:3f40) - ld a, [wPlayerBikeSurfState] + ld a, [wPlayerState] cp PLAYER_SURF jr z, .surf cp PLAYER_SURF_PIKA @@ -411,16 +411,16 @@ Function3f7d:: ret CheckSFX:: ; 3fbc (0:3fbc) - ld a, [wChannel5Flags] + ld a, [wChannel5Flags1] bit 0, a jr nz, .asm_3fda - ld a, [wChannel6Flags] + ld a, [wChannel6Flags1] bit 0, a jr nz, .asm_3fda - ld a, [wChannel7Flags] + ld a, [wChannel7Flags1] bit 0, a jr nz, .asm_3fda - ld a, [wChannel8Flags] + ld a, [wChannel8Flags1] bit 0, a jr nz, .asm_3fda and a @@ -432,7 +432,7 @@ CheckSFX:: ; 3fbc (0:3fbc) TerminateExpBarSound:: xor a - ld [wChannel5Flags], a + ld [wChannel5Flags1], a ld [wSoundInput], a ld [rNR10], a ld [rNR11], a diff --git a/home/cry.asm b/home/cry.asm index 6a6dd561..3fcda0c3 100644 --- a/home/cry.asm +++ b/home/cry.asm @@ -3,15 +3,16 @@ PlayStereoCry:: ; 39f0 (0:39f0) ld a, $1 ld [wStereoPanningMask], a pop af - jr continue_cry_fn + jr _PlayMonCry -PlayCry:: ; 39f9 (0:39f9) +PlayMonCry:: ; 39f9 (0:39f9) push af xor a ld [wStereoPanningMask], a ld [wCryTracks], a pop af -continue_cry_fn + +_PlayMonCry:: push hl push de push bc @@ -19,7 +20,7 @@ continue_cry_fn jr c, .asm_3a12 ld e, c ld d, b - call PlayCryHeader + call PlayCry call WaitSFX .asm_3a12 pop bc diff --git a/home/init.asm b/home/init.asm index b340be6b..cf5c18c9 100644 --- a/home/init.asm +++ b/home/init.asm @@ -1,5 +1,5 @@ Reset:: ; 5b0 (0:05b0) - call DisableAudio + call MapSetup_Sound_Off xor a ld [hMapAnims], a call ClearPalettes @@ -136,7 +136,7 @@ Init:: ; 5d1 (0:05d1) ld a, $30 call Predef - call DisableAudio + call MapSetup_Sound_Off xor a ld [wMapMusic], a jp GameInit diff --git a/home/text.asm b/home/text.asm index b689701d..994cc7e5 100644 --- a/home/text.asm +++ b/home/text.asm @@ -796,7 +796,7 @@ Text_TX_CRY ld e, [hl] inc hl ld d, [hl] - call PlayCry + call PlayMonCry pop de pop hl pop bc diff --git a/home/vblank.asm b/home/vblank.asm index 07113cd3..485b875c 100644 --- a/home/vblank.asm +++ b/home/vblank.asm @@ -124,9 +124,9 @@ VBlank0:: ; 180 .ok2 call Joypad - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) rst Bankswitch - call UpdateSound_ + call _UpdateSound ld a, [wROMBankBackup] rst Bankswitch ld a, [hSeconds] @@ -181,9 +181,9 @@ VBlank1:: ; 1f4 ld [rIF], a ei - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) rst Bankswitch - call UpdateSound_ + call _UpdateSound ld a, [wROMBankBackup] rst Bankswitch ; enable ints @@ -230,9 +230,9 @@ VBlank4:: ; 255 call AskSerial - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) rst Bankswitch - call UpdateSound_ + call _UpdateSound ld a, [wROMBankBackup] rst Bankswitch @@ -271,9 +271,9 @@ VBlank5:: ; 278 ld [rIF], a ei - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) rst Bankswitch - call UpdateSound_ + call _UpdateSound ld a, [wROMBankBackup] rst Bankswitch di @@ -291,9 +291,9 @@ VBlank2:: ; 2b0 ld a, [hROMBank] ld [wROMBankBackup], a - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) rst Bankswitch - call UpdateSound_ + call _UpdateSound ld a, [wROMBankBackup] rst Bankswitch @@ -369,9 +369,9 @@ VBlank3:: ; 2c4 ld [rIF], a ei - ld a, BANK(UpdateSound_) + ld a, BANK(_UpdateSound) rst Bankswitch - call UpdateSound_ + call _UpdateSound ld a, [wROMBankBackup] rst Bankswitch di diff --git a/items/item_effects.asm b/items/item_effects.asm index 2e87ed74..51523d62 100755 --- a/items/item_effects.asm +++ b/items/item_effects.asm @@ -1417,7 +1417,7 @@ Functionf12c: ; f12c (3:712c) predef FlagPredef .asm_f15a xor a - ld [wDanger], a + ld [wLowHealthAlarm], a ld a, [wd002] cp REVIVE jr z, .asm_f16a @@ -1451,7 +1451,7 @@ FullRestore: ; f17e (3:717e) Functionf19a: ; f19a (3:719a) xor a - ld [wDanger], a + ld [wLowHealthAlarm], a call Functionf319 ld a, $20 call GetPartyParamLocation @@ -1528,7 +1528,7 @@ Functionf1ff: ; f1ff (3:71ff) ld a, $1 ret nc xor a - ld [wDanger], a + ld [wLowHealthAlarm], a call Functionf3eb call Functionf327 call RestoreBattlemonHP @@ -2060,7 +2060,7 @@ PokeFlute: ; f55c (3:755c) jp z, PrintText ld hl, Text_PlayedThePokeFlute ; $75c6 call PrintText - ld a, [wDanger] + ld a, [wLowHealthAlarm] and $80 jr nz, .asm_f59e .asm_f59e @@ -1,5 +1,6 @@ INCLUDE "macros/enum.asm" INCLUDE "macros/basestats.asm" +INCLUDE "macros/code.asm" INCLUDE "macros/scripts/audio.asm" INCLUDE "macros/scripts/maps.asm" @@ -102,14 +103,6 @@ dab: MACRO ; dwb address, bank endr ENDM -lb: MACRO ; r, hi, lo - ld \1, (\2 & $ff) << 8 + (\3 & $ff) - ENDM - -ln: MACRO ; r, hi, lo - ld \1, (\2 & $f) << 4 + (\3 & $f) - ENDM - bccoord equs "coord bc," decoord equs "coord de," hlcoord equs "coord hl," @@ -235,17 +228,6 @@ ENDM palettes EQUS "* 8" -ldpixel: MACRO -if _NARG >= 5 - lb \1, \2 * 8 + \4, \3 * 8 + \5 -else - lb \1, \2 * 8, \3 * 8 -endc -endm - -depixel EQUS "ldpixel de," -bcpixel EQUS "ldpixel bc," - dbpixel: MACRO if _NARG >= 4 db \1 * 8 + \3, \2 * 8 + \4 @@ -287,37 +269,6 @@ menu_coords: MACRO db \4, \3 ; end coords ENDM -jumptable: MACRO - ld a, [\2] - ld e, a - ld d, 0 - ld hl, \1 - add hl, de - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - jp hl -endm - -maskbits: macro -; returns to x -; usage in rejection sampling -; .loop -; call Random -; maskbits 30 -; and x -; cp 30 -; jr nc, .loop - -x = 1 -rept 8 -IF \1 > x -x = (x + 1) * 2 +- 1 -ENDC -endr -endm - homecall: MACRO ld a, [hROMBank] push af diff --git a/macros/code.asm b/macros/code.asm new file mode 100644 index 00000000..9429884c --- /dev/null +++ b/macros/code.asm @@ -0,0 +1,106 @@ +; Syntactic sugar macros + +lb: MACRO ; r, hi, lo + ld \1, ((\2) & $ff) << 8 | ((\3) & $ff) +ENDM + +ln: MACRO ; r, hi, lo + ld \1, ((\2) & $f) << 4 | ((\3) & $f) +ENDM + +ldpixel: MACRO +if _NARG >= 5 + lb \1, \2 * 8 + \4, \3 * 8 + \5 +else + lb \1, \2 * 8, \3 * 8 +endc +ENDM + +depixel EQUS "ldpixel de," +bcpixel EQUS "ldpixel bc," + +; Design patterns + +jumptable: MACRO + ld a, [\2] + ld e, a + ld d, 0 + ld hl, \1 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl +ENDM + +maskbits: MACRO +; masks just enough bits to cover the first argument +; the second argument is an optional shift amount +; e.g. "maskbits 26" becomes "and %00011111" (since 26 - 1 = %00011001) +; and "maskbits 3, 2" becomes "and %00001100" (since "maskbits 3" becomes %00000011) +; example usage in rejection sampling: +; .loop +; call Random +; maskbits 26 +; cp 26 +; jr nc, .loop +x = 1 +rept 8 +if x + 1 < (\1) +x = x << 1 | 1 +endc +endr +if _NARG == 2 + and x << (\2) +else + and x +endc +ENDM + +calc_sine_wave: MACRO +; input: a = a signed 6-bit value +; output: a = d * sin(a * pi/32) + and %111111 + cp %100000 + jr nc, .negative\@ + call .apply\@ + ld a, h + ret +.negative\@ + and %011111 + call .apply\@ + ld a, h + xor $ff + inc a + ret +.apply\@ + ld e, a + ld a, d + ld d, 0 +if _NARG == 1 + ld hl, \1 +else + ld hl, .sinetable\@ +endc + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, 0 +.multiply\@ ; factor amplitude + srl a + jr nc, .even\@ + add hl, de +.even\@ + sla e + rl d + and a + jr nz, .multiply\@ + ret +if _NARG == 0 +.sinetable\@ + sine_table 32 +endc +ENDM diff --git a/macros/wram.asm b/macros/wram.asm index d7ba1834..1df2ee28 100755 --- 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,14 +129,12 @@ 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) +\1PitchOffset:: db ; raises existing octaves (to repeat phrases) \1NoteDuration:: db ; frames remaining for the current note -\1Field0x16:: ds 1 ; c117 +\1Field16:: ds 1 ; c117 ds 1 ; c118 \1LoopCount:: db \1Tempo:: dw @@ -149,16 +147,16 @@ channel_struct: MACRO \1PitchWheelTarget:: dw ; frequency endpoint for pitch wheel \1PitchWheelAmount:: db ; c124 \1PitchWheelAmountFraction:: db ; c125 -\1Field0x25:: ds 1 ; c126 +\1Field25:: ds 1 ; c126 ds 1 ; c127 \1CryPitch:: dw -\1Field0x29:: ds 1 -\1Field0x2a:: ds 2 -\1Field0x2c:: ds 1 +\1Field29:: ds 1 +\1Field2a:: ds 2 +\1Field2c:: ds 1 \1NoteLength:: db ; frames per 16th note -\1Field0x2e:: ds 1 ; c12f -\1Field0x2f:: ds 1 ; c130 -\1Field0x30:: ds 1 ; c131 +\1Field2e:: ds 1 ; c12f +\1Field2f:: ds 1 ; c130 +\1Field30:: ds 1 ; c131 ds 1 ; c132 ENDM @@ -736,7 +736,9 @@ SECTION "bank6", ROMX, BANK[$6] SECTION "bank7", ROMX, BANK[$7] LoadMapGroupRoof:: - dr $1c000, $1ffbd + dr $1c000, $1f84c + +INCLUDE "audio/music/credits.asm" SECTION "bank8", ROMX, BANK[$8] dr $20000, $23e3d @@ -1382,7 +1384,9 @@ PlayBattleAnim:: dr $cc0d7, $cc283 BattleAnimCommands:: - dr $cc283, $d0000 + dr $cc283, $cfce3 + +INCLUDE "audio/music/postcredits.asm" SECTION "bank34", ROMX, BANK[$34] dr $d0000, $d4000 @@ -1445,21 +1449,12 @@ GoldSilverIntro: ENDC SECTION "bank3a", ROMX, BANK[$3a] -DisableAudio_:: - dr $e8000, $e805c - -UpdateSound_:: - dr $e805c, $e8b30 - -PlayMusic_:: - dr $e8b30, $e8b79 - -PlayCryHeader_:: - dr $e8b79, $e8c04 - -PlaySFX_:: -; dr $e8c04, $ec000 - dr $e8c04, $e9492 +INCLUDE "audio/engine.asm" +INCLUDE "data/trainers/encounter_music.asm" +INCLUDE "audio/music_pointers.asm" +INCLUDE "audio/music/nothing.asm" +INCLUDE "audio/cry_pointers.asm" +INCLUDE "audio/sfx_pointers.asm" INCLUDE "audio/music/route36.asm" INCLUDE "audio/music/rivalbattle.asm" @@ -1525,7 +1520,43 @@ INCLUDE "data/pokemon/cries.asm" INCLUDE "audio/cries.asm" SECTION "bank3d", ROMX, BANK[$3d] - dr $f4000, $f8000 +INCLUDE "audio/music/viridiancity.asm" +INCLUDE "audio/music/celadoncity.asm" +INCLUDE "audio/music/wildpokemonvictory.asm" +INCLUDE "audio/music/successfulcapture.asm" +INCLUDE "audio/music/gymleadervictory.asm" +INCLUDE "audio/music/mtmoonsquare.asm" +INCLUDE "audio/music/gym.asm" +INCLUDE "audio/music/pallettown.asm" +INCLUDE "audio/music/profoakspokemontalk.asm" +INCLUDE "audio/music/profoak.asm" +INCLUDE "audio/music/lookrival.asm" +INCLUDE "audio/music/aftertherivalfight.asm" +INCLUDE "audio/music/surf.asm" +INCLUDE "audio/music/nationalpark.asm" +INCLUDE "audio/music/azaleatown.asm" +INCLUDE "audio/music/cherrygrovecity.asm" +INCLUDE "audio/music/unioncave.asm" +INCLUDE "audio/music/johtowildbattle.asm" +INCLUDE "audio/music/johtowildbattlenight.asm" +INCLUDE "audio/music/johtotrainerbattle.asm" +INCLUDE "audio/music/lookyoungster.asm" +INCLUDE "audio/music/tintower.asm" +INCLUDE "audio/music/sprouttower.asm" +INCLUDE "audio/music/burnedtower.asm" +INCLUDE "audio/music/mom.asm" +INCLUDE "audio/music/victoryroad.asm" +INCLUDE "audio/music/pokemonlullaby.asm" +INCLUDE "audio/music/pokemonmarch.asm" +INCLUDE "audio/music/goldsilveropening.asm" +INCLUDE "audio/music/goldsilveropening2.asm" +INCLUDE "audio/music/lookhiker.asm" +INCLUDE "audio/music/lookrocket.asm" +INCLUDE "audio/music/rockettheme.asm" +INCLUDE "audio/music/mainmenu.asm" +INCLUDE "audio/music/lookkimonogirl.asm" +INCLUDE "audio/music/pokeflutechannel.asm" +INCLUDE "audio/music/bugcatchingcontest.asm" SECTION "bank3e", ROMX, BANK[$3e] Functionf8000:: @@ -73,7 +73,7 @@ wMusicNoiseSampleSet:: ; c1a4 ds 1 wSFXNoiseSampleSet:: ; c1a5 ds 1 -wDanger:: ; c1a6 +wLowHealthAlarm:: ; c1a6 ; bit 7: on/off ; bit 4: pitch ; bit 0-3: counter @@ -98,7 +98,7 @@ wCryLength:: ; c1b2 ds 2 wLastVolume:: ; c1b4 ds 1 -wc1b5:: ds 1 ; c1b5 +wUnusedMusicF9Flag:: ds 1 ; c1b5 wSFXPriority:: ; c1b6 ; if nonzero, turn off music when playing sfx ds 1 @@ -2991,7 +2991,7 @@ wLastDexMode:: ds 1 ; d67e wWhichRegisteredItem:: ds 1 ; d680 wRegisteredItem:: ds 1 ; d681 -wPlayerBikeSurfState:: ds 1 ; d682 +wPlayerState:: ds 1 ; d682 wd683:: ds 1 ; d683 wd684:: ds 1 ; d684 |