pokered/audio/engine_1.asm

1738 lines
33 KiB
NASM
Raw Normal View History

2014-01-07 03:34:14 +00:00
; The first of three duplicated sound engines.
Audio1_UpdateMusic::
ld c, Ch1
2014-01-07 03:34:14 +00:00
.loop
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelSoundIDs
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and a
jr z, .nextChannel
ld a, c
cp Ch5
2015-08-09 05:32:44 +00:00
jr nc, .applyAffects ; if sfx channel
ld a, [wMuteAudioAndPauseMusic]
2014-01-07 03:34:14 +00:00
and a
2015-08-09 05:32:44 +00:00
jr z, .applyAffects
2014-01-07 03:34:14 +00:00
bit 7, a
jr nz, .nextChannel
set 7, a
2015-08-09 05:32:44 +00:00
ld [wMuteAudioAndPauseMusic], a
xor a ; disable all channels' output
ld [rNR51], a
ld [rNR30], a
2014-01-07 03:34:14 +00:00
ld a, $80
2015-08-09 05:32:44 +00:00
ld [rNR30], a
2014-01-07 03:34:14 +00:00
jr .nextChannel
2015-08-09 05:32:44 +00:00
.applyAffects
call Audio1_ApplyMusicAffects
2014-01-07 03:34:14 +00:00
.nextChannel
ld a, c
inc c ; inc channel number
cp Ch8
2014-06-09 20:58:02 +00:00
jr nz, .loop
2014-01-07 03:34:14 +00:00
ret
; this routine checks flags for music effects currently applied
; to the channel and calls certain functions based on flags.
Audio1_ApplyMusicAffects:
2014-01-07 03:34:14 +00:00
ld b, $0
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteDelayCounters ; delay until next note
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
cp $1 ; if the delay is 1, play next note
jp z, Audio1_PlayNextNote
2014-01-07 03:34:14 +00:00
dec a ; otherwise, decrease the delay timer
ld [hl], a
ld a, c
cp Ch5
2014-01-07 03:34:14 +00:00
jr nc, .startChecks ; if a sfx channel
ld hl, wChannelSoundIDs + Ch5
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and a
jr z, .startChecks
ret
.startChecks
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
bit BIT_ROTATE_DUTY_CYCLE, [hl]
2014-01-07 03:34:14 +00:00
jr z, .checkForExecuteMusic
call Audio1_ApplyDutyCyclePattern
2014-01-07 03:34:14 +00:00
.checkForExecuteMusic
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
bit BIT_EXECUTE_MUSIC, [hl]
jr nz, .checkForPitchSlide
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
bit BIT_NOISE_OR_SFX, [hl]
jr nz, .skipPitchSlideVibrato
.checkForPitchSlide
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
bit BIT_PITCH_SLIDE_ON, [hl]
2014-01-07 03:34:14 +00:00
jr z, .checkVibratoDelay
jp Audio1_ApplyPitchSlide
2014-01-07 03:34:14 +00:00
.checkVibratoDelay
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoDelayCounters
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and a ; check if delay is over
jr z, .checkForVibrato
dec [hl] ; otherwise, dec delay
.skipPitchSlideVibrato
2014-01-07 03:34:14 +00:00
ret
.checkForVibrato
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoExtents
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and a
jr nz, .vibrato
ret ; no vibrato
.vibrato
ld d, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoRates
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and $f
and a
2015-08-09 05:32:44 +00:00
jr z, .applyVibrato
dec [hl] ; decrement counter
2014-01-07 03:34:14 +00:00
ret
2015-08-09 05:32:44 +00:00
.applyVibrato
2014-01-07 03:34:14 +00:00
ld a, [hl]
swap [hl]
or [hl]
2015-08-09 05:32:44 +00:00
ld [hl], a ; reload the counter
ld hl, wChannelFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld e, [hl] ; get note pitch
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
; 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]
2014-01-07 03:34:14 +00:00
ld a, d
and $f
ld d, a
ld a, e
sub d
jr nc, .noCarry
2015-08-09 05:32:44 +00:00
ld a, 0
2014-01-07 03:34:14 +00:00
.noCarry
jr .done
.unset
2015-08-09 05:32:44 +00:00
set BIT_VIBRATO_DIRECTION, [hl]
2014-01-07 03:34:14 +00:00
ld a, d
and $f0
swap a
add e
jr nc, .done
ld a, $ff
.done
ld d, a
2015-08-09 05:32:44 +00:00
ld b, REG_FREQUENCY_LO
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld [hl], d
ret
; this routine executes all music commands that take up no time,
; like tempo changes, duty cycle changes etc. and doesn't return
2014-01-07 03:34:14 +00:00
; until the first note is reached
Audio1_PlayNextNote:
2015-08-09 05:32:44 +00:00
; reload the vibrato delay counter
ld hl, wChannelVibratoDelayCounterReloadValues
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoDelayCounters
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
res BIT_PITCH_SLIDE_ON, [hl]
res BIT_PITCH_SLIDE_DECREASING, [hl]
call Audio1_sound_ret
2014-01-07 03:34:14 +00:00
ret
Audio1_sound_ret:
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
cp $ff ; is this command a sound_ret?
jp nz, Audio1_sound_call ; no
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
bit BIT_SOUND_CALL, [hl]
2014-01-07 03:34:14 +00:00
jr nz, .returnFromCall
ld a, c
cp Ch4
2014-01-07 03:34:14 +00:00
jr nc, .noiseOrSfxChannel
2015-08-09 05:32:44 +00:00
jr .disableChannelOutput
2014-01-07 03:34:14 +00:00
.noiseOrSfxChannel
2015-08-09 05:32:44 +00:00
res BIT_NOISE_OR_SFX, [hl]
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
res BIT_EXECUTE_MUSIC, [hl]
cp Ch7
2015-08-09 05:32:44 +00:00
jr nz, .skipSfxChannel3
; restart hardware channel 3 (wave channel) output
2014-01-07 03:34:14 +00:00
ld a, $0
2015-08-09 05:32:44 +00:00
ld [rNR30], a
2014-01-07 03:34:14 +00:00
ld a, $80
2015-08-09 05:32:44 +00:00
ld [rNR30], a
.skipSfxChannel3
jr nz, .dontDisable
2015-08-09 05:32:44 +00:00
ld a, [wDisableChannelOutputWhenSfxEnds]
2014-01-07 03:34:14 +00:00
and a
jr z, .dontDisable
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wDisableChannelOutputWhenSfxEnds], a
jr .disableChannelOutput
.dontDisable
jr .afterDisable
2014-01-07 03:34:14 +00:00
.returnFromCall
res 1, [hl]
ld d, $0
ld a, c
add a
ld e, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
add hl, de
push hl ; store current channel address
2015-08-09 05:32:44 +00:00
ld hl, wChannelReturnAddresses
2014-01-07 03:34:14 +00:00
add hl, de
ld e, l
ld d, h
pop hl
ld a, [de]
ld [hli], a
inc de
ld a, [de]
ld [hl], a ; loads channel address to return to
jp Audio1_sound_ret
2015-08-09 05:32:44 +00:00
.disableChannelOutput
ld hl, Audio1_HWChannelDisableMasks
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld a, [rNR51]
2014-01-07 03:34:14 +00:00
and [hl]
2015-08-09 05:32:44 +00:00
ld [rNR51], a
.afterDisable
ld a, [wChannelSoundIDs + Ch5]
2015-08-09 05:32:44 +00:00
cp CRY_SFX_START
jr nc, .maybeCry
2015-08-09 05:32:44 +00:00
jr .skipCry
.maybeCry
ld a, [wChannelSoundIDs + Ch5]
2015-08-09 05:32:44 +00:00
cp CRY_SFX_END
jr z, .skipCry
jr c, .cry
jr .skipCry
.cry
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch5
jr z, .skipRewind
2015-08-09 05:32:44 +00:00
call Audio1_GoBackOneCommandIfCry
2014-01-07 03:34:14 +00:00
ret c
.skipRewind
2015-08-09 05:32:44 +00:00
ld a, [wSavedVolume]
ld [rNR50], a
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wSavedVolume], a
.skipCry
ld hl, wChannelSoundIDs
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], b
ret
Audio1_sound_call:
cp $fd ; is this command a sound_call?
jp nz, Audio1_sound_loop ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
push af
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
pop af
ld e, a
push de ; store pointer
ld d, $0
ld a, c
add a
ld e, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
add hl, de
push hl
2015-08-09 05:32:44 +00:00
ld hl, wChannelReturnAddresses
2014-01-07 03:34:14 +00:00
add hl, de
ld e, l
ld d, h
pop hl
ld a, [hli]
ld [de], a
inc de
ld a, [hld]
ld [de], a ; copy current channel address
pop de
ld [hl], e
inc hl
ld [hl], d ; overwrite current address with pointer
ld b, $0
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
set BIT_SOUND_CALL, [hl] ; set the call flag
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_sound_loop:
cp $fe ; is this command a sound_loop?
jp nz, Audio1_note_type ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld e, a
and a
jr z, .infiniteLoop
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelLoopCounters
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
cp e
jr nz, .loopAgain
ld a, $1 ; if no more loops to make,
ld [hl], a
call Audio1_GetNextMusicByte ; skip pointer
call Audio1_GetNextMusicByte
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
.loopAgain ; inc loop count
inc a
ld [hl], a
; fall through
.infiniteLoop ; overwrite current address with pointer
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
push af
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld b, a
ld d, $0
ld a, c
add a
ld e, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
add hl, de
pop af
ld [hli], a
ld [hl], b
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_note_type:
2014-01-07 03:34:14 +00:00
and $f0
cp $d0 ; is this command a note_type?
jp nz, Audio1_toggle_perfect_pitch ; no
2015-08-09 05:32:44 +00:00
ld a, d
2014-01-07 03:34:14 +00:00
and $f
ld b, $0
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteSpeeds
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a ; store low nibble as speed
ld a, c
cp Ch4
2014-01-07 03:34:14 +00:00
jr z, .noiseChannel ; noise channel has 0 params
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
ld a, c
cp Ch3
2014-01-07 03:34:14 +00:00
jr z, .musicChannel3
cp Ch7
2015-08-09 05:32:44 +00:00
jr nz, .skipChannel3
ld hl, wSfxWaveInstrument
jr .channel3
2014-01-07 03:34:14 +00:00
.musicChannel3
2015-08-09 05:32:44 +00:00
ld hl, wMusicWaveInstrument
.channel3
2014-01-07 03:34:14 +00:00
ld a, d
and $f
2015-08-09 05:32:44 +00:00
ld [hl], a ; store low nibble of param as wave instrument
2014-01-07 03:34:14 +00:00
ld a, d
and $30
sla a
ld d, a
; fall through
; if channel 3, store high nibble as volume
; else, store volume (high nibble) and fade (low nibble)
2015-08-09 05:32:44 +00:00
.skipChannel3
ld b, 0
ld hl, wChannelVolumes
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], d
.noiseChannel
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_toggle_perfect_pitch:
2014-01-07 03:34:14 +00:00
ld a, d
cp $e8 ; is this command a toggle_perfect_pitch?
jr nz, Audio1_vibrato ; no
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
xor $1
2015-08-09 05:32:44 +00:00
ld [hl], a ; flip bit 0 of wChannelFlags1
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_vibrato:
2014-01-07 03:34:14 +00:00
cp $ea ; is this command a vibrato?
jr nz, Audio1_pitch_slide ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
ld b, 0
ld hl, wChannelVibratoDelayCounters
2014-01-07 03:34:14 +00:00
add hl, bc
2014-06-09 20:58:02 +00:00
ld [hl], a ; store delay
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoDelayCounterReloadValues
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a ; store delay
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
; 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.
2014-01-07 03:34:14 +00:00
and $f0
swap a
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelVibratoExtents
2014-01-07 03:34:14 +00:00
add hl, bc
srl a
ld e, a
adc b
swap a
or e
2015-08-09 05:32:44 +00:00
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.
2014-01-07 03:34:14 +00:00
ld a, d
and $f
ld d, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoRates
2014-01-07 03:34:14 +00:00
add hl, bc
swap a
or d
2015-08-09 05:32:44 +00:00
ld [hl], a
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_pitch_slide:
cp $eb ; is this command a pitch_slide?
jr nz, Audio1_duty_cycle ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
ld b, 0
ld hl, wChannelPitchSlideLengthModifiers
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld [hl], a
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
and $f0
swap a
ld b, a
ld a, d
and $f
2015-08-09 05:32:44 +00:00
call Audio1_CalculateFrequency
ld b, 0
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld [hl], d
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld [hl], e
ld b, 0
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
set BIT_PITCH_SLIDE_ON, [hl]
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
jp Audio1_note_length
2014-01-07 03:34:14 +00:00
Audio1_duty_cycle:
cp $ec ; is this command a duty_cycle?
jr nz, Audio1_tempo ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
rrca
rrca
and $c0
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelDutyCycles
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a ; store duty cycle
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_tempo:
2014-01-07 03:34:14 +00:00
cp $ed ; is this command a tempo?
jr nz, Audio1_stereo_panning ; no
2015-08-09 05:32:44 +00:00
ld a, c
cp Ch5
2014-01-07 03:34:14 +00:00
jr nc, .sfxChannel
call Audio1_GetNextMusicByte
2015-08-09 05:32:44 +00:00
ld [wMusicTempo], a ; store first param
call Audio1_GetNextMusicByte
2015-08-09 05:32:44 +00:00
ld [wMusicTempo + 1], a ; store second param
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wChannelNoteDelayCountersFractionalPart], a ; clear RAM
ld [wChannelNoteDelayCountersFractionalPart + 1], a
ld [wChannelNoteDelayCountersFractionalPart + 2], a
ld [wChannelNoteDelayCountersFractionalPart + 3], a
2014-01-07 03:34:14 +00:00
jr .musicChannelDone
.sfxChannel
call Audio1_GetNextMusicByte
2015-08-09 05:32:44 +00:00
ld [wSfxTempo], a ; store first param
call Audio1_GetNextMusicByte
2015-08-09 05:32:44 +00:00
ld [wSfxTempo + 1], a ; store second param
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wChannelNoteDelayCountersFractionalPart + 4], a ; clear RAM
ld [wChannelNoteDelayCountersFractionalPart + 5], a
ld [wChannelNoteDelayCountersFractionalPart + 6], a
ld [wChannelNoteDelayCountersFractionalPart + 7], a
2014-01-07 03:34:14 +00:00
.musicChannelDone
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_stereo_panning:
cp $ee ; is this command a stereo_panning?
jr nz, Audio1_unknownmusic0xef ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
ld [wStereoPanning], a ; store panning
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
; this appears to never be used
Audio1_unknownmusic0xef:
2014-01-07 03:34:14 +00:00
cp $ef ; is this command an unknownmusic0xef?
jr nz, Audio1_duty_cycle_pattern ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
push bc
2015-08-09 05:32:44 +00:00
call Audio1_PlaySound
2014-01-07 03:34:14 +00:00
pop bc
2015-08-09 05:32:44 +00:00
ld a, [wDisableChannelOutputWhenSfxEnds]
2014-01-07 03:34:14 +00:00
and a
jr nz, .skip
ld a, [wChannelSoundIDs + Ch8]
2015-08-09 05:32:44 +00:00
ld [wDisableChannelOutputWhenSfxEnds], a
2014-01-07 03:34:14 +00:00
xor a
ld [wChannelSoundIDs + Ch8], a
2014-01-07 03:34:14 +00:00
.skip
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_duty_cycle_pattern:
cp $fc ; is this command a duty_cycle_pattern?
jr nz, Audio1_volume ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
ld b, 0
ld hl, wChannelDutyCyclePatterns
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a ; store full pattern
and %11000000
ld hl, wChannelDutyCycles
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a ; store first duty cycle
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
set BIT_ROTATE_DUTY_CYCLE, [hl]
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_volume:
2014-06-09 17:22:35 +00:00
cp $f0 ; is this command a volume?
jr nz, Audio1_execute_music ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
ld [rNR50], a ; store volume
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_execute_music:
cp $f8 ; is this command an execute_music?
jr nz, Audio1_octave ; no
2015-08-09 05:32:44 +00:00
ld b, $0
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
set BIT_EXECUTE_MUSIC, [hl]
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_octave:
2014-01-07 03:34:14 +00:00
and $f0
cp $e0 ; is this command an octave?
jr nz, Audio1_sfx_note ; no
2015-08-09 05:32:44 +00:00
ld hl, wChannelOctaves
ld b, 0
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, d
and $f
ld [hl], a ; store low nibble as octave
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
; 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
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch4 ; is this a noise or sfx channel?
jr c, Audio1_pitch_sweep ; no
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, bc
bit BIT_EXECUTE_MUSIC, [hl] ; is execute_music being used?
jr nz, Audio1_pitch_sweep ; yes
call Audio1_note_length
2015-08-09 05:32:44 +00:00
; This code seems to do the same thing as what Audio1_ApplyDutyCycleAndSoundLength
2015-08-09 05:32:44 +00:00
; does below.
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelDutyCycles
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
or d
ld d, a
2015-08-09 05:32:44 +00:00
ld b, REG_DUTY_SOUND_LEN
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld [hl], d
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld b, REG_VOLUME_ENVELOPE
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld [hl], d
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
ld e, a
ld a, c
cp Ch8
2015-08-09 05:32:44 +00:00
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.
2014-01-07 03:34:14 +00:00
push de
call Audio1_GetNextMusicByte
2014-01-07 03:34:14 +00:00
pop de
2015-08-09 05:32:44 +00:00
.skip
2014-01-07 03:34:14 +00:00
ld d, a
push de
call Audio1_ApplyDutyCycleAndSoundLength
2015-08-09 05:32:44 +00:00
call Audio1_EnableChannelOutput
2014-01-07 03:34:14 +00:00
pop de
2015-08-09 05:32:44 +00:00
call Audio1_ApplyWavePatternAndFrequency
2014-01-07 03:34:14 +00:00
ret
Audio1_pitch_sweep:
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch5
jr c, Audio1_note ; if not a sfx
2014-01-07 03:34:14 +00:00
ld a, d
cp $10 ; is this command a pitch_sweep?
jr nz, Audio1_note ; no
2014-01-07 03:34:14 +00:00
ld b, $0
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
bit BIT_EXECUTE_MUSIC, [hl]
jr nz, Audio1_note ; no
2015-08-09 05:32:44 +00:00
call Audio1_GetNextMusicByte
ld [rNR10], a
jp Audio1_sound_ret
2014-01-07 03:34:14 +00:00
Audio1_note:
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch4
jr nz, Audio1_note_length ; if not noise channel
2014-01-07 03:34:14 +00:00
ld a, d
and $f0
cp $b0 ; is this command a dnote?
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
2014-01-07 03:34:14 +00:00
swap a
ld b, a
ld a, d
and $f
ld d, a
ld a, b
push de
push bc
jr .playDnote
2014-01-07 03:34:14 +00:00
.dnote
2014-01-07 03:34:14 +00:00
ld a, d
and $f
push af
push bc
call Audio1_GetNextMusicByte ; get dnote instrument
.playDnote
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld a, [wDisableChannelOutputWhenSfxEnds]
2014-01-07 03:34:14 +00:00
and a
jr nz, .skipDnote
2014-01-07 03:34:14 +00:00
ld a, d
2015-08-09 05:32:44 +00:00
call Audio1_PlaySound
.skipDnote
2014-01-07 03:34:14 +00:00
pop bc
pop de
Audio1_note_length:
2014-01-07 03:34:14 +00:00
ld a, d
push af
and $f
inc a
2015-08-09 05:32:44 +00:00
ld b, 0
2014-01-07 03:34:14 +00:00
ld e, a ; store note length (in 16ths)
ld d, b
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteSpeeds
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
ld l, b
2015-08-09 05:32:44 +00:00
call Audio1_MultiplyAdd
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch5
2014-01-07 03:34:14 +00:00
jr nc, .sfxChannel
2015-08-09 05:32:44 +00:00
ld a, [wMusicTempo]
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld a, [wMusicTempo + 1]
2014-01-07 03:34:14 +00:00
ld e, a
jr .skip
.sfxChannel
ld d, $1
ld e, $0
cp Ch8
2014-01-07 03:34:14 +00:00
jr z, .skip ; if noise channel
2015-08-09 05:32:44 +00:00
call Audio1_SetSfxTempo
ld a, [wSfxTempo]
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld a, [wSfxTempo + 1]
2014-01-07 03:34:14 +00:00
ld e, a
.skip
2015-08-09 05:32:44 +00:00
ld a, l ; a = note_length * note_speed
ld b, 0
ld hl, wChannelNoteDelayCountersFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
ld l, [hl]
2015-08-09 05:32:44 +00:00
call Audio1_MultiplyAdd
2014-01-07 03:34:14 +00:00
ld e, l
2015-08-09 05:32:44 +00:00
ld d, h ; de = note_delay_frac_part + (note_length * note_speed * tempo)
ld hl, wChannelNoteDelayCountersFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], e
ld a, d
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteDelayCounters
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
bit BIT_EXECUTE_MUSIC, [hl]
jr nz, Audio1_note_pitch
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
bit BIT_NOISE_OR_SFX, [hl]
jr z, Audio1_note_pitch
2014-01-07 03:34:14 +00:00
pop hl
ret
Audio1_note_pitch:
2014-01-07 03:34:14 +00:00
pop af
and $f0
cp $c0 ; compare to rest
jr nz, .notRest
ld a, c
cp Ch5
2015-08-09 05:32:44 +00:00
jr nc, .next
; If this isn't an SFX channel, try the corresponding SFX channel.
ld hl, wChannelSoundIDs + Ch5
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and a
jr nz, .done
; fall through
2015-08-09 05:32:44 +00:00
.next
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch3
2015-08-09 05:32:44 +00:00
jr z, .channel3
cp Ch7
2015-08-09 05:32:44 +00:00
jr nz, .notChannel3
.channel3
ld b, 0
ld hl, Audio1_HWChannelDisableMasks
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld a, [rNR51]
2014-01-07 03:34:14 +00:00
and [hl]
2015-08-09 05:32:44 +00:00
ld [rNR51], a ; disable hardware channel 3's output
2014-01-07 03:34:14 +00:00
jr .done
2015-08-09 05:32:44 +00:00
.notChannel3
ld b, REG_VOLUME_ENVELOPE
call Audio1_GetRegisterPointer
ld a, $8 ; fade in sound
2014-01-07 03:34:14 +00:00
ld [hli], a
inc hl
2015-08-09 05:32:44 +00:00
ld a, $80 ; restart sound
2014-01-07 03:34:14 +00:00
ld [hl], a
.done
ret
.notRest
swap a
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelOctaves
2014-01-07 03:34:14 +00:00
add hl, bc
ld b, [hl]
2015-08-09 05:32:44 +00:00
call Audio1_CalculateFrequency
ld b, 0
ld hl, wChannelFlags1
add hl, bc
bit BIT_PITCH_SLIDE_ON, [hl]
jr z, .skipPitchSlide
call Audio1_InitPitchSlideVars
.skipPitchSlide
2014-01-07 03:34:14 +00:00
push de
ld a, c
cp Ch5
2015-08-09 05:32:44 +00:00
jr nc, .sfxChannel ; if sfx channel
; If this isn't an SFX channel, try the corresponding SFX channel.
ld hl, wChannelSoundIDs + Ch5
2015-08-09 05:32:44 +00:00
ld d, 0
2014-01-07 03:34:14 +00:00
ld e, a
add hl, de
ld a, [hl]
and a
2015-08-09 05:32:44 +00:00
jr nz, .noSfx
jr .sfxChannel
.noSfx
2014-01-07 03:34:14 +00:00
pop de
ret
2015-08-09 05:32:44 +00:00
.sfxChannel
ld b, 0
ld hl, wChannelVolumes
2014-01-07 03:34:14 +00:00
add hl, bc
ld d, [hl]
2015-08-09 05:32:44 +00:00
ld b, REG_VOLUME_ENVELOPE
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld [hl], d
call Audio1_ApplyDutyCycleAndSoundLength
2015-08-09 05:32:44 +00:00
call Audio1_EnableChannelOutput
2014-01-07 03:34:14 +00:00
pop de
ld b, $0
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
bit BIT_PERFECT_PITCH, [hl] ; has toggle_perfect_pitch been used?
2015-08-09 05:32:44 +00:00
jr z, .skipFrequencyInc
inc e ; if yes, increment the frequency by 1
jr nc, .skipFrequencyInc
2014-01-07 03:34:14 +00:00
inc d
2015-08-09 05:32:44 +00:00
.skipFrequencyInc
ld hl, wChannelFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], e
2015-08-09 05:32:44 +00:00
call Audio1_ApplyWavePatternAndFrequency
2014-01-07 03:34:14 +00:00
ret
Audio1_EnableChannelOutput:
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, Audio1_HWChannelEnableMasks
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld a, [rNR51]
or [hl] ; set this channel's bits
2014-01-07 03:34:14 +00:00
ld d, a
ld a, c
cp Ch8
2015-08-09 05:32:44 +00:00
jr z, .noiseChannelOrNoSfx
cp Ch5
2014-01-07 03:34:14 +00:00
jr nc, .skip ; if sfx channel
2015-08-09 05:32:44 +00:00
; If this isn't an SFX channel, try the corresponding SFX channel.
ld hl, wChannelSoundIDs + Ch5
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
and a
jr nz, .skip
2015-08-09 05:32:44 +00:00
.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, Audio1_HWChannelEnableMasks
2014-01-07 03:34:14 +00:00
add hl, bc
and [hl]
ld d, a
2015-08-09 05:32:44 +00:00
ld a, [rNR51]
ld hl, Audio1_HWChannelDisableMasks
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
and [hl] ; reset this channel's output bits
or d ; set this channel's output bits that enabled in [wStereoPanning]
2014-01-07 03:34:14 +00:00
ld d, a
.skip
ld a, d
2015-08-09 05:32:44 +00:00
ld [rNR51], a
2014-01-07 03:34:14 +00:00
ret
Audio1_ApplyDutyCycleAndSoundLength:
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelNoteDelayCounters ; use the note delay as sound length
2014-01-07 03:34:14 +00:00
add hl, bc
ld d, [hl]
ld a, c
cp Ch3
2015-08-09 05:32:44 +00:00
jr z, .skipDuty ; if music channel 3
cp Ch7
2015-08-09 05:32:44 +00:00
jr z, .skipDuty ; if sfx channel 3
; include duty cycle (except on channel 3 which doesn't have it)
2014-01-07 03:34:14 +00:00
ld a, d
and $3f
ld d, a
ld hl, wChannelDutyCycles
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
or d
ld d, a
2015-08-09 05:32:44 +00:00
.skipDuty
ld b, REG_DUTY_SOUND_LEN
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld [hl], d
ret
Audio1_ApplyWavePatternAndFrequency:
2014-01-07 03:34:14 +00:00
ld a, c
cp Ch3
2014-01-07 03:34:14 +00:00
jr z, .channel3
cp Ch7
2015-08-09 05:32:44 +00:00
jr nz, .notChannel3
2014-01-07 03:34:14 +00:00
; fall through
.channel3
push de
2015-08-09 05:32:44 +00:00
ld de, wMusicWaveInstrument
cp Ch3
2015-08-09 05:32:44 +00:00
jr z, .next
ld de, wSfxWaveInstrument
.next
2014-01-07 03:34:14 +00:00
ld a, [de]
add a
2015-08-09 05:32:44 +00:00
ld d, 0
2014-01-07 03:34:14 +00:00
ld e, a
ld hl, Audio1_WavePointers
2014-01-07 03:34:14 +00:00
add hl, de
ld e, [hl]
inc hl
ld d, [hl]
2015-08-09 05:32:44 +00:00
ld hl, $ff30 ; wave pattern RAM
2014-01-07 03:34:14 +00:00
ld b, $f
2015-08-09 05:32:44 +00:00
ld a, $0 ; stop hardware channel 3
ld [rNR30], a
2014-01-07 03:34:14 +00:00
.loop
ld a, [de]
inc de
ld [hli], a
ld a, b
dec b
and a
jr nz, .loop
2015-08-09 05:32:44 +00:00
ld a, $80 ; start hardware channel 3
ld [rNR30], a
2014-01-07 03:34:14 +00:00
pop de
2015-08-09 05:32:44 +00:00
.notChannel3
2014-01-07 03:34:14 +00:00
ld a, d
2015-08-09 05:32:44 +00:00
or $80 ; use counter mode (i.e. disable output when the counter reaches 0)
and $c7 ; zero the unused bits in the register
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld b, REG_FREQUENCY_LO
call Audio1_GetRegisterPointer
ld [hl], e ; store frequency low byte
2014-01-07 03:34:14 +00:00
inc hl
2015-08-09 05:32:44 +00:00
ld [hl], d ; store frequency high byte
call Audio1_ApplyFrequencyModifier
2014-01-07 03:34:14 +00:00
ret
Audio1_SetSfxTempo:
2015-08-09 05:32:44 +00:00
call Audio1_IsCry
jr nc, .notCry
ld d, 0
ld a, [wTempoModifier]
2014-01-07 03:34:14 +00:00
add $80
2015-08-09 05:32:44 +00:00
jr nc, .next
2014-01-07 03:34:14 +00:00
inc d
2015-08-09 05:32:44 +00:00
.next
ld [wSfxTempo + 1], a
2014-01-07 03:34:14 +00:00
ld a, d
2015-08-09 05:32:44 +00:00
ld [wSfxTempo], a
jr .done
.notCry
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wSfxTempo + 1], a
2014-01-07 03:34:14 +00:00
ld a, $1
2015-08-09 05:32:44 +00:00
ld [wSfxTempo], a
.done
2014-01-07 03:34:14 +00:00
ret
Audio1_ApplyFrequencyModifier:
2015-08-09 05:32:44 +00:00
call Audio1_IsCry
jr nc, .done
; if playing a cry, add the cry's frequency modifier
ld a, [wFrequencyModifier]
2014-01-07 03:34:14 +00:00
add e
2015-08-09 05:32:44 +00:00
jr nc, .noCarry
2014-01-07 03:34:14 +00:00
inc d
2015-08-09 05:32:44 +00:00
.noCarry
2014-01-07 03:34:14 +00:00
dec hl
ld e, a
ld [hl], e
inc hl
ld [hl], d
2015-08-09 05:32:44 +00:00
.done
2014-01-07 03:34:14 +00:00
ret
Audio1_GoBackOneCommandIfCry:
2015-08-09 05:32:44 +00:00
call Audio1_IsCry
jr nc, .done
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
ld e, c
2015-08-09 05:32:44 +00:00
ld d, 0
2014-01-07 03:34:14 +00:00
sla e
rl d
add hl, de
ld a, [hl]
2015-08-09 05:32:44 +00:00
sub 1
2014-01-07 03:34:14 +00:00
ld [hl], a
inc hl
ld a, [hl]
2015-08-09 05:32:44 +00:00
sbc 0
2014-01-07 03:34:14 +00:00
ld [hl], a
scf
ret
2015-08-09 05:32:44 +00:00
.done
2014-01-07 03:34:14 +00:00
scf
ccf
ret
Audio1_IsCry:
2015-08-09 05:32:44 +00:00
; Returns whether the currently playing audio is a cry in carry.
ld a, [wChannelSoundIDs + Ch5]
2015-08-09 05:32:44 +00:00
cp CRY_SFX_START
jr nc, .next
jr .no
.next
cp CRY_SFX_END
jr z, .no
jr c, .yes
.no
2014-01-07 03:34:14 +00:00
scf
ccf
ret
2015-08-09 05:32:44 +00:00
.yes
2014-01-07 03:34:14 +00:00
scf
ret
Audio1_ApplyPitchSlide:
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
bit BIT_PITCH_SLIDE_DECREASING, [hl]
2015-08-09 05:32:44 +00:00
jp nz, .frequencyDecreasing
; frequency increasing
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld e, [hl]
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld d, [hl]
ld hl, wChannelPitchSlideFrequencySteps
2014-01-07 03:34:14 +00:00
add hl, bc
ld l, [hl]
ld h, b
add hl, de
ld d, h
ld e, l
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
push hl
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
pop hl
add [hl]
ld [hl], a
2015-08-09 05:32:44 +00:00
ld a, 0
2014-01-07 03:34:14 +00:00
adc e
ld e, a
2015-08-09 05:32:44 +00:00
ld a, 0
2014-01-07 03:34:14 +00:00
adc d
ld d, a
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
cp d
2015-08-09 05:32:44 +00:00
jp c, .reachedTargetFrequency
jr nz, .applyUpdatedFrequency
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
cp e
2015-08-09 05:32:44 +00:00
jp c, .reachedTargetFrequency
jr .applyUpdatedFrequency
.frequencyDecreasing
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld d, [hl]
ld hl, wChannelPitchSlideFrequencySteps
2014-01-07 03:34:14 +00:00
add hl, bc
ld e, [hl]
sub e
ld e, a
ld a, d
sbc b
ld d, a
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
add a
ld [hl], a
ld a, e
sbc b
ld e, a
ld a, d
sbc b
ld d, a
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, d
cp [hl]
2015-08-09 05:32:44 +00:00
jr c, .reachedTargetFrequency
jr nz, .applyUpdatedFrequency
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, e
cp [hl]
2015-08-09 05:32:44 +00:00
jr c, .reachedTargetFrequency
.applyUpdatedFrequency
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], e
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], d
2015-08-09 05:32:44 +00:00
ld b, REG_FREQUENCY_LO
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld a, e
ld [hli], a
ld [hl], d
ret
2015-08-09 05:32:44 +00:00
.reachedTargetFrequency
; Turn off pitch slide when the target frequency has been reached.
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
res BIT_PITCH_SLIDE_ON, [hl]
res BIT_PITCH_SLIDE_DECREASING, [hl]
2014-01-07 03:34:14 +00:00
ret
Audio1_InitPitchSlideVars:
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], d
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld [hl], e
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteDelayCounters
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
ld hl, wChannelPitchSlideLengthModifiers
2014-01-07 03:34:14 +00:00
add hl, bc
sub [hl]
2015-08-09 05:32:44 +00:00
jr nc, .next
ld a, 1
.next
2014-01-07 03:34:14 +00:00
ld [hl], a
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, e
sub [hl]
ld e, a
ld a, d
sbc b
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
sub [hl]
2015-08-09 05:32:44 +00:00
jr c, .targetFrequencyGreater
2014-01-07 03:34:14 +00:00
ld d, a
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
set BIT_PITCH_SLIDE_DECREASING, [hl]
2015-08-09 05:32:44 +00:00
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
2014-01-07 03:34:14 +00:00
add hl, bc
ld d, [hl]
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld e, [hl]
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
sub e
ld e, a
2015-08-09 05:32:44 +00:00
; 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.
2014-01-07 03:34:14 +00:00
ld a, d
sbc b
ld d, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
sub d
ld d, a
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
res BIT_PITCH_SLIDE_DECREASING, [hl]
2015-08-09 05:32:44 +00:00
.next2
ld hl, wChannelPitchSlideLengthModifiers
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
.divideLoop
2014-01-07 03:34:14 +00:00
inc b
ld a, e
sub [hl]
ld e, a
2015-08-09 05:32:44 +00:00
jr nc, .divideLoop
2014-01-07 03:34:14 +00:00
ld a, d
and a
2015-08-09 05:32:44 +00:00
jr z, .doneDividing
2014-01-07 03:34:14 +00:00
dec a
ld d, a
2015-08-09 05:32:44 +00:00
jr .divideLoop
.doneDividing
ld a, e ; a = remainder - dividend
2014-01-07 03:34:14 +00:00
add [hl]
2015-08-09 05:32:44 +00:00
ld d, b ; d = quotient + 1
ld b, 0
ld hl, wChannelPitchSlideFrequencySteps
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld [hl], d ; store quotient + 1
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld [hl], a ; store remainder - dividend
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld [hl], a ; store remainder - dividend
2014-01-07 03:34:14 +00:00
ret
Audio1_ApplyDutyCyclePattern:
2015-08-09 05:32:44 +00:00
ld b, 0
ld hl, wChannelDutyCyclePatterns
2014-01-07 03:34:14 +00:00
add hl, bc
ld a, [hl]
rlca
rlca
ld [hl], a
and $c0
ld d, a
2015-08-09 05:32:44 +00:00
ld b, REG_DUTY_SOUND_LEN
call Audio1_GetRegisterPointer
2014-01-07 03:34:14 +00:00
ld a, [hl]
and $3f
or d
ld [hl], a
ret
Audio1_GetNextMusicByte:
2015-08-09 05:32:44 +00:00
ld d, 0
2014-01-07 03:34:14 +00:00
ld a, c
add a
ld e, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
add hl, de
ld a, [hli]
ld e, a
ld a, [hld]
ld d, a
ld a, [de] ; get next music command
inc de
ld [hl], e ; store address of next command
inc hl
ld [hl], d
ret
Audio1_GetRegisterPointer:
2015-08-09 05:32:44 +00:00
; hl = address of hardware sound register b for software channel c
2014-01-07 03:34:14 +00:00
ld a, c
2015-08-09 05:32:44 +00:00
ld hl, Audio1_HWChannelBaseAddresses
2014-01-07 03:34:14 +00:00
add l
jr nc, .noCarry
inc h
.noCarry
ld l, a
ld a, [hl]
add b
ld l, a
ld h, $ff
ret
Audio1_MultiplyAdd:
2015-08-09 05:32:44 +00:00
; hl = l + (a * de)
ld h, 0
2014-01-07 03:34:14 +00:00
.loop
srl a
2015-08-09 05:32:44 +00:00
jr nc, .skipAdd
2014-01-07 03:34:14 +00:00
add hl, de
2015-08-09 05:32:44 +00:00
.skipAdd
2014-01-07 03:34:14 +00:00
sla e
rl d
and a
jr z, .done
jr .loop
.done
ret
Audio1_CalculateFrequency:
2015-08-09 05:32:44 +00:00
; return the frequency for note a, octave b in de
ld h, 0
2014-01-07 03:34:14 +00:00
ld l, a
add hl, hl
ld d, h
ld e, l
ld hl, Audio1_Pitches
2014-01-07 03:34:14 +00:00
add hl, de
ld e, [hl]
inc hl
ld d, [hl]
ld a, b
.loop
2015-08-09 05:32:44 +00:00
cp 7
2014-01-07 03:34:14 +00:00
jr z, .done
sra d
rr e
inc a
jr .loop
.done
2015-08-09 05:32:44 +00:00
ld a, 8
2014-01-07 03:34:14 +00:00
add d
ld d, a
ret
Audio1_PlaySound::
2015-08-09 05:32:44 +00:00
ld [wSoundID], a
2014-01-07 03:34:14 +00:00
cp $ff
2015-08-09 05:32:44 +00:00
jp z, .stopAllAudio
cp MAX_SFX_ID_1
2015-08-09 05:32:44 +00:00
jp z, .playSfx
jp c, .playSfx
2014-01-07 03:34:14 +00:00
cp $fe
2015-08-09 05:32:44 +00:00
jr z, .playMusic
jp nc, .playSfx
.playMusic
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wUnusedC000], a
ld [wDisableChannelOutputWhenSfxEnds], a
ld [wMusicTempo + 1], a
ld [wMusicWaveInstrument], a
ld [wSfxWaveInstrument], a
2014-01-07 03:34:14 +00:00
ld d, $8
2015-08-09 05:32:44 +00:00
ld hl, wChannelReturnAddresses
call .FillMem
ld hl, wChannelCommandPointers
call .FillMem
2014-01-07 03:34:14 +00:00
ld d, $4
2015-08-09 05:32:44 +00:00
ld hl, wChannelSoundIDs
call .FillMem
ld hl, wChannelFlags1
call .FillMem
ld hl, wChannelDutyCycles
call .FillMem
ld hl, wChannelDutyCyclePatterns
call .FillMem
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoDelayCounters
call .FillMem
ld hl, wChannelVibratoExtents
call .FillMem
ld hl, wChannelVibratoRates
call .FillMem
ld hl, wChannelFrequencyLowBytes
call .FillMem
ld hl, wChannelVibratoDelayCounterReloadValues
call .FillMem
ld hl, wChannelFlags2
call .FillMem
ld hl, wChannelPitchSlideLengthModifiers
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideFrequencySteps
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2015-08-09 05:32:44 +00:00
call .FillMem
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2015-08-09 05:32:44 +00:00
call .FillMem
2014-01-07 03:34:14 +00:00
ld a, $1
2015-08-09 05:32:44 +00:00
ld hl, wChannelLoopCounters
call .FillMem
ld hl, wChannelNoteDelayCounters
call .FillMem
ld hl, wChannelNoteSpeeds
call .FillMem
ld [wMusicTempo], a
2014-01-07 03:34:14 +00:00
ld a, $ff
2015-08-09 05:32:44 +00:00
ld [wStereoPanning], a
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [rNR50], a
2014-01-07 03:34:14 +00:00
ld a, $8
2015-08-09 05:32:44 +00:00
ld [rNR10], a
ld a, 0
ld [rNR51], a
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [rNR30], a
2014-01-07 03:34:14 +00:00
ld a, $80
2015-08-09 05:32:44 +00:00
ld [rNR30], a
2014-01-07 03:34:14 +00:00
ld a, $77
2015-08-09 05:32:44 +00:00
ld [rNR50], a
jp .playSoundCommon
2014-01-07 03:34:14 +00:00
2015-08-09 05:32:44 +00:00
.playSfx
2014-01-07 03:34:14 +00:00
ld l, a
ld e, a
2015-08-09 05:32:44 +00:00
ld h, 0
2014-01-07 03:34:14 +00:00
ld d, h
add hl, hl
add hl, de
ld de, SFX_Headers_1
2014-01-07 03:34:14 +00:00
add hl, de
ld a, h
2015-08-09 05:32:44 +00:00
ld [wSfxHeaderPointer], a
2014-01-07 03:34:14 +00:00
ld a, l
2015-08-09 05:32:44 +00:00
ld [wSfxHeaderPointer + 1], a
2014-01-07 03:34:14 +00:00
ld a, [hl]
and $c0
rlca
rlca
ld c, a
2015-08-09 05:32:44 +00:00
.sfxChannelLoop
2014-01-07 03:34:14 +00:00
ld d, c
ld a, c
add a
add c
ld c, a
2015-08-09 05:32:44 +00:00
ld b, 0
ld a, [wSfxHeaderPointer]
2014-01-07 03:34:14 +00:00
ld h, a
2015-08-09 05:32:44 +00:00
ld a, [wSfxHeaderPointer + 1]
2014-01-07 03:34:14 +00:00
ld l, a
add hl, bc
ld c, d
ld a, [hl]
and $f
2015-08-09 05:32:44 +00:00
ld e, a ; software channel ID
ld d, 0
ld hl, wChannelSoundIDs
2014-01-07 03:34:14 +00:00
add hl, de
ld a, [hl]
and a
jr z, .playChannel
2014-01-07 03:34:14 +00:00
ld a, e
cp Ch8
jr nz, .notNoiseChannel
2015-08-09 05:32:44 +00:00
ld a, [wSoundID]
cp NOISE_INSTRUMENTS_END
jr nc, .notNoiseInstrument
2014-01-07 03:34:14 +00:00
ret
.notNoiseInstrument
2014-01-07 03:34:14 +00:00
ld a, [hl]
cp NOISE_INSTRUMENTS_END
jr z, .playChannel
jr c, .playChannel
.notNoiseChannel
2015-08-09 05:32:44 +00:00
ld a, [wSoundID]
2014-01-07 03:34:14 +00:00
cp [hl]
jr z, .playChannel
jr c, .playChannel
2014-01-07 03:34:14 +00:00
ret
.playChannel
2014-01-07 03:34:14 +00:00
xor a
push de
ld h, d
ld l, e
add hl, hl
ld d, h
ld e, l
2015-08-09 05:32:44 +00:00
ld hl, wChannelReturnAddresses
2014-01-07 03:34:14 +00:00
add hl, de
ld [hli], a
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
add hl, de
ld [hli], a
ld [hl], a
pop de
2015-08-09 05:32:44 +00:00
ld hl, wChannelSoundIDs
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelDutyCycles
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelDutyCyclePatterns
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoDelayCounters
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoExtents
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoRates
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelVibratoDelayCounterReloadValues
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideLengthModifiers
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideFrequencySteps
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelFlags2
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld a, $1
2015-08-09 05:32:44 +00:00
ld hl, wChannelLoopCounters
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteDelayCounters
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteSpeeds
2014-01-07 03:34:14 +00:00
add hl, de
ld [hl], a
ld a, e
cp Ch5
jr nz, .skipSweepDisable
2014-01-07 03:34:14 +00:00
ld a, $8
2015-08-09 05:32:44 +00:00
ld [rNR10], a ; sweep off
.skipSweepDisable
2014-01-07 03:34:14 +00:00
ld a, c
and a
2015-08-09 05:32:44 +00:00
jp z, .playSoundCommon
2014-01-07 03:34:14 +00:00
dec c
2015-08-09 05:32:44 +00:00
jp .sfxChannelLoop
2014-01-07 03:34:14 +00:00
2015-08-09 05:32:44 +00:00
.stopAllAudio
2014-01-07 03:34:14 +00:00
ld a, $80
2015-08-09 05:32:44 +00:00
ld [rNR52], a ; sound hardware on
ld [rNR30], a ; wave playback on
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [rNR51], a ; no sound output
ld [rNR32], a ; mute channel 3 (wave channel)
2014-01-07 03:34:14 +00:00
ld a, $8
2015-08-09 05:32:44 +00:00
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)
2014-01-07 03:34:14 +00:00
ld a, $40
2015-08-09 05:32:44 +00:00
ld [rNR14], a ; counter mode
ld [rNR24], a
ld [rNR44], a
2014-01-07 03:34:14 +00:00
ld a, $77
2015-08-09 05:32:44 +00:00
ld [rNR50], a ; full volume
2014-01-07 03:34:14 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wUnusedC000], a
ld [wDisableChannelOutputWhenSfxEnds], a
ld [wMuteAudioAndPauseMusic], a
ld [wMusicTempo + 1], a
ld [wSfxTempo + 1], a
ld [wMusicWaveInstrument], a
ld [wSfxWaveInstrument], a
2014-01-07 03:34:14 +00:00
ld d, $a0
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
call .FillMem
2014-01-07 03:34:14 +00:00
ld a, $1
ld d, $18
2015-08-09 05:32:44 +00:00
ld hl, wChannelNoteDelayCounters
call .FillMem
ld [wMusicTempo], a
ld [wSfxTempo], a
2014-01-07 03:34:14 +00:00
ld a, $ff
2015-08-09 05:32:44 +00:00
ld [wStereoPanning], a
2014-01-07 03:34:14 +00:00
ret
; fills d bytes at hl with a
2015-08-09 05:32:44 +00:00
.FillMem
2014-01-07 03:34:14 +00:00
ld b, d
.loop
ld [hli], a
dec b
jr nz, .loop
ret
2015-08-09 05:32:44 +00:00
.playSoundCommon
ld a, [wSoundID]
2014-01-07 03:34:14 +00:00
ld l, a
ld e, a
2015-08-09 05:32:44 +00:00
ld h, 0
2014-01-07 03:34:14 +00:00
ld d, h
add hl, hl
add hl, de
ld de, SFX_Headers_1
2014-01-07 03:34:14 +00:00
add hl, de
ld e, l
ld d, h
2015-08-09 05:32:44 +00:00
ld hl, wChannelCommandPointers
2014-01-07 03:34:14 +00:00
ld a, [de] ; get channel number
ld b, a
rlca
rlca
and $3
ld c, a
ld a, b
and $f
ld b, c
inc b
inc de
2015-08-09 05:32:44 +00:00
ld c, 0
.commandPointerLoop
2014-01-07 03:34:14 +00:00
cp c
2015-08-09 05:32:44 +00:00
jr z, .next
2014-01-07 03:34:14 +00:00
inc c
inc hl
inc hl
2015-08-09 05:32:44 +00:00
jr .commandPointerLoop
.next
2014-01-07 03:34:14 +00:00
push hl
push bc
push af
2015-08-09 05:32:44 +00:00
ld b, 0
2014-01-07 03:34:14 +00:00
ld c, a
2015-08-09 05:32:44 +00:00
ld hl, wChannelSoundIDs
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
ld a, [wSoundID]
2014-01-07 03:34:14 +00:00
ld [hl], a
pop af
cp Ch4
2015-08-09 05:32:44 +00:00
jr c, .skipSettingFlag
ld hl, wChannelFlags1
2014-01-07 03:34:14 +00:00
add hl, bc
2015-08-09 05:32:44 +00:00
set BIT_NOISE_OR_SFX, [hl]
.skipSettingFlag
2014-01-07 03:34:14 +00:00
pop bc
pop hl
ld a, [de] ; get channel pointer
ld [hli], a
inc de
ld a, [de]
ld [hli], a
inc de
inc c
dec b
ld a, b
and a
ld a, [de]
inc de
2015-08-09 05:32:44 +00:00
jr nz, .commandPointerLoop
ld a, [wSoundID]
cp CRY_SFX_START
jr nc, .maybeCry
2015-08-09 05:32:44 +00:00
jr .done
.maybeCry
2015-08-09 05:32:44 +00:00
ld a, [wSoundID]
cp CRY_SFX_END
jr z, .done
jr c, .cry
jr .done
.cry
ld hl, wChannelSoundIDs + Ch5
2014-01-07 03:34:14 +00:00
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld hl, wChannelCommandPointers + Ch7 * 2 ; sfx wave channel pointer
ld de, Audio1_CryRet
2014-01-07 03:34:14 +00:00
ld [hl], e
inc hl
ld [hl], d ; overwrite pointer to point to sound_ret
2015-08-09 05:32:44 +00:00
ld a, [wSavedVolume]
2014-01-07 03:34:14 +00:00
and a
2015-08-09 05:32:44 +00:00
jr nz, .done
ld a, [rNR50]
ld [wSavedVolume], a
2014-01-07 03:34:14 +00:00
ld a, $77
2015-08-09 05:32:44 +00:00
ld [rNR50], a ; full volume
.done
2014-01-07 03:34:14 +00:00
ret
Audio1_CryRet:
sound_ret
2014-01-07 03:34:14 +00:00
Audio1_HWChannelBaseAddresses:
2015-08-09 05:32:44 +00:00
; 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
2014-01-07 03:34:14 +00:00
Audio1_HWChannelDisableMasks:
2015-08-09 05:32:44 +00:00
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
2014-01-07 03:34:14 +00:00
Audio1_HWChannelEnableMasks:
2015-08-09 05:32:44 +00:00
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
2014-01-07 03:34:14 +00:00
Audio1_Pitches:
2014-06-09 17:22:35 +00:00
dw $F82C ; C_
dw $F89D ; C#
dw $F907 ; D_
dw $F96B ; D#
dw $F9CA ; E_
dw $FA23 ; F_
dw $FA77 ; F#
dw $FAC7 ; G_
dw $FB12 ; G#
dw $FB58 ; A_
dw $FB9B ; A#
dw $FBDA ; B_