mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-09-09 09:51:34 -07:00
e6ea1889fb
The former is arguably misleading (as you don’t access the memory location in hl to retrieve the jump location), and is consequently deprecated in newer versions of rgbds. This fix silences these deprecation warnings.
3309 lines
54 KiB
NASM
3309 lines
54 KiB
NASM
; The entire sound engine. Uses section "audio" in WRAM.
|
|
|
|
; Interfaces are in bank 0.
|
|
|
|
; Notable functions:
|
|
; FadeMusic
|
|
; PlayStereoSFX
|
|
|
|
_MapSetup_Sound_Off:: ; e8000
|
|
; restart sound operation
|
|
; clear all relevant hardware registers & wram
|
|
push hl
|
|
push de
|
|
push bc
|
|
push af
|
|
call MusicOff
|
|
ld hl, rNR50 ; channel control registers
|
|
xor a
|
|
ld [hli], a ; rNR50 ; volume/vin
|
|
ld [hli], a ; rNR51 ; sfx channels
|
|
ld a, $80 ; all channels on
|
|
ld [hli], a ; ff26 ; music channels
|
|
|
|
ld hl, rNR10 ; sound channel registers
|
|
ld e, $4 ; number of channels
|
|
.clearsound
|
|
; sound channel 1 2 3 4
|
|
xor a
|
|
ld [hli], a ; rNR10, rNR20, rNR30, rNR40 ; sweep = 0
|
|
|
|
ld [hli], a ; rNR11, rNR21, rNR31, rNR41 ; length/wavepattern = 0
|
|
ld a, $8
|
|
ld [hli], a ; rNR12, rNR22, rNR32, rNR42 ; envelope = 0
|
|
xor a
|
|
ld [hli], a ; rNR13, rNR23, rNR33, rNR43 ; frequency lo = 0
|
|
ld a, $80
|
|
ld [hli], a ; rNR14, rNR24, rNR34, rNR44 ; restart sound (freq hi = 0)
|
|
dec e
|
|
jr nz, .clearsound
|
|
|
|
ld hl, Channels ; start of channel data
|
|
ld de, ChannelsEnd - Channels ; length of area to clear (entire sound wram area)
|
|
.clearchannels ; clear Channel1-$c2bf
|
|
xor a
|
|
ld [hli], a
|
|
dec de
|
|
ld a, e
|
|
or d
|
|
jr nz, .clearchannels
|
|
ld a, $77 ; max
|
|
ld [Volume], a
|
|
call MusicOn
|
|
pop af
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
; e803d
|
|
|
|
MusicFadeRestart: ; e803d
|
|
; restart but keep the music id to fade in to
|
|
ld a, [MusicFadeIDHi]
|
|
push af
|
|
ld a, [MusicFadeIDLo]
|
|
push af
|
|
call _MapSetup_Sound_Off
|
|
pop af
|
|
ld [MusicFadeIDLo], a
|
|
pop af
|
|
ld [MusicFadeIDHi], a
|
|
ret
|
|
|
|
; e8051
|
|
|
|
MusicOn: ; e8051
|
|
ld a, 1
|
|
ld [MusicPlaying], a
|
|
ret
|
|
|
|
; e8057
|
|
|
|
MusicOff: ; e8057
|
|
xor a
|
|
ld [MusicPlaying], a
|
|
ret
|
|
|
|
; e805c
|
|
|
|
_UpdateSound:: ; e805c
|
|
; called once per frame
|
|
; no use updating audio if it's not playing
|
|
ld a, [MusicPlaying]
|
|
and a
|
|
ret z
|
|
; start at ch1
|
|
xor a
|
|
ld [CurChannel], a ; just
|
|
ld [SoundOutput], a ; off
|
|
ld bc, Channel1
|
|
.loop
|
|
; is the channel active?
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jp z, .nextchannel
|
|
; check time left in the current note
|
|
ld hl, Channel1NoteDuration - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp $2 ; 1 or 0?
|
|
jr c, .noteover
|
|
dec [hl]
|
|
jr .continue_sound_update
|
|
|
|
.noteover
|
|
; reset vibrato delay
|
|
ld hl, Channel1VibratoDelay - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, Channel1VibratoDelayCount - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; turn vibrato off for now
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
res SOUND_PITCH_WHEEL, [hl]
|
|
; get next note
|
|
call ParseMusic
|
|
.continue_sound_update
|
|
call ApplyPitchWheel
|
|
; duty cycle
|
|
ld hl, Channel1DutyCycle - Channel1
|
|
add hl, bc
|
|
ld a, [hli]
|
|
ld [wCurTrackDuty], a
|
|
; intensity
|
|
ld a, [hli]
|
|
ld [wCurTrackIntensity], a
|
|
; frequency
|
|
ld a, [hli]
|
|
ld [wCurTrackFrequency], a
|
|
ld a, [hl]
|
|
ld [wCurTrackFrequency + 1], a
|
|
; vibrato, noise
|
|
call HandleTrackVibrato ; handle vibrato and other things
|
|
call HandleNoise
|
|
; turn off music when playing sfx?
|
|
ld a, [SFXPriority]
|
|
and a
|
|
jr z, .next
|
|
; are we in a sfx channel right now?
|
|
ld a, [CurChannel]
|
|
cp $4
|
|
jr nc, .next
|
|
; are any sfx channels active?
|
|
; if so, mute
|
|
ld hl, Channel5Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .restnote
|
|
ld hl, Channel6Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .restnote
|
|
ld hl, Channel7Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .restnote
|
|
ld hl, Channel8Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr z, .next
|
|
.restnote
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_REST, [hl] ; Rest
|
|
.next
|
|
; are we in a sfx channel right now?
|
|
ld a, [CurChannel]
|
|
cp $4 ; sfx
|
|
jr nc, .sfx_channel
|
|
ld hl, Channel5Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .sound_channel_on
|
|
.sfx_channel
|
|
call UpdateChannels
|
|
ld hl, Channel1Tracks - Channel1
|
|
add hl, bc
|
|
ld a, [SoundOutput]
|
|
or [hl]
|
|
ld [SoundOutput], a
|
|
.sound_channel_on
|
|
; clear note flags
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
xor a
|
|
ld [hl], a
|
|
.nextchannel
|
|
; next channel
|
|
ld hl, Channel2 - Channel1
|
|
add hl, bc
|
|
ld c, l
|
|
ld b, h
|
|
ld a, [CurChannel]
|
|
inc a
|
|
ld [CurChannel], a
|
|
cp $8 ; are we done?
|
|
jp nz, .loop ; do it all again
|
|
|
|
call PlayDanger
|
|
; fade music in/out
|
|
call FadeMusic
|
|
; write volume to hardware register
|
|
ld a, [Volume]
|
|
ld [rNR50], a
|
|
; write SO on/off to hardware register
|
|
ld a, [SoundOutput]
|
|
ld [rNR51], a
|
|
ret
|
|
|
|
; e8125
|
|
|
|
UpdateChannels: ; e8125
|
|
ld hl, .ChannelFnPtrs
|
|
ld a, [CurChannel]
|
|
and $7
|
|
add a
|
|
ld e, a
|
|
ld d, 0
|
|
add hl, de
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
jp hl
|
|
|
|
.ChannelFnPtrs:
|
|
dw .Channel1
|
|
dw .Channel2
|
|
dw .Channel3
|
|
dw .Channel4
|
|
; sfx ch ptrs are identical to music chs
|
|
; ..except 5
|
|
dw .Channel5
|
|
dw .Channel6
|
|
dw .Channel7
|
|
dw .Channel8
|
|
|
|
.Channel1:
|
|
ld a, [Danger]
|
|
bit 7, a
|
|
ret nz
|
|
.Channel5:
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
bit NOTE_UNKN_3, [hl]
|
|
jr z, .asm_e8159
|
|
;
|
|
ld a, [SoundInput]
|
|
ld [rNR10], a
|
|
.asm_e8159
|
|
bit NOTE_REST, [hl] ; rest
|
|
jr nz, .ch1rest
|
|
bit NOTE_NOISE_SAMPLING, [hl]
|
|
jr nz, .asm_e81a2
|
|
bit NOTE_FREQ_OVERRIDE, [hl]
|
|
jr nz, .frequency_override
|
|
bit NOTE_VIBRATO_OVERRIDE, [hl]
|
|
jr nz, .asm_e8184
|
|
jr .check_duty_override
|
|
|
|
.frequency_override
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR13], a
|
|
ld a, [wCurTrackFrequency + 1]
|
|
ld [rNR14], a
|
|
.check_duty_override
|
|
bit NOTE_DUTY_OVERRIDE, [hl]
|
|
ret z
|
|
ld a, [wCurTrackDuty]
|
|
ld d, a
|
|
ld a, [rNR11]
|
|
and $3f ; sound length
|
|
or d
|
|
ld [rNR11], a
|
|
ret
|
|
|
|
.asm_e8184
|
|
ld a, [wCurTrackDuty]
|
|
ld d, a
|
|
ld a, [rNR11]
|
|
and $3f ; sound length
|
|
or d
|
|
ld [rNR11], a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR13], a
|
|
ret
|
|
|
|
.ch1rest
|
|
ld a, [rNR52]
|
|
and %10001110 ; ch1 off
|
|
ld [rNR52], a
|
|
ld hl, rNR10
|
|
call ClearChannel
|
|
ret
|
|
|
|
.asm_e81a2
|
|
ld hl, wCurTrackDuty
|
|
ld a, $3f ; sound length
|
|
or [hl]
|
|
ld [rNR11], a
|
|
ld a, [wCurTrackIntensity]
|
|
ld [rNR12], a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR13], a
|
|
ld a, [wCurTrackFrequency + 1]
|
|
or $80
|
|
ld [rNR14], a
|
|
ret
|
|
|
|
.Channel2:
|
|
.Channel6:
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
bit NOTE_REST, [hl] ; rest
|
|
jr nz, .ch2rest
|
|
bit NOTE_NOISE_SAMPLING, [hl]
|
|
jr nz, .asm_e8204
|
|
bit NOTE_VIBRATO_OVERRIDE, [hl]
|
|
jr nz, .asm_e81e6
|
|
bit NOTE_DUTY_OVERRIDE, [hl]
|
|
ret z
|
|
ld a, [wCurTrackDuty]
|
|
ld d, a
|
|
ld a, [rNR21]
|
|
and $3f ; sound length
|
|
or d
|
|
ld [rNR21], a
|
|
ret
|
|
|
|
.asm_e81db ; unused
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR23], a
|
|
ld a, [wCurTrackFrequency + 1]
|
|
ld [rNR24], a
|
|
ret
|
|
|
|
.asm_e81e6
|
|
ld a, [wCurTrackDuty]
|
|
ld d, a
|
|
ld a, [rNR21]
|
|
and $3f ; sound length
|
|
or d
|
|
ld [rNR21], a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR23], a
|
|
ret
|
|
|
|
.ch2rest
|
|
ld a, [rNR52]
|
|
and %10001101 ; ch2 off
|
|
ld [rNR52], a
|
|
ld hl, rNR20
|
|
call ClearChannel
|
|
ret
|
|
|
|
.asm_e8204
|
|
ld hl, wCurTrackDuty
|
|
ld a, $3f ; sound length
|
|
or [hl]
|
|
ld [rNR21], a
|
|
ld a, [wCurTrackIntensity]
|
|
ld [rNR22], a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR23], a
|
|
ld a, [wCurTrackFrequency + 1]
|
|
or $80 ; initial (restart)
|
|
ld [rNR24], a
|
|
ret
|
|
|
|
.Channel3:
|
|
.Channel7:
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
bit NOTE_REST, [hl] ; rest
|
|
jr nz, .ch3rest
|
|
bit NOTE_NOISE_SAMPLING, [hl]
|
|
jr nz, .asm_e824d
|
|
bit NOTE_VIBRATO_OVERRIDE, [hl]
|
|
jr nz, .asm_e823a
|
|
ret
|
|
|
|
.asm_e822f ; unused
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR33], a
|
|
ld a, [wCurTrackFrequency + 1]
|
|
ld [rNR34], a
|
|
ret
|
|
|
|
.asm_e823a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR33], a
|
|
ret
|
|
|
|
.ch3rest
|
|
ld a, [rNR52]
|
|
and %10001011 ; ch3 off
|
|
ld [rNR52], a
|
|
ld hl, rNR30
|
|
call ClearChannel
|
|
ret
|
|
|
|
.asm_e824d
|
|
ld a, $3f
|
|
ld [rNR31], a
|
|
xor a
|
|
ld [rNR30], a
|
|
call .asm_e8268
|
|
ld a, $80
|
|
ld [rNR30], a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR33], a
|
|
ld a, [wCurTrackFrequency + 1]
|
|
or $80
|
|
ld [rNR34], a
|
|
ret
|
|
|
|
.asm_e8268
|
|
push hl
|
|
ld a, [wCurTrackIntensity]
|
|
and $f ; only 0-9 are valid
|
|
ld l, a
|
|
ld h, 0
|
|
; hl << 4
|
|
; each wavepattern is $f bytes long
|
|
; so seeking is done in $10s
|
|
rept 4
|
|
add hl, hl
|
|
endr
|
|
ld de, WaveSamples
|
|
add hl, de
|
|
; load wavepattern into rWave_0-rWave_f
|
|
ld a, [hli]
|
|
ld [rWave_0], a
|
|
ld a, [hli]
|
|
ld [rWave_1], a
|
|
ld a, [hli]
|
|
ld [rWave_2], a
|
|
ld a, [hli]
|
|
ld [rWave_3], a
|
|
ld a, [hli]
|
|
ld [rWave_4], a
|
|
ld a, [hli]
|
|
ld [rWave_5], a
|
|
ld a, [hli]
|
|
ld [rWave_6], a
|
|
ld a, [hli]
|
|
ld [rWave_7], a
|
|
ld a, [hli]
|
|
ld [rWave_8], a
|
|
ld a, [hli]
|
|
ld [rWave_9], a
|
|
ld a, [hli]
|
|
ld [rWave_a], a
|
|
ld a, [hli]
|
|
ld [rWave_b], a
|
|
ld a, [hli]
|
|
ld [rWave_c], a
|
|
ld a, [hli]
|
|
ld [rWave_d], a
|
|
ld a, [hli]
|
|
ld [rWave_e], a
|
|
ld a, [hli]
|
|
ld [rWave_f], a
|
|
pop hl
|
|
ld a, [wCurTrackIntensity]
|
|
and $f0
|
|
sla a
|
|
ld [rNR32], a
|
|
ret
|
|
|
|
.Channel4:
|
|
.Channel8:
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
bit NOTE_REST, [hl] ; rest
|
|
jr nz, .ch4rest
|
|
bit NOTE_NOISE_SAMPLING, [hl]
|
|
jr nz, .asm_e82d4
|
|
ret
|
|
|
|
.asm_e82c1 ; unused
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR43], a
|
|
ret
|
|
|
|
.ch4rest
|
|
ld a, [rNR52]
|
|
and %10000111 ; ch4 off
|
|
ld [rNR52], a
|
|
ld hl, rNR40
|
|
call ClearChannel
|
|
ret
|
|
|
|
.asm_e82d4
|
|
ld a, $3f ; sound length
|
|
ld [rNR41], a
|
|
ld a, [wCurTrackIntensity]
|
|
ld [rNR42], a
|
|
ld a, [wCurTrackFrequency]
|
|
ld [rNR43], a
|
|
ld a, $80
|
|
ld [rNR44], a
|
|
ret
|
|
|
|
; e82e7
|
|
|
|
_CheckSFX: ; e82e7
|
|
; return carry if any sfx channels are active
|
|
ld hl, Channel5Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .sfxon
|
|
ld hl, Channel6Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .sfxon
|
|
ld hl, Channel7Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .sfxon
|
|
ld hl, Channel8Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .sfxon
|
|
and a
|
|
ret
|
|
|
|
.sfxon
|
|
scf
|
|
ret
|
|
|
|
; e8307
|
|
|
|
PlayDanger: ; e8307
|
|
ld a, [Danger]
|
|
bit 7, a
|
|
ret z
|
|
and $7f
|
|
ld d, a
|
|
call _CheckSFX
|
|
jr c, .asm_e8335
|
|
and a
|
|
jr z, .asm_e8323
|
|
cp 16 ; halfway
|
|
jr z, .asm_e831e
|
|
jr .asm_e8335
|
|
|
|
.asm_e831e
|
|
ld hl, Tablee8354
|
|
jr .updatehw
|
|
|
|
.asm_e8323
|
|
ld hl, Tablee8350
|
|
.updatehw
|
|
xor a
|
|
ld [rNR10], a ; sweep off
|
|
ld a, [hli]
|
|
ld [rNR11], a ; sound length / duty cycle
|
|
ld a, [hli]
|
|
ld [rNR12], a ; ch1 volume envelope
|
|
ld a, [hli]
|
|
ld [rNR13], a ; ch1 frequency lo
|
|
ld a, [hli]
|
|
ld [rNR14], a ; ch1 frequency hi
|
|
.asm_e8335
|
|
ld a, d
|
|
inc a
|
|
cp 30
|
|
jr c, .asm_e833c
|
|
xor a
|
|
.asm_e833c
|
|
or $80
|
|
ld [Danger], a
|
|
; is hw ch1 on?
|
|
ld a, [SoundOutput]
|
|
and $11
|
|
ret nz
|
|
; if not, turn it on
|
|
ld a, [SoundOutput]
|
|
or $11
|
|
ld [SoundOutput], a
|
|
ret
|
|
|
|
; e8350
|
|
|
|
Tablee8350: ; e8350
|
|
db $80 ; duty 50%
|
|
db $e2 ; volume 14, envelope decrease sweep 2
|
|
db $50 ; frequency: $750
|
|
db $87 ; restart sound
|
|
; e8354
|
|
|
|
Tablee8354: ; e8354
|
|
db $80 ; duty 50%
|
|
db $e2 ; volume 14, envelope decrease sweep 2
|
|
db $ee ; frequency: $6ee
|
|
db $86 ; restart sound
|
|
; e8358
|
|
|
|
FadeMusic: ; e8358
|
|
; fade music if applicable
|
|
; usage:
|
|
; write to MusicFade
|
|
; song fades out at the given rate
|
|
; load song id in MusicFadeID
|
|
; fade new song in
|
|
; notes:
|
|
; max # frames per volume level is $3f
|
|
|
|
; fading?
|
|
ld a, [MusicFade]
|
|
and a
|
|
ret z
|
|
; has the count ended?
|
|
ld a, [MusicFadeCount]
|
|
and a
|
|
jr z, .update
|
|
; count down
|
|
dec a
|
|
ld [MusicFadeCount], a
|
|
ret
|
|
|
|
.update
|
|
ld a, [MusicFade]
|
|
ld d, a
|
|
; get new count
|
|
and $3f
|
|
ld [MusicFadeCount], a
|
|
; get SO1 volume
|
|
ld a, [Volume]
|
|
and $7
|
|
; which way are we fading?
|
|
bit 7, d
|
|
jr nz, .fadein
|
|
; fading out
|
|
and a
|
|
jr z, .novolume
|
|
dec a
|
|
jr .updatevolume
|
|
|
|
.novolume
|
|
; make sure volume is off
|
|
xor a
|
|
ld [Volume], a
|
|
; did we just get on a bike?
|
|
ld a, [PlayerState]
|
|
cp $1 ; bicycle
|
|
jr z, .bicycle
|
|
push bc
|
|
; restart sound
|
|
call MusicFadeRestart
|
|
; get new song id
|
|
ld a, [MusicFadeIDLo]
|
|
and a
|
|
jr z, .quit ; this assumes there are fewer than 256 songs!
|
|
ld e, a
|
|
ld a, [MusicFadeIDHi]
|
|
ld d, a
|
|
; load new song
|
|
call _PlayMusic
|
|
.quit
|
|
; cleanup
|
|
pop bc
|
|
; stop fading
|
|
xor a
|
|
ld [MusicFade], a
|
|
ret
|
|
|
|
.bicycle
|
|
push bc
|
|
; restart sound
|
|
call MusicFadeRestart
|
|
; this turns the volume up
|
|
; turn it back down
|
|
xor a
|
|
ld [Volume], a
|
|
; get new song id
|
|
ld a, [MusicFadeIDLo]
|
|
ld e, a
|
|
ld a, [MusicFadeIDHi]
|
|
ld d, a
|
|
; load new song
|
|
call _PlayMusic
|
|
pop bc
|
|
; fade in
|
|
ld hl, MusicFade
|
|
set 7, [hl]
|
|
ret
|
|
|
|
.fadein
|
|
; are we done?
|
|
cp $7
|
|
jr nc, .maxvolume
|
|
; inc volume
|
|
inc a
|
|
jr .updatevolume
|
|
|
|
.maxvolume
|
|
; we're done
|
|
xor a
|
|
ld [MusicFade], a
|
|
ret
|
|
|
|
.updatevolume
|
|
; hi = lo
|
|
ld d, a
|
|
swap a
|
|
or d
|
|
ld [Volume], a
|
|
ret
|
|
|
|
; e83d1
|
|
|
|
LoadNote: ; e83d1
|
|
; wait for pitch wheel to finish
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
bit SOUND_PITCH_WHEEL, [hl]
|
|
ret z
|
|
; get note duration
|
|
ld hl, Channel1NoteDuration - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, wCurNoteDuration
|
|
sub [hl]
|
|
jr nc, .ok
|
|
ld a, 1
|
|
.ok
|
|
ld [hl], a
|
|
; get frequency
|
|
ld hl, Channel1Frequency - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; get direction of pitch wheel
|
|
ld hl, Channel1PitchWheelTarget - Channel1
|
|
add hl, bc
|
|
ld a, e
|
|
sub [hl]
|
|
ld e, a
|
|
ld a, d
|
|
sbc a, 0
|
|
ld d, a
|
|
ld hl, Channel1PitchWheelTarget + 1 - Channel1
|
|
add hl, bc
|
|
sub [hl]
|
|
jr nc, .greater_than
|
|
ld hl, Channel1Flags3 - Channel1
|
|
add hl, bc
|
|
set SOUND_PITCH_WHEEL_DIR, [hl]
|
|
; get frequency
|
|
ld hl, Channel1Frequency - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; ????
|
|
ld hl, Channel1PitchWheelTarget - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
sub e
|
|
ld e, a
|
|
ld a, d
|
|
sbc a, 0
|
|
ld d, a
|
|
; ????
|
|
ld hl, Channel1PitchWheelTarget + 1 - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
sub d
|
|
ld d, a
|
|
jr .resume
|
|
|
|
.greater_than
|
|
ld hl, Channel1Flags3 - Channel1
|
|
add hl, bc
|
|
res SOUND_PITCH_WHEEL_DIR, [hl]
|
|
; get frequency
|
|
ld hl, Channel1Frequency - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; get distance from pitch wheel target
|
|
ld hl, Channel1PitchWheelTarget - Channel1
|
|
add hl, bc
|
|
ld a, e
|
|
sub [hl]
|
|
ld e, a
|
|
ld a, d
|
|
sbc a, 0
|
|
ld d, a
|
|
ld hl, Channel1PitchWheelTarget + 1 - Channel1
|
|
add hl, bc
|
|
sub [hl]
|
|
ld d, a
|
|
.resume
|
|
; de = x * [wCurNoteDuration] + y
|
|
; x + 1 -> d
|
|
; y -> a
|
|
push bc
|
|
ld hl, wCurNoteDuration
|
|
ld b, 0 ; quotient
|
|
.loop
|
|
inc b
|
|
ld a, e
|
|
sub [hl]
|
|
ld e, a
|
|
jr nc, .loop
|
|
ld a, d
|
|
and a
|
|
jr z, .quit
|
|
dec d
|
|
jr .loop
|
|
|
|
.quit
|
|
ld a, e ; remainder
|
|
add [hl]
|
|
ld d, b ; quotient
|
|
pop bc
|
|
ld hl, Channel1PitchWheelAmount - Channel1
|
|
add hl, bc
|
|
ld [hl], d ; quotient
|
|
ld hl, Channel1PitchWheelAmountFraction - Channel1
|
|
add hl, bc
|
|
ld [hl], a ; remainder
|
|
ld hl, Channel1Field0x25 - Channel1
|
|
add hl, bc
|
|
xor a
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e8466
|
|
|
|
HandleTrackVibrato: ; e8466
|
|
; handle duty, cry pitch, and vibrato
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
bit SOUND_DUTY, [hl] ; duty
|
|
jr z, .next
|
|
ld hl, Channel1SFXDutyLoop - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
rlca
|
|
rlca
|
|
ld [hl], a
|
|
and $c0
|
|
ld [wCurTrackDuty], a
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_DUTY_OVERRIDE, [hl]
|
|
.next
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
bit SOUND_CRY_PITCH, [hl]
|
|
jr z, .vibrato
|
|
ld hl, Channel1CryPitch - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld hl, wCurTrackFrequency
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
add hl, de
|
|
ld e, l
|
|
ld d, h
|
|
ld hl, wCurTrackFrequency
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
.vibrato
|
|
; is vibrato on?
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
bit SOUND_VIBRATO, [hl] ; vibrato
|
|
jr z, .quit
|
|
; is vibrato active for this note yet?
|
|
; is the delay over?
|
|
ld hl, Channel1VibratoDelayCount - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a
|
|
jr nz, .subexit
|
|
; is the extent nonzero?
|
|
ld hl, Channel1VibratoExtent - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .quit
|
|
; save it for later
|
|
ld d, a
|
|
; is it time to toggle vibrato up/down?
|
|
ld hl, Channel1VibratoRate - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and $f ; count
|
|
jr z, .toggle
|
|
.subexit
|
|
dec [hl]
|
|
jr .quit
|
|
|
|
.toggle
|
|
; refresh count
|
|
ld a, [hl]
|
|
swap [hl]
|
|
or [hl]
|
|
ld [hl], a
|
|
; ????
|
|
ld a, [wCurTrackFrequency]
|
|
ld e, a
|
|
; toggle vibrato up/down
|
|
ld hl, Channel1Flags3 - Channel1
|
|
add hl, bc
|
|
bit SOUND_VIBRATO_DIR, [hl] ; vibrato up/down
|
|
jr z, .down
|
|
; up
|
|
; vibrato down
|
|
res SOUND_VIBRATO_DIR, [hl]
|
|
; get the delay
|
|
ld a, d
|
|
and $f ; lo
|
|
;
|
|
ld d, a
|
|
ld a, e
|
|
sub d
|
|
jr nc, .no_carry
|
|
ld a, 0
|
|
jr .no_carry
|
|
|
|
.down
|
|
; vibrato up
|
|
set SOUND_VIBRATO_DIR, [hl]
|
|
; get the delay
|
|
ld a, d
|
|
and $f0 ; hi
|
|
swap a ; move it to lo
|
|
;
|
|
add e
|
|
jr nc, .no_carry
|
|
ld a, $ff
|
|
.no_carry
|
|
ld [wCurTrackFrequency], a
|
|
;
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_VIBRATO_OVERRIDE, [hl]
|
|
.quit
|
|
ret
|
|
|
|
; e84f9
|
|
|
|
ApplyPitchWheel: ; e84f9
|
|
; quit if pitch wheel inactive
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
bit SOUND_PITCH_WHEEL, [hl]
|
|
ret z
|
|
; de = Frequency
|
|
ld hl, Channel1Frequency - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; check whether pitch wheel is going up or down
|
|
ld hl, Channel1Flags3 - Channel1
|
|
add hl, bc
|
|
bit SOUND_PITCH_WHEEL_DIR, [hl]
|
|
jr z, .decreasing
|
|
; frequency += [Channel*PitchWheelAmount]
|
|
ld hl, Channel1PitchWheelAmount - Channel1
|
|
add hl, bc
|
|
ld l, [hl]
|
|
ld h, 0
|
|
add hl, de
|
|
ld d, h
|
|
ld e, l
|
|
; [Channel*Field0x25] += [Channel*PitchWheelAmountFraction]
|
|
; if rollover: Frequency += 1
|
|
ld hl, Channel1PitchWheelAmountFraction - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, Channel1Field0x25 - Channel1
|
|
add hl, bc
|
|
add [hl]
|
|
ld [hl], a
|
|
ld a, 0
|
|
adc e
|
|
ld e, a
|
|
ld a, 0
|
|
adc d
|
|
ld d, a
|
|
; Compare the dw at [Channel*PitchWheelTarget] to de.
|
|
; If frequency is greater, we're finished.
|
|
; Otherwise, load the frequency and set two flags.
|
|
ld hl, Channel1PitchWheelTarget + 1 - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp d
|
|
jp c, .finished_pitch_wheel
|
|
jr nz, .continue_pitch_wheel
|
|
ld hl, Channel1PitchWheelTarget - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp e
|
|
jp c, .finished_pitch_wheel
|
|
jr .continue_pitch_wheel
|
|
|
|
.decreasing
|
|
; frequency -= [Channel*PitchWheelAmount]
|
|
ld a, e
|
|
ld hl, Channel1PitchWheelAmount - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
sub e
|
|
ld e, a
|
|
ld a, d
|
|
sbc a, 0
|
|
ld d, a
|
|
; [Channel*Field0x25] *= 2
|
|
; if rollover: Frequency -= 1
|
|
ld hl, Channel1PitchWheelAmountFraction - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
add a
|
|
ld [hl], a
|
|
ld a, e
|
|
sbc a, 0
|
|
ld e, a
|
|
ld a, d
|
|
sbc a, 0
|
|
ld d, a
|
|
; Compare the dw at [Channel*PitchWheelTarget] to de.
|
|
; If frequency is lower, we're finished.
|
|
; Otherwise, load the frequency and set two flags.
|
|
ld hl, Channel1PitchWheelTarget + 1 - Channel1
|
|
add hl, bc
|
|
ld a, d
|
|
cp [hl]
|
|
jr c, .finished_pitch_wheel
|
|
jr nz, .continue_pitch_wheel
|
|
ld hl, Channel1PitchWheelTarget - Channel1
|
|
add hl, bc
|
|
ld a, e
|
|
cp [hl]
|
|
jr nc, .continue_pitch_wheel
|
|
.finished_pitch_wheel
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
res SOUND_PITCH_WHEEL, [hl]
|
|
ld hl, Channel1Flags3 - Channel1
|
|
add hl, bc
|
|
res SOUND_PITCH_WHEEL_DIR, [hl]
|
|
ret
|
|
|
|
.continue_pitch_wheel
|
|
ld hl, Channel1Frequency - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_FREQ_OVERRIDE, [hl]
|
|
set NOTE_DUTY_OVERRIDE, [hl]
|
|
ret
|
|
|
|
; e858c
|
|
|
|
HandleNoise: ; e858c
|
|
; is noise sampling on?
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_NOISE, [hl] ; noise sampling
|
|
ret z
|
|
; are we in a sfx channel?
|
|
ld a, [CurChannel]
|
|
bit 2, a ; sfx
|
|
jr nz, .next
|
|
; is ch8 on? (noise)
|
|
ld hl, Channel8Flags
|
|
bit SOUND_CHANNEL_ON, [hl] ; on?
|
|
jr z, .next
|
|
; is ch8 playing noise?
|
|
bit SOUND_NOISE, [hl]
|
|
ret nz ; quit if so
|
|
;
|
|
.next
|
|
ld a, [wNoiseSampleDelay]
|
|
and a
|
|
jr z, ReadNoiseSample
|
|
dec a
|
|
ld [wNoiseSampleDelay], a
|
|
ret
|
|
|
|
; e85af
|
|
|
|
ReadNoiseSample: ; e85af
|
|
; sample struct:
|
|
; [wx] [yy] [zz]
|
|
; w: ? either 2 or 3
|
|
; x: duration
|
|
; zz: intensity
|
|
; yy: frequency
|
|
|
|
; de = [NoiseSampleAddress]
|
|
ld hl, NoiseSampleAddress
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
|
|
; is it empty?
|
|
ld a, e
|
|
or d
|
|
jr z, .quit
|
|
|
|
ld a, [de]
|
|
inc de
|
|
|
|
cp $ff
|
|
jr z, .quit
|
|
|
|
and $f
|
|
inc a
|
|
ld [wNoiseSampleDelay], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [wCurTrackIntensity], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [wCurTrackFrequency], a
|
|
xor a
|
|
ld [wCurTrackFrequency + 1], a
|
|
|
|
ld hl, NoiseSampleAddress
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_NOISE_SAMPLING, [hl]
|
|
ret
|
|
|
|
.quit
|
|
ret
|
|
|
|
; e85e1
|
|
|
|
ParseMusic: ; e85e1
|
|
; parses until a note is read or the song is ended
|
|
call GetMusicByte ; store next byte in a
|
|
cp $ff ; is the song over?
|
|
jr z, .endchannel
|
|
cp $d0 ; is it a note?
|
|
jr c, .readnote
|
|
; then it's a command
|
|
.readcommand
|
|
call ParseMusicCommand
|
|
jr ParseMusic ; start over
|
|
|
|
.readnote
|
|
; CurMusicByte contains current note
|
|
; special notes
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_SFX, [hl]
|
|
jp nz, ParseSFXOrRest
|
|
bit SOUND_REST, [hl] ; rest
|
|
jp nz, ParseSFXOrRest
|
|
bit SOUND_NOISE, [hl] ; noise sample
|
|
jp nz, GetNoiseSample
|
|
; normal note
|
|
; set note duration (bottom nybble)
|
|
ld a, [CurMusicByte]
|
|
and $f
|
|
call SetNoteDuration
|
|
; get note pitch (top nybble)
|
|
ld a, [CurMusicByte]
|
|
swap a
|
|
and $f
|
|
jr z, .rest ; pitch 0-> rest
|
|
; update pitch
|
|
ld hl, Channel1Pitch - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; store pitch in e
|
|
ld e, a
|
|
; store octave in d
|
|
ld hl, Channel1Octave - Channel1
|
|
add hl, bc
|
|
ld d, [hl]
|
|
; update frequency
|
|
call GetFrequency
|
|
ld hl, Channel1Frequency - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
; ????
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_NOISE_SAMPLING, [hl]
|
|
jp LoadNote
|
|
|
|
.rest
|
|
; note = rest
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_REST, [hl] ; Rest
|
|
ret
|
|
|
|
.endchannel
|
|
; $ff is reached in music data
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_SUBROUTINE, [hl] ; in a subroutine?
|
|
jr nz, .readcommand ; execute
|
|
ld a, [CurChannel]
|
|
cp $4 ; channels 0-3?
|
|
jr nc, .chan_5to8
|
|
; ????
|
|
ld hl, Channel5Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr nz, .ok
|
|
.chan_5to8
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_REST, [hl]
|
|
call nz, RestoreVolume
|
|
; end music
|
|
ld a, [CurChannel]
|
|
cp $4 ; channel 5?
|
|
jr nz, .ok
|
|
; ????
|
|
xor a
|
|
ld [rNR10], a ; sweep = 0
|
|
.ok
|
|
; stop playing
|
|
; turn channel off
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
res SOUND_CHANNEL_ON, [hl]
|
|
; note = rest
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_REST, [hl]
|
|
; clear music id & bank
|
|
ld hl, Channel1MusicID - Channel1
|
|
add hl, bc
|
|
xor a
|
|
ld [hli], a ; id hi
|
|
ld [hli], a ; id lo
|
|
ld [hli], a ; bank
|
|
ret
|
|
|
|
; e8679
|
|
|
|
RestoreVolume: ; e8679
|
|
; ch5 only
|
|
ld a, [CurChannel]
|
|
cp $4
|
|
ret nz
|
|
xor a
|
|
ld hl, Channel6CryPitch
|
|
ld [hli], a
|
|
ld [hl], a
|
|
ld hl, Channel8CryPitch
|
|
ld [hli], a
|
|
ld [hl], a
|
|
ld a, [LastVolume]
|
|
ld [Volume], a
|
|
xor a
|
|
ld [LastVolume], a
|
|
ld [SFXPriority], a
|
|
ret
|
|
|
|
; e8698
|
|
|
|
ParseSFXOrRest: ; e8698
|
|
; turn noise sampling on
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_NOISE_SAMPLING, [hl] ; noise sample
|
|
; update note duration
|
|
ld a, [CurMusicByte]
|
|
call SetNoteDuration ; top nybble doesnt matter?
|
|
; update intensity from next param
|
|
call GetMusicByte
|
|
ld hl, Channel1Intensity - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; update lo frequency from next param
|
|
call GetMusicByte
|
|
ld hl, Channel1FrequencyLo - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; are we on the last channel? (noise sampling)
|
|
ld a, [CurChannel]
|
|
and $3
|
|
cp $3
|
|
ret z
|
|
; update hi frequency from next param
|
|
call GetMusicByte
|
|
ld hl, Channel1FrequencyHi - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e86c5
|
|
|
|
GetNoiseSample: ; e86c5
|
|
; load ptr to sample header in NoiseSampleAddress
|
|
; are we on the last channel?
|
|
ld a, [CurChannel]
|
|
and $3
|
|
cp $3
|
|
; ret if not
|
|
ret nz
|
|
; update note duration
|
|
ld a, [CurMusicByte]
|
|
and $f
|
|
call SetNoteDuration
|
|
; check current channel
|
|
ld a, [CurChannel]
|
|
bit 2, a ; are we in a sfx channel?
|
|
jr nz, .sfx
|
|
ld hl, Channel8Flags
|
|
bit SOUND_CHANNEL_ON, [hl] ; is ch8 on? (noise)
|
|
ret nz
|
|
ld a, [MusicNoiseSampleSet]
|
|
jr .next
|
|
|
|
.sfx
|
|
ld a, [SFXNoiseSampleSet]
|
|
.next
|
|
; load noise sample set id into de
|
|
ld e, a
|
|
ld d, 0
|
|
; load ptr to noise sample set in hl
|
|
ld hl, Drumkits
|
|
add hl, de
|
|
add hl, de
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
; get pitch
|
|
ld a, [CurMusicByte]
|
|
swap a
|
|
; non-rest note?
|
|
and $f
|
|
ret z
|
|
; use 'pitch' to seek noise sample set
|
|
ld e, a
|
|
ld d, 0
|
|
add hl, de
|
|
add hl, de
|
|
; load sample pointer into NoiseSampleAddress
|
|
ld a, [hli]
|
|
ld [NoiseSampleAddressLo], a
|
|
ld a, [hl]
|
|
ld [NoiseSampleAddressHi], a
|
|
; clear ????
|
|
xor a
|
|
ld [wNoiseSampleDelay], a
|
|
ret
|
|
|
|
; e870f
|
|
|
|
ParseMusicCommand: ; e870f
|
|
; reload command
|
|
ld a, [CurMusicByte]
|
|
; get command #
|
|
sub a, $d0 ; first command
|
|
ld e, a
|
|
ld d, 0
|
|
; seek command pointer
|
|
ld hl, MusicCommands
|
|
add hl, de
|
|
add hl, de
|
|
; jump to the new pointer
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
jp hl
|
|
|
|
; e8720
|
|
|
|
MusicCommands: ; e8720
|
|
; pointer to each command in order
|
|
; octaves
|
|
dw Music_Octave8 ; octave 8
|
|
dw Music_Octave7 ; octave 7
|
|
dw Music_Octave6 ; octave 6
|
|
dw Music_Octave5 ; octave 5
|
|
dw Music_Octave4 ; octave 4
|
|
dw Music_Octave3 ; octave 3
|
|
dw Music_Octave2 ; octave 2
|
|
dw Music_Octave1 ; octave 1
|
|
dw Music_NoteType ; note length + intensity
|
|
dw Music_ForceOctave ; set starting octave
|
|
dw Music_Tempo ; tempo
|
|
dw Music_DutyCycle ; duty cycle
|
|
dw Music_Intensity ; intensity
|
|
dw Music_SoundStatus ; update sound status
|
|
dw Music_SoundDuty ; sfx duty
|
|
dw Music_ToggleSFX ; sound on/off
|
|
dw Music_SlidePitchTo ; pitch wheel
|
|
dw Music_Vibrato ; vibrato
|
|
dw MusicE2 ; unused
|
|
dw Music_ToggleNoise ; music noise sampling
|
|
dw Music_Panning ; force panning
|
|
dw Music_Volume ; volume
|
|
dw Music_Tone ; tone
|
|
dw MusicE7 ; unused
|
|
dw MusicE8 ; unused
|
|
dw Music_TempoRelative ; global tempo
|
|
dw Music_RestartChannel ; restart current channel from header
|
|
dw Music_NewSong ; new song
|
|
dw Music_SFXPriorityOn ; sfx priority on
|
|
dw Music_SFXPriorityOff ; sfx priority off
|
|
dw MusicEE ; unused
|
|
dw Music_StereoPanning ; stereo panning
|
|
dw Music_SFXToggleNoise ; sfx noise sampling
|
|
dw MusicF1 ; nothing
|
|
dw MusicF2 ; nothing
|
|
dw MusicF3 ; nothing
|
|
dw MusicF4 ; nothing
|
|
dw MusicF5 ; nothing
|
|
dw MusicF6 ; nothing
|
|
dw MusicF7 ; nothing
|
|
dw MusicF8 ; nothing
|
|
dw MusicF9 ; unused
|
|
dw Music_SetCondition ; setcondition
|
|
dw Music_JumpIf ; jumpif
|
|
dw Music_JumpChannel ; jump
|
|
dw Music_LoopChannel ; loop
|
|
dw Music_CallChannel ; call
|
|
dw Music_EndChannel ; return
|
|
; e8780
|
|
|
|
MusicF1: ; e8780
|
|
MusicF2: ; e8780
|
|
MusicF3: ; e8780
|
|
MusicF4: ; e8780
|
|
MusicF5: ; e8780
|
|
MusicF6: ; e8780
|
|
MusicF7: ; e8780
|
|
MusicF8: ; e8780
|
|
ret
|
|
|
|
; e8781
|
|
|
|
Music_EndChannel: ; e8781
|
|
; called when $ff is encountered w/ subroutine flag set
|
|
; end music stream
|
|
; return to caller of the subroutine
|
|
; reset subroutine flag
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
res SOUND_SUBROUTINE, [hl]
|
|
; copy LastMusicAddress to MusicAddress
|
|
ld hl, Channel1LastMusicAddress - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ret
|
|
|
|
; e8796
|
|
|
|
Music_CallChannel: ; e8796
|
|
; call music stream (subroutine)
|
|
; parameters: ll hh ; pointer to subroutine
|
|
; get pointer from next 2 bytes
|
|
call GetMusicByte
|
|
ld e, a
|
|
call GetMusicByte
|
|
ld d, a
|
|
push de
|
|
; copy MusicAddress to LastMusicAddress
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld hl, Channel1LastMusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
; load pointer into MusicAddress
|
|
pop de
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
; set subroutine flag
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
set SOUND_SUBROUTINE, [hl]
|
|
ret
|
|
|
|
; e87bc
|
|
|
|
Music_JumpChannel: ; e87bc
|
|
; jump
|
|
; parameters: ll hh ; pointer
|
|
; get pointer from next 2 bytes
|
|
call GetMusicByte
|
|
ld e, a
|
|
call GetMusicByte
|
|
ld d, a
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ret
|
|
|
|
; e87cc
|
|
|
|
Music_LoopChannel: ; e87cc
|
|
; loops xx - 1 times
|
|
; 00: infinite
|
|
; params: 3
|
|
; xx ll hh
|
|
; xx : loop count
|
|
; ll hh : pointer
|
|
|
|
; get loop count
|
|
call GetMusicByte
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_LOOPING, [hl] ; has the loop been initiated?
|
|
jr nz, .checkloop
|
|
and a ; loop counter 0 = infinite
|
|
jr z, .loop
|
|
; initiate loop
|
|
dec a
|
|
set SOUND_LOOPING, [hl] ; set loop flag
|
|
ld hl, Channel1LoopCount - Channel1
|
|
add hl, bc
|
|
ld [hl], a ; store loop counter
|
|
.checkloop
|
|
ld hl, Channel1LoopCount - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a ; are we done?
|
|
jr z, .endloop
|
|
dec [hl]
|
|
.loop
|
|
; get pointer
|
|
call GetMusicByte
|
|
ld e, a
|
|
call GetMusicByte
|
|
ld d, a
|
|
; load new pointer into MusicAddress
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ret
|
|
|
|
.endloop
|
|
; reset loop flag
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
res SOUND_LOOPING, [hl]
|
|
; skip to next command
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
inc de ; skip
|
|
inc de ; pointer
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
ret
|
|
|
|
; e880e
|
|
|
|
Music_SetCondition: ; e880e
|
|
; set condition for a jump
|
|
; used with FB
|
|
; params: 1
|
|
; xx ; condition
|
|
|
|
; set condition
|
|
call GetMusicByte
|
|
ld hl, Channel1Condition - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e8817
|
|
|
|
Music_JumpIf: ; e8817
|
|
; conditional jump
|
|
; used with FA
|
|
; params: 3
|
|
; xx: condition
|
|
; ll hh: pointer
|
|
|
|
; check condition
|
|
; a = condition
|
|
call GetMusicByte
|
|
; if existing condition matches, jump to new address
|
|
ld hl, Channel1Condition - Channel1
|
|
add hl, bc
|
|
cp [hl]
|
|
jr z, .jump
|
|
; skip to next command
|
|
; get address
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; skip pointer
|
|
inc de
|
|
inc de
|
|
; update address
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
ret
|
|
|
|
.jump
|
|
; jump to the new address
|
|
; get pointer
|
|
call GetMusicByte
|
|
ld e, a
|
|
call GetMusicByte
|
|
ld d, a
|
|
; update pointer in MusicAddress
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ret
|
|
|
|
; e883e
|
|
|
|
MusicEE; e883e
|
|
; conditional jump
|
|
; checks a byte in ram corresponding to the current channel
|
|
; doesn't seem to be set by any commands
|
|
; params: 2
|
|
; ll hh ; pointer
|
|
|
|
; if ????, jump
|
|
; get channel
|
|
ld a, [CurChannel]
|
|
and $3 ; ch0-3
|
|
ld e, a
|
|
ld d, 0
|
|
; hl = Channel1JumpCondition + channel id
|
|
ld hl, Channel1JumpCondition
|
|
add hl, de
|
|
; if set, jump
|
|
ld a, [hl]
|
|
and a
|
|
jr nz, .jump
|
|
; skip to next command
|
|
; get address
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; skip pointer
|
|
inc de
|
|
inc de
|
|
; update address
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
ret
|
|
|
|
.jump
|
|
; reset jump flag
|
|
ld [hl], 0
|
|
; de = pointer
|
|
call GetMusicByte
|
|
ld e, a
|
|
call GetMusicByte
|
|
ld d, a
|
|
; update address
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ret
|
|
|
|
; e886d
|
|
|
|
MusicF9: ; e886d
|
|
; sets some flag
|
|
; seems to be unused
|
|
; params: 0
|
|
ld a, 1
|
|
ld [wc2b5], a
|
|
ret
|
|
|
|
; e8873
|
|
|
|
MusicE2: ; e8873
|
|
; seems to have been dummied out
|
|
; params: 1
|
|
call GetMusicByte
|
|
ld hl, Channel1Field0x2c - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_UNKN_0B, [hl]
|
|
ret
|
|
|
|
; e8882
|
|
|
|
Music_Vibrato: ; e8882
|
|
; vibrato
|
|
; params: 2
|
|
; 1: [xx]
|
|
; delay in frames
|
|
; 2: [yz]
|
|
; y: extent
|
|
; z: rate (# frames per cycle)
|
|
|
|
; set vibrato flag?
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_VIBRATO, [hl]
|
|
; start at lower frequency (extent is positive)
|
|
ld hl, Channel1Flags3 - Channel1
|
|
add hl, bc
|
|
res SOUND_VIBRATO_DIR, [hl]
|
|
; get delay
|
|
call GetMusicByte
|
|
; update delay
|
|
ld hl, Channel1VibratoDelay - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; update delay count
|
|
ld hl, Channel1VibratoDelayCount - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; update extent
|
|
; this is split into halves only to get added back together at the last second
|
|
; get extent/rate
|
|
call GetMusicByte
|
|
ld hl, Channel1VibratoExtent - Channel1
|
|
add hl, bc
|
|
ld d, a
|
|
; get top nybble
|
|
and $f0
|
|
swap a
|
|
srl a ; halve
|
|
ld e, a
|
|
adc a, 0; round up
|
|
swap a
|
|
or e
|
|
ld [hl], a
|
|
; update rate
|
|
ld hl, Channel1VibratoRate - Channel1
|
|
add hl, bc
|
|
; get bottom nybble
|
|
ld a, d
|
|
and $f
|
|
ld d, a
|
|
swap a
|
|
or d
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e88bd
|
|
|
|
Music_SlidePitchTo: ; e88bd
|
|
; set the target for pitch wheel
|
|
; params: 2
|
|
; note duration
|
|
; target note
|
|
call GetMusicByte
|
|
ld [wCurNoteDuration], a
|
|
|
|
call GetMusicByte
|
|
; pitch in e
|
|
ld d, a
|
|
and $f
|
|
ld e, a
|
|
|
|
; octave in d
|
|
ld a, d
|
|
swap a
|
|
and $f
|
|
ld d, a
|
|
call GetFrequency
|
|
ld hl, Channel1PitchWheelTarget - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
ld hl, Channel1PitchWheelTarget + 1 - Channel1
|
|
add hl, bc
|
|
ld [hl], d
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_PITCH_WHEEL, [hl]
|
|
ret
|
|
|
|
; e88e4
|
|
|
|
Music_Tone: ; e88e4
|
|
; tone
|
|
; params: 1 (dw)
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_CRY_PITCH, [hl]
|
|
ld hl, Channel1CryPitch + 1 - Channel1
|
|
add hl, bc
|
|
call GetMusicByte
|
|
ld [hld], a
|
|
call GetMusicByte
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e88f7
|
|
|
|
MusicE7: ; e88f7
|
|
; unused
|
|
; params: 1
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_UNKN_0E, [hl]
|
|
call GetMusicByte
|
|
ld hl, Channel1Field0x29 - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e8906
|
|
|
|
Music_SoundDuty: ; e8906
|
|
; sequence of 4 duty cycles to be looped
|
|
; params: 1 (4 2-bit duty cycle arguments)
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_DUTY, [hl] ; duty cycle
|
|
; sound duty sequence
|
|
call GetMusicByte
|
|
rrca
|
|
rrca
|
|
ld hl, Channel1SFXDutyLoop - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
; update duty cycle
|
|
and $c0 ; only uses top 2 bits
|
|
ld hl, Channel1DutyCycle - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e891e
|
|
|
|
MusicE8: ; e891e
|
|
; unused
|
|
; params: 1
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_UNKN_0D, [hl]
|
|
call GetMusicByte
|
|
ld hl, Channel1Field0x2a - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e892d
|
|
|
|
Music_ToggleSFX: ; e892d
|
|
; toggle something
|
|
; params: none
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_SFX, [hl]
|
|
jr z, .on
|
|
res SOUND_SFX, [hl]
|
|
ret
|
|
|
|
.on
|
|
set SOUND_SFX, [hl]
|
|
ret
|
|
|
|
; e893b
|
|
|
|
Music_ToggleNoise: ; e893b
|
|
; toggle music noise sampling
|
|
; can't be used as a straight toggle since the param is not read from on->off
|
|
; params:
|
|
; noise on: 1
|
|
; noise off: 0
|
|
; check if noise sampling is on
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_NOISE, [hl]
|
|
jr z, .on
|
|
; turn noise sampling off
|
|
res SOUND_NOISE, [hl]
|
|
ret
|
|
|
|
.on
|
|
; turn noise sampling on
|
|
set SOUND_NOISE, [hl]
|
|
call GetMusicByte
|
|
ld [MusicNoiseSampleSet], a
|
|
ret
|
|
|
|
; e894f
|
|
|
|
Music_SFXToggleNoise: ; e894f
|
|
; toggle sfx noise sampling
|
|
; params:
|
|
; on: 1
|
|
; off: 0
|
|
; check if noise sampling is on
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
bit SOUND_NOISE, [hl]
|
|
jr z, .on
|
|
; turn noise sampling off
|
|
res SOUND_NOISE, [hl]
|
|
ret
|
|
|
|
.on
|
|
; turn noise sampling on
|
|
set SOUND_NOISE, [hl]
|
|
call GetMusicByte
|
|
ld [SFXNoiseSampleSet], a
|
|
ret
|
|
|
|
; e8963
|
|
|
|
Music_NoteType: ; e8963
|
|
; note length
|
|
; # frames per 16th note
|
|
; intensity: see Music_Intensity
|
|
; params: 2
|
|
; note length
|
|
call GetMusicByte
|
|
ld hl, Channel1NoteLength - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ld a, [CurChannel]
|
|
and $3
|
|
cp CHAN4 ; CHAN8 & $3
|
|
ret z
|
|
; intensity
|
|
call Music_Intensity
|
|
ret
|
|
|
|
; e8977
|
|
|
|
Music_SoundStatus: ; e8977
|
|
; update sound status
|
|
; params: 1
|
|
call GetMusicByte
|
|
ld [SoundInput], a
|
|
ld hl, Channel1NoteFlags - Channel1
|
|
add hl, bc
|
|
set NOTE_UNKN_3, [hl]
|
|
ret
|
|
|
|
; e8984
|
|
|
|
Music_DutyCycle: ; e8984
|
|
; duty cycle
|
|
; params: 1
|
|
call GetMusicByte
|
|
rrca
|
|
rrca
|
|
and $c0
|
|
ld hl, Channel1DutyCycle - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e8991
|
|
|
|
Music_Intensity: ; e8991
|
|
; intensity
|
|
; params: 1
|
|
; hi: pressure
|
|
; lo: velocity
|
|
call GetMusicByte
|
|
ld hl, Channel1Intensity - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e899a
|
|
|
|
Music_Tempo: ; e899a
|
|
; global tempo
|
|
; params: 2
|
|
; de: tempo
|
|
call GetMusicByte
|
|
ld d, a
|
|
call GetMusicByte
|
|
ld e, a
|
|
call SetGlobalTempo
|
|
ret
|
|
|
|
; e89a6
|
|
|
|
Music_Octave8: ; e89a6
|
|
Music_Octave7: ; e89a6
|
|
Music_Octave6: ; e89a6
|
|
Music_Octave5: ; e89a6
|
|
Music_Octave4: ; e89a6
|
|
Music_Octave3: ; e89a6
|
|
Music_Octave2: ; e89a6
|
|
Music_Octave1: ; e89a6
|
|
; set octave based on lo nybble of the command
|
|
ld hl, Channel1Octave - Channel1
|
|
add hl, bc
|
|
ld a, [CurMusicByte]
|
|
and 7
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e89b1
|
|
|
|
Music_ForceOctave: ; e89b1
|
|
; set starting octave
|
|
; this forces all notes up by the starting octave
|
|
; params: 1
|
|
call GetMusicByte
|
|
ld hl, Channel1PitchOffset - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e89ba
|
|
|
|
Music_StereoPanning: ; e89ba
|
|
; stereo panning
|
|
; params: 1
|
|
; stereo on?
|
|
ld a, [Options]
|
|
bit 5, a ; stereo
|
|
jr nz, Music_Panning
|
|
; skip param
|
|
call GetMusicByte
|
|
ret
|
|
|
|
; e89c5
|
|
|
|
Music_Panning: ; e89c5
|
|
; force panning
|
|
; params: 1
|
|
call SetLRTracks
|
|
call GetMusicByte
|
|
ld hl, Channel1Tracks - Channel1
|
|
add hl, bc
|
|
and [hl]
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e89d2
|
|
|
|
Music_Volume: ; e89d2
|
|
; set volume
|
|
; params: 1
|
|
; see Volume
|
|
; read param even if it's not used
|
|
call GetMusicByte
|
|
; is the song fading?
|
|
ld a, [MusicFade]
|
|
and a
|
|
ret nz
|
|
; reload param
|
|
ld a, [CurMusicByte]
|
|
; set volume
|
|
ld [Volume], a
|
|
ret
|
|
|
|
; e89e1
|
|
|
|
Music_TempoRelative: ; e89e1
|
|
; set global tempo to current channel tempo +- param
|
|
; params: 1 signed
|
|
call GetMusicByte
|
|
ld e, a
|
|
; check sign
|
|
cp $80
|
|
jr nc, .negative
|
|
;positive
|
|
ld d, 0
|
|
jr .ok
|
|
|
|
.negative
|
|
ld d, -1
|
|
.ok
|
|
ld hl, Channel1Tempo - Channel1
|
|
add hl, bc
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
add hl, de
|
|
ld e, l
|
|
ld d, h
|
|
call SetGlobalTempo
|
|
ret
|
|
|
|
; e89fd
|
|
|
|
Music_SFXPriorityOn: ; e89fd
|
|
; turn sfx priority on
|
|
; params: none
|
|
ld a, 1
|
|
ld [SFXPriority], a
|
|
ret
|
|
|
|
; e8a03
|
|
|
|
Music_SFXPriorityOff: ; e8a03
|
|
; turn sfx priority off
|
|
; params: none
|
|
xor a
|
|
ld [SFXPriority], a
|
|
ret
|
|
|
|
; e8a08
|
|
|
|
Music_RestartChannel: ; e8a08
|
|
; restart current channel from channel header (same bank)
|
|
; params: 2 (5)
|
|
; ll hh: pointer to new channel header
|
|
; header format: 0x yy zz
|
|
; x: channel # (0-3)
|
|
; zzyy: pointer to new music data
|
|
|
|
; update music id
|
|
ld hl, Channel1MusicID - Channel1
|
|
add hl, bc
|
|
ld a, [hli]
|
|
ld [MusicIDLo], a
|
|
ld a, [hl]
|
|
ld [MusicIDHi], a
|
|
; update music bank
|
|
ld hl, Channel1MusicBank - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [MusicBank], a
|
|
; get pointer to new channel header
|
|
call GetMusicByte
|
|
ld l, a
|
|
call GetMusicByte
|
|
ld h, a
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
push bc ; save current channel
|
|
call LoadChannel
|
|
call StartChannel
|
|
pop bc ; restore current channel
|
|
ret
|
|
|
|
; e8a30
|
|
|
|
Music_NewSong: ; e8a30
|
|
; new song
|
|
; params: 2
|
|
; de: song id
|
|
call GetMusicByte
|
|
ld e, a
|
|
call GetMusicByte
|
|
ld d, a
|
|
push bc
|
|
call _PlayMusic
|
|
pop bc
|
|
ret
|
|
|
|
; e8a3e
|
|
|
|
GetMusicByte: ; e8a3e
|
|
; returns byte from current address in a
|
|
; advances to next byte in music data
|
|
; input: bc = start of current channel
|
|
push hl
|
|
push de
|
|
; load address into de
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld a, [hli]
|
|
ld e, a
|
|
ld d, [hl]
|
|
; load bank into a
|
|
ld hl, Channel1MusicBank - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
; get byte
|
|
call _LoadMusicByte ; load data into CurMusicByte
|
|
inc de ; advance to next byte for next time this is called
|
|
; update channeldata address
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
ld a, e
|
|
ld [hli], a
|
|
ld [hl], d
|
|
; cleanup
|
|
pop de
|
|
pop hl
|
|
; store channeldata in a
|
|
ld a, [CurMusicByte]
|
|
ret
|
|
|
|
; e8a5d
|
|
|
|
GetFrequency: ; e8a5d
|
|
; generate frequency
|
|
; input:
|
|
; d: octave
|
|
; e: pitch
|
|
; output:
|
|
; de: frequency
|
|
|
|
; get octave
|
|
; get starting octave
|
|
ld hl, Channel1PitchOffset - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
swap a ; hi nybble
|
|
and $f
|
|
; add current octave
|
|
add d
|
|
push af ; we'll use this later
|
|
; get starting octave
|
|
ld hl, Channel1PitchOffset - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and $f ; lo nybble
|
|
ld l, a ; ok
|
|
ld d, 0
|
|
ld h, d
|
|
add hl, de ; add current pitch
|
|
add hl, hl ; skip 2 bytes for each
|
|
ld de, FrequencyTable
|
|
add hl, de
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; get our octave
|
|
pop af
|
|
; shift right by [7 - octave] bits
|
|
.loop
|
|
; [7 - octave] loops
|
|
cp $7
|
|
jr nc, .ok
|
|
; sra de
|
|
sra d
|
|
rr e
|
|
inc a
|
|
jr .loop
|
|
|
|
.ok
|
|
ld a, d
|
|
and $7 ; top 3 bits for frequency (11 total)
|
|
ld d, a
|
|
ret
|
|
|
|
; e8a8d
|
|
|
|
SetNoteDuration: ; e8a8d
|
|
; input: a = note duration in 16ths
|
|
; store delay units in de
|
|
inc a
|
|
ld e, a
|
|
ld d, 0
|
|
; store NoteLength in a
|
|
ld hl, Channel1NoteLength - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
; multiply NoteLength by delay units
|
|
ld l, 0; just multiply
|
|
call .Multiply
|
|
ld a, l ; % $100
|
|
; store Tempo in de
|
|
ld hl, Channel1Tempo - Channel1
|
|
add hl, bc
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; add ???? to the next result
|
|
ld hl, Channel1Field0x16 - Channel1
|
|
add hl, bc
|
|
ld l, [hl]
|
|
; multiply Tempo by last result (NoteLength * delay % $100)
|
|
call .Multiply
|
|
; copy result to de
|
|
ld e, l
|
|
ld d, h
|
|
; store result in ????
|
|
ld hl, Channel1Field0x16 - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
; store result in NoteDuration
|
|
ld hl, Channel1NoteDuration - Channel1
|
|
add hl, bc
|
|
ld [hl], d
|
|
ret
|
|
|
|
; e8ab8
|
|
|
|
.Multiply: ; e8ab8
|
|
; multiplies a and de
|
|
; adds the result to l
|
|
; stores the result in hl
|
|
ld h, 0
|
|
.loop
|
|
; halve a
|
|
srl a
|
|
; is there a remainder?
|
|
jr nc, .skip
|
|
; add it to the result
|
|
add hl, de
|
|
.skip
|
|
; add de, de
|
|
sla e
|
|
rl d
|
|
; are we done?
|
|
and a
|
|
jr nz, .loop
|
|
ret
|
|
|
|
; e8ac7
|
|
|
|
SetGlobalTempo: ; e8ac7
|
|
push bc ; save current channel
|
|
; are we dealing with music or sfx?
|
|
ld a, [CurChannel]
|
|
cp CHAN5
|
|
jr nc, .sfxchannels
|
|
ld bc, Channel1
|
|
call Tempo
|
|
ld bc, Channel2
|
|
call Tempo
|
|
ld bc, Channel3
|
|
call Tempo
|
|
ld bc, Channel4
|
|
call Tempo
|
|
jr .end
|
|
|
|
.sfxchannels
|
|
ld bc, Channel5
|
|
call Tempo
|
|
ld bc, Channel6
|
|
call Tempo
|
|
ld bc, Channel7
|
|
call Tempo
|
|
ld bc, Channel8
|
|
call Tempo
|
|
.end
|
|
pop bc ; restore current channel
|
|
ret
|
|
|
|
; e8b03
|
|
|
|
Tempo: ; e8b03
|
|
; input:
|
|
; de: note length
|
|
; update Tempo
|
|
ld hl, Channel1Tempo - Channel1
|
|
add hl, bc
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
; clear ????
|
|
xor a
|
|
ld hl, Channel1Field0x16 - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e8b11
|
|
|
|
StartChannel: ; e8b11
|
|
call SetLRTracks
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
set SOUND_CHANNEL_ON, [hl] ; turn channel on
|
|
ret
|
|
|
|
; e8b1b
|
|
|
|
SetLRTracks: ; e8b1b
|
|
; set tracks for a the current channel to default
|
|
; seems to be redundant since this is overwritten by stereo data later
|
|
push de
|
|
; store current channel in de
|
|
ld a, [CurChannel]
|
|
and $3
|
|
ld e, a
|
|
ld d, 0
|
|
; get this channel's lr tracks
|
|
call GetLRTracks
|
|
add hl, de ; de = channel 0-3
|
|
ld a, [hl]
|
|
; load lr tracks into Tracks
|
|
ld hl, Channel1Tracks - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
pop de
|
|
ret
|
|
|
|
; e8b30
|
|
|
|
_PlayMusic:: ; e8b30
|
|
; load music
|
|
call MusicOff
|
|
ld hl, MusicID
|
|
ld [hl], e ; song number
|
|
inc hl
|
|
ld [hl], d ; MusicIDHi (always $)
|
|
ld hl, Music
|
|
add hl, de ; three
|
|
add hl, de ; byte
|
|
add hl, de ; pointer
|
|
ld a, [hli]
|
|
ld [MusicBank], a
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl] ; music header address
|
|
call LoadMusicByte ; store first byte of music header in a
|
|
rlca
|
|
rlca
|
|
and $3 ; get number of channels
|
|
inc a
|
|
.loop
|
|
; start playing channels
|
|
push af
|
|
call LoadChannel
|
|
call StartChannel
|
|
pop af
|
|
dec a
|
|
jr nz, .loop
|
|
xor a
|
|
ld [wc2b5], a
|
|
ld [Channel1JumpCondition], a
|
|
ld [Channel2JumpCondition], a
|
|
ld [Channel3JumpCondition], a
|
|
ld [Channel4JumpCondition], a
|
|
ld [NoiseSampleAddressLo], a
|
|
ld [NoiseSampleAddressHi], a
|
|
ld [wNoiseSampleDelay], a
|
|
ld [MusicNoiseSampleSet], a
|
|
call MusicOn
|
|
ret
|
|
|
|
; e8b79
|
|
|
|
_PlayCryHeader:: ; e8b79
|
|
; Play cry de using parameters:
|
|
; CryPitch
|
|
; CryLength
|
|
|
|
call MusicOff
|
|
|
|
; Overload the music id with the cry id
|
|
ld hl, MusicID
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
|
|
; 3-byte pointers (bank, address)
|
|
ld hl, Cries
|
|
add hl, de
|
|
add hl, de
|
|
add hl, de
|
|
|
|
ld a, [hli]
|
|
ld [MusicBank], a
|
|
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
|
|
; Read the cry's sound header
|
|
call LoadMusicByte
|
|
; Top 2 bits contain the number of channels
|
|
rlca
|
|
rlca
|
|
and 3
|
|
|
|
; For each channel:
|
|
inc a
|
|
.loop
|
|
push af
|
|
call LoadChannel
|
|
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
set SOUND_REST, [hl]
|
|
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_CRY_PITCH, [hl]
|
|
|
|
ld hl, Channel1CryPitch - Channel1
|
|
add hl, bc
|
|
ld a, [CryPitch]
|
|
ld [hli], a
|
|
ld a, [CryPitch + 1]
|
|
ld [hl], a
|
|
|
|
; No tempo for channel 4
|
|
ld a, [CurChannel]
|
|
and 3
|
|
cp 3
|
|
jr nc, .start
|
|
|
|
; Tempo is effectively length
|
|
ld hl, Channel1Tempo - Channel1
|
|
add hl, bc
|
|
ld a, [CryLength]
|
|
ld [hli], a
|
|
ld a, [CryLength+1]
|
|
ld [hl], a
|
|
.start
|
|
call StartChannel
|
|
ld a, [wStereoPanningMask]
|
|
and a
|
|
jr z, .next
|
|
|
|
; Stereo only: Play cry from the monster's side.
|
|
; This only applies in-battle.
|
|
|
|
ld a, [Options]
|
|
bit 5, a ; stereo
|
|
jr z, .next
|
|
|
|
; [Tracks] &= [CryTracks]
|
|
ld hl, Channel1Tracks - Channel1
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, CryTracks
|
|
and [hl]
|
|
ld hl, Channel1Tracks - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
.next
|
|
pop af
|
|
dec a
|
|
jr nz, .loop
|
|
|
|
; Cries play at max volume, so we save the current volume for later.
|
|
ld a, [LastVolume]
|
|
and a
|
|
jr nz, .end
|
|
|
|
ld a, [Volume]
|
|
ld [LastVolume], a
|
|
ld a, $77
|
|
ld [Volume], a
|
|
|
|
.end
|
|
ld a, 1 ; stop playing music
|
|
ld [SFXPriority], a
|
|
call MusicOn
|
|
ret
|
|
|
|
; e8c04
|
|
|
|
_PlaySFX:: ; e8c04
|
|
; clear channels if they aren't already
|
|
call MusicOff
|
|
ld hl, Channel5Flags
|
|
bit SOUND_CHANNEL_ON, [hl] ; ch5 on?
|
|
jr z, .ch6
|
|
res SOUND_CHANNEL_ON, [hl] ; turn it off
|
|
xor a
|
|
ld [rNR11], a ; length/wavepattern = 0
|
|
ld a, $8
|
|
ld [rNR12], a ; envelope = 0
|
|
xor a
|
|
ld [rNR13], a ; frequency lo = 0
|
|
ld a, $80
|
|
ld [rNR14], a ; restart sound (freq hi = 0)
|
|
xor a
|
|
ld [SoundInput], a ; global sound off
|
|
ld [rNR10], a ; sweep = 0
|
|
.ch6
|
|
ld hl, Channel6Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr z, .ch7
|
|
res SOUND_CHANNEL_ON, [hl] ; turn it off
|
|
xor a
|
|
ld [rNR21], a ; length/wavepattern = 0
|
|
ld a, $8
|
|
ld [rNR22], a ; envelope = 0
|
|
xor a
|
|
ld [rNR23], a ; frequency lo = 0
|
|
ld a, $80
|
|
ld [rNR24], a ; restart sound (freq hi = 0)
|
|
.ch7
|
|
ld hl, Channel7Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr z, .ch8
|
|
res SOUND_CHANNEL_ON, [hl] ; turn it off
|
|
xor a
|
|
ld [rNR30], a ; sound mode #3 off
|
|
ld [rNR31], a ; length/wavepattern = 0
|
|
ld a, $8
|
|
ld [rNR32], a ; envelope = 0
|
|
xor a
|
|
ld [rNR33], a ; frequency lo = 0
|
|
ld a, $80
|
|
ld [rNR34], a ; restart sound (freq hi = 0)
|
|
.ch8
|
|
ld hl, Channel8Flags
|
|
bit SOUND_CHANNEL_ON, [hl]
|
|
jr z, .chscleared
|
|
res SOUND_CHANNEL_ON, [hl] ; turn it off
|
|
xor a
|
|
ld [rNR41], a ; length/wavepattern = 0
|
|
ld a, $8
|
|
ld [rNR42], a ; envelope = 0
|
|
xor a
|
|
ld [rNR43], a ; frequency lo = 0
|
|
ld a, $80
|
|
ld [rNR44], a ; restart sound (freq hi = 0)
|
|
xor a
|
|
ld [NoiseSampleAddressLo], a
|
|
ld [NoiseSampleAddressHi], a
|
|
.chscleared
|
|
; start reading sfx header for # chs
|
|
ld hl, MusicID
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ld hl, SFX
|
|
add hl, de ; three
|
|
add hl, de ; byte
|
|
add hl, de ; pointers
|
|
; get bank
|
|
ld a, [hli]
|
|
ld [MusicBank], a
|
|
; get address
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
; get # channels
|
|
call LoadMusicByte
|
|
rlca ; top 2
|
|
rlca ; bits
|
|
and $3
|
|
inc a ; # channels -> # loops
|
|
.startchannels
|
|
push af
|
|
call LoadChannel ; bc = current channel
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
set SOUND_SFX, [hl]
|
|
call StartChannel
|
|
pop af
|
|
dec a
|
|
jr nz, .startchannels
|
|
call MusicOn
|
|
xor a
|
|
ld [SFXPriority], a
|
|
ret
|
|
|
|
; e8ca6
|
|
|
|
PlayStereoSFX:: ; e8ca6
|
|
; play sfx de
|
|
|
|
call MusicOff
|
|
|
|
; standard procedure if stereo's off
|
|
ld a, [Options]
|
|
bit 5, a
|
|
jp z, _PlaySFX
|
|
|
|
; else, let's go ahead with this
|
|
ld hl, MusicID
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
|
|
; get sfx ptr
|
|
ld hl, SFX
|
|
add hl, de
|
|
add hl, de
|
|
add hl, de
|
|
|
|
; bank
|
|
ld a, [hli]
|
|
ld [MusicBank], a
|
|
; address
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
|
|
; bit 2-3
|
|
call LoadMusicByte
|
|
rlca
|
|
rlca
|
|
and 3 ; ch1-4
|
|
inc a
|
|
|
|
.loop
|
|
push af
|
|
call LoadChannel
|
|
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
set SOUND_SFX, [hl]
|
|
|
|
push de
|
|
; get tracks for this channel
|
|
ld a, [CurChannel]
|
|
and 3 ; ch1-4
|
|
ld e, a
|
|
ld d, 0
|
|
call GetLRTracks
|
|
add hl, de
|
|
ld a, [hl]
|
|
ld hl, wStereoPanningMask
|
|
and [hl]
|
|
|
|
ld hl, Channel1Tracks - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, Channel1Field0x30 - Channel1 ; $c131 - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld a, [CryTracks]
|
|
cp 2 ; ch 1-2
|
|
jr c, .skip
|
|
|
|
; ch3-4
|
|
ld a, [wSFXDuration]
|
|
|
|
ld hl, Channel1Field0x2e - Channel1 ; $c12f - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, Channel1Field0x2f - Channel1 ; $c130 - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, Channel1Flags2 - Channel1
|
|
add hl, bc
|
|
set SOUND_UNKN_0F, [hl]
|
|
|
|
.skip
|
|
pop de
|
|
|
|
; turn channel on
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
set SOUND_CHANNEL_ON, [hl] ; on
|
|
|
|
; done?
|
|
pop af
|
|
dec a
|
|
jr nz, .loop
|
|
|
|
; we're done
|
|
call MusicOn
|
|
ret
|
|
|
|
; e8d1b
|
|
|
|
LoadChannel: ; e8d1b
|
|
; prep channel for use
|
|
; input:
|
|
; de:
|
|
; get pointer to current channel
|
|
call LoadMusicByte
|
|
inc de
|
|
and $7 ; bit 0-2 (current channel)
|
|
ld [CurChannel], a
|
|
ld c, a
|
|
ld b, 0
|
|
ld hl, ChannelPointers
|
|
add hl, bc
|
|
add hl, bc
|
|
ld c, [hl]
|
|
inc hl
|
|
ld b, [hl] ; bc = channel pointer
|
|
ld hl, Channel1Flags - Channel1
|
|
add hl, bc
|
|
res SOUND_CHANNEL_ON, [hl] ; channel off
|
|
call ChannelInit
|
|
; load music pointer
|
|
ld hl, Channel1MusicAddress - Channel1
|
|
add hl, bc
|
|
call LoadMusicByte
|
|
ld [hli], a
|
|
inc de
|
|
call LoadMusicByte
|
|
ld [hl], a
|
|
inc de
|
|
; load music id
|
|
ld hl, Channel1MusicID - Channel1
|
|
add hl, bc
|
|
ld a, [MusicIDLo]
|
|
ld [hli], a
|
|
ld a, [MusicIDHi]
|
|
ld [hl], a
|
|
; load music bank
|
|
ld hl, Channel1MusicBank - Channel1
|
|
add hl, bc
|
|
ld a, [MusicBank]
|
|
ld [hl], a
|
|
ret
|
|
|
|
; e8d5b
|
|
|
|
ChannelInit: ; e8d5b
|
|
; make sure channel is cleared
|
|
; set default tempo and note length in case nothing is loaded
|
|
; input:
|
|
; bc = channel struct pointer
|
|
push de
|
|
xor a
|
|
; get channel struct location and length
|
|
ld hl, Channel1MusicID - Channel1 ; start
|
|
add hl, bc
|
|
ld e, Channel2 - Channel1 ; channel struct length
|
|
; clear channel
|
|
.loop
|
|
ld [hli], a
|
|
dec e
|
|
jr nz, .loop
|
|
; set tempo to default ($100)
|
|
ld hl, Channel1Tempo - Channel1
|
|
add hl, bc
|
|
xor a
|
|
ld [hli], a
|
|
inc a
|
|
ld [hl], a
|
|
; set note length to default ($1) (fast)
|
|
ld hl, Channel1NoteLength - Channel1
|
|
add hl, bc
|
|
ld [hl], a
|
|
pop de
|
|
ret
|
|
|
|
; e8d76
|
|
|
|
LoadMusicByte:: ; e8d76
|
|
; input:
|
|
; de = current music address
|
|
; output:
|
|
; a = CurMusicByte
|
|
ld a, [MusicBank]
|
|
call _LoadMusicByte
|
|
ld a, [CurMusicByte]
|
|
ret
|
|
|
|
; e8d80
|
|
|
|
FrequencyTable: ; e8d80
|
|
dw 0 ; __
|
|
dw $f82c ; C_
|
|
dw $f89d ; C#
|
|
dw $f907 ; D_
|
|
dw $f96b ; D#
|
|
dw $f9ca ; E_
|
|
dw $fa23 ; F_
|
|
dw $fa77 ; F#
|
|
dw $fac7 ; G_
|
|
dw $fb12 ; G#
|
|
dw $fb58 ; A_
|
|
dw $fb9b ; A#
|
|
dw $fbda ; B_
|
|
dw $fc16 ; C_
|
|
dw $fc4e ; C#
|
|
dw $fc83 ; D_
|
|
dw $fcb5 ; D#
|
|
dw $fce5 ; E_
|
|
dw $fd11 ; F_
|
|
dw $fd3b ; F#
|
|
dw $fd63 ; G_
|
|
dw $fd89 ; G#
|
|
dw $fdac ; A_
|
|
dw $fdcd ; A#
|
|
dw $fded ; B_
|
|
; e8db2
|
|
|
|
WaveSamples: ; e8db2
|
|
; these are streams of 32 4-bit values used as wavepatterns
|
|
; nothing interesting here!
|
|
dn 0, 2, 4, 6, 8, 10, 12, 14, 15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 1, 1
|
|
dn 0, 2, 4, 6, 8, 10, 12, 14, 14, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1
|
|
dn 1, 3, 6, 9, 11, 13, 14, 14, 14, 14, 15, 15, 15, 15, 14, 13, 13, 14, 15, 15, 15, 15, 14, 14, 14, 14, 13, 11, 9, 6, 3, 1
|
|
dn 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 15, 14, 13, 14, 15, 15, 14, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
|
dn 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 14, 15, 7, 7, 15, 14, 14, 13, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
|
dn 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 2, 2, 1, 1, 15, 15, 14, 14, 12, 12, 10, 10, 8, 8, 10, 10, 12, 12, 14, 14
|
|
dn 0, 2, 4, 6, 8, 10, 12, 14, 12, 11, 10, 9, 8, 7, 6, 5, 15, 15, 15, 14, 14, 13, 13, 12, 4, 4, 3, 3, 2, 2, 1, 1
|
|
dn 12, 0, 10, 9, 8, 7, 15, 5, 15, 15, 15, 14, 14, 13, 13, 12, 4, 4, 3, 3, 2, 2, 15, 1, 0, 2, 4, 6, 8, 10, 12, 14
|
|
dn 4, 4, 3, 3, 2, 2, 1, 15, 0, 0, 4, 6, 8, 10, 12, 14, 15, 8, 15, 14, 14, 13, 13, 12, 12, 11, 10, 9, 8, 7, 6, 5
|
|
dn 1, 1, 0, 0, 0, 0, 0, 8, 0, 0, 1, 3, 5, 7, 9, 10, 11, 4, 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1
|
|
; e8e52
|
|
|
|
Drumkits: ; e8e52
|
|
dw Drumkit0
|
|
dw Drumkit1
|
|
dw Drumkit2
|
|
dw Drumkit3
|
|
dw Drumkit4
|
|
dw Drumkit5
|
|
; e8e5e
|
|
|
|
Drumkit0: ; e8e5e
|
|
dw Drum00 ; rest
|
|
dw Snare1 ; c
|
|
dw Snare2 ; c#
|
|
dw Snare3 ; d
|
|
dw Snare4 ; d#
|
|
dw Drum05 ; e
|
|
dw Triangle1 ; f
|
|
dw Triangle2 ; f#
|
|
dw HiHat1 ; g
|
|
dw Snare5 ; g#
|
|
dw Snare6 ; a
|
|
dw Snare7 ; a#
|
|
dw HiHat2 ; b
|
|
Drumkit1: ; e8e78
|
|
dw Drum00
|
|
dw HiHat1
|
|
dw Snare5
|
|
dw Snare6
|
|
dw Snare7
|
|
dw HiHat2
|
|
dw HiHat3
|
|
dw Snare8
|
|
dw Triangle3
|
|
dw Triangle4
|
|
dw Snare9
|
|
dw Snare10
|
|
dw Snare11
|
|
Drumkit2: ; e8e92
|
|
dw Drum00
|
|
dw Snare1
|
|
dw Snare9
|
|
dw Snare10
|
|
dw Snare11
|
|
dw Drum05
|
|
dw Triangle1
|
|
dw Triangle2
|
|
dw HiHat1
|
|
dw Snare5
|
|
dw Snare6
|
|
dw Snare7
|
|
dw HiHat2
|
|
Drumkit3: ; e8eac
|
|
dw Drum21
|
|
dw Snare12
|
|
dw Snare13
|
|
dw Snare14
|
|
dw Kick1
|
|
dw Triangle5
|
|
dw Drum20
|
|
dw Drum27
|
|
dw Drum28
|
|
dw Drum29
|
|
dw Drum21
|
|
dw Kick2
|
|
dw Crash2
|
|
Drumkit4: ; e8ec6
|
|
dw Drum21
|
|
dw Drum20
|
|
dw Snare13
|
|
dw Snare14
|
|
dw Kick1
|
|
dw Drum33
|
|
dw Triangle5
|
|
dw Drum35
|
|
dw Drum31
|
|
dw Drum32
|
|
dw Drum36
|
|
dw Kick2
|
|
dw Crash1
|
|
Drumkit5: ; e8ee0
|
|
dw Drum00
|
|
dw Snare9
|
|
dw Snare10
|
|
dw Snare11
|
|
dw Drum27
|
|
dw Drum28
|
|
dw Drum29
|
|
dw Drum05
|
|
dw Triangle1
|
|
dw Crash1
|
|
dw Snare14
|
|
dw Snare13
|
|
dw Kick2
|
|
; e8efa
|
|
|
|
Drum00: ; e8efa
|
|
; unused
|
|
noise C#, 1, $11, $00
|
|
endchannel
|
|
; e8efe
|
|
|
|
Snare1: ; e8efe
|
|
noise C#, 1, $c1, $33
|
|
endchannel
|
|
; e8f02
|
|
|
|
Snare2: ; e8f02
|
|
noise C#, 1, $b1, $33
|
|
endchannel
|
|
; e8f06
|
|
|
|
Snare3: ; e8f06
|
|
noise C#, 1, $a1, $33
|
|
endchannel
|
|
; e8f0a
|
|
|
|
Snare4: ; e8f0a
|
|
noise C#, 1, $81, $33
|
|
endchannel
|
|
; e8f0e
|
|
|
|
Drum05: ; e8f0e
|
|
noise C#, 8, $84, $37
|
|
noise C#, 7, $84, $36
|
|
noise C#, 6, $83, $35
|
|
noise C#, 5, $83, $34
|
|
noise C#, 4, $82, $33
|
|
noise C#, 3, $81, $32
|
|
endchannel
|
|
; e8f21
|
|
|
|
Triangle1: ; e8f21
|
|
noise C#, 1, $51, $2a
|
|
endchannel
|
|
; e8f25
|
|
|
|
Triangle2: ; e8f25
|
|
noise C#, 2, $41, $2b
|
|
noise C#, 1, $61, $2a
|
|
endchannel
|
|
; e8f2c
|
|
|
|
HiHat1: ; e8f2c
|
|
noise C#, 1, $81, $10
|
|
endchannel
|
|
; e8f30
|
|
|
|
Snare5: ; e8f30
|
|
noise C#, 1, $82, $23
|
|
endchannel
|
|
; e8f34
|
|
|
|
Snare6: ; e8f34
|
|
noise C#, 1, $82, $25
|
|
endchannel
|
|
; e8f38
|
|
|
|
Snare7: ; e8f38
|
|
noise C#, 1, $82, $26
|
|
endchannel
|
|
; e8f3c
|
|
|
|
HiHat2: ; e8f3c
|
|
noise C#, 1, $a1, $10
|
|
endchannel
|
|
; e8f40
|
|
|
|
HiHat3: ; e8f40
|
|
noise C#, 1, $a2, $11
|
|
endchannel
|
|
; e8f44
|
|
|
|
Snare8: ; e8f44
|
|
noise C#, 1, $a2, $50
|
|
endchannel
|
|
; e8f48
|
|
|
|
Triangle3: ; e8f48
|
|
noise C#, 1, $a1, $18
|
|
noise C#, 1, $31, $33
|
|
endchannel
|
|
; e8f4f
|
|
|
|
Triangle4: ; e8f4f
|
|
noise C#, 3, $91, $28
|
|
noise C#, 1, $71, $18
|
|
endchannel
|
|
; e8f56
|
|
|
|
Snare9: ; e8f56
|
|
noise C#, 1, $91, $22
|
|
endchannel
|
|
; e8f5a
|
|
|
|
Snare10: ; e8f5a
|
|
noise C#, 1, $71, $22
|
|
endchannel
|
|
; e8f5e
|
|
|
|
Snare11: ; e8f5e
|
|
noise C#, 1, $61, $22
|
|
endchannel
|
|
; e8f62
|
|
|
|
Drum20: ; e8f62
|
|
noise C#, 1, $11, $11
|
|
endchannel
|
|
; e8f66
|
|
|
|
Drum21: ; e8f66
|
|
endchannel
|
|
; e8f67
|
|
|
|
Snare12: ; e8f67
|
|
noise C#, 1, $91, $33
|
|
endchannel
|
|
; e8f6b
|
|
|
|
Snare13: ; e8f6b
|
|
noise C#, 1, $51, $32
|
|
endchannel
|
|
; e8f6f
|
|
|
|
Snare14: ; e8f6f
|
|
noise C#, 1, $81, $31
|
|
endchannel
|
|
; e8f73
|
|
|
|
Kick1: ; e8f73
|
|
noise C#, 1, $88, $6b
|
|
noise C#, 1, $71, $00
|
|
endchannel
|
|
; e8f7a
|
|
|
|
Triangle5: ; e8f7a
|
|
noise D_, 1, $91, $18
|
|
endchannel
|
|
; e8f7e
|
|
|
|
Drum27: ; e8f7e
|
|
noise C#, 8, $92, $10
|
|
endchannel
|
|
; e8f82
|
|
|
|
Drum28: ; e8f82
|
|
noise D_, 4, $91, $00
|
|
noise D_, 4, $11, $00
|
|
endchannel
|
|
; e8f89
|
|
|
|
Drum29: ; e8f89
|
|
noise D_, 4, $91, $11
|
|
noise D_, 4, $11, $00
|
|
endchannel
|
|
; e8f90
|
|
|
|
Crash1: ; e8f90
|
|
noise D_, 4, $88, $15
|
|
noise C#, 1, $65, $12
|
|
endchannel
|
|
; e8f97
|
|
|
|
Drum31: ; e8f97
|
|
noise D_, 4, $51, $21
|
|
noise D_, 4, $11, $11
|
|
endchannel
|
|
; e8f9e
|
|
|
|
Drum32: ; e8f9e
|
|
noise D_, 4, $51, $50
|
|
noise D_, 4, $11, $11
|
|
endchannel
|
|
; e8fa5
|
|
|
|
Drum33: ; e8fa5
|
|
noise C#, 1, $a1, $31
|
|
endchannel
|
|
; e8fa9
|
|
|
|
Crash2: ; e8fa9
|
|
noise C#, 1, $84, $12
|
|
endchannel
|
|
; e8fad
|
|
|
|
Drum35: ; e8fad
|
|
noise D_, 4, $81, $00
|
|
noise D_, 4, $11, $00
|
|
endchannel
|
|
; e8fb4
|
|
|
|
Drum36: ; e8fb4
|
|
noise D_, 4, $81, $21
|
|
noise D_, 4, $11, $11
|
|
endchannel
|
|
; e8fbb
|
|
|
|
Kick2: ; e8fbb
|
|
noise C#, 1, $a8, $6b
|
|
noise C#, 1, $71, $00
|
|
endchannel
|
|
; e8fc2
|
|
|
|
GetLRTracks: ; e8fc2
|
|
; gets the default sound l/r channels
|
|
; stores mono/stereo table in hl
|
|
ld a, [Options]
|
|
bit 5, a ; stereo
|
|
; made redundant, could have had a purpose in gold
|
|
jr nz, .stereo
|
|
ld hl, MonoTracks
|
|
ret
|
|
|
|
.stereo
|
|
ld hl, StereoTracks
|
|
ret
|
|
|
|
; e8fd1
|
|
|
|
MonoTracks: ; e8fd1
|
|
; bit corresponds to track #
|
|
; hi: left channel
|
|
; lo: right channel
|
|
db $11, $22, $44, $88
|
|
; e8fd5
|
|
|
|
StereoTracks: ; e8fd5
|
|
; made redundant
|
|
; seems to be modified on a per-song basis
|
|
db $11, $22, $44, $88
|
|
; e8fd9
|
|
|
|
ChannelPointers: ; e8fd9
|
|
; music channels
|
|
dw Channel1
|
|
dw Channel2
|
|
dw Channel3
|
|
dw Channel4
|
|
; sfx channels
|
|
dw Channel5
|
|
dw Channel6
|
|
dw Channel7
|
|
dw Channel8
|
|
; e8fe9
|
|
|
|
ClearChannels:: ; e8fe9
|
|
; runs ClearChannel for all 4 channels
|
|
; doesn't seem to be used, but functionally identical to MapSetup_Sound_Off
|
|
ld hl, rNR50
|
|
xor a
|
|
ld [hli], a
|
|
ld [hli], a
|
|
ld a, $80
|
|
ld [hli], a
|
|
ld hl, rNR10
|
|
ld e, $4
|
|
.loop
|
|
call ClearChannel
|
|
dec e
|
|
jr nz, .loop
|
|
ret
|
|
|
|
; e8ffe
|
|
|
|
ClearChannel: ; e8ffe
|
|
; input: hl = beginning hw sound register (rNR10, rNR20, rNR30, rNR40)
|
|
; output: 00 00 80 00 80
|
|
|
|
; sound channel 1 2 3 4
|
|
xor a
|
|
ld [hli], a ; rNR10, rNR20, rNR30, rNR40 ; sweep = 0
|
|
|
|
ld [hli], a ; rNR11, rNR21, rNR31, rNR41 ; length/wavepattern = 0
|
|
ld a, $8
|
|
ld [hli], a ; rNR12, rNR22, rNR32, rNR42 ; envelope = 0
|
|
xor a
|
|
ld [hli], a ; rNR13, rNR23, rNR33, rNR43 ; frequency lo = 0
|
|
ld a, $80
|
|
ld [hli], a ; rNR14, rNR24, rNR34, rNR44 ; restart sound (freq hi = 0)
|
|
ret
|
|
|
|
; e900a
|