diff options
author | Rangi <35663410+Rangi42@users.noreply.github.com> | 2020-12-18 09:09:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-18 09:09:51 -0500 |
commit | 0e25150cab59a8f5822ad7cfad176e3a35b4dc71 (patch) | |
tree | bfdfeca0aaa7b708a4a971dc42a2a19a33c4a0cc | |
parent | b1ae1098d06d9865c767471e539fa65f77101aaa (diff) | |
parent | 89f8e366d65c15b8645564b3e2409070ac9717a4 (diff) |
Merge pull request #86 from ZoomTen/audio-engine
Disassemble the rest of the audio engine
-rw-r--r-- | audio/drumkits.inc | 140 | ||||
-rw-r--r-- | audio/engine.asm | 2345 | ||||
-rw-r--r-- | audio/intensity_overrides.inc | 33 | ||||
-rw-r--r-- | audio/notes.inc | 26 | ||||
-rw-r--r-- | audio/wave_overrides.inc | 11 | ||||
-rw-r--r-- | audio/wave_samples.inc | 27 | ||||
-rw-r--r-- | constants/audio_constants.asm | 17 | ||||
-rw-r--r-- | home/cry.asm | 6 | ||||
-rw-r--r-- | layout.link | 10 | ||||
-rw-r--r-- | ram/wram.asm | 31 | ||||
-rwxr-xr-x | shim.sym | 13 |
11 files changed, 2601 insertions, 58 deletions
diff --git a/audio/drumkits.inc b/audio/drumkits.inc new file mode 100644 index 0000000..642d5fd --- /dev/null +++ b/audio/drumkits.inc @@ -0,0 +1,140 @@ +Drumkits: + dw Drumkit0 + dw Drumkit1 + dw Drumkit2 + dw Drum00 + dw Drum00 + dw Drum00 + +Drumkit0: + dw Drum00 + dw Snare1 + dw Snare2 + dw Snare3 + dw Snare4 + dw Drum05 + dw Triangle1 + dw Triangle2 + dw HiHat1 + dw Snare5 + dw Snare6 + dw Snare7 + dw HiHat2 + +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 + +Drum00: + sound_ret + +Snare1: + noise_note 32, 12, 1, 51 + sound_ret + +Snare2: + noise_note 32, 11, 1, 51 + sound_ret + +Snare3: + noise_note 32, 10, 1, 51 + sound_ret + +Snare4: + noise_note 32, 8, 1, 51 + sound_ret + +Drum05: +; Reverse cymbal / wooshing sound + noise_note 39, 8, 4, 55 + noise_note 38, 8, 4, 54 + noise_note 37, 8, 3, 53 + noise_note 36, 8, 3, 52 + noise_note 35, 8, 2, 51 + noise_note 34, 8, 1, 50 + sound_ret + +Triangle1: + noise_note 32, 5, 1, 42 + sound_ret + +Triangle2: + noise_note 33, 4, 1, 43 + noise_note 32, 6, 1, 42 + sound_ret + +HiHat1: + noise_note 32, 8, 1, 16 + sound_ret + +Snare5: + noise_note 32, 8, 2, 35 + sound_ret + +Snare6: + noise_note 32, 8, 2, 37 + sound_ret + +Snare7: + noise_note 32, 8, 2, 38 + sound_ret + +HiHat2: + noise_note 32, 10, 1, 16 + sound_ret + +HiHat3: + noise_note 32, 10, 2, 17 + sound_ret + +Snare8: + noise_note 32, 10, 2, 80 + sound_ret + +Triangle3: + noise_note 32, 10, 1, 24 + noise_note 32, 3, 1, 51 + sound_ret + +Triangle4: + noise_note 34, 9, 1, 40 + noise_note 32, 7, 1, 24 + sound_ret + +Snare9: + noise_note 32, 9, 1, 34 + sound_ret + +Snare10: + noise_note 32, 7, 1, 34 + sound_ret + +Snare11: + noise_note 32, 6, 1, 34 + sound_ret diff --git a/audio/engine.asm b/audio/engine.asm index 157734c..f722621 100644 --- a/audio/engine.asm +++ b/audio/engine.asm @@ -1,6 +1,6 @@ INCLUDE "constants.asm" -SECTION "audio/engine.asm@Audio", ROMX +SECTION "audio/engine.asm", ROMX _DisableAudio:: push hl @@ -38,7 +38,7 @@ _DisableAudio:: or d jr nz, .clear - ld a, $77 + ld a, MAX_VOLUME ld [wVolume], a pop af @@ -94,7 +94,7 @@ UpdateChannel: .noteover call DisablePitchWheel - call Functione884f + call ParseMusic .continue_sound_update call Functione80b6 @@ -170,15 +170,15 @@ Functione80b6: ld [wCurTrackFrequency], a ld a, [hl] ld [wCurTrackFrequency + 1], a - ld a, $3f - ld [wc195], a + ld a, $3F + ld [wSoundLength], a call Functione85d8 - call Functione87f9 - call Functione8839 + call ReadNoiseSample + call HaltMusicWhileSFXPlaying call IsChannelSFXOn jr nc, .end - call Functione80fa + call UpdateChannels ld hl, CHANNEL_TRACKS add hl, bc ld a, [wSoundOutput] @@ -192,7 +192,7 @@ Functione80b6: ld [hl], a ret -Functione80fa: +UpdateChannels: ld hl, .jumptable ld a, [wCurChannel] maskbits NUM_CHANNELS @@ -206,9 +206,280 @@ Functione80fa: jp hl .jumptable - ; TODO +; Music channels + dw .Channel1 + dw .Channel2 + dw .Channel3 + dw .Channel4 +; SFX channels + dw .Channel5 + dw .Channel6 + dw .Channel7 + dw .Channel8 + +.Channel1: + ld a, [wLowHealthAlarm] + bit 7, a + ret nz + +.Channel5: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_PITCH_SWEEP, [hl] + jr z, .ch1_no_sweep + + ld a, [wPitchSweep] + ldh [rNR10], a + +.ch1_no_sweep + bit NOTE_REST, [hl] + jr nz, .ch1_rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .ch1_noise_sampling + bit NOTE_FREQ_OVERRIDE, [hl] + call nz, .ch1_freq_override + bit NOTE_INTENSITY_OVERRIDE, [hl] + call nz, .ch1_intensity_override + bit NOTE_DUTY_OVERRIDE, [hl] + call nz, .ch1_duty_override + ret + +.ch1_rest + ld a, %1000 ; stop envelope + ldh [rNR12], a + ld a, [wCurTrackFrequency + 1] + or $80 ; restart ch1 + ldh [rNR14], a + ret + +.ch1_noise_sampling + ld hl, wCurTrackDuty + ld a, [wSoundLength] + 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 + +.ch1_duty_override + ld a, [wCurTrackDuty] + ldh a, [rNR11] + and $3f + or d + ldh [rNR11], a + ret + +.ch1_intensity_override + ld a, [wCurTrackIntensity] + ldh [rNR12], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR14], a + ret + +.ch1_freq_override + ld a, [wCurTrackFrequency] + ldh [rNR13], a + ld a, [wCurTrackFrequency + 1] + ldh [rNR14], a + ret + +.Channel2: +.Channel6: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_REST, [hl] + jr nz, .ch2_rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .ch2_noise_sampling + bit NOTE_FREQ_OVERRIDE, [hl] + call nz, .ch2_freq_override + bit NOTE_INTENSITY_OVERRIDE, [hl] + call nz, .ch2_intensity_override + bit NOTE_DUTY_OVERRIDE, [hl] + call nz, .ch2_duty_override + ret + +.ch2_rest + ld a, $08 + ldh [rNR22], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR24], a + ret + +.ch2_noise_sampling + ld hl, wCurTrackDuty + ld a, [wSoundLength] + or [hl] + ldh [rNR21], a + ld a, [wCurTrackIntensity] + ldh [rNR22], a + ld a, [wCurTrackFrequency] + ldh [rNR23], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR24], a + ret + +.ch2_duty_override + ld a, [wCurTrackDuty] + ld d, a + ldh a, [rNR21] + and $3f + or d + ldh [rNR21], a + ret + +.ch2_intensity_override + ld a, [wCurTrackIntensity] + ldh [rNR22], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR24], a + ret + +.ch2_freq_override + ld a, [wCurTrackFrequency] + ldh [rNR23], a + ld a, [wCurTrackFrequency + 1] + ldh [rNR24], a + ret + +.Channel3: +.Channel7: + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + bit NOTE_REST, [hl] + jr nz, .ch3_rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .ch3_noise_sampling + bit NOTE_FREQ_OVERRIDE, [hl] + call nz, .ch3_freq_override + bit NOTE_INTENSITY_OVERRIDE, [hl] + call nz, .ch3_intensity_override + ret + +.ch3_rest + xor a + ldh [rNR30], a + ret + +.ch3_noise_sampling + ld a, [wSoundLength] + ldh [rNR31], a + xor a + ldh [rNR30], a + call .load_wave_pattern + ld a, $80 + ldh [rNR30], a + ld a, [wCurTrackFrequency] + ldh [rNR33], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR34], a + ret + +.ch3_freq_override + ld a, [wCurTrackFrequency] + ldh [rNR33], a + ld a, [wCurTrackFrequency + 1] + ldh [rNR34], a + ret + +.ch3_intensity_override + xor a + ldh [rNR30], a + call .load_wave_pattern + ld a, $80 + ldh [rNR30], a + ld a, [wCurTrackFrequency] + ldh [rNR33], a + ld a, [wCurTrackFrequency + 1] + or $80 + ldh [rNR34], a + ret + +.load_wave_pattern + push hl + ld a, [wCurTrackIntensity] +; only patterns 0 - 9 are valid + and $f + ld l, a + ld h, 0 +; hl << 4 (hl * $10), because each pattern is $f bytes +rept 4 + add hl, hl +endr + ld de, WaveSamples + add hl, de + ld de, rWave_0 + push bc + ld b, $10 +.load_pattern + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .load_pattern + + pop bc + 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] + jr nz, .ch4_rest + bit NOTE_NOISE_SAMPLING, [hl] + jr nz, .ch4_noise_sampling + bit NOTE_FREQ_OVERRIDE, [hl] + call nz, .ch4_freq_override + bit NOTE_INTENSITY_OVERRIDE, [hl] + call nz, .ch4_intensity_override + ret + +.ch4_rest + ld a, $08 + ldh [rNR42], a + ld a, $80 + ldh [rNR44], a + ret + +.ch4_noise_sampling + ld a, [wSoundLength] + ldh [rNR41], a + ld a, [wCurTrackIntensity] + ldh [rNR42], a + ld a, [wCurTrackFrequency] + ldh [rNR43], a + ld a, $80 + ldh [rNR44], a + ret + +.ch4_freq_override + ld a, [wCurTrackFrequency] + ldh [rNR43], a + ret + +.ch4_intensity_override + ld a, [wCurTrackIntensity] + ldh [rNR42], a + ld a, $80 + ldh [rNR44], a + ret -SECTION "audio/engine.asm@IsChannelSFXOn", ROMX IsChannelSFXOn: ; If it's not a valid channel, return ld a, [wCurChannel] @@ -249,12 +520,11 @@ IsAnySFXOn: scf ret -SECTION "audio/engine.asm@Functione82f0", ROMX Functione82f0: call IncrementTempo call PlayDanger call FadeMusic - call Functione841d + call DoSweepingFade ld a, [wVolume] ld [rNR50], a ld a, [wSoundOutput] @@ -502,7 +772,1676 @@ FadeMusic: ld [wVolume], a ret -SECTION "audio/engine.asm@Audio engine, part 2", ROMX +DoSweepingFade:: +; performs a sweeping fade effect starting from the +; left channel, then the right, then repeats + + ld a, [wSweepingFadeIndex] + and a + ret z + +; first nybble of wSweepingFadeIndex is the subroutine index +; second is the fade length + + swap a + and 7 + ld e, a + ld d, 0 + ld hl, .jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.jumptable + dw .DoFade1 + dw .DoFade2 + dw .DoFade3 + dw .DoFade4 + dw .DoFade5 + dw .DoFade6 + dw .DoFade1 + dw .DoFade1 + +.DoFade1: + ld a, 1 + call .SetIndex + xor a + ld [wSweepingFadeCounter], a + ld [wVolume], a + +.DoFade2: + call .LeftChannel + call .DecrementCounter + ret nc + call .IncreaseVolume + ret nc + ld a, 2 + call .SetIndex + +.DoFade3: + call .LeftChannel + call .DecrementCounter + ret nc + call .DecreaseVolume + ret nc + ld a, 3 + call .SetIndex + +.DoFade4: + call .RightChannel + call .DecrementCounter + ret nc + call .IncreaseVolume + ret nc + ld a, 4 + call .SetIndex + +.DoFade5: + call .RightChannel + call .DecrementCounter + ret nc + call .DecreaseVolume + ret nc + ld a, 0 + call .SetIndex + ret + +.DoFade6: + xor a + ld [wSweepingFadeIndex], a + ld a, MAX_VOLUME + ld [wVolume], a + ret + +.SetIndex: + swap a + ld d, a + ld a, [wSweepingFadeIndex] + and $f + or d + ld [wSweepingFadeIndex], a + ret + +.DecrementCounter: + ld a, [wSweepingFadeCounter] + and a + jr z, .reset_counter + dec a + ld [wSweepingFadeCounter], a + and a + ret + .reset_counter + ld a, [wSweepingFadeIndex] + and $f + ld [wSweepingFadeCounter], a + scf + ret + +.IncreaseVolume: + ld a, [wVolume] + and 7 + cp 7 + jr nc, .max_volume + inc a + ld d, a + swap a + or d + ld [wVolume], a + and a + ret +.max_volume + scf + ret + +.DecreaseVolume: + ld a, [wVolume] + and $f + jr z, .min_volume + dec a + ld d, a + swap a + or d + ld [wVolume], a + and a + ret +.min_volume + scf + ret + +.LeftChannel: + call IsAnySFXOn + ret c + ld a, [wSoundOutput] + and $f0 + ld [wSoundOutput], a + ret + +.RightChannel: + call IsAnySFXOn + ret c + ld a, [wSoundOutput] + and $0f + ld [wSoundOutput], a + ret + +LoadNote: + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_PITCH_WHEEL, [hl] + call nz, .get_note + bit SOUND_VIBRATO, [hl] + call nz, .vibrato + bit SOUND_UNKN_0E, [hl] + call nz, .flag_0e + bit SOUND_UNKN_0D, [hl] + call nz, .flag_0d + bit SOUND_UNKN_0B, [hl] + call nz, .flag_0b + ret + +.get_note + push hl + 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 + 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, 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] + 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] + 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, 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 + push bc + ld hl, wCurNoteDuration + ld b, 0 + +.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 + add [hl] + ld d, b + pop bc + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT + add hl, bc + ld [hl], d + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT_FRACTION + add hl, bc + ld [hl], a + ld hl, CHANNEL_FIELD25 + add hl, bc + xor a + ld [hl], a + pop hl + ret + +.vibrato + push hl + ld hl, CHANNEL_VIBRATO_DELAY + add hl, bc + ld a, [hl] + ld hl, CHANNEL_VIBRATO_DELAY_COUNT + add hl, bc + ld [hl], a + pop hl + ret + +.flag_0e + push hl + ld hl, CHANNEL_FLAGS3 + add hl, bc + res NOTE_INTENSITY_OVERRIDE, [hl] + pop hl + ret + +.flag_0d + push hl + ld hl, CHANNEL_FIELD2A + 1 + add hl, bc + xor a + ld [hl], a + pop hl + ret + +.flag_0b + push hl + ld hl, CHANNEL_FIELD2C + add hl, bc + ld a, [hl] + ld hl, CHANNEL_FIELD25 + 1 + add hl, bc + ld [hl], a + pop hl + ret + +Functione85d8:: + ld hl, CHANNEL_FLAGS2 + add hl, bc + bit SOUND_DUTY, [hl] + call nz, HandleDuty + bit SOUND_UNKN_0E, [hl] + call nz, Handle_0e + bit SOUND_CRY_PITCH, [hl] + call nz, Handle_crypitch + bit SOUND_PITCH_WHEEL, [hl] + call nz, ApplyPitchSlide + bit SOUND_VIBRATO, [hl] + call nz, HandleVibrato + bit SOUND_UNKN_0D, [hl] + call nz, Handle_0d + bit SOUND_UNKN_0B, [hl] + call nz, Handle_0b + bit SOUND_UNKN_0F, [hl] + call nz, HandleNoise + ret + +HandleDuty: + push hl + 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 0, [hl] + pop hl + ret + +ApplyPitchSlide: + push hl + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, CHANNEL_FLAGS3 + add hl, bc + bit SOUND_PITCH_WHEEL_DIR, [hl] + jr z, .decreasing + + ld hl, CHANNEL_PITCH_WHEEL_AMOUNT + add hl, bc + ld l, [hl] + ld h, 0 + add hl, de + ld d, h + ld e, l + 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 + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld a, [hl] + cp d + jp c, .finished_pitch_slide + jr nz, .continue_pitch_slide + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, [hl] + cp e + jp c, .finished_pitch_slide + jr .continue_pitch_slide + +.decreasing + 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 + 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 + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld a, d + cp [hl] + jr c, .finished_pitch_slide + jr nz, .continue_pitch_slide + ld hl, CHANNEL_PITCH_WHEEL_TARGET + add hl, bc + ld a, e + cp [hl] + jr nc, .continue_pitch_slide + +.finished_pitch_slide + ld hl, CHANNEL_FLAGS2 + add hl, bc + res 1, [hl] + ld hl, CHANNEL_FLAGS3 + add hl, bc + res 1, [hl] + ld hl, CHANNEL_PITCH_WHEEL_TARGET + 1 + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + +.continue_pitch_slide + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set 1, [hl] + pop hl + ret + + +HandleVibrato: + push hl + ld hl, CHANNEL_VIBRATO_DELAY_COUNT + add hl, bc + ld a, [hl] + and a + jr nz, .subexit + + ld hl, CHANNEL_VIBRATO_RATE + add hl, bc + ld a, [hl] + and $0f + jr z, .toggle + +.subexit + dec [hl] + jr .quit + +.toggle + ld a, [hl] + swap [hl] + or [hl] + ld [hl], a + ld hl, CHANNEL_VIBRATO_EXTENT + add hl, bc + ld a, [hl] + and a + jr z, .quit + + ld hl, CHANNEL_FLAGS3 + add hl, bc + bit SOUND_VIBRATO_DIR, [hl] + jr z, .down + + res SOUND_VIBRATO_DIR, [hl] + and $0f + ld d, a + ld a, [wCurTrackFrequency] + sub d + jr nc, .no_carry + + xor a + jr .no_carry + +.down + set SOUND_VIBRATO_DIR, [hl] + and $f0 + swap a + ld d, a + ld a, [wCurTrackFrequency] + add d + jr nc, .no_carry + + ld a, $ff + +.no_carry + ld [wCurTrackFrequency], a + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_FREQ_OVERRIDE, [hl] + +.quit + pop hl + ret + + +Handle_0b: + push hl + ld hl, CHANNEL_FIELD25 + 1 + add hl, bc + ld a, [hl] + and a + jr z, .set_rest + + dec [hl] + jr .done + +.set_rest + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] + +.done + pop hl + ret + + +Handle_crypitch: + push hl + ld hl, CHANNEL_CRY_PITCH + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, wCurTrackFrequency + push hl + ld a, [hli] + ld h, [hl] + ld l, a + add hl, de + ld e, l + ld d, h + pop hl + ld [hl], e + inc hl + ld [hl], d + pop hl + ret + + +Handle_0e: + push hl + ld hl, CHANNEL_FLAGS3 + add hl, bc + bit SOUND_UNKN_12, [hl] + jr nz, .skip + + set SOUND_UNKN_12, [hl] + jr .done + +.skip + res SOUND_UNKN_12, [hl] + ld hl, CHANNEL_PITCH + add hl, bc + ld a, [hl] + and a + jr z, .done + + ld hl, CHANNEL_FIELD29 + add hl, bc + add [hl] + ld e, a + ld hl, CHANNEL_OCTAVE + add hl, bc + ld d, [hl] + call GetFrequency + ld hl, wCurTrackFrequency + ld [hl], e + inc hl + ld [hl], d + +.done + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set SOUND_PITCH_WHEEL_DIR, [hl] + pop hl + ret + + +Handle_0d: + push hl + ld hl, CHANNEL_FIELD2A + add hl, bc + ld e, [hl] + ld d, 0 + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp CHAN3 + jr nz, .not_ch3 + + ld hl, WaveOverrides + call GetFromTable + jr c, .rest_done + + ld d, a + ld a, [wCurTrackIntensity] + and $c0 + or d + jr .intensity_done + +.not_ch3 + ld hl, IntensityOverrides + call GetFromTable + jr nc, .intensity_done + +.rest_done + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] + pop hl + ret + + +.intensity_done + ld [wCurTrackIntensity], a + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_INTENSITY_OVERRIDE, [hl] + pop hl + ret + + +GetFromTable: + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, CHANNEL_FIELD2A + 1 + add hl, bc + push hl + ld l, [hl] + ld h, 0 + add hl, de + ld a, [hl] + pop hl + cp $ff + jr z, .carry + + cp $fe + jr nz, .done_nocarry + + xor a + ld [hl], a + ld a, [de] + +.done_nocarry + inc [hl] + and a + ret +.carry + scf + ret + + +HandleNoise: + ld hl, CHANNEL_FIELD2E + add hl, bc + ld a, [hl] + and a + jr z, .skip + + dec [hl] + ld hl, CHANNEL_FIELD30 + add hl, bc + ld a, [hl] + ld hl, CHANNEL_TRACKS + add hl, bc + ld [hl], a + ret + +.skip + ld hl, CHANNEL_FIELD2F + add hl, bc + ld a, [hl] + and a + jr z, .skip2 + + dec [hl] + ld hl, CHANNEL_FIELD30 + add hl, bc + ld a, [hl] + swap a + or [hl] + ld hl, CHANNEL_TRACKS + add hl, bc + ld [hl], a + ret + +.skip2 + ld hl, CHANNEL_FIELD30 + add hl, bc + ld a, [hl] + swap a + ld hl, CHANNEL_TRACKS + add hl, bc + ld [hl], a + ld hl, CHANNEL_FLAGS2 + add hl, bc + res SOUND_UNKN_0F, [hl] + ret + + +ReadNoiseSample:: + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_NOISE, [hl] + ret z + + ld a, [wNoiseSampleDelay] + and a + jr z, .get_new_sample + + dec a + ld [wNoiseSampleDelay], a + ret + +.get_new_sample + ld hl, wNoiseSampleAddress + ld e, [hl] + inc hl + ld d, [hl] + ld a, [de] + inc de + cp $ff + jr z, .done + + and $0f + 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 + +.done + ret + + +HaltMusicWhileSFXPlaying:: + ld a, [wSFXPriority] + and a + ret z + + ld a, [wCurChannel] + cp CHAN5 + ret nc + + call IsAnySFXOn + ret nc + + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] + ret + + +ParseMusic:: + call GetMusicByte + cp sound_ret_cmd + jr z, .end_music + + cp FIRST_MUSIC_CMD + jr nc, .parse_commands + + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_SFX, [hl] + jr nz, .parse_sfx_or_rest + + bit SOUND_REST, [hl] + jr nz, .parse_sfx_or_rest + + bit SOUND_NOISE, [hl] + jr nz, .parse_noise + + call _ParseMusic + ret + +.parse_sfx_or_rest + call ParseSFXOrRest + ret + +.parse_noise + call GetNoiseSample + ret + +.end_music + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_SUBROUTINE, [hl] + jr nz, .parse_commands + + call IsChannelSFXOn + jr nc, .ok + + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_REST, [hl] + call nz, RestoreVolume + ld a, [wCurChannel] + cp CHAN5 + jr nz, .ok + + xor a + ldh [rNR10], a + +.ok + call StopChannel + ret + +.parse_commands + call ParseMusicCommand + jr ParseMusic + +RestoreVolume: + 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 + + +_ParseMusic: + ld a, [wCurMusicByte] + and $f + call SetNoteDuration + ld a, [wCurMusicByte] + swap a + and $f + jr z, .rest + + ld hl, CHANNEL_PITCH + add hl, bc + ld [hl], a + ld e, a + ld hl, CHANNEL_OCTAVE + add hl, bc + ld d, [hl] + 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] + call LoadNote + ret + + +.rest + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_REST, [hl] + ret + + +ParseSFXOrRest: +; turn noise sampling on + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set NOTE_NOISE_SAMPLING, [hl] + ld a, [wCurMusicByte] + call SetNoteDuration + +; update volume envelope from next param + call GetMusicByte + ld hl, CHANNEL_INTENSITY + add hl, bc + ld [hl], a + +; update lo frequence from next param + call GetMusicByte + ld hl, CHANNEL_FREQUENCY + add hl, bc + ld [hl], a + +; on noise channel? + 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: + ld a, [wCurChannel] + cp CHAN4 + ret nz + + ld a, [wCurMusicByte] + and $f + call SetNoteDuration + + ld a, [wNoiseSampleSet] + ld e, a + ld d, 0 + ld hl, Drumkits + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + + ld a, [wCurMusicByte] + swap a + and $f + ret z + + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld [wNoiseSampleAddress], a + ld a, [hl] + ld [wNoiseSampleAddress + 1], a + xor a + ld [wNoiseSampleDelay], a + ret + + +ParseMusicCommand: + ld a, [wCurMusicByte] + sub FIRST_MUSIC_CMD + ld e, a + ld d, 0 + ld hl, MusicCommands + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +MusicCommands: + dw Music_Octave8 + dw Music_Octave7 + dw Music_Octave6 + dw Music_Octave5 + dw Music_Octave4 + dw Music_Octave3 + dw Music_Octave2 + dw Music_Octave1 + dw Music_NoteType + dw Music_Transpose + dw Music_Tempo + dw Music_DutyCycle + dw Music_VolumeEnvelope + dw Music_PitchSweep + dw Music_DutyCyclePattern + dw Music_ToggleSFX + dw Music_PitchSlide + dw Music_Vibrato + dw MusicE2 + dw Music_ToggleNoise + dw Music_ForceStereoPanning + dw Music_Volume + dw Music_PitchOffset + dw MusicE7 + dw MusicE8 + dw Music_TempoRelative + dw Music_RestartChannel + dw Music_NewSong + dw Music_SFXPriorityOn + dw Music_SFXPriorityOff + dw MusicEE + dw Music_StereoPanning + dw MusicF0 + dw MusicF1 + dw MusicF2 + dw MusicF3 + dw MusicF4 + dw MusicF5 + dw MusicF6 + dw MusicF7 + dw MusicF8 + dw MusicF9 + dw Music_SetCondition + dw Music_JumpIf + dw Music_Jump + dw Music_Loop + dw Music_Call + dw Music_Ret + +MusicF0: +MusicF1: +MusicF2: +MusicF3: +MusicF4: +MusicF5: +MusicF6: +MusicF7: +MusicF8: + ret + +Music_Ret: + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_SUBROUTINE, [hl] + 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_Call: + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + push de + 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 + pop de + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_SUBROUTINE, [hl] + ret + +Music_Jump: + 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_Loop: + call GetMusicByte + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_LOOPING, [hl] + jr nz, .checkloop + + and a + jr z, .loop + + dec a + set SOUND_LOOPING, [hl] + ld hl, CHANNEL_LOOP_COUNT + add hl, bc + ld [hl], a + +.checkloop + ld hl, CHANNEL_LOOP_COUNT + add hl, bc + ld a, [hl] + and a + jr z, .endloop + dec [hl] + +.loop + 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 + +.endloop + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_LOOPING, [hl] + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + inc de + inc de + ld [hl], d + dec hl + ld [hl], e + ret + +Music_SetCondition: + call GetMusicByte + ld hl, CHANNEL_CONDITION + add hl, bc + ld [hl], a + ret + +Music_JumpIf: + call GetMusicByte + ld hl, CHANNEL_CONDITION + add hl, bc + cp [hl] + jr z, .jump + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + inc de + inc de + ld [hl], d + dec hl + ld [hl], e + ret + +.jump + 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 + +MusicEE: + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + ld e, a + ld d, 0 + ld hl, wChannel1JumpCondition + add hl, de + ld a, [hl] + and a + jr nz, .jump + + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + inc de + inc de + ld [hl], d + dec hl + ld [hl], e + ret + +.jump + ld [hl], 0 + 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 + +MusicF9: + ld a, 1 + ld [wc1b3], a + ret + +MusicE2: + 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: + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_VIBRATO, [hl] + res SOUND_VIBRATO, [hl] + call GetMusicByte + ld hl, CHANNEL_VIBRATO_DELAY + add hl, bc + ld [hl], a + call GetMusicByte + ld hl, CHANNEL_VIBRATO_EXTENT + add hl, bc + ld d, a + and $f0 + swap a + srl a + ld e, a + adc 0 + swap a + or e + ld [hl], a + ld hl, CHANNEL_VIBRATO_RATE + add hl, bc + ld a, d + and $0f + ld d, a + swap a + or d + ld [hl], a + ret + +Music_PitchSlide: + call GetMusicByte + ld [wCurNoteDuration], a + call GetMusicByte + ld d, a + and $f + ld e, a + 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_PitchOffset: + 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: + 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_DutyCyclePattern: + ld hl, CHANNEL_FLAGS2 + add hl, bc + set SOUND_DUTY, [hl] + call GetMusicByte + rrca + rrca + ld hl, CHANNEL_SFX_DUTY_LOOP + add hl, bc + ld [hl], a + and $c0 + ld hl, CHANNEL_DUTY_CYCLE + add hl, bc + ld [hl], a + ret + +MusicE8: + 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: + 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: + ld hl, CHANNEL_FLAGS1 + add hl, bc + bit SOUND_NOISE, [hl] + jr z, .on + res SOUND_NOISE, [hl] + ret +.on + set SOUND_NOISE, [hl] + call GetMusicByte + ld [wNoiseSampleSet], a + ret + +Music_NoteType: + call GetMusicByte + ld hl, CHANNEL_NOTE_LENGTH + add hl, bc + ld [hl], a + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp CHAN4 + ret z + call Music_VolumeEnvelope + ret + +Music_PitchSweep: + call GetMusicByte + ld [wPitchSweep], a + ld hl, CHANNEL_NOTE_FLAGS + add hl, bc + set 3, [hl] + ret + +Music_DutyCycle: + call GetMusicByte + rrca + rrca + and $c0 + ld hl, CHANNEL_DUTY_CYCLE + add hl, bc + ld [hl], a + ret + + +Music_VolumeEnvelope: + call GetMusicByte + ld hl, CHANNEL_INTENSITY + add hl, bc + ld [hl], a + ret + +Music_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: + ld hl, CHANNEL_OCTAVE + add hl, bc + ld a, [wCurMusicByte] + and 7 + ld [hl], a + ret + +Music_Transpose: + call GetMusicByte + ld hl, CHANNEL_PITCH_OFFSET + add hl, bc + ld [hl], a + ret + +Music_StereoPanning: + ld a, [wce5f] + bit 5, a + ret z + +Music_ForceStereoPanning: + call SetLRTracks + call GetMusicByte + ld hl, CHANNEL_TRACKS + add hl, bc + and [hl] + ld [hl], a + ret + +Music_Volume: + call GetMusicByte + ld a, [wMusicFade] + and a + ret nz + ld a, [wCurMusicByte] + ld [wVolume], a + ret + +Music_TempoRelative: + 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: + ld a, 1 + ld [wSFXPriority], a + ret + +Music_SFXPriorityOff: + xor a + ld [wSFXPriority], a + ret + +Music_RestartChannel: + ld hl, CHANNEL_MUSIC_ID + add hl, bc + ld a, [hli] + ld [wMusicID], a + ld a, [hl] + ld [wMusicID + 1], a + ld hl, CHANNEL_MUSIC_BANK + add hl, bc + ld a, [hl] + ld [wMusicBank], a + call GetMusicByte + ld l, a + call GetMusicByte + ld h, a + ld e, [hl] + inc hl + ld d, [hl] + push bc + call LoadChannel + call StartChannel + pop bc + ret + +Music_NewSong: + call GetMusicByte + ld e, a + call GetMusicByte + ld d, a + push bc + call _PlayMusic + pop bc + ret + +GetMusicByte: + push hl + push de + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, CHANNEL_MUSIC_BANK + add hl, bc + ld a, [hl] + call _LoadMusicByte + ld [wCurMusicByte], a + inc de + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + ld [hl], e + inc hl + ld [hl], d + pop de + pop hl + ret + + +GetFrequency: +; generate frequency +; input: +; d: octave +; e: pitch +; output: +; de: frequency + +; get octave + ld hl, CHANNEL_PITCH_OFFSET + add hl, bc + ld a, [hl] + swap a + and $f + add d + + push af + + ld hl, CHANNEL_PITCH_OFFSET + add hl, bc + ld a, [hl] + and $f + ld l, a + ld d, 0 + ld h, d + add hl, de + add hl, hl + + ld de, FrequencyTable + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + + pop af + +.loop +; [7 - octave] loops + cp 7 + jr nc, .ok + + sra d + rr e + inc a + jr .loop + +.ok + ld a, d + and $07 + ld d, a + ret + + +SetNoteDuration: +; input: a = note duration in 16ths + + inc a + ld e, a + ld d, 0 + ld hl, CHANNEL_NOTE_LENGTH + add hl, bc + ld a, [hl] + ld l, 0 + call .Multiply + ld a, l + ld hl, CHANNEL_TEMPO + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, CHANNEL_FIELD16 + add hl, bc + ld l, [hl] + call .Multiply + ld e, l + ld d, h + ld hl, CHANNEL_FIELD16 + add hl, bc + ld [hl], e + 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 + jr nc, .skip + +; add the remainder to the result + add hl, de + +.skip +; de * 2 + sla e + rl d + +; done multiplying? + and a + jr nz, .loop + ret SetGlobalTempo: push bc @@ -573,7 +2512,7 @@ SetLRTracks: maskbits NUM_MUSIC_CHANS ld e, a ld d, 0 - ld hl, $52B3 ; FIXME + ld hl, LRTracks add hl, de ld a, [hl] ld hl, CHANNEL_TRACKS @@ -588,29 +2527,399 @@ _PlayMusic:: ld [hl], e inc hl ld [hl], d - ld hl, Music + ld hl, SongHeaderPointers + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld [wMusicBank], a + ld e, [hl] + inc hl + ld d, [hl] + call LoadMusicByte + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a +.loop + push af + call LoadChannel + call StartChannel + pop af + dec a + jr nz, .loop + xor a + ld [wc1b3], a + ld [wChannel1JumpCondition], a + ld [wChannel2JumpCondition], a + ld [wChannel3JumpCondition], a + ld [wChannel4JumpCondition], a + ret + + +_PlayCryHeader:: + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + + ld hl, CryHeaderPointers + add hl, de + add hl, de + add hl, de + + ld a, [hli] + ld [wMusicBank], a + + ld e, [hl] + inc hl + ld d, [hl] + + call LoadMusicByte + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a + +.loop + push af + call LoadChannel + + 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 + + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp 3 + jr nc, .start + +; no tempo for ch4 + 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 + + ld a, [wce5f] + bit 5, a + jr z, .next + + 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 + + ld a, [wLastVolume] + and a + jr nz, .end + + ld a, [wVolume] + ld [wLastVolume], a + ld a, MAX_VOLUME + ld [wVolume], a + +.end +; stop playing music + ld a, 1 + ld [wSFXPriority], a + ret + + +_PlaySFX:: + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + ld hl, SFXPointers +; three byte pointers + add hl, de + add hl, de + add hl, de +; get bank + ld a, [hli] + ld [wMusicBank], a + ld e, [hl] + inc hl + ld d, [hl] + call LoadMusicByte + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a + +.start_channels + push af + call LoadChannel + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_SFX, [hl] + call StartChannel + pop af + dec a + jr nz, .start_channels + ret + + ld a, [wce5f] + bit 5, a ; Stereo flag? + jr z, _PlaySFX + + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + + ld hl, SFXPointers add hl, de add hl, de add hl, de + ld a, [hli] ld [wMusicBank], a ld e, [hl] inc hl ld d, [hl] + call LoadMusicByte rlca rlca maskbits NUM_MUSIC_CHANS inc a + .loop push af call LoadChannel + ld hl, CHANNEL_FLAGS1 + + add hl, bc + set SOUND_SFX, [hl] + push de + + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + ld e, a + ld d, 0 + ld hl, LRTracks + 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 + jr c, .skip + + 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 + + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_CHANNEL_ON, [hl] + + pop af + dec a + jr nz, .loop + + ret + + ld hl, wMusicID + ld [hl], e + inc hl + ld [hl], d + ld hl, SFXPointers + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld [wMusicBank], a + ld e, [hl] + inc hl + ld d, [hl] + call LoadMusicByte + rlca + rlca + maskbits NUM_MUSIC_CHANS + inc a + +.cry_channels + push af + call LoadChannel + ld hl, CHANNEL_FLAGS1 + add hl, bc + set SOUND_SFX, [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 + ld a, [wCurChannel] + maskbits NUM_MUSIC_CHANS + cp 3 + jr nc, .cry_ok + + ld hl, CHANNEL_TEMPO + add hl, bc + ld a, [wCryLength] + ld [hli], a + ld a, [wCryLength + 1] + ld [hl], a + +.cry_ok call StartChannel pop af dec a + jr nz, .cry_channels + + ret + + +LoadChannel:: + call LoadMusicByte + inc de + and 7 + 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] + ld hl, CHANNEL_FLAGS1 + add hl, bc + res SOUND_CHANNEL_ON, [hl] + call ChannelInit + ld hl, CHANNEL_MUSIC_ADDRESS + add hl, bc + call LoadMusicByte + ld [hli], a + inc de + call LoadMusicByte + ld [hl], a + inc de + ld hl, CHANNEL_MUSIC_ID + add hl, bc + ld a, [wMusicID] + ld [hli], a + ld a, [wMusicID + 1] + ld [hl], a + ld hl, CHANNEL_MUSIC_BANK + add hl, bc + ld a, [wMusicBank] + ld [hl], a + ret + + +ChannelInit: + push de + xor a + ld hl, CHANNEL_MUSIC_ID + add hl, bc + ld e, CHANNEL_STRUCT_LENGTH + +.loop + ld [hli], a + dec e jr nz, .loop + + ld hl, CHANNEL_TEMPO + add hl, bc xor a - ; TODO + ld [hli], a + inc a + ld [hl], a + ld hl, CHANNEL_NOTE_LENGTH + add hl, bc + ld [hl], a + pop de + ret + + +LoadMusicByte:: + ld a, [wMusicBank] + call _LoadMusicByte + ret + +INCLUDE "audio/notes.inc" + +INCLUDE "audio/wave_samples.inc" + +INCLUDE "audio/wave_overrides.inc" + +INCLUDE "audio/intensity_overrides.inc" + +INCLUDE "audio/drumkits.inc" + +LRTracks: +; bit corresponds to track # +; hi: left channel +; lo: right channel + 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 -SECTION "audio/engine.asm@Song Header Pointers", ROMX INCLUDE "audio/song_header_pointers.inc" diff --git a/audio/intensity_overrides.inc b/audio/intensity_overrides.inc new file mode 100644 index 0000000..3740427 --- /dev/null +++ b/audio/intensity_overrides.inc @@ -0,0 +1,33 @@ +IntensityOverrides: + dw .override1 + dw .override2 + dw .override3 + dw .override4 + dw Drumkits + dw Drumkits + +.override1 + db $11, $21, $31, $41, $51, $61, $71, $81, $91, $A1, $B1, $C1, $D1, $E1 + db $F1, $F1, $F1, $F1, $F1, $F1, $E1, $E1, $E1, $E1, $D1, $D1, $D1, $D1 + db $C1, $C1, $C1, $C1, $B1, $B1, $B1, $B1, $A1, $A1, $A1, $A1, $91, $91 + db $91, $91, $81, $81, $81, $81, $71, $71, $71, $71, $61, $61, $61, $61 + db $51, $51, $51, $51, $41, $41, $41, $41, $31, $31, $31, $31, $21, $21 + db $21, $21, $11, $11, $11, $11 + db -1 + +.override2 + db $11, $91, $D1, $F1, $F1, $F1, $F1, $F1, $D1, $D1, $D1, $D1, $A1, $A1 + db $A1, $A1, $81, $81, $81, $81, $61, $61, $61, $61, $41, $41, $41, $41 + db $21, $21, $21, $21 + db -1 + +.override3 + db $31, $51, $A1, $51, $F1, $51, $F1, $51, $F1, $51, $F1, $51, $D1, $51 + db $D1, $51, $B1, $51, $B1, $51, $91, $51, $91, $51, $71, $51, $71, $51 + db $51, $51, $51, $51, $31, $51, $31, $51, $11, $51, $11, $51 + db -1 + +.override4 + db $F0, $E0, $D0, $C0, $B0, $A0, $90, $80, $70, $60, $50, $40, $30, $20 + db $10, $00 + db -1 diff --git a/audio/notes.inc b/audio/notes.inc new file mode 100644 index 0000000..eeb8495 --- /dev/null +++ b/audio/notes.inc @@ -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/wave_overrides.inc b/audio/wave_overrides.inc new file mode 100644 index 0000000..8876dc6 --- /dev/null +++ b/audio/wave_overrides.inc @@ -0,0 +1,11 @@ +WaveOverrides: + dw .override + dw .override + dw .override + dw .override + dw .override + dw .override + +.override + db $0A, $0B, $0C, $0D, $0E, $0F, $10, $11, $12, $13, $14, $15, $16, $17 + db -1 diff --git a/audio/wave_samples.inc b/audio/wave_samples.inc new file mode 100644 index 0000000..bc40b9d --- /dev/null +++ b/audio/wave_samples.inc @@ -0,0 +1,27 @@ +WaveSamples: + 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 ; 0 + 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 ; 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 ; 2 + 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 ; 3 + 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 ; 4 + dn 0, 0, 2, 3, 4, 5, 6, 7, 8, 10, 12, 7, 14, 14, 15, 7, 7, 15, 14, 14, 13, 7, 10, 8, 7, 6, 5, 4, 3, 2, 1, 4 ; 5 + dn 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 15 ; 6 + dn 0, 15, 0, 15, 0, 14, 0, 14, 0, 13, 0, 13, 0, 12, 0, 12, 0, 11, 0, 11, 0, 10, 0, 10, 0, 9, 0, 9, 0, 8, 0, 8 ; 7 + dn 0, 7, 0, 7, 0, 6, 0, 6, 0, 5, 0, 5, 0, 4, 0, 4, 0, 3, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0 ; 8 + dn 15, 15, 15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8 ; 9 + dn 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; a + dn 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; b + dn 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; c + dn 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; d + dn 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; e + dn 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; f + +; inaccessible beyond this point? + dn 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + dn 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; diff --git a/constants/audio_constants.asm b/constants/audio_constants.asm index 51dc36f..39a99f6 100644 --- a/constants/audio_constants.asm +++ b/constants/audio_constants.asm @@ -42,7 +42,7 @@ 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_PITCH_OFFSET EQUS "(wChannel1StartingOctave - wChannel1)" CHANNEL_NOTE_DURATION EQUS "(wChannel1NoteDuration - wChannel1)" CHANNEL_FIELD16 EQUS "(wChannel1Field16 - wChannel1)" CHANNEL_LOOP_COUNT EQUS "(wChannel1LoopCount - wChannel1)" @@ -93,16 +93,17 @@ NOISE_CHAN_F EQU 2 ; bit set in CHAN5-CHAN7 const_def const SOUND_VIBRATO_DIR ; 0 const SOUND_PITCH_WHEEL_DIR ; 1 + const SOUND_UNKN_12 ; 2 ; NoteFlags 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 + const NOTE_DUTY_OVERRIDE ; 0 + const NOTE_FREQ_OVERRIDE ; 1 + const NOTE_INTENSITY_OVERRIDE ; 2 + const NOTE_PITCH_SWEEP ; 3 + const NOTE_NOISE_SAMPLING ; 4 + const NOTE_REST ; 5 + const NOTE_VIBRATO_OVERRIDE ; 6 ; wVolume VOLUME_SO1_F EQU 3 diff --git a/home/cry.asm b/home/cry.asm index 3dbe63f..994bc29 100644 --- a/home/cry.asm +++ b/home/cry.asm @@ -5,15 +5,15 @@ SECTION "home/cry.asm", ROM0 PlayStereoCry:: push af ld a, $1 - ld [wc1b9], a + ld [wStereoPanningMask], a pop af jr _PlayCry PlayCry:: push af xor a - ld [wc1b9], a - ld [wc1ba], a + ld [wStereoPanningMask], a + ld [wCryTracks], a pop af _PlayCry: push hl diff --git a/layout.link b/layout.link index a52e750..ab1e182 100644 --- a/layout.link +++ b/layout.link @@ -906,15 +906,7 @@ ROMX $39 ROMX $3a org $4000 - "audio/engine.asm@Audio" - org $42bd - "audio/engine.asm@IsChannelSFXOn" - "audio/engine.asm@Functione82f0" - org $4cee - "audio/engine.asm@Audio engine, part 2" - org $52c7 - "audio/engine.asm@Song Header Pointers" - org $52ee + "audio/engine.asm" "audio/songs/none.asm" ROMX $3b diff --git a/ram/wram.asm b/ram/wram.asm index 56e87b8..6b7fa0f 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -22,9 +22,9 @@ wChannel8:: channel_struct wChannel8 wCurTrackDuty:: db wCurTrackIntensity:: db wCurTrackFrequency:: dw -wc195:: db - - ds 2 ; TODO +wSoundLength:: db +wCurNoteDuration:: db +wCurMusicByte:: db wCurChannel:: db wVolume:: db @@ -34,12 +34,15 @@ wSoundOutput:: ; bit 0-3: ch1-4 so1 on/off db - ds 1 ; TODO +wPitchSweep:: db wMusicID:: dw wMusicBank:: db - ds 5 ; TODO +wNoiseSampleAddress:: dw +wNoiseSampleDelay:: db +wc1a2:: db +wNoiseSampleSet:: db wLowHealthAlarm:: ; bit 7: on/off @@ -58,19 +61,27 @@ wMusicFadeID:: wMusicFadeIDLow:: db wMusicFadeIDHigh:: db - ds 2 ; TODO +wSweepingFadeIndex:: db +wSweepingFadeCounter:: db wIncrementTempo: dw wMapMusic:: db wCryPitch:: dw wCryLength:: dw - ds 7 ; TODO +wLastVolume:: db +wc1b3:: db +wSFXPriority:: db +wChannel1JumpCondition:: db +wChannel2JumpCondition:: db +wChannel3JumpCondition:: db +wChannel4JumpCondition:: db + +wStereoPanningMask:: db -wc1b9:: db -wc1ba:: db +wCryTracks:: db ; either wChannelsEnd or wMusicEnd, unsure - ds 1 ; TODO +wSFXDuration:: db wMusicInitEnd:: @@ -151,22 +151,15 @@ 33:625D BattleAnim_Sine_e 33:6263 BattleAnim_Cosine_e -3A:441D Functione841d -3A:45D8 Functione85d8 -3A:47F9 Functione87f9 -3A:4839 Functione8839 -3A:484F Functione884f -3A:4D9D _PlayCryHeader -3A:4E22 _PlaySFX -3A:4F11 LoadChannel -3A:4F6C LoadMusicByte -3A:52C7 Music +3A:536D SFXPointers +3A:52FB CryHeaderPointers 3F:40E9 InGameDebugMenu 3F:4305 TrainerGear 3F:4C24 Functionfcc24 3F:4E3E Functionfce3e 3F:5B66 Functionfdb66 +3F:6255 Functionfe255 3F:64CE MonsterTest 3F:654E PicTest 3F:6750 PicTestMenu |