diff options
Diffstat (limited to 'audio/engine.asm')
-rw-r--r-- | audio/engine.asm | 2345 |
1 files changed, 2327 insertions, 18 deletions
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" |