diff options
-rw-r--r-- | audio/engine_1.asm | 402 | ||||
-rw-r--r-- | audio/engine_2.asm | 1163 | ||||
-rw-r--r-- | audio/engine_3.asm | 1115 | ||||
-rw-r--r-- | audio/music/yellow/meetjessiejames.asm | 1 | ||||
-rw-r--r-- | constants/music_constants.asm | 28 | ||||
-rwxr-xr-x | macros/audio_macros.asm | 8 | ||||
-rwxr-xr-x | wram.asm | 20 |
7 files changed, 1439 insertions, 1298 deletions
diff --git a/audio/engine_1.asm b/audio/engine_1.asm index 8b021acf..a8389819 100644 --- a/audio/engine_1.asm +++ b/audio/engine_1.asm @@ -57,25 +57,25 @@ Audio1_ApplyMusicAffects: .startChecks ld hl, wChannelFlags1 add hl, bc - bit BIT_ROTATE_DUTY, [hl] + bit BIT_ROTATE_DUTY_CYCLE, [hl] jr z, .checkForExecuteMusic - call Audio1_ApplyDutyCycle + call Audio1_ApplyDutyCyclePattern .checkForExecuteMusic ld b, 0 ld hl, wChannelFlags2 add hl, bc bit BIT_EXECUTE_MUSIC, [hl] - jr nz, .checkForPitchBend + jr nz, .checkForPitchSlide ld hl, wChannelFlags1 add hl, bc bit BIT_NOISE_OR_SFX, [hl] - jr nz, .skipPitchBendVibrato -.checkForPitchBend + jr nz, .skipPitchSlideVibrato +.checkForPitchSlide ld hl, wChannelFlags1 add hl, bc - bit BIT_PITCH_BEND_ON, [hl] + bit BIT_PITCH_SLIDE_ON, [hl] jr z, .checkVibratoDelay - jp Audio1_ApplyPitchBend + jp Audio1_ApplyPitchSlide .checkVibratoDelay ld hl, wChannelVibratoDelayCounters add hl, bc @@ -83,7 +83,7 @@ Audio1_ApplyMusicAffects: and a ; check if delay is over jr z, .checkForVibrato dec [hl] ; otherwise, dec delay -.skipPitchBendVibrato +.skipPitchSlideVibrato ret .checkForVibrato ld hl, wChannelVibratoExtents @@ -142,7 +142,7 @@ Audio1_ApplyMusicAffects: ret ; this routine executes all music commands that take up no time, -; like tempo changes, duty changes etc. and doesn't return +; like tempo changes, duty cycle changes etc. and doesn't return ; until the first note is reached Audio1_PlayNextNote: ; reload the vibrato delay counter @@ -155,20 +155,20 @@ Audio1_PlayNextNote: ld hl, wChannelFlags1 add hl, bc - res BIT_PITCH_BEND_ON, [hl] - res BIT_PITCH_BEND_DECREASING, [hl] - call Audio1_endchannel + res BIT_PITCH_SLIDE_ON, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] + call Audio1_sound_ret ret -Audio1_endchannel: +Audio1_sound_ret: call Audio1_GetNextMusicByte ld d, a - cp $ff ; is this command an endchannel? - jp nz, Audio1_callchannel ; no + cp $ff ; is this command a sound_ret? + jp nz, Audio1_sound_call ; no ld b, 0 ld hl, wChannelFlags1 add hl, bc - bit BIT_CHANNEL_CALL, [hl] + bit BIT_SOUND_CALL, [hl] jr nz, .returnFromCall ld a, c cp Ch4 @@ -187,15 +187,15 @@ Audio1_endchannel: ld a, $80 ld [rNR30], a .skipSfxChannel3 - jr nz, .asm_9222 + jr nz, .dontDisable ld a, [wDisableChannelOutputWhenSfxEnds] and a - jr z, .asm_9222 + jr z, .dontDisable xor a ld [wDisableChannelOutputWhenSfxEnds], a jr .disableChannelOutput -.asm_9222 - jr .asm_9248 +.dontDisable + jr .afterDisable .returnFromCall res 1, [hl] ld d, $0 @@ -215,19 +215,19 @@ Audio1_endchannel: inc de ld a, [de] ld [hl], a ; loads channel address to return to - jp Audio1_endchannel + jp Audio1_sound_ret .disableChannelOutput ld hl, Audio1_HWChannelDisableMasks add hl, bc ld a, [rNR51] and [hl] ld [rNR51], a -.asm_9248 +.afterDisable ld a, [wChannelSoundIDs + Ch5] cp CRY_SFX_START - jr nc, .asm_9251 + jr nc, .maybeCry jr .skipCry -.asm_9251 +.maybeCry ld a, [wChannelSoundIDs + Ch5] cp CRY_SFX_END jr z, .skipCry @@ -236,10 +236,10 @@ Audio1_endchannel: .cry ld a, c cp Ch5 - jr z, .asm_9265 + jr z, .skipRewind call Audio1_GoBackOneCommandIfCry ret c -.asm_9265 +.skipRewind ld a, [wSavedVolume] ld [rNR50], a xor a @@ -250,9 +250,9 @@ Audio1_endchannel: ld [hl], b ret -Audio1_callchannel: - cp $fd ; is this command a callchannel? - jp nz, Audio1_loopchannel ; no +Audio1_sound_call: + cp $fd ; is this command a sound_call? + jp nz, Audio1_sound_loop ; no call Audio1_GetNextMusicByte push af call Audio1_GetNextMusicByte @@ -284,12 +284,12 @@ Audio1_callchannel: ld b, $0 ld hl, wChannelFlags1 add hl, bc - set BIT_CHANNEL_CALL, [hl] ; set the call flag - jp Audio1_endchannel + set BIT_SOUND_CALL, [hl] ; set the call flag + jp Audio1_sound_ret -Audio1_loopchannel: - cp $fe ; is this command a loopchannel? - jp nz, Audio1_notetype ; no +Audio1_sound_loop: + cp $fe ; is this command a sound_loop? + jp nz, Audio1_note_type ; no call Audio1_GetNextMusicByte ld e, a and a @@ -304,7 +304,7 @@ Audio1_loopchannel: ld [hl], a call Audio1_GetNextMusicByte ; skip pointer call Audio1_GetNextMusicByte - jp Audio1_endchannel + jp Audio1_sound_ret .loopAgain ; inc loop count inc a ld [hl], a @@ -323,12 +323,12 @@ Audio1_loopchannel: pop af ld [hli], a ld [hl], b - jp Audio1_endchannel + jp Audio1_sound_ret -Audio1_notetype: +Audio1_note_type: and $f0 - cp $d0 ; is this command a notetype? - jp nz, Audio1_toggleperfectpitch ; no + cp $d0 ; is this command a note_type? + jp nz, Audio1_toggle_perfect_pitch ; no ld a, d and $f ld b, $0 @@ -367,11 +367,11 @@ Audio1_notetype: add hl, bc ld [hl], d .noiseChannel - jp Audio1_endchannel + jp Audio1_sound_ret -Audio1_toggleperfectpitch: +Audio1_toggle_perfect_pitch: ld a, d - cp $e8 ; is this command a toggleperfectpitch? + cp $e8 ; is this command a toggle_perfect_pitch? jr nz, Audio1_vibrato ; no ld b, 0 ld hl, wChannelFlags1 @@ -379,11 +379,11 @@ Audio1_toggleperfectpitch: ld a, [hl] xor $1 ld [hl], a ; flip bit 0 of wChannelFlags1 - jp Audio1_endchannel + jp Audio1_sound_ret Audio1_vibrato: cp $ea ; is this command a vibrato? - jr nz, Audio1_pitchbend ; no + jr nz, Audio1_pitch_slide ; no call Audio1_GetNextMusicByte ld b, 0 ld hl, wChannelVibratoDelayCounters @@ -427,14 +427,14 @@ Audio1_vibrato: or d ld [hl], a - jp Audio1_endchannel + jp Audio1_sound_ret -Audio1_pitchbend: - cp $eb ; is this command a pitchbend? - jr nz, Audio1_duty ; no +Audio1_pitch_slide: + cp $eb ; is this command a pitch_slide? + jr nz, Audio1_duty_cycle ; no call Audio1_GetNextMusicByte ld b, 0 - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, bc ld [hl], a call Audio1_GetNextMusicByte @@ -446,36 +446,36 @@ Audio1_pitchbend: and $f call Audio1_CalculateFrequency ld b, 0 - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld [hl], d - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld [hl], e ld b, 0 ld hl, wChannelFlags1 add hl, bc - set BIT_PITCH_BEND_ON, [hl] + set BIT_PITCH_SLIDE_ON, [hl] call Audio1_GetNextMusicByte ld d, a - jp Audio1_notelength + jp Audio1_note_length -Audio1_duty: - cp $ec ; is this command a duty? +Audio1_duty_cycle: + cp $ec ; is this command a duty_cycle? jr nz, Audio1_tempo ; no call Audio1_GetNextMusicByte rrca rrca and $c0 ld b, 0 - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, bc - ld [hl], a ; store duty - jp Audio1_endchannel + ld [hl], a ; store duty cycle + jp Audio1_sound_ret Audio1_tempo: cp $ed ; is this command a tempo? - jr nz, Audio1_stereopanning ; no + jr nz, Audio1_stereo_panning ; no ld a, c cp Ch5 jr nc, .sfxChannel @@ -500,19 +500,19 @@ Audio1_tempo: ld [wChannelNoteDelayCountersFractionalPart + 6], a ld [wChannelNoteDelayCountersFractionalPart + 7], a .musicChannelDone - jp Audio1_endchannel + jp Audio1_sound_ret -Audio1_stereopanning: - cp $ee ; is this command a stereopanning? +Audio1_stereo_panning: + cp $ee ; is this command a stereo_panning? jr nz, Audio1_unknownmusic0xef ; no call Audio1_GetNextMusicByte ld [wStereoPanning], a ; store panning - jp Audio1_endchannel + jp Audio1_sound_ret ; this appears to never be used Audio1_unknownmusic0xef: cp $ef ; is this command an unknownmusic0xef? - jr nz, Audio1_dutycycle ; no + jr nz, Audio1_duty_cycle_pattern ; no call Audio1_GetNextMusicByte push bc call Audio1_PlaySound @@ -525,72 +525,72 @@ Audio1_unknownmusic0xef: xor a ld [wChannelSoundIDs + Ch8], a .skip - jp Audio1_endchannel + jp Audio1_sound_ret -Audio1_dutycycle: - cp $fc ; is this command a dutycycle? +Audio1_duty_cycle_pattern: + cp $fc ; is this command a duty_cycle_pattern? jr nz, Audio1_volume ; no call Audio1_GetNextMusicByte ld b, 0 - ld hl, wChannelDutyCycles + ld hl, wChannelDutyCyclePatterns add hl, bc - ld [hl], a ; store full cycle - and $c0 - ld hl, wChannelDuties + ld [hl], a ; store full pattern + and %11000000 + ld hl, wChannelDutyCycles add hl, bc - ld [hl], a ; store first duty + ld [hl], a ; store first duty cycle ld hl, wChannelFlags1 add hl, bc - set BIT_ROTATE_DUTY, [hl] - jp Audio1_endchannel + set BIT_ROTATE_DUTY_CYCLE, [hl] + jp Audio1_sound_ret Audio1_volume: cp $f0 ; is this command a volume? - jr nz, Audio1_executemusic ; no + jr nz, Audio1_execute_music ; no call Audio1_GetNextMusicByte ld [rNR50], a ; store volume - jp Audio1_endchannel + jp Audio1_sound_ret -Audio1_executemusic: - cp $f8 ; is this command an executemusic? +Audio1_execute_music: + cp $f8 ; is this command an execute_music? jr nz, Audio1_octave ; no ld b, $0 ld hl, wChannelFlags2 add hl, bc set BIT_EXECUTE_MUSIC, [hl] - jp Audio1_endchannel + jp Audio1_sound_ret Audio1_octave: and $f0 cp $e0 ; is this command an octave? - jr nz, Audio1_sfxnote ; no + jr nz, Audio1_sfx_note ; no ld hl, wChannelOctaves ld b, 0 add hl, bc ld a, d and $f ld [hl], a ; store low nibble as octave - jp Audio1_endchannel + jp Audio1_sound_ret -; sfxnote is either squarenote or noisenote depending on the channel -Audio1_sfxnote: - cp $20 ; is this command a sfxnote? - jr nz, Audio1_pitchenvelope +; sfx_note is either square_note or noise_note depending on the channel +Audio1_sfx_note: + cp $20 ; is this command a sfx_note? + jr nz, Audio1_pitch_sweep ld a, c cp Ch4 ; is this a noise or sfx channel? - jr c, Audio1_pitchenvelope ; no + jr c, Audio1_pitch_sweep ; no ld b, 0 ld hl, wChannelFlags2 add hl, bc - bit BIT_EXECUTE_MUSIC, [hl] ; is executemusic being used? - jr nz, Audio1_pitchenvelope ; yes - call Audio1_notelength + bit BIT_EXECUTE_MUSIC, [hl] ; is execute_music being used? + jr nz, Audio1_pitch_sweep ; yes + call Audio1_note_length -; This code seems to do the same thing as what Audio1_ApplyDutyAndSoundLength +; This code seems to do the same thing as what Audio1_ApplyDutyCycleAndSoundLength ; does below. ld d, a ld b, 0 - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, bc ld a, [hl] or d @@ -619,18 +619,18 @@ Audio1_sfxnote: .skip ld d, a push de - call Audio1_ApplyDutyAndSoundLength + call Audio1_ApplyDutyCycleAndSoundLength call Audio1_EnableChannelOutput pop de call Audio1_ApplyWavePatternAndFrequency ret -Audio1_pitchenvelope: +Audio1_pitch_sweep: ld a, c cp Ch5 jr c, Audio1_note ; if not a sfx ld a, d - cp $10 ; is this command a pitchenvelope? + cp $10 ; is this command a pitch_sweep? jr nz, Audio1_note ; no ld b, $0 ld hl, wChannelFlags2 @@ -639,17 +639,27 @@ Audio1_pitchenvelope: jr nz, Audio1_note ; no call Audio1_GetNextMusicByte ld [rNR10], a - jp Audio1_endchannel + jp Audio1_sound_ret Audio1_note: ld a, c cp Ch4 - jr nz, Audio1_notelength ; if not noise channel + jr nz, Audio1_note_length ; if not noise channel ld a, d and $f0 cp $b0 ; is this command a dnote? - jr z, Audio1_dnote - jr nc, Audio1_notelength ; no + jr z, .dnote + jr nc, Audio1_note_length ; no + + ; this executes when on the noise channel and + ; the command id is less than $b0 + ; in this case, the upper nybble is used as the noise instrument ($1-$a) + ; and the lower nybble is the length minus 1 (0-15) + ; however, this doesn't work for instrument #2 because the command id + ; is captured by the noise_note command (command id $2x) + ; this essentially acts like a dnote command that is only 1 byte + ; instead of 2 and can only be used with instruments 1 and 3 through 10 + ; this is unused by the game swap a ld b, a ld a, d @@ -658,26 +668,26 @@ Audio1_note: ld a, b push de push bc - jr asm_94fd + jr .playDnote -Audio1_dnote: +.dnote ld a, d and $f push af push bc call Audio1_GetNextMusicByte ; get dnote instrument -asm_94fd +.playDnote ld d, a ld a, [wDisableChannelOutputWhenSfxEnds] and a - jr nz, .asm_9508 + jr nz, .skipDnote ld a, d call Audio1_PlaySound -.asm_9508 +.skipDnote pop bc pop de -Audio1_notelength: +Audio1_note_length: ld a, d push af and $f @@ -727,15 +737,15 @@ Audio1_notelength: ld hl, wChannelFlags2 add hl, bc bit BIT_EXECUTE_MUSIC, [hl] - jr nz, Audio1_notepitch + jr nz, Audio1_note_pitch ld hl, wChannelFlags1 add hl, bc bit BIT_NOISE_OR_SFX, [hl] - jr z, Audio1_notepitch + jr z, Audio1_note_pitch pop hl ret -Audio1_notepitch: +Audio1_note_pitch: pop af and $f0 cp $c0 ; compare to rest @@ -784,10 +794,10 @@ Audio1_notepitch: ld b, 0 ld hl, wChannelFlags1 add hl, bc - bit BIT_PITCH_BEND_ON, [hl] - jr z, .skipPitchBend - call Audio1_InitPitchBendVars -.skipPitchBend + bit BIT_PITCH_SLIDE_ON, [hl] + jr z, .skipPitchSlide + call Audio1_InitPitchSlideVars +.skipPitchSlide push de ld a, c cp Ch5 @@ -812,13 +822,13 @@ Audio1_notepitch: ld b, REG_VOLUME_ENVELOPE call Audio1_GetRegisterPointer ld [hl], d - call Audio1_ApplyDutyAndSoundLength + call Audio1_ApplyDutyCycleAndSoundLength call Audio1_EnableChannelOutput pop de ld b, $0 ld hl, wChannelFlags1 add hl, bc - bit BIT_PERFECT_PITCH, [hl] ; has toggleperfectpitch been used? + bit BIT_PERFECT_PITCH, [hl] ; has toggle_perfect_pitch been used? jr z, .skipFrequencyInc inc e ; if yes, increment the frequency by 1 jr nc, .skipFrequencyInc @@ -867,7 +877,7 @@ Audio1_EnableChannelOutput: ld [rNR51], a ret -Audio1_ApplyDutyAndSoundLength: +Audio1_ApplyDutyCycleAndSoundLength: ld b, 0 ld hl, wChannelNoteDelayCounters ; use the note delay as sound length add hl, bc @@ -877,11 +887,11 @@ Audio1_ApplyDutyAndSoundLength: jr z, .skipDuty ; if music channel 3 cp Ch7 jr z, .skipDuty ; if sfx channel 3 -; include duty (except on channel 3 which doesn't have it) +; include duty cycle (except on channel 3 which doesn't have it) ld a, d and $3f ld d, a - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, bc ld a, [hl] or d @@ -1022,29 +1032,29 @@ Audio1_IsCry: scf ret -Audio1_ApplyPitchBend: +Audio1_ApplyPitchSlide: ld hl, wChannelFlags1 add hl, bc - bit BIT_PITCH_BEND_DECREASING, [hl] + bit BIT_PITCH_SLIDE_DECREASING, [hl] jp nz, .frequencyDecreasing ; frequency increasing - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld e, [hl] - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld l, [hl] ld h, b add hl, de ld d, h ld e, l - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, bc push hl - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld a, [hl] pop hl @@ -1056,26 +1066,26 @@ Audio1_ApplyPitchBend: ld a, 0 adc d ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] cp d jp c, .reachedTargetFrequency jr nz, .applyUpdatedFrequency - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, [hl] cp e jp c, .reachedTargetFrequency jr .applyUpdatedFrequency .frequencyDecreasing - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld a, [hl] - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld e, [hl] sub e @@ -1083,7 +1093,7 @@ Audio1_ApplyPitchBend: ld a, d sbc b ld d, a - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld a, [hl] add a @@ -1094,22 +1104,22 @@ Audio1_ApplyPitchBend: ld a, d sbc b ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, d cp [hl] jr c, .reachedTargetFrequency jr nz, .applyUpdatedFrequency - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, e cp [hl] jr c, .reachedTargetFrequency .applyUpdatedFrequency - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld [hl], e - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld [hl], d ld b, REG_FREQUENCY_LO @@ -1119,38 +1129,38 @@ Audio1_ApplyPitchBend: ld [hl], d ret .reachedTargetFrequency -; Turn off pitch bend when the target frequency has been reached. +; Turn off pitch slide when the target frequency has been reached. ld hl, wChannelFlags1 add hl, bc - res BIT_PITCH_BEND_ON, [hl] - res BIT_PITCH_BEND_DECREASING, [hl] + res BIT_PITCH_SLIDE_ON, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] ret -Audio1_InitPitchBendVars: - ld hl, wChannelPitchBendCurrentFrequencyHighBytes +Audio1_InitPitchSlideVars: + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld [hl], d - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld [hl], e ld hl, wChannelNoteDelayCounters add hl, bc ld a, [hl] - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, bc sub [hl] jr nc, .next ld a, 1 .next ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, e sub [hl] ld e, a ld a, d sbc b - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc sub [hl] jr c, .targetFrequencyGreater @@ -1158,18 +1168,18 @@ Audio1_InitPitchBendVars: ld b, 0 ld hl, wChannelFlags1 add hl, bc - set BIT_PITCH_BEND_DECREASING, [hl] + set BIT_PITCH_SLIDE_DECREASING, [hl] jr .next2 .targetFrequencyGreater ; If the target frequency is greater, subtract the current frequency from ; the target frequency to get the absolute difference. - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld e, [hl] - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, [hl] sub e @@ -1184,7 +1194,7 @@ Audio1_InitPitchBendVars: sbc b ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] sub d @@ -1192,10 +1202,10 @@ Audio1_InitPitchBendVars: ld b, 0 ld hl, wChannelFlags1 add hl, bc - res BIT_PITCH_BEND_DECREASING, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] .next2 - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, bc .divideLoop inc b @@ -1214,20 +1224,20 @@ Audio1_InitPitchBendVars: add [hl] ld d, b ; d = quotient + 1 ld b, 0 - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld [hl], d ; store quotient + 1 - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld [hl], a ; store remainder - dividend - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, bc ld [hl], a ; store remainder - dividend ret -Audio1_ApplyDutyCycle: +Audio1_ApplyDutyCyclePattern: ld b, 0 - ld hl, wChannelDutyCycles + ld hl, wChannelDutyCyclePatterns add hl, bc ld a, [hl] rlca @@ -1322,7 +1332,7 @@ Audio1_PlaySound:: ld [wSoundID], a cp $ff jp z, .stopAllAudio - cp MAX_SFX_ID + cp MAX_SFX_ID_1 jp z, .playSfx jp c, .playSfx cp $fe @@ -1346,10 +1356,10 @@ Audio1_PlaySound:: call .FillMem ld hl, wChannelFlags1 call .FillMem - ld hl, wChannelDuties - call .FillMem ld hl, wChannelDutyCycles call .FillMem + ld hl, wChannelDutyCyclePatterns + call .FillMem ld hl, wChannelVibratoDelayCounters call .FillMem ld hl, wChannelVibratoExtents @@ -1362,21 +1372,21 @@ Audio1_PlaySound:: call .FillMem ld hl, wChannelFlags2 call .FillMem - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers call .FillMem - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps call .FillMem - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart call .FillMem - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart call .FillMem - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes call .FillMem - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes call .FillMem - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes call .FillMem - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes call .FillMem ld a, $1 ld hl, wChannelLoopCounters @@ -1441,26 +1451,26 @@ Audio1_PlaySound:: add hl, de ld a, [hl] and a - jr z, .asm_99a3 + jr z, .playChannel ld a, e - cp $7 - jr nz, .asm_999a + cp Ch8 + jr nz, .notNoiseChannel ld a, [wSoundID] - cp $14 - jr nc, .asm_9993 + cp NOISE_INSTRUMENTS_END + jr nc, .notNoiseInstrument ret -.asm_9993 +.notNoiseInstrument ld a, [hl] - cp $14 - jr z, .asm_99a3 - jr c, .asm_99a3 -.asm_999a + cp NOISE_INSTRUMENTS_END + jr z, .playChannel + jr c, .playChannel +.notNoiseChannel ld a, [wSoundID] cp [hl] - jr z, .asm_99a3 - jr c, .asm_99a3 + jr z, .playChannel + jr c, .playChannel ret -.asm_99a3 +.playChannel xor a push de ld h, d @@ -1483,10 +1493,10 @@ Audio1_PlaySound:: ld hl, wChannelFlags1 add hl, de ld [hl], a - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, de ld [hl], a - ld hl, wChannelDutyCycles + ld hl, wChannelDutyCyclePatterns add hl, de ld [hl], a ld hl, wChannelVibratoDelayCounters @@ -1504,28 +1514,28 @@ Audio1_PlaySound:: ld hl, wChannelVibratoDelayCounterReloadValues add hl, de ld [hl], a - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, de ld [hl], a - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, de ld [hl], a - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, de ld [hl], a ld hl, wChannelFlags2 @@ -1543,10 +1553,10 @@ Audio1_PlaySound:: ld [hl], a ld a, e cp Ch5 - jr nz, .asm_9a2b + jr nz, .skipSweepDisable ld a, $8 ld [rNR10], a ; sweep off -.asm_9a2b +.skipSweepDisable ld a, c and a jp z, .playSoundCommon @@ -1667,9 +1677,9 @@ Audio1_PlaySound:: jr nz, .commandPointerLoop ld a, [wSoundID] cp CRY_SFX_START - jr nc, .asm_9aeb + jr nc, .maybeCry jr .done -.asm_9aeb +.maybeCry ld a, [wSoundID] cp CRY_SFX_END jr z, .done @@ -1682,10 +1692,10 @@ Audio1_PlaySound:: ld [hli], a ld [hl], a ld hl, wChannelCommandPointers + Ch7 * 2 ; sfx wave channel pointer - ld de, Audio1_CryEndchannel + ld de, Audio1_CryRet ld [hl], e inc hl - ld [hl], d ; overwrite pointer to point to endchannel + ld [hl], d ; overwrite pointer to point to sound_ret ld a, [wSavedVolume] and a jr nz, .done @@ -1696,7 +1706,7 @@ Audio1_PlaySound:: .done ret -Audio1_CryEndchannel: +Audio1_CryRet: sound_ret Audio1_HWChannelBaseAddresses: @@ -1725,5 +1735,3 @@ Audio1_Pitches: dw $FB58 ; A_ dw $FB9B ; A# dw $FBDA ; B_ - - diff --git a/audio/engine_2.asm b/audio/engine_2.asm index 4f7f6277..df719c67 100644 --- a/audio/engine_2.asm +++ b/audio/engine_2.asm @@ -1,9 +1,11 @@ ; The second of three duplicated sound engines. +; This copy has a few differences relating to battle sound effects +; and the low health alarm that plays in battle Audio2_UpdateMusic:: ld c, Ch1 .loop - ld b, $0 + ld b, 0 ld hl, wChannelSoundIDs add hl, bc ld a, [hl] @@ -19,7 +21,7 @@ Audio2_UpdateMusic:: jr nz, .nextChannel set 7, a ld [wMuteAudioAndPauseMusic], a - xor a + xor a ; disable all channels' output ld [rNR51], a ld [rNR30], a ld a, $80 @@ -29,19 +31,13 @@ Audio2_UpdateMusic:: call Audio2_ApplyMusicAffects .nextChannel ld a, c - inc c + inc c ; inc channel number cp Ch8 jr nz, .loop ret ; this routine checks flags for music effects currently applied ; to the channel and calls certain functions based on flags. -; known flags for wChannelFlags1: -; 0: toggleperfectpitch has been used -; 1: call has been used -; 3: a toggle used only by this routine for vibrato -; 4: pitchbend flag -; 6: dutycycle flag Audio2_ApplyMusicAffects: ld b, $0 ld hl, wChannelNoteDelayCounters ; delay until next note @@ -63,36 +59,36 @@ Audio2_ApplyMusicAffects: .startChecks ld hl, wChannelFlags1 add hl, bc - bit 6, [hl] ; dutycycle + bit BIT_ROTATE_DUTY_CYCLE, [hl] jr z, .checkForExecuteMusic - call Audio2_ApplyDutyCycle + call Audio2_ApplyDutyCyclePattern .checkForExecuteMusic - ld b, $0 + ld b, 0 ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] - jr nz, .checkForPitchBend + bit BIT_EXECUTE_MUSIC, [hl] + jr nz, .checkForPitchSlide ld hl, wChannelFlags1 add hl, bc - bit 2, [hl] - jr nz, .disablePitchBendVibrato -.checkForPitchBend + bit BIT_NOISE_OR_SFX, [hl] + jr nz, .skipPitchSlideVibrato +.checkForPitchSlide ld hl, wChannelFlags1 add hl, bc - bit 4, [hl] ; pitchbend + bit BIT_PITCH_SLIDE_ON, [hl] jr z, .checkVibratoDelay - jp Audio2_ApplyPitchBend + jp Audio2_ApplyPitchSlide .checkVibratoDelay - ld hl, wChannelVibratoDelayCounters ; vibrato delay + ld hl, wChannelVibratoDelayCounters add hl, bc ld a, [hl] and a ; check if delay is over jr z, .checkForVibrato dec [hl] ; otherwise, dec delay -.disablePitchBendVibrato +.skipPitchSlideVibrato ret .checkForVibrato - ld hl, wChannelVibratoExtents ; vibrato rate + ld hl, wChannelVibratoExtents add hl, bc ld a, [hl] and a @@ -105,33 +101,35 @@ Audio2_ApplyMusicAffects: ld a, [hl] and $f and a - jr z, .vibratoAlreadyDone - dec [hl] ; apply vibrato pitch change + jr z, .applyVibrato + dec [hl] ; decrement counter ret -.vibratoAlreadyDone +.applyVibrato ld a, [hl] swap [hl] or [hl] - ld [hl], a ; reset the vibrato value and start again + ld [hl], a ; reload the counter ld hl, wChannelFrequencyLowBytes add hl, bc ld e, [hl] ; get note pitch ld hl, wChannelFlags1 add hl, bc - bit 3, [hl] ; this is the only code that sets/resets bit three so - jr z, .unset ; it continuously alternates which path it takes - res 3, [hl] +; This is the only code that sets/resets the vibrato direction bit, so it +; continuously alternates which path it takes. + bit BIT_VIBRATO_DIRECTION, [hl] + jr z, .unset + res BIT_VIBRATO_DIRECTION, [hl] ld a, d and $f ld d, a ld a, e sub d jr nc, .noCarry - ld a, $0 + ld a, 0 .noCarry jr .done .unset - set 3, [hl] + set BIT_VIBRATO_DIRECTION, [hl] ld a, d and $f0 swap a @@ -140,70 +138,75 @@ Audio2_ApplyMusicAffects: ld a, $ff .done ld d, a - ld b, $3 - call Audio2_21ff7 + ld b, REG_FREQUENCY_LO + call Audio2_GetRegisterPointer ld [hl], d ret ; this routine executes all music commands that take up no time, -; like tempo changes, duty changes etc. and doesn't return +; like tempo changes, duty cycle changes etc. and doesn't return ; until the first note is reached Audio2_PlayNextNote: +; reload the vibrato delay counter ld hl, wChannelVibratoDelayCounterReloadValues add hl, bc ld a, [hl] ld hl, wChannelVibratoDelayCounters add hl, bc ld [hl], a + ld hl, wChannelFlags1 add hl, bc - res 4, [hl] - res 5, [hl] + res BIT_PITCH_SLIDE_ON, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] + ; --- this section is only present in this copy of the sound engine ld a, c cp Ch5 jr nz, .beginChecks - ld a, [wLowHealthAlarm] ;low health alarm enabled? + ld a, [wLowHealthAlarm] ; low health alarm enabled? bit 7, a ret nz .beginChecks - call Audio2_endchannel + ; --- + call Audio2_sound_ret ret -Audio2_endchannel: +Audio2_sound_ret: call Audio2_GetNextMusicByte ld d, a - cp $ff ; is this command an endchannel? - jp nz, Audio2_callchannel ; no - ld b, $0 ; yes + cp $ff ; is this command a sound_ret? + jp nz, Audio2_sound_call ; no + ld b, 0 ld hl, wChannelFlags1 add hl, bc - bit 1, [hl] + bit BIT_SOUND_CALL, [hl] jr nz, .returnFromCall ld a, c cp Ch4 jr nc, .noiseOrSfxChannel - jr .asm_219c0 + jr .disableChannelOutput .noiseOrSfxChannel - res 2, [hl] + res BIT_NOISE_OR_SFX, [hl] ld hl, wChannelFlags2 add hl, bc - res 0, [hl] + res BIT_EXECUTE_MUSIC, [hl] cp Ch7 - jr nz, .notSfxChannel3 + jr nz, .skipSfxChannel3 +; restart hardware channel 3 (wave channel) output ld a, $0 ld [rNR30], a ld a, $80 ld [rNR30], a -.notSfxChannel3 - jr nz, .asm_219a3 +.skipSfxChannel3 + jr nz, .dontDisable ld a, [wDisableChannelOutputWhenSfxEnds] and a - jr z, .asm_219a3 + jr z, .dontDisable xor a ld [wDisableChannelOutputWhenSfxEnds], a - jr .asm_219c0 -.asm_219a3 - jr .asm_219c9 + jr .disableChannelOutput +.dontDisable + jr .afterDisable .returnFromCall res 1, [hl] ld d, $0 @@ -223,45 +226,45 @@ Audio2_endchannel: inc de ld a, [de] ld [hl], a ; loads channel address to return to - jp Audio2_endchannel -.asm_219c0 - ld hl, Unknown_222de + jp Audio2_sound_ret +.disableChannelOutput + ld hl, Audio2_HWChannelDisableMasks add hl, bc ld a, [rNR51] and [hl] ld [rNR51], a -.asm_219c9 +.afterDisable ld a, [wChannelSoundIDs + Ch5] - cp $14 - jr nc, .asm_219d2 - jr .asm_219ef -.asm_219d2 + cp CRY_SFX_START + jr nc, .maybeCry + jr .skipCry +.maybeCry ld a, [wChannelSoundIDs + Ch5] - cp $86 - jr z, .asm_219ef - jr c, .asm_219dd - jr .asm_219ef -.asm_219dd + cp CRY_SFX_END + jr z, .skipCry + jr c, .cry + jr .skipCry +.cry ld a, c cp Ch5 - jr z, .asm_219e6 - call Audio2_21e6d + jr z, .skipRewind + call Audio2_GoBackOneCommandIfCry ret c -.asm_219e6 +.skipRewind ld a, [wSavedVolume] ld [rNR50], a xor a ld [wSavedVolume], a -.asm_219ef +.skipCry ld hl, wChannelSoundIDs add hl, bc ld [hl], b ret -Audio2_callchannel: - cp $fd ; is this command a callchannel? - jp nz, Audio2_loopchannel ; no - call Audio2_GetNextMusicByte ; yes +Audio2_sound_call: + cp $fd ; is this command a sound_call? + jp nz, Audio2_sound_loop ; no + call Audio2_GetNextMusicByte push af call Audio2_GetNextMusicByte ld d, a @@ -292,17 +295,17 @@ Audio2_callchannel: ld b, $0 ld hl, wChannelFlags1 add hl, bc - set 1, [hl] ; set the call flag - jp Audio2_endchannel + set BIT_SOUND_CALL, [hl] ; set the call flag + jp Audio2_sound_ret -Audio2_loopchannel: - cp $fe ; is this command a loopchannel? - jp nz, Audio2_notetype ; no - call Audio2_GetNextMusicByte ; yes +Audio2_sound_loop: + cp $fe ; is this command a sound_loop? + jp nz, Audio2_note_type ; no + call Audio2_GetNextMusicByte ld e, a and a jr z, .infiniteLoop - ld b, $0 + ld b, 0 ld hl, wChannelLoopCounters add hl, bc ld a, [hl] @@ -312,7 +315,7 @@ Audio2_loopchannel: ld [hl], a call Audio2_GetNextMusicByte ; skip pointer call Audio2_GetNextMusicByte - jp Audio2_endchannel + jp Audio2_sound_ret .loopAgain ; inc loop count inc a ld [hl], a @@ -331,13 +334,13 @@ Audio2_loopchannel: pop af ld [hli], a ld [hl], b - jp Audio2_endchannel + jp Audio2_sound_ret -Audio2_notetype: +Audio2_note_type: and $f0 - cp $d0 ; is this command a notetype? - jp nz, Audio2_toggleperfectpitch ; no - ld a, d ; yes + cp $d0 ; is this command a note_type? + jp nz, Audio2_toggle_perfect_pitch ; no + ld a, d and $f ld b, $0 ld hl, wChannelNoteSpeeds @@ -352,15 +355,15 @@ Audio2_notetype: cp Ch3 jr z, .musicChannel3 cp Ch7 - jr nz, .notChannel3 + jr nz, .skipChannel3 ld hl, wSfxWaveInstrument - jr .sfxChannel3 + jr .channel3 .musicChannel3 ld hl, wMusicWaveInstrument -.sfxChannel3 +.channel3 ld a, d and $f - ld [hl], a ; store low nibble of param as duty + ld [hl], a ; store low nibble of param as wave instrument ld a, d and $30 sla a @@ -369,31 +372,31 @@ Audio2_notetype: ; if channel 3, store high nibble as volume ; else, store volume (high nibble) and fade (low nibble) -.notChannel3 - ld b, $0 +.skipChannel3 + ld b, 0 ld hl, wChannelVolumes add hl, bc ld [hl], d .noiseChannel - jp Audio2_endchannel + jp Audio2_sound_ret -Audio2_toggleperfectpitch: +Audio2_toggle_perfect_pitch: ld a, d - cp $e8 ; is this command a toggleperfectpitch? + cp $e8 ; is this command a toggle_perfect_pitch? jr nz, Audio2_vibrato ; no - ld b, $0 ; yes + ld b, 0 ld hl, wChannelFlags1 add hl, bc ld a, [hl] xor $1 ld [hl], a ; flip bit 0 of wChannelFlags1 - jp Audio2_endchannel + jp Audio2_sound_ret Audio2_vibrato: cp $ea ; is this command a vibrato? - jr nz, Audio2_pitchbend ; no - call Audio2_GetNextMusicByte ; yes - ld b, $0 + jr nz, Audio2_pitch_slide ; no + call Audio2_GetNextMusicByte + ld b, 0 ld hl, wChannelVibratoDelayCounters add hl, bc ld [hl], a ; store delay @@ -402,9 +405,16 @@ Audio2_vibrato: ld [hl], a ; store delay call Audio2_GetNextMusicByte ld d, a + +; The high nybble of the command byte is the extent of the vibrato. +; Let n be the extent. +; The upper nybble of the channel's byte in the wChannelVibratoExtents +; array will store the extent above the note: (n / 2) + (n % 2). +; The lower nybble will store the extent below the note: (n / 2). +; These two values add to the total extent, n. and $f0 swap a - ld b, $0 + ld b, 0 ld hl, wChannelVibratoExtents add hl, bc srl a @@ -412,7 +422,13 @@ Audio2_vibrato: adc b swap a or e - ld [hl], a ; store rate as both high and low nibbles + ld [hl], a + +; The low nybble of the command byte is the rate of the vibrato. +; The high and low nybbles of the channel's byte in the wChannelVibratoRates +; array are both initialised to this value because the high nybble is the +; counter reload value and the low nybble is the counter itself, which should +; start at its value upon reload. ld a, d and $f ld d, a @@ -420,17 +436,18 @@ Audio2_vibrato: add hl, bc swap a or d - ld [hl], a ; store depth as both high and low nibbles - jp Audio2_endchannel + ld [hl], a -Audio2_pitchbend: - cp $eb ; is this command a pitchbend? - jr nz, Audio2_duty ; no - call Audio2_GetNextMusicByte ; yes - ld b, $0 - ld hl, wChannelPitchBendLengthModifiers + jp Audio2_sound_ret + +Audio2_pitch_slide: + cp $eb ; is this command a pitch_slide? + jr nz, Audio2_duty_cycle ; no + call Audio2_GetNextMusicByte + ld b, 0 + ld hl, wChannelPitchSlideLengthModifiers add hl, bc - ld [hl], a ; store first param + ld [hl], a call Audio2_GetNextMusicByte ld d, a and $f0 @@ -438,39 +455,39 @@ Audio2_pitchbend: ld b, a ld a, d and $f - call Audio2_22017 - ld b, $0 - ld hl, wChannelPitchBendTargetFrequencyHighBytes + call Audio2_CalculateFrequency + ld b, 0 + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc - ld [hl], d ; store unknown part of second param - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld [hl], d + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc - ld [hl], e ; store unknown part of second param - ld b, $0 + ld [hl], e + ld b, 0 ld hl, wChannelFlags1 add hl, bc - set 4, [hl] ; set pitchbend flag + set BIT_PITCH_SLIDE_ON, [hl] call Audio2_GetNextMusicByte ld d, a - jp Audio2_notelength + jp Audio2_note_length -Audio2_duty: - cp $ec ; is this command a duty? +Audio2_duty_cycle: + cp $ec ; is this command a duty_cycle? jr nz, Audio2_tempo ; no - call Audio2_GetNextMusicByte ; yes + call Audio2_GetNextMusicByte rrca rrca and $c0 - ld b, $0 - ld hl, wChannelDuties + ld b, 0 + ld hl, wChannelDutyCycles add hl, bc - ld [hl], a ; store duty - jp Audio2_endchannel + ld [hl], a ; store duty cycle + jp Audio2_sound_ret Audio2_tempo: cp $ed ; is this command a tempo? - jr nz, Audio2_stereopanning ; no - ld a, c ; yes + jr nz, Audio2_stereo_panning ; no + ld a, c cp Ch5 jr nc, .sfxChannel call Audio2_GetNextMusicByte @@ -494,20 +511,20 @@ Audio2_tempo: ld [wChannelNoteDelayCountersFractionalPart + 6], a ld [wChannelNoteDelayCountersFractionalPart + 7], a .musicChannelDone - jp Audio2_endchannel + jp Audio2_sound_ret -Audio2_stereopanning: - cp $ee ; is this command a stereopanning? +Audio2_stereo_panning: + cp $ee ; is this command a stereo_panning? jr nz, Audio2_unknownmusic0xef ; no - call Audio2_GetNextMusicByte ; yes + call Audio2_GetNextMusicByte ld [wStereoPanning], a ; store panning - jp Audio2_endchannel + jp Audio2_sound_ret ; this appears to never be used Audio2_unknownmusic0xef: cp $ef ; is this command an unknownmusic0xef? - jr nz, Audio2_dutycycle ; no - call Audio2_GetNextMusicByte ; yes + jr nz, Audio2_duty_cycle_pattern ; no + call Audio2_GetNextMusicByte push bc call Audio2_PlaySound pop bc @@ -519,124 +536,141 @@ Audio2_unknownmusic0xef: xor a ld [wChannelSoundIDs + Ch8], a .skip - jp Audio2_endchannel + jp Audio2_sound_ret -Audio2_dutycycle: - cp $fc ; is this command a dutycycle? +Audio2_duty_cycle_pattern: + cp $fc ; is this command a duty_cycle_pattern? jr nz, Audio2_volume ; no - call Audio2_GetNextMusicByte ; yes - ld b, $0 - ld hl, wChannelDutyCycles + call Audio2_GetNextMusicByte + ld b, 0 + ld hl, wChannelDutyCyclePatterns add hl, bc - ld [hl], a ; store full cycle - and $c0 - ld hl, wChannelDuties + ld [hl], a ; store full pattern + and %11000000 + ld hl, wChannelDutyCycles add hl, bc - ld [hl], a ; store first duty + ld [hl], a ; store first duty cycle ld hl, wChannelFlags1 add hl, bc - set 6, [hl] ; set dutycycle flag - jp Audio2_endchannel + set BIT_ROTATE_DUTY_CYCLE, [hl] + jp Audio2_sound_ret Audio2_volume: cp $f0 ; is this command a volume? - jr nz, Audio2_executemusic ; no - call Audio2_GetNextMusicByte ; yes + jr nz, Audio2_execute_music ; no + call Audio2_GetNextMusicByte ld [rNR50], a ; store volume - jp Audio2_endchannel + jp Audio2_sound_ret -Audio2_executemusic: - cp $f8 ; is this command an executemusic? +Audio2_execute_music: + cp $f8 ; is this command an execute_music? jr nz, Audio2_octave ; no - ld b, $0 ; yes + ld b, $0 ld hl, wChannelFlags2 add hl, bc - set 0, [hl] - jp Audio2_endchannel + set BIT_EXECUTE_MUSIC, [hl] + jp Audio2_sound_ret Audio2_octave: and $f0 cp $e0 ; is this command an octave? - jr nz, Audio2_sfxnote ; no - ld hl, wChannelOctaves ; yes - ld b, $0 + jr nz, Audio2_sfx_note ; no + ld hl, wChannelOctaves + ld b, 0 add hl, bc ld a, d and $f ld [hl], a ; store low nibble as octave - jp Audio2_endchannel + jp Audio2_sound_ret -; sfxnote is either squarenote or noisenote depending on the channel -Audio2_sfxnote: - cp $20 ; is this command an sfxnote? - jr nz, Audio2_pitchenvelope ; no +; sfx_note is either square_note or noise_note depending on the channel +Audio2_sfx_note: + cp $20 ; is this command a sfx_note? + jr nz, Audio2_pitch_sweep ld a, c cp Ch4 ; is this a noise or sfx channel? - jr c, Audio2_pitchenvelope ; no - ld b, $0 + jr c, Audio2_pitch_sweep ; no + ld b, 0 ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] - jr nz, Audio2_pitchenvelope ; no - call Audio2_notelength + bit BIT_EXECUTE_MUSIC, [hl] ; is execute_music being used? + jr nz, Audio2_pitch_sweep ; yes + call Audio2_note_length + +; This code seems to do the same thing as what Audio2_ApplyDutyCycleAndSoundLength +; does below. ld d, a - ld b, $0 - ld hl, wChannelDuties + ld b, 0 + ld hl, wChannelDutyCycles add hl, bc ld a, [hl] or d ld d, a - ld b, $1 - call Audio2_21ff7 + ld b, REG_DUTY_SOUND_LEN + call Audio2_GetRegisterPointer ld [hl], d + call Audio2_GetNextMusicByte ld d, a - ld b, $2 - call Audio2_21ff7 + ld b, REG_VOLUME_ENVELOPE + call Audio2_GetRegisterPointer ld [hl], d call Audio2_GetNextMusicByte ld e, a ld a, c cp Ch8 - ld a, $0 - jr z, .sfxNoiseChannel ; only two params for noise channel + ld a, 0 + jr z, .skip +; Channels 1 through 3 have 2 registers that control frequency, but the noise +; channel a single register (the polynomial counter) that controls frequency, +; so this command has one less byte on the noise channel. push de call Audio2_GetNextMusicByte pop de -.sfxNoiseChannel +.skip ld d, a push de - call Audio2_21daa - call Audio2_21d79 + call Audio2_ApplyDutyCycleAndSoundLength + call Audio2_EnableChannelOutput pop de - call Audio2_21dcc + call Audio2_ApplyWavePatternAndFrequency ret -Audio2_pitchenvelope: +Audio2_pitch_sweep: ld a, c cp Ch5 jr c, Audio2_note ; if not a sfx ld a, d - cp $10 ; is this command a pitchenvelope? + cp $10 ; is this command a pitch_sweep? jr nz, Audio2_note ; no ld b, $0 ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] + bit BIT_EXECUTE_MUSIC, [hl] jr nz, Audio2_note ; no - call Audio2_GetNextMusicByte ; yes + call Audio2_GetNextMusicByte ld [rNR10], a - jp Audio2_endchannel + jp Audio2_sound_ret Audio2_note: ld a, c cp Ch4 - jr nz, Audio2_notelength ; if not noise channel + jr nz, Audio2_note_length ; if not noise channel ld a, d and $f0 cp $b0 ; is this command a dnote? - jr z, Audio2_dnote ; yes - jr nc, Audio2_notelength ; no + jr z, .dnote + jr nc, Audio2_note_length ; no + + ; this executes when on the noise channel and + ; the command id is less than $b0 + ; in this case, the upper nybble is used as the noise instrument ($1-$a) + ; and the lower nybble is the length minus 1 (0-15) + ; however, this doesn't work for instrument #2 because the command id + ; is captured by the noise_note command (command id $2x) + ; this essentially acts like a dnote command that is only 1 byte + ; instead of 2 and can only be used with instruments 1 and 3 through 10 + ; this is unused by the game swap a ld b, a ld a, d @@ -645,38 +679,38 @@ Audio2_note: ld a, b push de push bc - jr asm_21c7e + jr .playDnote -Audio2_dnote: +.dnote ld a, d and $f push af push bc call Audio2_GetNextMusicByte ; get dnote instrument -asm_21c7e +.playDnote ld d, a ld a, [wDisableChannelOutputWhenSfxEnds] and a - jr nz, .asm_21c89 + jr nz, .skipDnote ld a, d call Audio2_PlaySound -.asm_21c89 +.skipDnote pop bc pop de -Audio2_notelength: +Audio2_note_length: ld a, d push af and $f inc a - ld b, $0 - ld e, a ; store note length (in 16ths) + ld b, 0 + ld e, a ; store note length (in 16ths) ld d, b ld hl, wChannelNoteSpeeds add hl, bc ld a, [hl] ld l, b - call Audio2_22006 + call Audio2_MultiplyAdd ld a, c cp Ch5 jr nc, .sfxChannel @@ -690,20 +724,20 @@ Audio2_notelength: ld e, $0 cp Ch8 jr z, .skip ; if noise channel - call Audio2_21e2f + call Audio2_SetSfxTempo ld a, [wSfxTempo] ld d, a ld a, [wSfxTempo + 1] ld e, a .skip - ld a, l - ld b, $0 + ld a, l ; a = note_length * note_speed + ld b, 0 ld hl, wChannelNoteDelayCountersFractionalPart add hl, bc ld l, [hl] - call Audio2_22006 + call Audio2_MultiplyAdd ld e, l - ld d, h + ld d, h ; de = note_delay_frac_part + (note_length * note_speed * tempo) ld hl, wChannelNoteDelayCountersFractionalPart add hl, bc ld [hl], e @@ -713,192 +747,198 @@ Audio2_notelength: ld [hl], a ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] - jr nz, Audio2_notepitch + bit BIT_EXECUTE_MUSIC, [hl] + jr nz, Audio2_note_pitch ld hl, wChannelFlags1 add hl, bc - bit 2, [hl] - jr z, Audio2_notepitch + bit BIT_NOISE_OR_SFX, [hl] + jr z, Audio2_note_pitch pop hl ret -Audio2_notepitch: +Audio2_note_pitch: pop af and $f0 cp $c0 ; compare to rest jr nz, .notRest ld a, c cp Ch5 - jr nc, .sfxChannel + jr nc, .next +; If this isn't an SFX channel, try the corresponding SFX channel. ld hl, wChannelSoundIDs + Ch5 add hl, bc ld a, [hl] and a jr nz, .done ; fall through -.sfxChannel +.next ld a, c cp Ch3 - jr z, .musicChannel3 + jr z, .channel3 cp Ch7 - jr nz, .notSfxChannel3 -.musicChannel3 - ld b, $0 - ld hl, Unknown_222de + jr nz, .notChannel3 +.channel3 + ld b, 0 + ld hl, Audio2_HWChannelDisableMasks add hl, bc ld a, [rNR51] and [hl] - ld [rNR51], a + ld [rNR51], a ; disable hardware channel 3's output jr .done -.notSfxChannel3 - ld b, $2 - call Audio2_21ff7 - ld a, $8 +.notChannel3 + ld b, REG_VOLUME_ENVELOPE + call Audio2_GetRegisterPointer + ld a, $8 ; fade in sound ld [hli], a inc hl - ld a, $80 + ld a, $80 ; restart sound ld [hl], a .done ret .notRest swap a - ld b, $0 + ld b, 0 ld hl, wChannelOctaves add hl, bc ld b, [hl] - call Audio2_22017 - ld b, $0 + call Audio2_CalculateFrequency + ld b, 0 ld hl, wChannelFlags1 add hl, bc - bit 4, [hl] - jr z, .asm_21d39 - call Audio2_21f4e -.asm_21d39 + bit BIT_PITCH_SLIDE_ON, [hl] + jr z, .skipPitchSlide + call Audio2_InitPitchSlideVars +.skipPitchSlide push de ld a, c cp Ch5 - jr nc, .skip ; if sfx channel + jr nc, .sfxChannel ; if sfx channel +; If this isn't an SFX channel, try the corresponding SFX channel. ld hl, wChannelSoundIDs + Ch5 - ld d, $0 + ld d, 0 ld e, a add hl, de ld a, [hl] and a - jr nz, .asm_21d4c - jr .skip -.asm_21d4c + jr nz, .noSfx + jr .sfxChannel +.noSfx pop de ret -.skip - ld b, $0 +.sfxChannel + ld b, 0 ld hl, wChannelVolumes add hl, bc ld d, [hl] - ld b, $2 - call Audio2_21ff7 + ld b, REG_VOLUME_ENVELOPE + call Audio2_GetRegisterPointer ld [hl], d - call Audio2_21daa - call Audio2_21d79 + call Audio2_ApplyDutyCycleAndSoundLength + call Audio2_EnableChannelOutput pop de ld b, $0 ld hl, wChannelFlags1 add hl, bc - bit 0, [hl] ; has toggleperfectpitch been used? - jr z, .skip2 - inc e ; if yes, increment the pitch by 1 - jr nc, .skip2 + bit BIT_PERFECT_PITCH, [hl] ; has toggle_perfect_pitch been used? + jr z, .skipFrequencyInc + inc e ; if yes, increment the frequency by 1 + jr nc, .skipFrequencyInc inc d -.skip2 +.skipFrequencyInc ld hl, wChannelFrequencyLowBytes add hl, bc ld [hl], e - call Audio2_21dcc + call Audio2_ApplyWavePatternAndFrequency ret -Audio2_21d79: - ld b, $0 - ld hl, Unknown_222e6 +Audio2_EnableChannelOutput: + ld b, 0 + ld hl, Audio2_HWChannelEnableMasks add hl, bc ld a, [rNR51] - or [hl] + or [hl] ; set this channel's bits ld d, a ld a, c cp Ch8 - jr z, .sfxNoiseChannel + jr z, .noiseChannelOrNoSfx cp Ch5 jr nc, .skip ; if sfx channel +; If this isn't an SFX channel, try the corresponding SFX channel. ld hl, wChannelSoundIDs + Ch5 add hl, bc ld a, [hl] and a jr nz, .skip -.sfxNoiseChannel +.noiseChannelOrNoSfx +; If this is the SFX noise channel or a music channel whose corresponding +; SFX channel is off, apply stereo panning. ld a, [wStereoPanning] - ld hl, Unknown_222e6 + ld hl, Audio2_HWChannelEnableMasks add hl, bc and [hl] ld d, a ld a, [rNR51] - ld hl, Unknown_222de + ld hl, Audio2_HWChannelDisableMasks add hl, bc - and [hl] - or d + and [hl] ; reset this channel's output bits + or d ; set this channel's output bits that enabled in [wStereoPanning] ld d, a .skip ld a, d ld [rNR51], a ret -Audio2_21daa: - ld b, $0 - ld hl, wChannelNoteDelayCounters +Audio2_ApplyDutyCycleAndSoundLength: + ld b, 0 + ld hl, wChannelNoteDelayCounters ; use the note delay as sound length add hl, bc ld d, [hl] ld a, c cp Ch3 - jr z, .channel3 ; if music channel 3 + jr z, .skipDuty ; if music channel 3 cp Ch7 - jr z, .channel3 ; if sfx channel 3 + jr z, .skipDuty ; if sfx channel 3 +; include duty cycle (except on channel 3 which doesn't have it) ld a, d and $3f ld d, a - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, bc ld a, [hl] or d ld d, a -.channel3 - ld b, $1 - call Audio2_21ff7 +.skipDuty + ld b, REG_DUTY_SOUND_LEN + call Audio2_GetRegisterPointer ld [hl], d ret -Audio2_21dcc: +Audio2_ApplyWavePatternAndFrequency: ld a, c cp Ch3 jr z, .channel3 cp Ch7 - jr nz, .notSfxChannel3 + jr nz, .notChannel3 ; fall through .channel3 push de ld de, wMusicWaveInstrument cp Ch3 - jr z, .musicChannel3 + jr z, .next ld de, wSfxWaveInstrument -.musicChannel3 +.next ld a, [de] add a - ld d, $0 + ld d, 0 ld e, a ld hl, Audio2_WavePointers add hl, de ld e, [hl] inc hl ld d, [hl] - ld hl, $ff30 + ld hl, $ff30 ; wave pattern RAM ld b, $f - ld a, $0 + ld a, $0 ; stop hardware channel 3 ld [rNR30], a .loop ld a, [de] @@ -908,196 +948,207 @@ Audio2_21dcc: dec b and a jr nz, .loop - ld a, $80 + ld a, $80 ; start hardware channel 3 ld [rNR30], a pop de -.notSfxChannel3 +.notChannel3 ld a, d - or $80 - and $c7 + or $80 ; use counter mode (i.e. disable output when the counter reaches 0) + and $c7 ; zero the unused bits in the register ld d, a - ld b, $3 - call Audio2_21ff7 - ld [hl], e + ld b, REG_FREQUENCY_LO + call Audio2_GetRegisterPointer + ld [hl], e ; store frequency low byte inc hl - ld [hl], d + ld [hl], d ; store frequency high byte + ; --- this section is only present in this copy of the sound engine ld a, c cp Ch5 jr c, .musicChannel - call Audio2_21e56 + call Audio2_ApplyFrequencyModifier .musicChannel + ; --- ret -Audio2_21e19: +; --- this section is only present in this copy of the sound engine +; unused +Audio2_ResetCryModifiers: ld a, c cp Ch5 - jr nz, .asm_21e2e + jr nz, .skip ld a, [wLowHealthAlarm] bit 7, a - jr z, .asm_21e2e + jr z, .skip xor a ld [wFrequencyModifier], a ld a, $80 ld [wTempoModifier], a -.asm_21e2e +.skip ret +; --- -Audio2_21e2f: - call Audio2_21e8b - jr c, .asm_21e39 - call Audio2_21e9f - jr nc, .asm_21e4c -.asm_21e39 - ld d, $0 +Audio2_SetSfxTempo: + call Audio2_IsCry + jr c, .skipCryCheck + call Audio2_IsBattleSFX + jr nc, .notCry +.skipCryCheck + ld d, 0 ld a, [wTempoModifier] add $80 - jr nc, .asm_21e43 + jr nc, .next inc d -.asm_21e43 +.next ld [wSfxTempo + 1], a ld a, d ld [wSfxTempo], a - jr .asm_21e55 -.asm_21e4c + jr .done +.notCry xor a ld [wSfxTempo + 1], a ld a, $1 ld [wSfxTempo], a -.asm_21e55 +.done ret -Audio2_21e56: - call Audio2_21e8b - jr c, .asm_21e60 - call Audio2_21e9f - jr nc, .asm_21e6c -.asm_21e60 +Audio2_ApplyFrequencyModifier: + call Audio2_IsCry + jr c, .skipCryCheck + call Audio2_IsBattleSFX + jr nc, .done +.skipCryCheck +; if playing a cry, add the cry's frequency modifier ld a, [wFrequencyModifier] add e - jr nc, .asm_21e67 + jr nc, .noCarry inc d -.asm_21e67 +.noCarry dec hl ld e, a ld [hl], e inc hl ld [hl], d -.asm_21e6c +.done ret -Audio2_21e6d: - call Audio2_21e8b - jr nc, .asm_21e88 +Audio2_GoBackOneCommandIfCry: + call Audio2_IsCry + jr nc, .done ld hl, wChannelCommandPointers ld e, c - ld d, $0 + ld d, 0 sla e rl d add hl, de ld a, [hl] - sub $1 + sub 1 ld [hl], a inc hl ld a, [hl] - sbc $0 + sbc 0 ld [hl], a scf ret -.asm_21e88 +.done scf ccf ret -Audio2_21e8b: +Audio2_IsCry: +; Returns whether the currently playing audio is a cry in carry. ld a, [wChannelSoundIDs + Ch5] - cp $14 - jr nc, .asm_21e94 - jr .asm_21e9a -.asm_21e94 - cp $86 - jr z, .asm_21e9a - jr c, .asm_21e9d -.asm_21e9a + cp CRY_SFX_START + jr nc, .next + jr .no +.next + cp CRY_SFX_END + jr z, .no + jr c, .yes +.no scf ccf ret -.asm_21e9d +.yes scf ret -Audio2_21e9f: +; --- this section is only present in this copy of the sound engine +Audio2_IsBattleSFX: +; Returns whether the currently playing audio is a cry in carry. ld a, [wChannelSoundIDs + Ch8] ld b, a ld a, [wChannelSoundIDs + Ch5] or b - cp $9d - jr nc, .asm_21ead - jr .asm_21eb3 -.asm_21ead - cp $ea - jr z, .asm_21eb3 - jr c, .asm_21eb6 -.asm_21eb3 + cp BATTLE_SFX_START + jr nc, .next + jr .no +.next + cp BATTLE_SFX_END + jr z, .no + jr c, .yes +.no scf ccf ret -.asm_21eb6 +.yes scf ret +; --- -Audio2_ApplyPitchBend: +Audio2_ApplyPitchSlide: ld hl, wChannelFlags1 add hl, bc - bit 5, [hl] - jp nz, .asm_21eff - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + bit BIT_PITCH_SLIDE_DECREASING, [hl] + jp nz, .frequencyDecreasing +; frequency increasing + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld e, [hl] - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld l, [hl] ld h, b add hl, de ld d, h ld e, l - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, bc push hl - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld a, [hl] pop hl add [hl] ld [hl], a - ld a, $0 + ld a, 0 adc e ld e, a - ld a, $0 + ld a, 0 adc d ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] cp d - jp c, .asm_21f45 - jr nz, .asm_21f32 - ld hl, wChannelPitchBendTargetFrequencyLowBytes + jp c, .reachedTargetFrequency + jr nz, .applyUpdatedFrequency + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, [hl] cp e - jp c, .asm_21f45 - jr .asm_21f32 -.asm_21eff - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + jp c, .reachedTargetFrequency + jr .applyUpdatedFrequency +.frequencyDecreasing + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld a, [hl] - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld e, [hl] sub e @@ -1105,7 +1156,7 @@ Audio2_ApplyPitchBend: ld a, d sbc b ld d, a - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld a, [hl] add a @@ -1116,129 +1167,140 @@ Audio2_ApplyPitchBend: ld a, d sbc b ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, d cp [hl] - jr c, .asm_21f45 - jr nz, .asm_21f32 - ld hl, wChannelPitchBendTargetFrequencyLowBytes + jr c, .reachedTargetFrequency + jr nz, .applyUpdatedFrequency + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, e cp [hl] - jr c, .asm_21f45 -.asm_21f32 - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + jr c, .reachedTargetFrequency +.applyUpdatedFrequency + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld [hl], e - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld [hl], d - ld b, $3 - call Audio2_21ff7 + ld b, REG_FREQUENCY_LO + call Audio2_GetRegisterPointer ld a, e ld [hli], a ld [hl], d ret -.asm_21f45 +.reachedTargetFrequency +; Turn off pitch slide when the target frequency has been reached. ld hl, wChannelFlags1 add hl, bc - res 4, [hl] - res 5, [hl] + res BIT_PITCH_SLIDE_ON, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] ret -Audio2_21f4e: - ld hl, wChannelPitchBendCurrentFrequencyHighBytes +Audio2_InitPitchSlideVars: + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld [hl], d - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld [hl], e ld hl, wChannelNoteDelayCounters add hl, bc ld a, [hl] - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, bc sub [hl] - jr nc, .asm_21f66 - ld a, $1 -.asm_21f66 + jr nc, .next + ld a, 1 +.next ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, e sub [hl] ld e, a ld a, d sbc b - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc sub [hl] - jr c, .asm_21f82 + jr c, .targetFrequencyGreater ld d, a - ld b, $0 + ld b, 0 ld hl, wChannelFlags1 add hl, bc - set 5, [hl] - jr .asm_21fa5 -.asm_21f82 - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + set BIT_PITCH_SLIDE_DECREASING, [hl] + jr .next2 +.targetFrequencyGreater +; If the target frequency is greater, subtract the current frequency from +; the target frequency to get the absolute difference. + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld e, [hl] - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, [hl] sub e ld e, a + +; Bug. Instead of borrowing from the high byte of the target frequency as it +; should, it borrows from the high byte of the current frequency instead. +; This means that the result will be 0x200 greater than it should be if the +; low byte of the current frequency is greater than the low byte of the +; target frequency. ld a, d sbc b ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] sub d ld d, a - ld b, $0 + ld b, 0 ld hl, wChannelFlags1 add hl, bc - res 5, [hl] -.asm_21fa5 - ld hl, wChannelPitchBendLengthModifiers + res BIT_PITCH_SLIDE_DECREASING, [hl] + +.next2 + ld hl, wChannelPitchSlideLengthModifiers add hl, bc -.asm_21fa9 +.divideLoop inc b ld a, e sub [hl] ld e, a - jr nc, .asm_21fa9 + jr nc, .divideLoop ld a, d and a - jr z, .asm_21fb7 + jr z, .doneDividing dec a ld d, a - jr .asm_21fa9 -.asm_21fb7 - ld a, e + jr .divideLoop +.doneDividing + ld a, e ; a = remainder - dividend add [hl] - ld d, b - ld b, $0 - ld hl, wChannelPitchBendFrequencySteps + ld d, b ; d = quotient + 1 + ld b, 0 + ld hl, wChannelPitchSlideFrequencySteps add hl, bc - ld [hl], d - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld [hl], d ; store quotient + 1 + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc - ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld [hl], a ; store remainder - dividend + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, bc - ld [hl], a + ld [hl], a ; store remainder - dividend ret -Audio2_ApplyDutyCycle: - ld b, $0 - ld hl, wChannelDutyCycles +Audio2_ApplyDutyCyclePattern: + ld b, 0 + ld hl, wChannelDutyCyclePatterns add hl, bc ld a, [hl] rlca @@ -1246,8 +1308,8 @@ Audio2_ApplyDutyCycle: ld [hl], a and $c0 ld d, a - ld b, $1 - call Audio2_21ff7 + ld b, REG_DUTY_SOUND_LEN + call Audio2_GetRegisterPointer ld a, [hl] and $3f or d @@ -1255,7 +1317,7 @@ Audio2_ApplyDutyCycle: ret Audio2_GetNextMusicByte: - ld d, $0 + ld d, 0 ld a, c add a ld e, a @@ -1272,9 +1334,10 @@ Audio2_GetNextMusicByte: ld [hl], d ret -Audio2_21ff7: +Audio2_GetRegisterPointer: +; hl = address of hardware sound register b for software channel c ld a, c - ld hl, Unknown_222d6 + ld hl, Audio2_HWChannelBaseAddresses add l jr nc, .noCarry inc h @@ -1286,13 +1349,14 @@ Audio2_21ff7: ld h, $ff ret -Audio2_22006: - ld h, $0 +Audio2_MultiplyAdd: +; hl = l + (a * de) + ld h, 0 .loop srl a - jr nc, .noCarry + jr nc, .skipAdd add hl, de -.noCarry +.skipAdd sla e rl d and a @@ -1301,8 +1365,9 @@ Audio2_22006: .done ret -Audio2_22017: - ld h, $0 +Audio2_CalculateFrequency: +; return the frequency for note a, octave b in de + ld h, 0 ld l, a add hl, hl ld d, h @@ -1314,14 +1379,14 @@ Audio2_22017: ld d, [hl] ld a, b .loop - cp Ch8 + cp 7 jr z, .done sra d rr e inc a jr .loop .done - ld a, $8 + ld a, 8 add d ld d, a ret @@ -1329,14 +1394,15 @@ Audio2_22017: Audio2_PlaySound:: ld [wSoundID], a cp $ff - jp z, Audio2_221f3 - cp $e9 - jp z, Audio2_2210d - jp c, Audio2_2210d + jp z, .stopAllAudio + cp MAX_SFX_ID_2 + jp z, .playSfx + jp c, .playSfx cp $fe - jr z, .asm_2204c - jp nc, Audio2_2210d -.asm_2204c + jr z, .playMusic + jp nc, .playSfx + +.playMusic xor a ld [wUnusedC000], a ld [wDisableChannelOutputWhenSfxEnds], a @@ -1345,53 +1411,53 @@ Audio2_PlaySound:: ld [wSfxWaveInstrument], a ld d, $8 ld hl, wChannelReturnAddresses - call FillAudioRAM2 + call .FillMem ld hl, wChannelCommandPointers - call FillAudioRAM2 + call .FillMem ld d, $4 ld hl, wChannelSoundIDs - call FillAudioRAM2 + call .FillMem ld hl, wChannelFlags1 - call FillAudioRAM2 - ld hl, wChannelDuties - call FillAudioRAM2 + call .FillMem ld hl, wChannelDutyCycles - call FillAudioRAM2 + call .FillMem + ld hl, wChannelDutyCyclePatterns + call .FillMem ld hl, wChannelVibratoDelayCounters - call FillAudioRAM2 + call .FillMem ld hl, wChannelVibratoExtents - call FillAudioRAM2 + call .FillMem ld hl, wChannelVibratoRates - call FillAudioRAM2 + call .FillMem ld hl, wChannelFrequencyLowBytes - call FillAudioRAM2 + call .FillMem ld hl, wChannelVibratoDelayCounterReloadValues - call FillAudioRAM2 + call .FillMem ld hl, wChannelFlags2 - call FillAudioRAM2 - ld hl, wChannelPitchBendLengthModifiers - call FillAudioRAM2 - ld hl, wChannelPitchBendFrequencySteps - call FillAudioRAM2 - ld hl, wChannelPitchBendFrequencyStepsFractionalPart - call FillAudioRAM2 - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart - call FillAudioRAM2 - ld hl, wChannelPitchBendCurrentFrequencyHighBytes - call FillAudioRAM2 - ld hl, wChannelPitchBendCurrentFrequencyLowBytes - call FillAudioRAM2 - ld hl, wChannelPitchBendTargetFrequencyHighBytes - call FillAudioRAM2 - ld hl, wChannelPitchBendTargetFrequencyLowBytes - call FillAudioRAM2 + call .FillMem + ld hl, wChannelPitchSlideLengthModifiers + call .FillMem + ld hl, wChannelPitchSlideFrequencySteps + call .FillMem + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart + call .FillMem + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart + call .FillMem + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes + call .FillMem + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes + call .FillMem + ld hl, wChannelPitchSlideTargetFrequencyHighBytes + call .FillMem + ld hl, wChannelPitchSlideTargetFrequencyLowBytes + call .FillMem ld a, $1 ld hl, wChannelLoopCounters - call FillAudioRAM2 + call .FillMem ld hl, wChannelNoteDelayCounters - call FillAudioRAM2 + call .FillMem ld hl, wChannelNoteSpeeds - call FillAudioRAM2 + call .FillMem ld [wMusicTempo], a ld a, $ff ld [wStereoPanning], a @@ -1399,7 +1465,7 @@ Audio2_PlaySound:: ld [rNR50], a ld a, $8 ld [rNR10], a - ld a, $0 + ld a, 0 ld [rNR51], a xor a ld [rNR30], a @@ -1407,12 +1473,12 @@ Audio2_PlaySound:: ld [rNR30], a ld a, $77 ld [rNR50], a - jp Audio2_2224e + jp .playSoundCommon -Audio2_2210d: +.playSfx ld l, a ld e, a - ld h, $0 + ld h, 0 ld d, h add hl, hl add hl, de @@ -1427,13 +1493,13 @@ Audio2_2210d: rlca rlca ld c, a -.asm_22126 +.sfxChannelLoop ld d, c ld a, c add a add c ld c, a - ld b, $0 + ld b, 0 ld a, [wSfxHeaderPointer] ld h, a ld a, [wSfxHeaderPointer + 1] @@ -1442,32 +1508,32 @@ Audio2_2210d: ld c, d ld a, [hl] and $f - ld e, a - ld d, $0 + ld e, a ; software channel ID + ld d, 0 ld hl, wChannelSoundIDs add hl, de ld a, [hl] and a - jr z, .asm_22162 + jr z, .playChannel ld a, e - cp $7 - jr nz, .asm_22159 + cp Ch8 + jr nz, .notNoiseChannel ld a, [wSoundID] - cp $14 - jr nc, .asm_22152 + cp NOISE_INSTRUMENTS_END + jr nc, .notNoiseInstrument ret -.asm_22152 +.notNoiseInstrument ld a, [hl] - cp $14 - jr z, .asm_22162 - jr c, .asm_22162 -.asm_22159 + cp NOISE_INSTRUMENTS_END + jr z, .playChannel + jr c, .playChannel +.notNoiseChannel ld a, [wSoundID] cp [hl] - jr z, .asm_22162 - jr c, .asm_22162 + jr z, .playChannel + jr c, .playChannel ret -.asm_22162 +.playChannel xor a push de ld h, d @@ -1490,10 +1556,10 @@ Audio2_2210d: ld hl, wChannelFlags1 add hl, de ld [hl], a - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, de ld [hl], a - ld hl, wChannelDutyCycles + ld hl, wChannelDutyCyclePatterns add hl, de ld [hl], a ld hl, wChannelVibratoDelayCounters @@ -1511,28 +1577,28 @@ Audio2_2210d: ld hl, wChannelVibratoDelayCounterReloadValues add hl, de ld [hl], a - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, de ld [hl], a - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, de ld [hl], a - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, de ld [hl], a ld hl, wChannelFlags2 @@ -1549,35 +1615,35 @@ Audio2_2210d: add hl, de ld [hl], a ld a, e - cp $4 - jr nz, .asm_221ea + cp Ch5 + jr nz, .skipSweepDisable ld a, $8 - ld [rNR10], a -.asm_221ea + ld [rNR10], a ; sweep off +.skipSweepDisable ld a, c and a - jp z, Audio2_2224e + jp z, .playSoundCommon dec c - jp .asm_22126 + jp .sfxChannelLoop -Audio2_221f3: +.stopAllAudio ld a, $80 - ld [rNR52], a - ld [rNR30], a + ld [rNR52], a ; sound hardware on + ld [rNR30], a ; wave playback on xor a - ld [rNR51], a - ld [rNR32], a + ld [rNR51], a ; no sound output + ld [rNR32], a ; mute channel 3 (wave channel) ld a, $8 - ld [rNR10], a - ld [rNR12], a - ld [rNR22], a - ld [rNR42], a + ld [rNR10], a ; sweep off + ld [rNR12], a ; mute channel 1 (pulse channel 1) + ld [rNR22], a ; mute channel 2 (pulse channel 2) + ld [rNR42], a ; mute channel 4 (noise channel) ld a, $40 - ld [rNR14], a + ld [rNR14], a ; counter mode ld [rNR24], a ld [rNR44], a ld a, $77 - ld [rNR50], a + ld [rNR50], a ; full volume xor a ld [wUnusedC000], a ld [wDisableChannelOutputWhenSfxEnds], a @@ -1588,11 +1654,11 @@ Audio2_221f3: ld [wSfxWaveInstrument], a ld d, $a0 ld hl, wChannelCommandPointers - call FillAudioRAM2 + call .FillMem ld a, $1 ld d, $18 ld hl, wChannelNoteDelayCounters - call FillAudioRAM2 + call .FillMem ld [wMusicTempo], a ld [wSfxTempo], a ld a, $ff @@ -1600,7 +1666,7 @@ Audio2_221f3: ret ; fills d bytes at hl with a -FillAudioRAM2: +.FillMem ld b, d .loop ld [hli], a @@ -1608,11 +1674,11 @@ FillAudioRAM2: jr nz, .loop ret -Audio2_2224e: +.playSoundCommon ld a, [wSoundID] ld l, a ld e, a - ld h, $0 + ld h, 0 ld d, h add hl, hl add hl, de @@ -1632,31 +1698,31 @@ Audio2_2224e: ld b, c inc b inc de - ld c, $0 -.asm_22270 + ld c, 0 +.commandPointerLoop cp c - jr z, .asm_22278 + jr z, .next inc c inc hl inc hl - jr .asm_22270 -.asm_22278 + jr .commandPointerLoop +.next push hl push bc push af - ld b, $0 + ld b, 0 ld c, a ld hl, wChannelSoundIDs add hl, bc ld a, [wSoundID] ld [hl], a pop af - cp $3 - jr c, .asm_22291 + cp Ch4 + jr c, .skipSettingFlag ld hl, wChannelFlags1 add hl, bc - set 2, [hl] -.asm_22291 + set BIT_NOISE_OR_SFX, [hl] +.skipSettingFlag pop bc pop hl ld a, [de] ; get channel pointer @@ -1671,52 +1737,53 @@ Audio2_2224e: and a ld a, [de] inc de - jr nz, .asm_22270 + jr nz, .commandPointerLoop ld a, [wSoundID] - cp $14 - jr nc, .asm_222aa - jr .asm_222d4 -.asm_222aa + cp CRY_SFX_START + jr nc, .maybeCry + jr .done +.maybeCry ld a, [wSoundID] - cp $86 - jr z, .asm_222d4 - jr c, .asm_222b5 - jr .asm_222d4 -.asm_222b5 + cp CRY_SFX_END + jr z, .done + jr c, .cry + jr .done +.cry ld hl, wChannelSoundIDs + Ch5 ld [hli], a ld [hli], a ld [hli], a ld [hl], a - ld hl, wChannelCommandPointers + Ch7 * 2 ; sfx noise channel pointer - ld de, Noise2_endchannel + ld hl, wChannelCommandPointers + Ch7 * 2 ; sfx wave channel pointer + ld de, Audio2_CryRet ld [hl], e inc hl - ld [hl], d ; overwrite pointer to point to endchannel + ld [hl], d ; overwrite pointer to point to sound_ret ld a, [wSavedVolume] and a - jr nz, .asm_222d4 + jr nz, .done ld a, [rNR50] ld [wSavedVolume], a ld a, $77 - ld [rNR50], a -.asm_222d4 + ld [rNR50], a ; full volume +.done ret -Noise2_endchannel: +Audio2_CryRet: sound_ret -Unknown_222d6: - db $10, $15, $1A, $1F ; channels 0-3 - db $10, $15, $1A, $1F ; channels 4-7 +Audio2_HWChannelBaseAddresses: +; the low bytes of each HW channel's base address + db HW_CH1_BASE, HW_CH2_BASE, HW_CH3_BASE, HW_CH4_BASE ; channels 0-3 + db HW_CH1_BASE, HW_CH2_BASE, HW_CH3_BASE, HW_CH4_BASE ; channels 4-7 -Unknown_222de: - db $EE, $DD, $BB, $77 ; channels 0-3 - db $EE, $DD, $BB, $77 ; channels 4-7 +Audio2_HWChannelDisableMasks: + db HW_CH1_DISABLE_MASK, HW_CH2_DISABLE_MASK, HW_CH3_DISABLE_MASK, HW_CH4_DISABLE_MASK ; channels 0-3 + db HW_CH1_DISABLE_MASK, HW_CH2_DISABLE_MASK, HW_CH3_DISABLE_MASK, HW_CH4_DISABLE_MASK ; channels 4-7 -Unknown_222e6: - db $11, $22, $44, $88 ; channels 0-3 - db $11, $22, $44, $88 ; channels 4-7 +Audio2_HWChannelEnableMasks: + db HW_CH1_ENABLE_MASK, HW_CH2_ENABLE_MASK, HW_CH3_ENABLE_MASK, HW_CH4_ENABLE_MASK ; channels 0-3 + db HW_CH1_ENABLE_MASK, HW_CH2_ENABLE_MASK, HW_CH3_ENABLE_MASK, HW_CH4_ENABLE_MASK ; channels 4-7 Audio2_Pitches: dw $F82C ; C_ @@ -1731,5 +1798,3 @@ Audio2_Pitches: dw $FB58 ; A_ dw $FB9B ; A# dw $FBDA ; B_ - - diff --git a/audio/engine_3.asm b/audio/engine_3.asm index cf435740..f329c0c3 100644 --- a/audio/engine_3.asm +++ b/audio/engine_3.asm @@ -3,7 +3,7 @@ Audio3_UpdateMusic:: ld c, Ch1 .loop - ld b, $0 + ld b, 0 ld hl, wChannelSoundIDs add hl, bc ld a, [hl] @@ -19,7 +19,7 @@ Audio3_UpdateMusic:: jr nz, .nextChannel set 7, a ld [wMuteAudioAndPauseMusic], a - xor a + xor a ; disable all channels' output ld [rNR51], a ld [rNR30], a ld a, $80 @@ -36,18 +36,12 @@ Audio3_UpdateMusic:: ; this routine checks flags for music effects currently applied ; to the channel and calls certain functions based on flags. -; known flags for wChannelFlags1: -; 0: toggleperfectpitch has been used -; 1: call has been used -; 3: a toggle used only by this routine for vibrato -; 4: pitchbend flag -; 6: dutycycle flag Audio3_ApplyMusicAffects: ld b, $0 ld hl, wChannelNoteDelayCounters ; delay until next note add hl, bc ld a, [hl] - cp $1 ; if delay is 1, play next note + cp $1 ; if the delay is 1, play next note jp z, Audio3_PlayNextNote dec a ; otherwise, decrease the delay timer ld [hl], a @@ -63,36 +57,36 @@ Audio3_ApplyMusicAffects: .startChecks ld hl, wChannelFlags1 add hl, bc - bit 6, [hl] ; dutycycle + bit BIT_ROTATE_DUTY_CYCLE, [hl] jr z, .checkForExecuteMusic - call Audio3_ApplyDutyCycle + call Audio3_ApplyDutyCyclePattern .checkForExecuteMusic - ld b, $0 + ld b, 0 ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] - jr nz, .checkForPitchBend + bit BIT_EXECUTE_MUSIC, [hl] + jr nz, .checkForPitchSlide ld hl, wChannelFlags1 add hl, bc - bit 2, [hl] - jr nz, .disablePitchBendVibrato -.checkForPitchBend + bit BIT_NOISE_OR_SFX, [hl] + jr nz, .skipPitchSlideVibrato +.checkForPitchSlide ld hl, wChannelFlags1 add hl, bc - bit 4, [hl] ; pitchbend + bit BIT_PITCH_SLIDE_ON, [hl] jr z, .checkVibratoDelay - jp Audio3_ApplyPitchBend + jp Audio3_ApplyPitchSlide .checkVibratoDelay - ld hl, wChannelVibratoDelayCounters ; vibrato delay + ld hl, wChannelVibratoDelayCounters add hl, bc ld a, [hl] and a ; check if delay is over jr z, .checkForVibrato dec [hl] ; otherwise, dec delay -.disablePitchBendVibrato +.skipPitchSlideVibrato ret .checkForVibrato - ld hl, wChannelVibratoExtents ; vibrato rate + ld hl, wChannelVibratoExtents add hl, bc ld a, [hl] and a @@ -105,33 +99,35 @@ Audio3_ApplyMusicAffects: ld a, [hl] and $f and a - jr z, .vibratoAlreadyDone - dec [hl] ; apply vibrato pitch change + jr z, .applyVibrato + dec [hl] ; decrement counter ret -.vibratoAlreadyDone +.applyVibrato ld a, [hl] swap [hl] or [hl] - ld [hl], a ; reset the vibrato value and start again + ld [hl], a ; reload the counter ld hl, wChannelFrequencyLowBytes add hl, bc ld e, [hl] ; get note pitch ld hl, wChannelFlags1 add hl, bc - bit 3, [hl] ; this is the only code that sets/resets bit three so - jr z, .unset ; it continuously alternates which path it takes - res 3, [hl] +; This is the only code that sets/resets the vibrato direction bit, so it +; continuously alternates which path it takes. + bit BIT_VIBRATO_DIRECTION, [hl] + jr z, .unset + res BIT_VIBRATO_DIRECTION, [hl] ld a, d and $f ld d, a ld a, e sub d jr nc, .noCarry - ld a, $0 + ld a, 0 .noCarry jr .done .unset - set 3, [hl] + set BIT_VIBRATO_DIRECTION, [hl] ld a, d and $f0 swap a @@ -140,63 +136,66 @@ Audio3_ApplyMusicAffects: ld a, $ff .done ld d, a - ld b, $3 - call Audio3_7d8ac + ld b, REG_FREQUENCY_LO + call Audio3_GetRegisterPointer ld [hl], d ret ; this routine executes all music commands that take up no time, -; like tempo changes, duty changes etc. and doesn't return +; like tempo changes, duty cycle changes etc. and doesn't return ; until the first note is reached Audio3_PlayNextNote: +; reload the vibrato delay counter ld hl, wChannelVibratoDelayCounterReloadValues add hl, bc ld a, [hl] ld hl, wChannelVibratoDelayCounters add hl, bc ld [hl], a + ld hl, wChannelFlags1 add hl, bc - res 4, [hl] - res 5, [hl] - call Audio3_endchannel + res BIT_PITCH_SLIDE_ON, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] + call Audio3_sound_ret ret -Audio3_endchannel: +Audio3_sound_ret: call Audio3_GetNextMusicByte ld d, a - cp $ff ; is this command an endchannel? - jp nz, Audio3_callchannel ; no - ld b, $0 ; yes + cp $ff ; is this command a sound_ret? + jp nz, Audio3_sound_call ; no + ld b, 0 ld hl, wChannelFlags1 add hl, bc - bit 1, [hl] + bit BIT_SOUND_CALL, [hl] jr nz, .returnFromCall ld a, c cp Ch4 jr nc, .noiseOrSfxChannel - jr .asm_7d2b3 + jr .disableChannelOutput .noiseOrSfxChannel - res 2, [hl] + res BIT_NOISE_OR_SFX, [hl] ld hl, wChannelFlags2 add hl, bc - res 0, [hl] + res BIT_EXECUTE_MUSIC, [hl] cp Ch7 - jr nz, .notSfxChannel3 + jr nz, .skipSfxChannel3 +; restart hardware channel 3 (wave channel) output ld a, $0 ld [rNR30], a ld a, $80 ld [rNR30], a -.notSfxChannel3 - jr nz, .asm_7d296 +.skipSfxChannel3 + jr nz, .dontDisable ld a, [wDisableChannelOutputWhenSfxEnds] and a - jr z, .asm_7d296 + jr z, .dontDisable xor a ld [wDisableChannelOutputWhenSfxEnds], a - jr .asm_7d2b3 -.asm_7d296 - jr .asm_7d2bc + jr .disableChannelOutput +.dontDisable + jr .afterDisable .returnFromCall res 1, [hl] ld d, $0 @@ -216,45 +215,45 @@ Audio3_endchannel: inc de ld a, [de] ld [hl], a ; loads channel address to return to - jp Audio3_endchannel -.asm_7d2b3 - ld hl, Unknown_7db93 + jp Audio3_sound_ret +.disableChannelOutput + ld hl, Audio3_HWChannelDisableMasks add hl, bc ld a, [rNR51] and [hl] ld [rNR51], a -.asm_7d2bc +.afterDisable ld a, [wChannelSoundIDs + Ch5] - cp $14 - jr nc, .asm_7d2c5 - jr .asm_7d2e2 -.asm_7d2c5 + cp CRY_SFX_START + jr nc, .maybeCry + jr .skipCry +.maybeCry ld a, [wChannelSoundIDs + Ch5] - cp $86 - jr z, .asm_7d2e2 - jr c, .asm_7d2d0 - jr .asm_7d2e2 -.asm_7d2d0 + cp CRY_SFX_END + jr z, .skipCry + jr c, .cry + jr .skipCry +.cry ld a, c cp Ch5 - jr z, .asm_7d2d9 - call Audio3_7d73b + jr z, .skipRewind + call Audio3_GoBackOneCommandIfCry ret c -.asm_7d2d9 +.skipRewind ld a, [wSavedVolume] ld [rNR50], a xor a ld [wSavedVolume], a -.asm_7d2e2 +.skipCry ld hl, wChannelSoundIDs add hl, bc ld [hl], b ret -Audio3_callchannel: - cp $fd ; is this command a callchannel? - jp nz, Audio3_loopchannel ; no - call Audio3_GetNextMusicByte ; yes +Audio3_sound_call: + cp $fd ; is this command a sound_call? + jp nz, Audio3_sound_loop ; no + call Audio3_GetNextMusicByte push af call Audio3_GetNextMusicByte ld d, a @@ -285,27 +284,27 @@ Audio3_callchannel: ld b, $0 ld hl, wChannelFlags1 add hl, bc - set 1, [hl] ; set the call flag - jp Audio3_endchannel + set BIT_SOUND_CALL, [hl] ; set the call flag + jp Audio3_sound_ret -Audio3_loopchannel: - cp $fe ; is this command a loopchannel? - jp nz, Audio3_notetype ; no - call Audio3_GetNextMusicByte ; yes +Audio3_sound_loop: + cp $fe ; is this command a sound_loop? + jp nz, Audio3_note_type ; no + call Audio3_GetNextMusicByte ld e, a and a jr z, .infiniteLoop - ld b, $0 + ld b, 0 ld hl, wChannelLoopCounters add hl, bc ld a, [hl] cp e jr nz, .loopAgain - ld a, $1 ; if no more loops to make + ld a, $1 ; if no more loops to make, ld [hl], a call Audio3_GetNextMusicByte ; skip pointer call Audio3_GetNextMusicByte - jp Audio3_endchannel + jp Audio3_sound_ret .loopAgain ; inc loop count inc a ld [hl], a @@ -324,13 +323,13 @@ Audio3_loopchannel: pop af ld [hli], a ld [hl], b - jp Audio3_endchannel + jp Audio3_sound_ret -Audio3_notetype: +Audio3_note_type: and $f0 - cp $d0 ; is this command a notetype? - jp nz, Audio3_toggleperfectpitch ; no - ld a, d ; yes + cp $d0 ; is this command a note_type? + jp nz, Audio3_toggle_perfect_pitch ; no + ld a, d and $f ld b, $0 ld hl, wChannelNoteSpeeds @@ -345,15 +344,15 @@ Audio3_notetype: cp Ch3 jr z, .musicChannel3 cp Ch7 - jr nz, .notChannel3 + jr nz, .skipChannel3 ld hl, wSfxWaveInstrument - jr .sfxChannel3 + jr .channel3 .musicChannel3 ld hl, wMusicWaveInstrument -.sfxChannel3 +.channel3 ld a, d and $f - ld [hl], a ; store low nibble of param as duty + ld [hl], a ; store low nibble of param as wave instrument ld a, d and $30 sla a @@ -362,31 +361,31 @@ Audio3_notetype: ; if channel 3, store high nibble as volume ; else, store volume (high nibble) and fade (low nibble) -.notChannel3 - ld b, $0 +.skipChannel3 + ld b, 0 ld hl, wChannelVolumes add hl, bc ld [hl], d .noiseChannel - jp Audio3_endchannel + jp Audio3_sound_ret -Audio3_toggleperfectpitch: +Audio3_toggle_perfect_pitch: ld a, d - cp $e8 ; is this command a toggleperfectpitch? + cp $e8 ; is this command a toggle_perfect_pitch? jr nz, Audio3_vibrato ; no - ld b, $0 ; yes + ld b, 0 ld hl, wChannelFlags1 add hl, bc ld a, [hl] xor $1 ld [hl], a ; flip bit 0 of wChannelFlags1 - jp Audio3_endchannel + jp Audio3_sound_ret Audio3_vibrato: cp $ea ; is this command a vibrato? - jr nz, Audio3_pitchbend ; no - call Audio3_GetNextMusicByte ; yes - ld b, $0 + jr nz, Audio3_pitch_slide ; no + call Audio3_GetNextMusicByte + ld b, 0 ld hl, wChannelVibratoDelayCounters add hl, bc ld [hl], a ; store delay @@ -395,9 +394,16 @@ Audio3_vibrato: ld [hl], a ; store delay call Audio3_GetNextMusicByte ld d, a + +; The high nybble of the command byte is the extent of the vibrato. +; Let n be the extent. +; The upper nybble of the channel's byte in the wChannelVibratoExtents +; array will store the extent above the note: (n / 2) + (n % 2). +; The lower nybble will store the extent below the note: (n / 2). +; These two values add to the total extent, n. and $f0 swap a - ld b, $0 + ld b, 0 ld hl, wChannelVibratoExtents add hl, bc srl a @@ -405,7 +411,13 @@ Audio3_vibrato: adc b swap a or e - ld [hl], a ; store rate as both high and low nibbles + ld [hl], a + +; The low nybble of the command byte is the rate of the vibrato. +; The high and low nybbles of the channel's byte in the wChannelVibratoRates +; array are both initialised to this value because the high nybble is the +; counter reload value and the low nybble is the counter itself, which should +; start at its value upon reload. ld a, d and $f ld d, a @@ -413,17 +425,18 @@ Audio3_vibrato: add hl, bc swap a or d - ld [hl], a ; store depth as both high and low nibbles - jp Audio3_endchannel + ld [hl], a -Audio3_pitchbend: - cp $eb ; is this command a pitchbend? - jr nz, Audio3_duty ; no - call Audio3_GetNextMusicByte ; yes - ld b, $0 - ld hl, wChannelPitchBendLengthModifiers + jp Audio3_sound_ret + +Audio3_pitch_slide: + cp $eb ; is this command a pitch_slide? + jr nz, Audio3_duty_cycle ; no + call Audio3_GetNextMusicByte + ld b, 0 + ld hl, wChannelPitchSlideLengthModifiers add hl, bc - ld [hl], a ; store first param + ld [hl], a call Audio3_GetNextMusicByte ld d, a and $f0 @@ -431,39 +444,39 @@ Audio3_pitchbend: ld b, a ld a, d and $f - call Audio3_7d8cc - ld b, $0 - ld hl, wChannelPitchBendTargetFrequencyHighBytes + call Audio3_CalculateFrequency + ld b, 0 + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc - ld [hl], d ; store unknown part of second param - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld [hl], d + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc - ld [hl], e ; store unknown part of second param - ld b, $0 + ld [hl], e + ld b, 0 ld hl, wChannelFlags1 add hl, bc - set 4, [hl] ; set pitchbend flag + set BIT_PITCH_SLIDE_ON, [hl] call Audio3_GetNextMusicByte ld d, a - jp Audio3_notelength + jp Audio3_note_length -Audio3_duty: - cp $ec ; is this command a duty? +Audio3_duty_cycle: + cp $ec ; is this command a duty_cycle? jr nz, Audio3_tempo ; no - call Audio3_GetNextMusicByte ; yes + call Audio3_GetNextMusicByte rrca rrca and $c0 - ld b, $0 - ld hl, wChannelDuties + ld b, 0 + ld hl, wChannelDutyCycles add hl, bc - ld [hl], a ; store duty - jp Audio3_endchannel + ld [hl], a ; store duty cycle + jp Audio3_sound_ret Audio3_tempo: cp $ed ; is this command a tempo? - jr nz, Audio3_stereopanning ; no - ld a, c ; yes + jr nz, Audio3_stereo_panning ; no + ld a, c cp Ch5 jr nc, .sfxChannel call Audio3_GetNextMusicByte @@ -487,20 +500,20 @@ Audio3_tempo: ld [wChannelNoteDelayCountersFractionalPart + 6], a ld [wChannelNoteDelayCountersFractionalPart + 7], a .musicChannelDone - jp Audio3_endchannel + jp Audio3_sound_ret -Audio3_stereopanning: - cp $ee ; is this command a stereopanning? +Audio3_stereo_panning: + cp $ee ; is this command a stereo_panning? jr nz, Audio3_unknownmusic0xef ; no - call Audio3_GetNextMusicByte ; yes + call Audio3_GetNextMusicByte ld [wStereoPanning], a ; store panning - jp Audio3_endchannel + jp Audio3_sound_ret ; this appears to never be used Audio3_unknownmusic0xef: cp $ef ; is this command an unknownmusic0xef? - jr nz, Audio3_dutycycle ; no - call Audio3_GetNextMusicByte ; yes + jr nz, Audio3_duty_cycle_pattern ; no + call Audio3_GetNextMusicByte push bc call Audio3_PlaySound pop bc @@ -512,124 +525,141 @@ Audio3_unknownmusic0xef: xor a ld [wChannelSoundIDs + Ch8], a .skip - jp Audio3_endchannel + jp Audio3_sound_ret -Audio3_dutycycle: - cp $fc ; is this command a dutycycle? +Audio3_duty_cycle_pattern: + cp $fc ; is this command a duty_cycle_pattern? jr nz, Audio3_volume ; no - call Audio3_GetNextMusicByte ; yes - ld b, $0 - ld hl, wChannelDutyCycles + call Audio3_GetNextMusicByte + ld b, 0 + ld hl, wChannelDutyCyclePatterns add hl, bc - ld [hl], a ; store full cycle - and $c0 - ld hl, wChannelDuties + ld [hl], a ; store full pattern + and %11000000 + ld hl, wChannelDutyCycles add hl, bc - ld [hl], a ; store first duty + ld [hl], a ; store first duty cycle ld hl, wChannelFlags1 add hl, bc - set 6, [hl] ; set duty flag - jp Audio3_endchannel + set BIT_ROTATE_DUTY_CYCLE, [hl] + jp Audio3_sound_ret Audio3_volume: cp $f0 ; is this command a volume? - jr nz, Audio3_executemusic ; no - call Audio3_GetNextMusicByte ; yes + jr nz, Audio3_execute_music ; no + call Audio3_GetNextMusicByte ld [rNR50], a ; store volume - jp Audio3_endchannel + jp Audio3_sound_ret -Audio3_executemusic: - cp $f8 ; is this command an executemusic? +Audio3_execute_music: + cp $f8 ; is this command an execute_music? jr nz, Audio3_octave ; no - ld b, $0 ; yes + ld b, $0 ld hl, wChannelFlags2 add hl, bc - set 0, [hl] - jp Audio3_endchannel + set BIT_EXECUTE_MUSIC, [hl] + jp Audio3_sound_ret Audio3_octave: and $f0 cp $e0 ; is this command an octave? - jr nz, Audio3_sfxnote ; no - ld hl, wChannelOctaves ; yes - ld b, $0 + jr nz, Audio3_sfx_note ; no + ld hl, wChannelOctaves + ld b, 0 add hl, bc ld a, d and $f ld [hl], a ; store low nibble as octave - jp Audio3_endchannel + jp Audio3_sound_ret -; sfxnote is either squarenote or noisenote depending on the channel -Audio3_sfxnote: - cp $20 ; is this command an sfxnote? - jr nz, Audio3_pitchenvelope ; no +; sfx_note is either square_note or noise_note depending on the channel +Audio3_sfx_note: + cp $20 ; is this command a sfx_note? + jr nz, Audio3_pitch_sweep ld a, c cp Ch4 ; is this a noise or sfx channel? - jr c, Audio3_pitchenvelope ; no - ld b, $0 + jr c, Audio3_pitch_sweep ; no + ld b, 0 ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] - jr nz, Audio3_pitchenvelope ; no - call Audio3_notelength ; yes + bit BIT_EXECUTE_MUSIC, [hl] ; is execute_music being used? + jr nz, Audio3_pitch_sweep ; yes + call Audio3_note_length + +; This code seems to do the same thing as what Audio3_ApplyDutyCycleAndSoundLength +; does below. ld d, a - ld b, $0 - ld hl, wChannelDuties + ld b, 0 + ld hl, wChannelDutyCycles add hl, bc ld a, [hl] or d ld d, a - ld b, $1 - call Audio3_7d8ac + ld b, REG_DUTY_SOUND_LEN + call Audio3_GetRegisterPointer ld [hl], d + call Audio3_GetNextMusicByte ld d, a - ld b, $2 - call Audio3_7d8ac + ld b, REG_VOLUME_ENVELOPE + call Audio3_GetRegisterPointer ld [hl], d call Audio3_GetNextMusicByte ld e, a ld a, c cp Ch8 - ld a, $0 - jr z, .sfxNoiseChannel ; only two params for noise channel + ld a, 0 + jr z, .skip +; Channels 1 through 3 have 2 registers that control frequency, but the noise +; channel a single register (the polynomial counter) that controls frequency, +; so this command has one less byte on the noise channel. push de call Audio3_GetNextMusicByte pop de -.sfxNoiseChannel +.skip ld d, a push de - call Audio3_7d69d - call Audio3_7d66c + call Audio3_ApplyDutyCycleAndSoundLength + call Audio3_EnableChannelOutput pop de - call Audio3_7d6bf + call Audio3_ApplyWavePatternAndFrequency ret -Audio3_pitchenvelope: +Audio3_pitch_sweep: ld a, c cp Ch5 jr c, Audio3_note ; if not a sfx ld a, d - cp $10 ; is this command an pitchenvelope? + cp $10 ; is this command a pitch_sweep? jr nz, Audio3_note ; no ld b, $0 ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] + bit BIT_EXECUTE_MUSIC, [hl] jr nz, Audio3_note ; no - call Audio3_GetNextMusicByte ; yes + call Audio3_GetNextMusicByte ld [rNR10], a - jp Audio3_endchannel + jp Audio3_sound_ret Audio3_note: ld a, c cp Ch4 - jr nz, Audio3_notelength ; if not noise channel + jr nz, Audio3_note_length ; if not noise channel ld a, d and $f0 cp $b0 ; is this command a dnote? - jr z, Audio3_dnote ; yes - jr nc, Audio3_notelength ; no + jr z, .dnote + jr nc, Audio3_note_length ; no + + ; this executes when on the noise channel and + ; the command id is less than $b0 + ; in this case, the upper nybble is used as the noise instrument ($1-$a) + ; and the lower nybble is the length minus 1 (0-15) + ; however, this doesn't work for instrument #2 because the command id + ; is captured by the noise_note command (command id $2x) + ; this essentially acts like a dnote command that is only 1 byte + ; instead of 2 and can only be used with instruments 1 and 3 through 10 + ; this is unused by the game swap a ld b, a ld a, d @@ -638,38 +668,38 @@ Audio3_note: ld a, b push de push bc - jr asm_7d571 + jr .playDnote -Audio3_dnote: +.dnote ld a, d and $f push af push bc call Audio3_GetNextMusicByte ; get dnote instrument -asm_7d571 +.playDnote ld d, a ld a, [wDisableChannelOutputWhenSfxEnds] and a - jr nz, .asm_7d57c + jr nz, .skipDnote ld a, d call Audio3_PlaySound -.asm_7d57c +.skipDnote pop bc pop de -Audio3_notelength: +Audio3_note_length: ld a, d push af and $f inc a - ld b, $0 + ld b, 0 ld e, a ; store note length (in 16ths) ld d, b ld hl, wChannelNoteSpeeds add hl, bc ld a, [hl] ld l, b - call Audio3_7d8bb + call Audio3_MultiplyAdd ld a, c cp Ch5 jr nc, .sfxChannel @@ -683,20 +713,20 @@ Audio3_notelength: ld e, $0 cp Ch8 jr z, .skip ; if noise channel - call Audio3_7d707 + call Audio3_SetSfxTempo ld a, [wSfxTempo] ld d, a ld a, [wSfxTempo + 1] ld e, a .skip - ld a, l - ld b, $0 + ld a, l ; a = note_length * note_speed + ld b, 0 ld hl, wChannelNoteDelayCountersFractionalPart add hl, bc ld l, [hl] - call Audio3_7d8bb + call Audio3_MultiplyAdd ld e, l - ld d, h + ld d, h ; de = note_delay_frac_part + (note_length * note_speed * tempo) ld hl, wChannelNoteDelayCountersFractionalPart add hl, bc ld [hl], e @@ -706,192 +736,198 @@ Audio3_notelength: ld [hl], a ld hl, wChannelFlags2 add hl, bc - bit 0, [hl] - jr nz, Audio3_notepitch + bit BIT_EXECUTE_MUSIC, [hl] + jr nz, Audio3_note_pitch ld hl, wChannelFlags1 add hl, bc - bit 2, [hl] - jr z, Audio3_notepitch + bit BIT_NOISE_OR_SFX, [hl] + jr z, Audio3_note_pitch pop hl ret -Audio3_notepitch: +Audio3_note_pitch: pop af and $f0 cp $c0 ; compare to rest jr nz, .notRest ld a, c cp Ch5 - jr nc, .sfxChannel + jr nc, .next +; If this isn't an SFX channel, try the corresponding SFX channel. ld hl, wChannelSoundIDs + Ch5 add hl, bc ld a, [hl] and a - jr nz, .quit + jr nz, .done ; fall through -.sfxChannel +.next ld a, c cp Ch3 - jr z, .musicChannel3 + jr z, .channel3 cp Ch7 - jr nz, .notSfxChannel3 -.musicChannel3 - ld b, $0 - ld hl, Unknown_7db93 + jr nz, .notChannel3 +.channel3 + ld b, 0 + ld hl, Audio3_HWChannelDisableMasks add hl, bc ld a, [rNR51] and [hl] - ld [rNR51], a - jr .quit -.notSfxChannel3 - ld b, $2 - call Audio3_7d8ac - ld a, $8 + ld [rNR51], a ; disable hardware channel 3's output + jr .done +.notChannel3 + ld b, REG_VOLUME_ENVELOPE + call Audio3_GetRegisterPointer + ld a, $8 ; fade in sound ld [hli], a inc hl - ld a, $80 + ld a, $80 ; restart sound ld [hl], a -.quit +.done ret .notRest swap a - ld b, $0 + ld b, 0 ld hl, wChannelOctaves add hl, bc ld b, [hl] - call Audio3_7d8cc - ld b, $0 + call Audio3_CalculateFrequency + ld b, 0 ld hl, wChannelFlags1 add hl, bc - bit 4, [hl] - jr z, .asm_7d62c - call Audio3_7d803 -.asm_7d62c + bit BIT_PITCH_SLIDE_ON, [hl] + jr z, .skipPitchSlide + call Audio3_InitPitchSlideVars +.skipPitchSlide push de ld a, c cp Ch5 - jr nc, .skip ; if sfx Channel + jr nc, .sfxChannel ; if sfx channel +; If this isn't an SFX channel, try the corresponding SFX channel. ld hl, wChannelSoundIDs + Ch5 - ld d, $0 + ld d, 0 ld e, a add hl, de ld a, [hl] and a - jr nz, .done - jr .skip -.done + jr nz, .noSfx + jr .sfxChannel +.noSfx pop de ret -.skip - ld b, $0 +.sfxChannel + ld b, 0 ld hl, wChannelVolumes add hl, bc ld d, [hl] - ld b, $2 - call Audio3_7d8ac + ld b, REG_VOLUME_ENVELOPE + call Audio3_GetRegisterPointer ld [hl], d - call Audio3_7d69d - call Audio3_7d66c + call Audio3_ApplyDutyCycleAndSoundLength + call Audio3_EnableChannelOutput pop de ld b, $0 ld hl, wChannelFlags1 add hl, bc - bit 0, [hl] ; has toggleperfectpitch been used? - jr z, .skip2 - inc e ; if yes, increment the pitch by 1 - jr nc, .skip2 + bit BIT_PERFECT_PITCH, [hl] ; has toggle_perfect_pitch been used? + jr z, .skipFrequencyInc + inc e ; if yes, increment the frequency by 1 + jr nc, .skipFrequencyInc inc d -.skip2 +.skipFrequencyInc ld hl, wChannelFrequencyLowBytes add hl, bc ld [hl], e - call Audio3_7d6bf + call Audio3_ApplyWavePatternAndFrequency ret -Audio3_7d66c: - ld b, $0 - ld hl, Unknown_7db9b +Audio3_EnableChannelOutput: + ld b, 0 + ld hl, Audio3_HWChannelEnableMasks add hl, bc ld a, [rNR51] - or [hl] + or [hl] ; set this channel's bits ld d, a ld a, c cp Ch8 - jr z, .sfxNoiseChannel + jr z, .noiseChannelOrNoSfx cp Ch5 jr nc, .skip ; if sfx channel +; If this isn't an SFX channel, try the corresponding SFX channel. ld hl, wChannelSoundIDs + Ch5 add hl, bc ld a, [hl] and a jr nz, .skip -.sfxNoiseChannel +.noiseChannelOrNoSfx +; If this is the SFX noise channel or a music channel whose corresponding +; SFX channel is off, apply stereo panning. ld a, [wStereoPanning] - ld hl, Unknown_7db9b + ld hl, Audio3_HWChannelEnableMasks add hl, bc and [hl] ld d, a ld a, [rNR51] - ld hl, Unknown_7db93 + ld hl, Audio3_HWChannelDisableMasks add hl, bc - and [hl] - or d + and [hl] ; reset this channel's output bits + or d ; set this channel's output bits that enabled in [wStereoPanning] ld d, a .skip ld a, d ld [rNR51], a ret -Audio3_7d69d: - ld b, $0 - ld hl, wChannelNoteDelayCounters +Audio3_ApplyDutyCycleAndSoundLength: + ld b, 0 + ld hl, wChannelNoteDelayCounters ; use the note delay as sound length add hl, bc ld d, [hl] ld a, c cp Ch3 - jr z, .channel3 ; if music channel 3 + jr z, .skipDuty ; if music channel 3 cp Ch7 - jr z, .channel3 ; if sfx channel 3 + jr z, .skipDuty ; if sfx channel 3 +; include duty cycle (except on channel 3 which doesn't have it) ld a, d and $3f ld d, a - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, bc ld a, [hl] or d ld d, a -.channel3 - ld b, $1 - call Audio3_7d8ac +.skipDuty + ld b, REG_DUTY_SOUND_LEN + call Audio3_GetRegisterPointer ld [hl], d ret -Audio3_7d6bf: +Audio3_ApplyWavePatternAndFrequency: ld a, c cp Ch3 jr z, .channel3 cp Ch7 - jr nz, .notSfxChannel3 + jr nz, .notChannel3 ; fall through .channel3 push de ld de, wMusicWaveInstrument cp Ch3 - jr z, .musicChannel3 + jr z, .next ld de, wSfxWaveInstrument -.musicChannel3 +.next ld a, [de] add a - ld d, $0 + ld d, 0 ld e, a ld hl, Audio3_WavePointers add hl, de ld e, [hl] inc hl ld d, [hl] - ld hl, $ff30 + ld hl, $ff30 ; wave pattern RAM ld b, $f - ld a, $0 + ld a, $0 ; stop hardware channel 3 ld [rNR30], a .loop ld a, [de] @@ -901,152 +937,155 @@ Audio3_7d6bf: dec b and a jr nz, .loop - ld a, $80 + ld a, $80 ; start hardware channel 3 ld [rNR30], a pop de -.notSfxChannel3 +.notChannel3 ld a, d - or $80 - and $c7 + or $80 ; use counter mode (i.e. disable output when the counter reaches 0) + and $c7 ; zero the unused bits in the register ld d, a - ld b, $3 - call Audio3_7d8ac - ld [hl], e + ld b, REG_FREQUENCY_LO + call Audio3_GetRegisterPointer + ld [hl], e ; store frequency low byte inc hl - ld [hl], d - call Audio3_7d729 + ld [hl], d ; store frequency high byte + call Audio3_ApplyFrequencyModifier ret -Audio3_7d707: - call Audio3_7d759 - jr nc, .asm_7d71f - ld d, $0 +Audio3_SetSfxTempo: + call Audio3_IsCry + jr nc, .notCry + ld d, 0 ld a, [wTempoModifier] add $80 - jr nc, .asm_7d716 + jr nc, .next inc d -.asm_7d716 +.next ld [wSfxTempo + 1], a ld a, d ld [wSfxTempo], a - jr .asm_7d728 -.asm_7d71f + jr .done +.notCry xor a ld [wSfxTempo + 1], a ld a, $1 ld [wSfxTempo], a -.asm_7d728 +.done ret -Audio3_7d729: - call Audio3_7d759 - jr nc, .asm_7d73a +Audio3_ApplyFrequencyModifier: + call Audio3_IsCry + jr nc, .done +; if playing a cry, add the cry's frequency modifier ld a, [wFrequencyModifier] add e - jr nc, .asm_7d735 + jr nc, .noCarry inc d -.asm_7d735 +.noCarry dec hl ld e, a ld [hl], e inc hl ld [hl], d -.asm_7d73a +.done ret -Audio3_7d73b: - call Audio3_7d759 - jr nc, .asm_7d756 +Audio3_GoBackOneCommandIfCry: + call Audio3_IsCry + jr nc, .done ld hl, wChannelCommandPointers ld e, c - ld d, $0 + ld d, 0 sla e rl d add hl, de ld a, [hl] - sub $1 + sub 1 ld [hl], a inc hl ld a, [hl] - sbc $0 + sbc 0 ld [hl], a scf ret -.asm_7d756 +.done scf ccf ret -Audio3_7d759: +Audio3_IsCry: +; Returns whether the currently playing audio is a cry in carry. ld a, [wChannelSoundIDs + Ch5] - cp $14 - jr nc, .asm_7d762 - jr .asm_7d768 -.asm_7d762 - cp $86 - jr z, .asm_7d768 - jr c, .asm_7d76b -.asm_7d768 + cp CRY_SFX_START + jr nc, .next + jr .no +.next + cp CRY_SFX_END + jr z, .no + jr c, .yes +.no scf ccf ret -.asm_7d76b +.yes scf ret -Audio3_ApplyPitchBend: +Audio3_ApplyPitchSlide: ld hl, wChannelFlags1 add hl, bc - bit 5, [hl] - jp nz, .asm_7d7b4 - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + bit BIT_PITCH_SLIDE_DECREASING, [hl] + jp nz, .frequencyDecreasing +; frequency increasing + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld e, [hl] - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld l, [hl] ld h, b add hl, de ld d, h ld e, l - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, bc push hl - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld a, [hl] pop hl add [hl] ld [hl], a - ld a, $0 + ld a, 0 adc e ld e, a - ld a, $0 + ld a, 0 adc d ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] cp d - jp c, .asm_7d7fa - jr nz, .asm_7d7e7 - ld hl, wChannelPitchBendTargetFrequencyLowBytes + jp c, .reachedTargetFrequency + jr nz, .applyUpdatedFrequency + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, [hl] cp e - jp c, .asm_7d7fa - jr .asm_7d7e7 -.asm_7d7b4 - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + jp c, .reachedTargetFrequency + jr .applyUpdatedFrequency +.frequencyDecreasing + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld a, [hl] - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, bc ld e, [hl] sub e @@ -1054,7 +1093,7 @@ Audio3_ApplyPitchBend: ld a, d sbc b ld d, a - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc ld a, [hl] add a @@ -1065,129 +1104,140 @@ Audio3_ApplyPitchBend: ld a, d sbc b ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, d cp [hl] - jr c, .asm_7d7fa - jr nz, .asm_7d7e7 - ld hl, wChannelPitchBendTargetFrequencyLowBytes + jr c, .reachedTargetFrequency + jr nz, .applyUpdatedFrequency + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, e cp [hl] - jr c, .asm_7d7fa -.asm_7d7e7 - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + jr c, .reachedTargetFrequency +.applyUpdatedFrequency + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld [hl], e - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld [hl], d - ld b, $3 - call Audio3_7d8ac + ld b, REG_FREQUENCY_LO + call Audio3_GetRegisterPointer ld a, e ld [hli], a ld [hl], d ret -.asm_7d7fa +.reachedTargetFrequency +; Turn off pitch slide when the target frequency has been reached. ld hl, wChannelFlags1 add hl, bc - res 4, [hl] - res 5, [hl] + res BIT_PITCH_SLIDE_ON, [hl] + res BIT_PITCH_SLIDE_DECREASING, [hl] ret -Audio3_7d803: - ld hl, wChannelPitchBendCurrentFrequencyHighBytes +Audio3_InitPitchSlideVars: + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld [hl], d - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld [hl], e ld hl, wChannelNoteDelayCounters add hl, bc ld a, [hl] - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, bc sub [hl] - jr nc, .asm_7d81b - ld a, $1 -.asm_7d81b + jr nc, .next + ld a, 1 +.next ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, e sub [hl] ld e, a ld a, d sbc b - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc sub [hl] - jr c, .asm_7d837 + jr c, .targetFrequencyGreater ld d, a - ld b, $0 + ld b, 0 ld hl, wChannelFlags1 add hl, bc - set 5, [hl] - jr .asm_7d85a -.asm_7d837 - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + set BIT_PITCH_SLIDE_DECREASING, [hl] + jr .next2 +.targetFrequencyGreater +; If the target frequency is greater, subtract the current frequency from +; the target frequency to get the absolute difference. + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, bc ld d, [hl] - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, bc ld e, [hl] - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, bc ld a, [hl] sub e ld e, a + +; Bug. Instead of borrowing from the high byte of the target frequency as it +; should, it borrows from the high byte of the current frequency instead. +; This means that the result will be 0x200 greater than it should be if the +; low byte of the current frequency is greater than the low byte of the +; target frequency. ld a, d sbc b ld d, a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] sub d ld d, a - ld b, $0 + ld b, 0 ld hl, wChannelFlags1 add hl, bc - res 5, [hl] -.asm_7d85a - ld hl, wChannelPitchBendLengthModifiers + res BIT_PITCH_SLIDE_DECREASING, [hl] + +.next2 + ld hl, wChannelPitchSlideLengthModifiers add hl, bc -.asm_7d85e +.divideLoop inc b ld a, e sub [hl] ld e, a - jr nc, .asm_7d85e + jr nc, .divideLoop ld a, d and a - jr z, .asm_7d86c + jr z, .doneDividing dec a ld d, a - jr .asm_7d85e -.asm_7d86c - ld a, e + jr .divideLoop +.doneDividing + ld a, e ; a = remainder - dividend add [hl] - ld d, b - ld b, $0 - ld hl, wChannelPitchBendFrequencySteps + ld d, b ; d = quotient + 1 + ld b, 0 + ld hl, wChannelPitchSlideFrequencySteps add hl, bc - ld [hl], d - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld [hl], d ; store quotient + 1 + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, bc - ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld [hl], a ; store remainder - dividend + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, bc - ld [hl], a + ld [hl], a ; store remainder - dividend ret -Audio3_ApplyDutyCycle: - ld b, $0 - ld hl, wChannelDutyCycles +Audio3_ApplyDutyCyclePattern: + ld b, 0 + ld hl, wChannelDutyCyclePatterns add hl, bc ld a, [hl] rlca @@ -1195,8 +1245,8 @@ Audio3_ApplyDutyCycle: ld [hl], a and $c0 ld d, a - ld b, $1 - call Audio3_7d8ac + ld b, REG_DUTY_SOUND_LEN + call Audio3_GetRegisterPointer ld a, [hl] and $3f or d @@ -1204,7 +1254,7 @@ Audio3_ApplyDutyCycle: ret Audio3_GetNextMusicByte: - ld d, $0 + ld d, 0 ld a, c add a ld e, a @@ -1221,9 +1271,10 @@ Audio3_GetNextMusicByte: ld [hl], d ret -Audio3_7d8ac: +Audio3_GetRegisterPointer: +; hl = address of hardware sound register b for software channel c ld a, c - ld hl, Unknown_7db8b + ld hl, Audio3_HWChannelBaseAddresses add l jr nc, .noCarry inc h @@ -1235,13 +1286,14 @@ Audio3_7d8ac: ld h, $ff ret -Audio3_7d8bb: - ld h, $0 +Audio3_MultiplyAdd: +; hl = l + (a * de) + ld h, 0 .loop srl a - jr nc, .noCarry + jr nc, .skipAdd add hl, de -.noCarry +.skipAdd sla e rl d and a @@ -1250,8 +1302,9 @@ Audio3_7d8bb: .done ret -Audio3_7d8cc: - ld h, $0 +Audio3_CalculateFrequency: +; return the frequency for note a, octave b in de + ld h, 0 ld l, a add hl, hl ld d, h @@ -1263,14 +1316,14 @@ Audio3_7d8cc: ld d, [hl] ld a, b .loop - cp $7 + cp 7 jr z, .done sra d rr e inc a jr .loop .done - ld a, $8 + ld a, 8 add d ld d, a ret @@ -1278,14 +1331,15 @@ Audio3_7d8cc: Audio3_PlaySound:: ld [wSoundID], a cp $ff - jp z, Audio3_7daa8 - cp $c2 - jp z, Audio3_7d9c2 - jp c, Audio3_7d9c2 + jp z, .stopAllAudio + cp MAX_SFX_ID_3 + jp z, .playSfx + jp c, .playSfx cp $fe - jr z, .asm_7d901 - jp nc, Audio3_7d9c2 -.asm_7d901 + jr z, .playMusic + jp nc, .playSfx + +.playMusic xor a ld [wUnusedC000], a ld [wDisableChannelOutputWhenSfxEnds], a @@ -1294,53 +1348,53 @@ Audio3_PlaySound:: ld [wSfxWaveInstrument], a ld d, $8 ld hl, wChannelReturnAddresses - call FillAudioRAM3 + call .FillMem ld hl, wChannelCommandPointers - call FillAudioRAM3 + call .FillMem ld d, $4 ld hl, wChannelSoundIDs - call FillAudioRAM3 + call .FillMem ld hl, wChannelFlags1 - call FillAudioRAM3 - ld hl, wChannelDuties - call FillAudioRAM3 + call .FillMem ld hl, wChannelDutyCycles - call FillAudioRAM3 + call .FillMem + ld hl, wChannelDutyCyclePatterns + call .FillMem ld hl, wChannelVibratoDelayCounters - call FillAudioRAM3 + call .FillMem ld hl, wChannelVibratoExtents - call FillAudioRAM3 + call .FillMem ld hl, wChannelVibratoRates - call FillAudioRAM3 + call .FillMem ld hl, wChannelFrequencyLowBytes - call FillAudioRAM3 + call .FillMem ld hl, wChannelVibratoDelayCounterReloadValues - call FillAudioRAM3 + call .FillMem ld hl, wChannelFlags2 - call FillAudioRAM3 - ld hl, wChannelPitchBendLengthModifiers - call FillAudioRAM3 - ld hl, wChannelPitchBendFrequencySteps - call FillAudioRAM3 - ld hl, wChannelPitchBendFrequencyStepsFractionalPart - call FillAudioRAM3 - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart - call FillAudioRAM3 - ld hl, wChannelPitchBendCurrentFrequencyHighBytes - call FillAudioRAM3 - ld hl, wChannelPitchBendCurrentFrequencyLowBytes - call FillAudioRAM3 - ld hl, wChannelPitchBendTargetFrequencyHighBytes - call FillAudioRAM3 - ld hl, wChannelPitchBendTargetFrequencyLowBytes - call FillAudioRAM3 + call .FillMem + ld hl, wChannelPitchSlideLengthModifiers + call .FillMem + ld hl, wChannelPitchSlideFrequencySteps + call .FillMem + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart + call .FillMem + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart + call .FillMem + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes + call .FillMem + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes + call .FillMem + ld hl, wChannelPitchSlideTargetFrequencyHighBytes + call .FillMem + ld hl, wChannelPitchSlideTargetFrequencyLowBytes + call .FillMem ld a, $1 ld hl, wChannelLoopCounters - call FillAudioRAM3 + call .FillMem ld hl, wChannelNoteDelayCounters - call FillAudioRAM3 + call .FillMem ld hl, wChannelNoteSpeeds - call FillAudioRAM3 + call .FillMem ld [wMusicTempo], a ld a, $ff ld [wStereoPanning], a @@ -1348,7 +1402,7 @@ Audio3_PlaySound:: ld [rNR50], a ld a, $8 ld [rNR10], a - ld a, $0 + ld a, 0 ld [rNR51], a xor a ld [rNR30], a @@ -1356,12 +1410,12 @@ Audio3_PlaySound:: ld [rNR30], a ld a, $77 ld [rNR50], a - jp Audio3_7db03 + jp .playSoundCommon -Audio3_7d9c2: +.playSfx ld l, a ld e, a - ld h, $0 + ld h, 0 ld d, h add hl, hl add hl, de @@ -1376,13 +1430,13 @@ Audio3_7d9c2: rlca rlca ld c, a -.asm_7d9db +.sfxChannelLoop ld d, c ld a, c add a add c ld c, a - ld b, $0 + ld b, 0 ld a, [wSfxHeaderPointer] ld h, a ld a, [wSfxHeaderPointer + 1] @@ -1391,32 +1445,32 @@ Audio3_7d9c2: ld c, d ld a, [hl] and $f - ld e, a - ld d, $0 + ld e, a ; software channel ID + ld d, 0 ld hl, wChannelSoundIDs add hl, de ld a, [hl] and a - jr z, .asm_7da17 + jr z, .playChannel ld a, e - cp $7 - jr nz, .asm_7da0e + cp Ch8 + jr nz, .notNoiseChannel ld a, [wSoundID] - cp $14 - jr nc, .asm_7da07 + cp NOISE_INSTRUMENTS_END + jr nc, .notNoiseInstrument ret -.asm_7da07 +.notNoiseInstrument ld a, [hl] - cp $14 - jr z, .asm_7da17 - jr c, .asm_7da17 -.asm_7da0e + cp NOISE_INSTRUMENTS_END + jr z, .playChannel + jr c, .playChannel +.notNoiseChannel ld a, [wSoundID] cp [hl] - jr z, .asm_7da17 - jr c, .asm_7da17 + jr z, .playChannel + jr c, .playChannel ret -.asm_7da17 +.playChannel xor a push de ld h, d @@ -1439,10 +1493,10 @@ Audio3_7d9c2: ld hl, wChannelFlags1 add hl, de ld [hl], a - ld hl, wChannelDuties + ld hl, wChannelDutyCycles add hl, de ld [hl], a - ld hl, wChannelDutyCycles + ld hl, wChannelDutyCyclePatterns add hl, de ld [hl], a ld hl, wChannelVibratoDelayCounters @@ -1460,28 +1514,28 @@ Audio3_7d9c2: ld hl, wChannelVibratoDelayCounterReloadValues add hl, de ld [hl], a - ld hl, wChannelPitchBendLengthModifiers + ld hl, wChannelPitchSlideLengthModifiers add hl, de ld [hl], a - ld hl, wChannelPitchBendFrequencySteps + ld hl, wChannelPitchSlideFrequencySteps add hl, de ld [hl], a - ld hl, wChannelPitchBendFrequencyStepsFractionalPart + ld hl, wChannelPitchSlideFrequencyStepsFractionalPart add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyFractionalPart + ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyHighBytes + ld hl, wChannelPitchSlideCurrentFrequencyHighBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendCurrentFrequencyLowBytes + ld hl, wChannelPitchSlideCurrentFrequencyLowBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyHighBytes + ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, de ld [hl], a - ld hl, wChannelPitchBendTargetFrequencyLowBytes + ld hl, wChannelPitchSlideTargetFrequencyLowBytes add hl, de ld [hl], a ld hl, wChannelFlags2 @@ -1498,35 +1552,35 @@ Audio3_7d9c2: add hl, de ld [hl], a ld a, e - cp $4 - jr nz, .asm_7da9f + cp Ch5 + jr nz, .skipSweepDisable ld a, $8 - ld [rNR10], a -.asm_7da9f + ld [rNR10], a ; sweep off +.skipSweepDisable ld a, c and a - jp z, Audio3_7db03 + jp z, .playSoundCommon dec c - jp .asm_7d9db + jp .sfxChannelLoop -Audio3_7daa8: +.stopAllAudio ld a, $80 - ld [rNR52], a - ld [rNR30], a + ld [rNR52], a ; sound hardware on + ld [rNR30], a ; wave playback on xor a - ld [rNR51], a - ld [rNR32], a + ld [rNR51], a ; no sound output + ld [rNR32], a ; mute channel 3 (wave channel) ld a, $8 - ld [rNR10], a - ld [rNR12], a - ld [rNR22], a - ld [rNR42], a + ld [rNR10], a ; sweep off + ld [rNR12], a ; mute channel 1 (pulse channel 1) + ld [rNR22], a ; mute channel 2 (pulse channel 2) + ld [rNR42], a ; mute channel 4 (noise channel) ld a, $40 - ld [rNR14], a + ld [rNR14], a ; counter mode ld [rNR24], a ld [rNR44], a ld a, $77 - ld [rNR50], a + ld [rNR50], a ; full volume xor a ld [wUnusedC000], a ld [wDisableChannelOutputWhenSfxEnds], a @@ -1537,11 +1591,11 @@ Audio3_7daa8: ld [wSfxWaveInstrument], a ld d, $a0 ld hl, wChannelCommandPointers - call FillAudioRAM3 + call .FillMem ld a, $1 ld d, $18 ld hl, wChannelNoteDelayCounters - call FillAudioRAM3 + call .FillMem ld [wMusicTempo], a ld [wSfxTempo], a ld a, $ff @@ -1549,7 +1603,7 @@ Audio3_7daa8: ret ; fills d bytes at hl with a -FillAudioRAM3: +.FillMem ld b, d .loop ld [hli], a @@ -1557,11 +1611,11 @@ FillAudioRAM3: jr nz, .loop ret -Audio3_7db03: +.playSoundCommon ld a, [wSoundID] ld l, a ld e, a - ld h, $0 + ld h, 0 ld d, h add hl, hl add hl, de @@ -1581,31 +1635,31 @@ Audio3_7db03: ld b, c inc b inc de - ld c, $0 -.asm_7db25 + ld c, 0 +.commandPointerLoop cp c - jr z, .asm_7db2d + jr z, .next inc c inc hl inc hl - jr .asm_7db25 -.asm_7db2d + jr .commandPointerLoop +.next push hl push bc push af - ld b, $0 + ld b, 0 ld c, a ld hl, wChannelSoundIDs add hl, bc ld a, [wSoundID] ld [hl], a pop af - cp $3 - jr c, .asm_7db46 + cp Ch4 + jr c, .skipSettingFlag ld hl, wChannelFlags1 add hl, bc - set 2, [hl] -.asm_7db46 + set BIT_NOISE_OR_SFX, [hl] +.skipSettingFlag pop bc pop hl ld a, [de] ; get channel pointer @@ -1620,52 +1674,53 @@ Audio3_7db03: and a ld a, [de] inc de - jr nz, .asm_7db25 + jr nz, .commandPointerLoop ld a, [wSoundID] - cp $14 - jr nc, .asm_7db5f - jr .asm_7db89 -.asm_7db5f + cp CRY_SFX_START + jr nc, .maybeCry + jr .done +.maybeCry ld a, [wSoundID] - cp $86 - jr z, .asm_7db89 - jr c, .asm_7db6a - jr .asm_7db89 -.asm_7db6a + cp CRY_SFX_END + jr z, .done + jr c, .cry + jr .done +.cry ld hl, wChannelSoundIDs + Ch5 ld [hli], a ld [hli], a ld [hli], a ld [hl], a - ld hl, wChannelCommandPointers + Ch7 * 2 ; sfx noise channel pointer - ld de, Noise3_endchannel + ld hl, wChannelCommandPointers + Ch7 * 2 ; sfx wave channel pointer + ld de, Audio3_CryRet ld [hl], e inc hl - ld [hl], d ; overwrite pointer to point to endchannel + ld [hl], d ; overwrite pointer to point to sound_ret ld a, [wSavedVolume] and a - jr nz, .asm_7db89 + jr nz, .done ld a, [rNR50] ld [wSavedVolume], a ld a, $77 - ld [rNR50], a -.asm_7db89 + ld [rNR50], a ; full volume +.done ret -Noise3_endchannel: +Audio3_CryRet: sound_ret -Unknown_7db8b: - db $10, $15, $1A, $1F ; channels 0-3 - db $10, $15, $1A, $1F ; channels 4-7 +Audio3_HWChannelBaseAddresses: +; the low bytes of each HW channel's base address + db HW_CH1_BASE, HW_CH2_BASE, HW_CH3_BASE, HW_CH4_BASE ; channels 0-3 + db HW_CH1_BASE, HW_CH2_BASE, HW_CH3_BASE, HW_CH4_BASE ; channels 4-7 -Unknown_7db93: - db $EE, $DD, $BB, $77 ; channels 0-3 - db $EE, $DD, $BB, $77 ; channels 4-7 +Audio3_HWChannelDisableMasks: + db HW_CH1_DISABLE_MASK, HW_CH2_DISABLE_MASK, HW_CH3_DISABLE_MASK, HW_CH4_DISABLE_MASK ; channels 0-3 + db HW_CH1_DISABLE_MASK, HW_CH2_DISABLE_MASK, HW_CH3_DISABLE_MASK, HW_CH4_DISABLE_MASK ; channels 4-7 -Unknown_7db9b: - db $11, $22, $44, $88 ; channels 0-3 - db $11, $22, $44, $88 ; channels 4-7 +Audio3_HWChannelEnableMasks: + db HW_CH1_ENABLE_MASK, HW_CH2_ENABLE_MASK, HW_CH3_ENABLE_MASK, HW_CH4_ENABLE_MASK ; channels 0-3 + db HW_CH1_ENABLE_MASK, HW_CH2_ENABLE_MASK, HW_CH3_ENABLE_MASK, HW_CH4_ENABLE_MASK ; channels 4-7 Audio3_Pitches: dw $F82C ; C_ @@ -1680,5 +1735,3 @@ Audio3_Pitches: dw $FB58 ; A_ dw $FB9B ; A# dw $FBDA ; B_ - - diff --git a/audio/music/yellow/meetjessiejames.asm b/audio/music/yellow/meetjessiejames.asm index 7f1f4598..d1f9f795 100644 --- a/audio/music/yellow/meetjessiejames.asm +++ b/audio/music/yellow/meetjessiejames.asm @@ -306,4 +306,3 @@ Music_MeetJessieJames_branch_83235:: note E_, 1 rest 1 sound_loop 0, Music_MeetJessieJames_branch_83235 - sound_ret diff --git a/constants/music_constants.asm b/constants/music_constants.asm index 9cf72b26..de91352e 100644 --- a/constants/music_constants.asm +++ b/constants/music_constants.asm @@ -20,19 +20,27 @@ REG_DUTY_SOUND_LEN EQU 1 REG_VOLUME_ENVELOPE EQU 2 REG_FREQUENCY_LO EQU 3 -MAX_SFX_ID EQU $B9 +MAX_SFX_ID_1 EQUS "SFX_SAFARI_ZONE_PA" +MAX_SFX_ID_2 EQUS "SFX_SILPH_SCOPE" +MAX_SFX_ID_3 EQUS "SFX_SHOOTING_STAR" -CRY_SFX_START EQU $14 -CRY_SFX_END EQU $86 +NOISE_INSTRUMENTS_START EQUS "SFX_NOISE_INSTRUMENT01" +NOISE_INSTRUMENTS_END EQUS "SFX_NOISE_INSTRUMENT19 + 1" + +CRY_SFX_START EQUS "SFX_CRY_00" +CRY_SFX_END EQUS "SFX_CRY_25 + 3" + +BATTLE_SFX_START EQUS "SFX_PECK" +BATTLE_SFX_END EQUS "SFX_SILPH_SCOPE + 1" ; wChannelFlags1 constants -BIT_PERFECT_PITCH EQU 0 ; controlled by toggleperfectpitch command -BIT_CHANNEL_CALL EQU 1 ; if in channel call -BIT_NOISE_OR_SFX EQU 2 ; if channel is the music noise channel or an SFX channel -BIT_VIBRATO_DIRECTION EQU 3 ; if the pitch is above or below normal (cycles) -BIT_PITCH_BEND_ON EQU 4 ; if pitch bend is active -BIT_PITCH_BEND_DECREASING EQU 5 ; if the pitch bend frequency is decreasing (instead of increasing) -BIT_ROTATE_DUTY EQU 6 ; if rotating duty +BIT_PERFECT_PITCH EQU 0 ; controlled by toggle_perfect_pitch command +BIT_SOUND_CALL EQU 1 ; if in sound call +BIT_NOISE_OR_SFX EQU 2 ; if channel is the music noise channel or an SFX channel +BIT_VIBRATO_DIRECTION EQU 3 ; if the pitch is above or below normal (cycles) +BIT_PITCH_SLIDE_ON EQU 4 ; if pitch slide is active +BIT_PITCH_SLIDE_DECREASING EQU 5 ; if the pitch slide frequency is decreasing (instead of increasing) +BIT_ROTATE_DUTY_CYCLE EQU 6 ; if rotating duty cycle ; wChannelFlags2 constant (only has one flag) BIT_EXECUTE_MUSIC EQU 0 ; if in execute music diff --git a/macros/audio_macros.asm b/macros/audio_macros.asm index a4cd6c3b..a2282445 100755 --- a/macros/audio_macros.asm +++ b/macros/audio_macros.asm @@ -86,6 +86,14 @@ dnote: MACRO db \1 ENDM +;format: instrument [1, 3-10], length (in 16ths) +; like dnote but one 1 byte instead of 2 +; can only be used with instruments 1-10, excluding 2 +; unused +dnote_short: MACRO + db (\1 << 4) | (\2 - 1) +ENDM + ;format: length (in 16ths) rest: MACRO db $C0 | (\1 - 1) @@ -101,10 +101,10 @@ wChannelFlags1:: ; c02e wChannelFlags2:: ; c036 ds 8 -wChannelDuties:: ; c03e +wChannelDutyCycles:: ; c03e ds 8 -wChannelDutyCycles:: ; c046 +wChannelDutyCyclePatterns:: ; c046 ds 8 wChannelVibratoDelayCounters:: ; c04e @@ -126,28 +126,28 @@ wChannelVibratoDelayCounterReloadValues:: ; c06e ; delay of the beginning of the vibrato from the start of the note ds 8 -wChannelPitchBendLengthModifiers:: ; c076 +wChannelPitchSlideLengthModifiers:: ; c076 ds 8 -wChannelPitchBendFrequencySteps:: ; c07e +wChannelPitchSlideFrequencySteps:: ; c07e ds 8 -wChannelPitchBendFrequencyStepsFractionalPart:: ; c086 +wChannelPitchSlideFrequencyStepsFractionalPart:: ; c086 ds 8 -wChannelPitchBendCurrentFrequencyFractionalPart:: ; c08e +wChannelPitchSlideCurrentFrequencyFractionalPart:: ; c08e ds 8 -wChannelPitchBendCurrentFrequencyHighBytes:: ; c096 +wChannelPitchSlideCurrentFrequencyHighBytes:: ; c096 ds 8 -wChannelPitchBendCurrentFrequencyLowBytes:: ; c09e +wChannelPitchSlideCurrentFrequencyLowBytes:: ; c09e ds 8 -wChannelPitchBendTargetFrequencyHighBytes:: ; c0a6 +wChannelPitchSlideTargetFrequencyHighBytes:: ; c0a6 ds 8 -wChannelPitchBendTargetFrequencyLowBytes:: ; c0ae +wChannelPitchSlideTargetFrequencyLowBytes:: ; c0ae ds 8 wChannelNoteDelayCounters:: ; c0b6 |