Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pret
GitHub Repository: pret/pokered
Path: blob/master/audio/engine_1.asm
1270 views
1
; The first of three duplicated sound engines.
2
3
Audio1_UpdateMusic::
4
ld c, CHAN1
5
.loop
6
ld b, 0
7
ld hl, wChannelSoundIDs
8
add hl, bc
9
ld a, [hl]
10
and a
11
jr z, .nextChannel
12
ld a, c
13
cp CHAN5
14
jr nc, .applyAffects ; if sfx channel
15
ld a, [wMuteAudioAndPauseMusic]
16
and a
17
jr z, .applyAffects
18
bit BIT_MUTE_AUDIO, a
19
jr nz, .nextChannel
20
set BIT_MUTE_AUDIO, a
21
ld [wMuteAudioAndPauseMusic], a
22
xor a ; disable all channels' output
23
ldh [rAUDTERM], a
24
ldh [rAUD3ENA], a
25
ld a, AUD3ENA_ON
26
ldh [rAUD3ENA], a
27
jr .nextChannel
28
.applyAffects
29
call Audio1_ApplyMusicAffects
30
.nextChannel
31
ld a, c
32
inc c ; inc channel number
33
cp CHAN8
34
jr nz, .loop
35
ret
36
37
; this routine checks flags for music effects currently applied
38
; to the channel and calls certain functions based on flags.
39
Audio1_ApplyMusicAffects:
40
ld b, $0
41
ld hl, wChannelNoteDelayCounters ; delay until next note
42
add hl, bc
43
ld a, [hl]
44
cp 1 ; if the delay is 1, play next note
45
jp z, Audio1_PlayNextNote
46
dec a ; otherwise, decrease the delay timer
47
ld [hl], a
48
ld a, c
49
cp CHAN5
50
jr nc, .startChecks ; if a sfx channel
51
ld hl, wChannelSoundIDs + CHAN5
52
add hl, bc
53
ld a, [hl]
54
and a
55
jr z, .startChecks
56
ret
57
.startChecks
58
ld hl, wChannelFlags1
59
add hl, bc
60
bit BIT_ROTATE_DUTY_CYCLE, [hl]
61
jr z, .checkForExecuteMusic
62
call Audio1_ApplyDutyCyclePattern
63
.checkForExecuteMusic
64
ld b, 0
65
ld hl, wChannelFlags2
66
add hl, bc
67
bit BIT_EXECUTE_MUSIC, [hl]
68
jr nz, .checkForPitchSlide
69
ld hl, wChannelFlags1
70
add hl, bc
71
bit BIT_NOISE_OR_SFX, [hl]
72
jr nz, .skipPitchSlideVibrato
73
.checkForPitchSlide
74
ld hl, wChannelFlags1
75
add hl, bc
76
bit BIT_PITCH_SLIDE_ON, [hl]
77
jr z, .checkVibratoDelay
78
jp Audio1_ApplyPitchSlide
79
.checkVibratoDelay
80
ld hl, wChannelVibratoDelayCounters
81
add hl, bc
82
ld a, [hl]
83
and a ; check if delay is over
84
jr z, .checkForVibrato
85
dec [hl] ; otherwise, dec delay
86
.skipPitchSlideVibrato
87
ret
88
.checkForVibrato
89
ld hl, wChannelVibratoExtents
90
add hl, bc
91
ld a, [hl]
92
and a
93
jr nz, .vibrato
94
ret ; no vibrato
95
.vibrato
96
ld d, a
97
ld hl, wChannelVibratoRates
98
add hl, bc
99
ld a, [hl]
100
and $f
101
and a
102
jr z, .applyVibrato
103
dec [hl] ; decrement counter
104
ret
105
.applyVibrato
106
ld a, [hl]
107
swap [hl]
108
or [hl]
109
ld [hl], a ; reload the counter
110
ld hl, wChannelFrequencyLowBytes
111
add hl, bc
112
ld e, [hl] ; get note pitch
113
ld hl, wChannelFlags1
114
add hl, bc
115
; This is the only code that sets/resets the vibrato direction bit, so it
116
; continuously alternates which path it takes.
117
bit BIT_VIBRATO_DIRECTION, [hl]
118
jr z, .unset
119
res BIT_VIBRATO_DIRECTION, [hl]
120
ld a, d
121
and $f
122
ld d, a
123
ld a, e
124
sub d
125
jr nc, .noCarry
126
ld a, 0
127
.noCarry
128
jr .done
129
.unset
130
set BIT_VIBRATO_DIRECTION, [hl]
131
ld a, d
132
and $f0
133
swap a
134
add e
135
jr nc, .done
136
ld a, $ff
137
.done
138
ld d, a
139
ld b, REG_FREQUENCY_LO
140
call Audio1_GetRegisterPointer
141
ld [hl], d
142
ret
143
144
; this routine executes all music commands that take up no time,
145
; like tempo changes, duty cycle changes etc. and doesn't return
146
; until the first note is reached
147
Audio1_PlayNextNote:
148
; reload the vibrato delay counter
149
ld hl, wChannelVibratoDelayCounterReloadValues
150
add hl, bc
151
ld a, [hl]
152
ld hl, wChannelVibratoDelayCounters
153
add hl, bc
154
ld [hl], a
155
156
ld hl, wChannelFlags1
157
add hl, bc
158
res BIT_PITCH_SLIDE_ON, [hl]
159
res BIT_PITCH_SLIDE_DECREASING, [hl]
160
call Audio1_sound_ret
161
ret
162
163
Audio1_sound_ret:
164
call Audio1_GetNextMusicByte
165
ld d, a
166
cp sound_ret_cmd
167
jp nz, Audio1_sound_call
168
ld b, 0
169
ld hl, wChannelFlags1
170
add hl, bc
171
bit BIT_SOUND_CALL, [hl]
172
jr nz, .returnFromCall
173
ld a, c
174
cp CHAN4
175
jr nc, .noiseOrSfxChannel
176
jr .disableChannelOutput
177
.noiseOrSfxChannel
178
res BIT_NOISE_OR_SFX, [hl]
179
ld hl, wChannelFlags2
180
add hl, bc
181
res BIT_EXECUTE_MUSIC, [hl]
182
cp CHAN7
183
jr nz, .skipSfxChannel3
184
; restart hardware channel 3 (wave channel) output
185
ld a, AUD3ENA_OFF
186
ldh [rAUD3ENA], a
187
ld a, AUD3ENA_ON
188
ldh [rAUD3ENA], a
189
.skipSfxChannel3
190
jr nz, .dontDisable
191
ld a, [wDisableChannelOutputWhenSfxEnds]
192
and a
193
jr z, .dontDisable
194
xor a
195
ld [wDisableChannelOutputWhenSfxEnds], a
196
jr .disableChannelOutput
197
.dontDisable
198
jr .afterDisable
199
.returnFromCall
200
res BIT_SOUND_CALL, [hl]
201
ld d, $0
202
ld a, c
203
add a
204
ld e, a
205
ld hl, wChannelCommandPointers
206
add hl, de
207
push hl ; store current channel address
208
ld hl, wChannelReturnAddresses
209
add hl, de
210
ld e, l
211
ld d, h
212
pop hl
213
ld a, [de]
214
ld [hli], a
215
inc de
216
ld a, [de]
217
ld [hl], a ; loads channel address to return to
218
jp Audio1_sound_ret
219
.disableChannelOutput
220
ld hl, Audio1_HWChannelDisableMasks
221
add hl, bc
222
ldh a, [rAUDTERM]
223
and [hl]
224
ldh [rAUDTERM], a
225
.afterDisable
226
ld a, [wChannelSoundIDs + CHAN5]
227
cp CRY_SFX_START
228
jr nc, .maybeCry
229
jr .skipCry
230
.maybeCry
231
ld a, [wChannelSoundIDs + CHAN5]
232
cp CRY_SFX_END
233
jr z, .skipCry
234
jr c, .cry
235
jr .skipCry
236
.cry
237
ld a, c
238
cp CHAN5
239
jr z, .skipRewind
240
call Audio1_GoBackOneCommandIfCry
241
ret c
242
.skipRewind
243
ld a, [wSavedVolume]
244
ldh [rAUDVOL], a
245
xor a
246
ld [wSavedVolume], a
247
.skipCry
248
ld hl, wChannelSoundIDs
249
add hl, bc
250
ld [hl], b
251
ret
252
253
Audio1_sound_call:
254
cp sound_call_cmd
255
jp nz, Audio1_sound_loop
256
call Audio1_GetNextMusicByte
257
push af
258
call Audio1_GetNextMusicByte
259
ld d, a
260
pop af
261
ld e, a
262
push de ; store pointer
263
ld d, $0
264
ld a, c
265
add a
266
ld e, a
267
ld hl, wChannelCommandPointers
268
add hl, de
269
push hl
270
ld hl, wChannelReturnAddresses
271
add hl, de
272
ld e, l
273
ld d, h
274
pop hl
275
ld a, [hli]
276
ld [de], a
277
inc de
278
ld a, [hld]
279
ld [de], a ; copy current channel address
280
pop de
281
ld [hl], e
282
inc hl
283
ld [hl], d ; overwrite current address with pointer
284
ld b, $0
285
ld hl, wChannelFlags1
286
add hl, bc
287
set BIT_SOUND_CALL, [hl] ; set the call flag
288
jp Audio1_sound_ret
289
290
Audio1_sound_loop:
291
cp sound_loop_cmd
292
jp nz, Audio1_note_type
293
call Audio1_GetNextMusicByte
294
ld e, a
295
and a
296
jr z, .infiniteLoop
297
ld b, 0
298
ld hl, wChannelLoopCounters
299
add hl, bc
300
ld a, [hl]
301
cp e
302
jr nz, .loopAgain
303
ld a, $1 ; if no more loops to make,
304
ld [hl], a
305
call Audio1_GetNextMusicByte ; skip pointer
306
call Audio1_GetNextMusicByte
307
jp Audio1_sound_ret
308
.loopAgain ; inc loop count
309
inc a
310
ld [hl], a
311
; fall through
312
.infiniteLoop ; overwrite current address with pointer
313
call Audio1_GetNextMusicByte
314
push af
315
call Audio1_GetNextMusicByte
316
ld b, a
317
ld d, $0
318
ld a, c
319
add a
320
ld e, a
321
ld hl, wChannelCommandPointers
322
add hl, de
323
pop af
324
ld [hli], a
325
ld [hl], b
326
jp Audio1_sound_ret
327
328
Audio1_note_type:
329
and $f0
330
cp note_type_cmd
331
jp nz, Audio1_toggle_perfect_pitch
332
ld a, d
333
and $f
334
ld b, $0
335
ld hl, wChannelNoteSpeeds
336
add hl, bc
337
ld [hl], a ; store low nibble as speed
338
ld a, c
339
cp CHAN4
340
jr z, .noiseChannel ; noise channel has 0 params
341
call Audio1_GetNextMusicByte
342
ld d, a
343
ld a, c
344
cp CHAN3
345
jr z, .musicChannel3
346
cp CHAN7
347
jr nz, .skipChannel3
348
ld hl, wSfxWaveInstrument
349
jr .channel3
350
.musicChannel3
351
ld hl, wMusicWaveInstrument
352
.channel3
353
ld a, d
354
and $f
355
ld [hl], a ; store low nibble of param as wave instrument
356
ld a, d
357
and $30
358
sla a
359
ld d, a
360
; fall through
361
362
; if channel 3, store high nibble as volume
363
; else, store volume (high nibble) and fade (low nibble)
364
.skipChannel3
365
ld b, 0
366
ld hl, wChannelVolumes
367
add hl, bc
368
ld [hl], d
369
.noiseChannel
370
jp Audio1_sound_ret
371
372
Audio1_toggle_perfect_pitch:
373
ld a, d
374
cp toggle_perfect_pitch_cmd
375
jr nz, Audio1_vibrato
376
ld b, 0
377
ld hl, wChannelFlags1
378
add hl, bc
379
ld a, [hl]
380
xor 1 << BIT_PERFECT_PITCH
381
ld [hl], a
382
jp Audio1_sound_ret
383
384
Audio1_vibrato:
385
cp vibrato_cmd
386
jr nz, Audio1_pitch_slide
387
call Audio1_GetNextMusicByte
388
ld b, 0
389
ld hl, wChannelVibratoDelayCounters
390
add hl, bc
391
ld [hl], a ; store delay
392
ld hl, wChannelVibratoDelayCounterReloadValues
393
add hl, bc
394
ld [hl], a ; store delay
395
call Audio1_GetNextMusicByte
396
ld d, a
397
398
; The high nybble of the command byte is the extent of the vibrato.
399
; Let n be the extent.
400
; The upper nybble of the channel's byte in the wChannelVibratoExtents
401
; array will store the extent above the note: (n / 2) + (n % 2).
402
; The lower nybble will store the extent below the note: (n / 2).
403
; These two values add to the total extent, n.
404
and $f0
405
swap a
406
ld b, 0
407
ld hl, wChannelVibratoExtents
408
add hl, bc
409
srl a
410
ld e, a
411
adc b
412
swap a
413
or e
414
ld [hl], a
415
416
; The low nybble of the command byte is the rate of the vibrato.
417
; The high and low nybbles of the channel's byte in the wChannelVibratoRates
418
; array are both initialised to this value because the high nybble is the
419
; counter reload value and the low nybble is the counter itself, which should
420
; start at its value upon reload.
421
ld a, d
422
and $f
423
ld d, a
424
ld hl, wChannelVibratoRates
425
add hl, bc
426
swap a
427
or d
428
ld [hl], a
429
430
jp Audio1_sound_ret
431
432
Audio1_pitch_slide:
433
cp pitch_slide_cmd
434
jr nz, Audio1_duty_cycle
435
call Audio1_GetNextMusicByte
436
ld b, 0
437
ld hl, wChannelPitchSlideLengthModifiers
438
add hl, bc
439
ld [hl], a
440
call Audio1_GetNextMusicByte
441
ld d, a
442
and $f0
443
swap a
444
ld b, a
445
ld a, d
446
and $f
447
call Audio1_CalculateFrequency
448
ld b, 0
449
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
450
add hl, bc
451
ld [hl], d
452
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
453
add hl, bc
454
ld [hl], e
455
ld b, 0
456
ld hl, wChannelFlags1
457
add hl, bc
458
set BIT_PITCH_SLIDE_ON, [hl]
459
call Audio1_GetNextMusicByte
460
ld d, a
461
jp Audio1_note_length
462
463
Audio1_duty_cycle:
464
cp duty_cycle_cmd
465
jr nz, Audio1_tempo
466
call Audio1_GetNextMusicByte
467
rrca
468
rrca
469
and $c0
470
ld b, 0
471
ld hl, wChannelDutyCycles
472
add hl, bc
473
ld [hl], a ; store duty cycle
474
jp Audio1_sound_ret
475
476
Audio1_tempo:
477
cp tempo_cmd
478
jr nz, Audio1_stereo_panning
479
ld a, c
480
cp CHAN5
481
jr nc, .sfxChannel
482
call Audio1_GetNextMusicByte
483
ld [wMusicTempo], a ; store first param
484
call Audio1_GetNextMusicByte
485
ld [wMusicTempo + 1], a ; store second param
486
xor a
487
ld [wChannelNoteDelayCountersFractionalPart], a ; clear RAM
488
ld [wChannelNoteDelayCountersFractionalPart + 1], a
489
ld [wChannelNoteDelayCountersFractionalPart + 2], a
490
ld [wChannelNoteDelayCountersFractionalPart + 3], a
491
jr .musicChannelDone
492
.sfxChannel
493
call Audio1_GetNextMusicByte
494
ld [wSfxTempo], a ; store first param
495
call Audio1_GetNextMusicByte
496
ld [wSfxTempo + 1], a ; store second param
497
xor a
498
ld [wChannelNoteDelayCountersFractionalPart + 4], a ; clear RAM
499
ld [wChannelNoteDelayCountersFractionalPart + 5], a
500
ld [wChannelNoteDelayCountersFractionalPart + 6], a
501
ld [wChannelNoteDelayCountersFractionalPart + 7], a
502
.musicChannelDone
503
jp Audio1_sound_ret
504
505
Audio1_stereo_panning:
506
cp stereo_panning_cmd
507
jr nz, Audio1_unknownmusic0xef
508
call Audio1_GetNextMusicByte
509
ld [wStereoPanning], a ; store panning
510
jp Audio1_sound_ret
511
512
; this appears to never be used
513
Audio1_unknownmusic0xef:
514
cp unknownmusic0xef_cmd
515
jr nz, Audio1_duty_cycle_pattern
516
call Audio1_GetNextMusicByte
517
push bc
518
call Audio1_PlaySound
519
pop bc
520
ld a, [wDisableChannelOutputWhenSfxEnds]
521
and a
522
jr nz, .skip
523
ld a, [wChannelSoundIDs + CHAN8]
524
ld [wDisableChannelOutputWhenSfxEnds], a
525
xor a
526
ld [wChannelSoundIDs + CHAN8], a
527
.skip
528
jp Audio1_sound_ret
529
530
Audio1_duty_cycle_pattern:
531
cp duty_cycle_pattern_cmd
532
jr nz, Audio1_volume
533
call Audio1_GetNextMusicByte
534
ld b, 0
535
ld hl, wChannelDutyCyclePatterns
536
add hl, bc
537
ld [hl], a ; store full pattern
538
and %11000000
539
ld hl, wChannelDutyCycles
540
add hl, bc
541
ld [hl], a ; store first duty cycle
542
ld hl, wChannelFlags1
543
add hl, bc
544
set BIT_ROTATE_DUTY_CYCLE, [hl]
545
jp Audio1_sound_ret
546
547
Audio1_volume:
548
cp volume_cmd
549
jr nz, Audio1_execute_music
550
call Audio1_GetNextMusicByte
551
ldh [rAUDVOL], a ; store volume
552
jp Audio1_sound_ret
553
554
Audio1_execute_music:
555
cp execute_music_cmd
556
jr nz, Audio1_octave
557
ld b, $0
558
ld hl, wChannelFlags2
559
add hl, bc
560
set BIT_EXECUTE_MUSIC, [hl]
561
jp Audio1_sound_ret
562
563
Audio1_octave:
564
and $f0
565
cp octave_cmd
566
jr nz, Audio1_sfx_note
567
ld hl, wChannelOctaves
568
ld b, 0
569
add hl, bc
570
ld a, d
571
and $f
572
ld [hl], a ; store low nibble as octave
573
jp Audio1_sound_ret
574
575
; sfx_note is either square_note or noise_note depending on the channel
576
Audio1_sfx_note:
577
cp sfx_note_cmd
578
jr nz, Audio1_pitch_sweep
579
ld a, c
580
cp CHAN4 ; is this a noise or sfx channel?
581
jr c, Audio1_pitch_sweep ; no
582
ld b, 0
583
ld hl, wChannelFlags2
584
add hl, bc
585
bit BIT_EXECUTE_MUSIC, [hl] ; is execute_music being used?
586
jr nz, Audio1_pitch_sweep ; yes
587
call Audio1_note_length
588
589
; This code seems to do the same thing as what Audio1_ApplyDutyCycleAndSoundLength
590
; does below.
591
ld d, a
592
ld b, 0
593
ld hl, wChannelDutyCycles
594
add hl, bc
595
ld a, [hl]
596
or d
597
ld d, a
598
ld b, REG_DUTY_SOUND_LEN
599
call Audio1_GetRegisterPointer
600
ld [hl], d
601
602
call Audio1_GetNextMusicByte
603
ld d, a
604
ld b, REG_VOLUME_ENVELOPE
605
call Audio1_GetRegisterPointer
606
ld [hl], d
607
call Audio1_GetNextMusicByte
608
ld e, a
609
ld a, c
610
cp CHAN8
611
ld a, 0
612
jr z, .skip
613
; Channels 1 through 3 have 2 registers that control frequency, but the noise
614
; channel a single register (the polynomial counter) that controls frequency,
615
; so this command has one less byte on the noise channel.
616
push de
617
call Audio1_GetNextMusicByte
618
pop de
619
.skip
620
ld d, a
621
push de
622
call Audio1_ApplyDutyCycleAndSoundLength
623
call Audio1_EnableChannelOutput
624
pop de
625
call Audio1_ApplyWavePatternAndFrequency
626
ret
627
628
Audio1_pitch_sweep:
629
ld a, c
630
cp CHAN5
631
jr c, Audio1_note ; if not a sfx
632
ld a, d
633
cp pitch_sweep_cmd
634
jr nz, Audio1_note
635
ld b, $0
636
ld hl, wChannelFlags2
637
add hl, bc
638
bit BIT_EXECUTE_MUSIC, [hl]
639
jr nz, Audio1_note ; no
640
call Audio1_GetNextMusicByte
641
ldh [rAUD1SWEEP], a
642
jp Audio1_sound_ret
643
644
Audio1_note:
645
ld a, c
646
cp CHAN4
647
jr nz, Audio1_note_length ; if not noise channel
648
ld a, d
649
and $f0
650
cp drum_note_cmd
651
jr z, .drum_note
652
jr nc, Audio1_note_length
653
654
; this executes when on the noise channel and
655
; the command id is less than drum_note_cmd ($b0)
656
; in this case, the upper nybble is used as the noise instrument ($1-$a)
657
; and the lower nybble is the length minus 1 (0-15)
658
; however, this doesn't work for instrument #2 because the command id
659
; is captured by the noise_note command (command id $2x)
660
; this essentially acts like a drum_note command that is only 1 byte
661
; instead of 2 and can only be used with instruments 1 and 3 through 10
662
; this is unused by the game
663
swap a
664
ld b, a
665
ld a, d
666
and $f
667
ld d, a
668
ld a, b
669
push de
670
push bc
671
jr .playDnote
672
673
.drum_note
674
ld a, d
675
and $f
676
push af
677
push bc
678
call Audio1_GetNextMusicByte ; get drum_note instrument
679
.playDnote
680
ld d, a
681
ld a, [wDisableChannelOutputWhenSfxEnds]
682
and a
683
jr nz, .skipDnote
684
ld a, d
685
call Audio1_PlaySound
686
.skipDnote
687
pop bc
688
pop de
689
690
Audio1_note_length:
691
ld a, d
692
push af
693
and $f
694
inc a
695
ld b, 0
696
ld e, a ; store note length (in 16ths)
697
ld d, b
698
ld hl, wChannelNoteSpeeds
699
add hl, bc
700
ld a, [hl]
701
ld l, b
702
call Audio1_MultiplyAdd
703
ld a, c
704
cp CHAN5
705
jr nc, .sfxChannel
706
ld a, [wMusicTempo]
707
ld d, a
708
ld a, [wMusicTempo + 1]
709
ld e, a
710
jr .skip
711
.sfxChannel
712
ld d, $1
713
ld e, $0
714
cp CHAN8
715
jr z, .skip ; if noise channel
716
call Audio1_SetSfxTempo
717
ld a, [wSfxTempo]
718
ld d, a
719
ld a, [wSfxTempo + 1]
720
ld e, a
721
.skip
722
ld a, l ; a = note_length * note_speed
723
ld b, 0
724
ld hl, wChannelNoteDelayCountersFractionalPart
725
add hl, bc
726
ld l, [hl]
727
call Audio1_MultiplyAdd
728
ld e, l
729
ld d, h ; de = note_delay_frac_part + (note_length * note_speed * tempo)
730
ld hl, wChannelNoteDelayCountersFractionalPart
731
add hl, bc
732
ld [hl], e
733
ld a, d
734
ld hl, wChannelNoteDelayCounters
735
add hl, bc
736
ld [hl], a
737
ld hl, wChannelFlags2
738
add hl, bc
739
bit BIT_EXECUTE_MUSIC, [hl]
740
jr nz, Audio1_note_pitch
741
ld hl, wChannelFlags1
742
add hl, bc
743
bit BIT_NOISE_OR_SFX, [hl]
744
jr z, Audio1_note_pitch
745
pop hl
746
ret
747
748
Audio1_note_pitch:
749
pop af
750
and $f0
751
cp rest_cmd
752
jr nz, .notRest
753
ld a, c
754
cp CHAN5
755
jr nc, .next
756
; If this isn't an SFX channel, try the corresponding SFX channel.
757
ld hl, wChannelSoundIDs + CHAN5
758
add hl, bc
759
ld a, [hl]
760
and a
761
jr nz, .done
762
; fall through
763
.next
764
ld a, c
765
cp CHAN3
766
jr z, .channel3
767
cp CHAN7
768
jr nz, .notChannel3
769
.channel3
770
ld b, 0
771
ld hl, Audio1_HWChannelDisableMasks
772
add hl, bc
773
ldh a, [rAUDTERM]
774
and [hl]
775
ldh [rAUDTERM], a ; disable hardware channel 3's output
776
jr .done
777
.notChannel3
778
ld b, REG_VOLUME_ENVELOPE
779
call Audio1_GetRegisterPointer
780
ld a, $8 ; fade in sound
781
ld [hli], a
782
inc hl
783
ld a, $80 ; restart sound
784
ld [hl], a
785
.done
786
ret
787
.notRest
788
swap a
789
ld b, 0
790
ld hl, wChannelOctaves
791
add hl, bc
792
ld b, [hl]
793
call Audio1_CalculateFrequency
794
ld b, 0
795
ld hl, wChannelFlags1
796
add hl, bc
797
bit BIT_PITCH_SLIDE_ON, [hl]
798
jr z, .skipPitchSlide
799
call Audio1_InitPitchSlideVars
800
.skipPitchSlide
801
push de
802
ld a, c
803
cp CHAN5
804
jr nc, .sfxChannel ; if sfx channel
805
; If this isn't an SFX channel, try the corresponding SFX channel.
806
ld hl, wChannelSoundIDs + CHAN5
807
ld d, 0
808
ld e, a
809
add hl, de
810
ld a, [hl]
811
and a
812
jr nz, .noSfx
813
jr .sfxChannel
814
.noSfx
815
pop de
816
ret
817
.sfxChannel
818
ld b, 0
819
ld hl, wChannelVolumes
820
add hl, bc
821
ld d, [hl]
822
ld b, REG_VOLUME_ENVELOPE
823
call Audio1_GetRegisterPointer
824
ld [hl], d
825
call Audio1_ApplyDutyCycleAndSoundLength
826
call Audio1_EnableChannelOutput
827
pop de
828
ld b, $0
829
ld hl, wChannelFlags1
830
add hl, bc
831
bit BIT_PERFECT_PITCH, [hl] ; has toggle_perfect_pitch been used?
832
jr z, .skipFrequencyInc
833
inc e ; if yes, increment the frequency by 1
834
jr nc, .skipFrequencyInc ; Likely a mistake, because `inc` does not set flag C.
835
; Fortunately this does not seem to affect any notes that actually occur.
836
inc d
837
.skipFrequencyInc
838
ld hl, wChannelFrequencyLowBytes
839
add hl, bc
840
ld [hl], e
841
call Audio1_ApplyWavePatternAndFrequency
842
ret
843
844
Audio1_EnableChannelOutput:
845
ld b, 0
846
ld hl, Audio1_HWChannelEnableMasks
847
add hl, bc
848
ldh a, [rAUDTERM]
849
or [hl] ; set this channel's bits
850
ld d, a
851
ld a, c
852
cp CHAN8
853
jr z, .noiseChannelOrNoSfx
854
cp CHAN5
855
jr nc, .skip ; if sfx channel
856
; If this isn't an SFX channel, try the corresponding SFX channel.
857
ld hl, wChannelSoundIDs + CHAN5
858
add hl, bc
859
ld a, [hl]
860
and a
861
jr nz, .skip
862
.noiseChannelOrNoSfx
863
; If this is the SFX noise channel or a music channel whose corresponding
864
; SFX channel is off, apply stereo panning.
865
ld a, [wStereoPanning]
866
ld hl, Audio1_HWChannelEnableMasks
867
add hl, bc
868
and [hl]
869
ld d, a
870
ldh a, [rAUDTERM]
871
ld hl, Audio1_HWChannelDisableMasks
872
add hl, bc
873
and [hl] ; reset this channel's output bits
874
or d ; set this channel's output bits that enabled in [wStereoPanning]
875
ld d, a
876
.skip
877
ld a, d
878
ldh [rAUDTERM], a
879
ret
880
881
Audio1_ApplyDutyCycleAndSoundLength:
882
ld b, 0
883
ld hl, wChannelNoteDelayCounters ; use the note delay as sound length
884
add hl, bc
885
ld d, [hl]
886
ld a, c
887
cp CHAN3
888
jr z, .skipDuty ; if music channel 3
889
cp CHAN7
890
jr z, .skipDuty ; if sfx channel 3
891
; include duty cycle (except on channel 3 which doesn't have it)
892
ld a, d
893
and $3f
894
ld d, a
895
ld hl, wChannelDutyCycles
896
add hl, bc
897
ld a, [hl]
898
or d
899
ld d, a
900
.skipDuty
901
ld b, REG_DUTY_SOUND_LEN
902
call Audio1_GetRegisterPointer
903
ld [hl], d
904
ret
905
906
Audio1_ApplyWavePatternAndFrequency:
907
ld a, c
908
cp CHAN3
909
jr z, .channel3
910
cp CHAN7
911
jr nz, .notChannel3
912
; fall through
913
.channel3
914
push de
915
ld de, wMusicWaveInstrument
916
cp CHAN3
917
jr z, .next
918
ld de, wSfxWaveInstrument
919
.next
920
ld a, [de]
921
add a
922
ld d, 0
923
ld e, a
924
ld hl, Audio1_WavePointers
925
add hl, de
926
ld e, [hl]
927
inc hl
928
ld d, [hl]
929
ld hl, _AUD3WAVERAM
930
ld b, AUD3WAVE_SIZE - 1
931
ld a, $0 ; stop hardware channel 3
932
ldh [rAUD3ENA], a
933
.loop
934
ld a, [de]
935
inc de
936
ld [hli], a
937
ld a, b
938
dec b
939
and a
940
jr nz, .loop
941
ld a, AUD3ENA_ON ; start hardware channel 3
942
ldh [rAUD3ENA], a
943
pop de
944
.notChannel3
945
ld a, d
946
or $80 ; use counter mode (i.e. disable output when the counter reaches 0)
947
and $c7 ; zero the unused bits in the register
948
ld d, a
949
ld b, REG_FREQUENCY_LO
950
call Audio1_GetRegisterPointer
951
ld [hl], e ; store frequency low byte
952
inc hl
953
ld [hl], d ; store frequency high byte
954
call Audio1_ApplyFrequencyModifier
955
ret
956
957
Audio1_SetSfxTempo:
958
call Audio1_IsCry
959
jr nc, .notCry
960
ld d, 0
961
ld a, [wTempoModifier]
962
add $80
963
jr nc, .next
964
inc d
965
.next
966
ld [wSfxTempo + 1], a
967
ld a, d
968
ld [wSfxTempo], a
969
jr .done
970
.notCry
971
xor a
972
ld [wSfxTempo + 1], a
973
ld a, $1
974
ld [wSfxTempo], a
975
.done
976
ret
977
978
Audio1_ApplyFrequencyModifier:
979
call Audio1_IsCry
980
jr nc, .done
981
; if playing a cry, add the cry's frequency modifier
982
ld a, [wFrequencyModifier]
983
add e
984
jr nc, .noCarry
985
inc d
986
.noCarry
987
dec hl
988
ld e, a
989
ld [hl], e
990
inc hl
991
ld [hl], d
992
.done
993
ret
994
995
Audio1_GoBackOneCommandIfCry:
996
call Audio1_IsCry
997
jr nc, .done
998
ld hl, wChannelCommandPointers
999
ld e, c
1000
ld d, 0
1001
sla e
1002
rl d
1003
add hl, de
1004
ld a, [hl]
1005
sub 1
1006
ld [hl], a
1007
inc hl
1008
ld a, [hl]
1009
sbc 0
1010
ld [hl], a
1011
scf
1012
ret
1013
.done
1014
scf
1015
ccf
1016
ret
1017
1018
Audio1_IsCry:
1019
; Returns whether the currently playing audio is a cry in carry.
1020
ld a, [wChannelSoundIDs + CHAN5]
1021
cp CRY_SFX_START
1022
jr nc, .next
1023
jr .no
1024
.next
1025
cp CRY_SFX_END
1026
jr z, .no
1027
jr c, .yes
1028
.no
1029
scf
1030
ccf
1031
ret
1032
.yes
1033
scf
1034
ret
1035
1036
Audio1_ApplyPitchSlide:
1037
ld hl, wChannelFlags1
1038
add hl, bc
1039
bit BIT_PITCH_SLIDE_DECREASING, [hl]
1040
jp nz, .frequencyDecreasing
1041
; frequency increasing
1042
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1043
add hl, bc
1044
ld e, [hl]
1045
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1046
add hl, bc
1047
ld d, [hl]
1048
ld hl, wChannelPitchSlideFrequencySteps
1049
add hl, bc
1050
ld l, [hl]
1051
ld h, b
1052
add hl, de
1053
ld d, h
1054
ld e, l
1055
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
1056
add hl, bc
1057
push hl
1058
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
1059
add hl, bc
1060
ld a, [hl]
1061
pop hl
1062
add [hl]
1063
ld [hl], a
1064
ld a, 0
1065
adc e
1066
ld e, a
1067
ld a, 0
1068
adc d
1069
ld d, a
1070
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
1071
add hl, bc
1072
ld a, [hl]
1073
cp d
1074
jp c, .reachedTargetFrequency
1075
jr nz, .applyUpdatedFrequency
1076
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
1077
add hl, bc
1078
ld a, [hl]
1079
cp e
1080
jp c, .reachedTargetFrequency
1081
jr .applyUpdatedFrequency
1082
.frequencyDecreasing
1083
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1084
add hl, bc
1085
ld a, [hl]
1086
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1087
add hl, bc
1088
ld d, [hl]
1089
ld hl, wChannelPitchSlideFrequencySteps
1090
add hl, bc
1091
ld e, [hl]
1092
sub e
1093
ld e, a
1094
ld a, d
1095
sbc b
1096
ld d, a
1097
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
1098
add hl, bc
1099
ld a, [hl]
1100
add a
1101
ld [hl], a
1102
ld a, e
1103
sbc b
1104
ld e, a
1105
ld a, d
1106
sbc b
1107
ld d, a
1108
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
1109
add hl, bc
1110
ld a, d
1111
cp [hl]
1112
jr c, .reachedTargetFrequency
1113
jr nz, .applyUpdatedFrequency
1114
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
1115
add hl, bc
1116
ld a, e
1117
cp [hl]
1118
jr c, .reachedTargetFrequency
1119
.applyUpdatedFrequency
1120
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1121
add hl, bc
1122
ld [hl], e
1123
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1124
add hl, bc
1125
ld [hl], d
1126
ld b, REG_FREQUENCY_LO
1127
call Audio1_GetRegisterPointer
1128
ld a, e
1129
ld [hli], a
1130
ld [hl], d
1131
ret
1132
.reachedTargetFrequency
1133
; Turn off pitch slide when the target frequency has been reached.
1134
ld hl, wChannelFlags1
1135
add hl, bc
1136
res BIT_PITCH_SLIDE_ON, [hl]
1137
res BIT_PITCH_SLIDE_DECREASING, [hl]
1138
ret
1139
1140
Audio1_InitPitchSlideVars:
1141
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1142
add hl, bc
1143
ld [hl], d
1144
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1145
add hl, bc
1146
ld [hl], e
1147
ld hl, wChannelNoteDelayCounters
1148
add hl, bc
1149
ld a, [hl]
1150
ld hl, wChannelPitchSlideLengthModifiers
1151
add hl, bc
1152
sub [hl]
1153
jr nc, .next
1154
ld a, 1
1155
.next
1156
ld [hl], a
1157
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
1158
add hl, bc
1159
ld a, e
1160
sub [hl]
1161
ld e, a
1162
ld a, d
1163
sbc b
1164
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
1165
add hl, bc
1166
sub [hl]
1167
jr c, .targetFrequencyGreater
1168
ld d, a
1169
ld b, 0
1170
ld hl, wChannelFlags1
1171
add hl, bc
1172
set BIT_PITCH_SLIDE_DECREASING, [hl]
1173
jr .next2
1174
.targetFrequencyGreater
1175
; If the target frequency is greater, subtract the current frequency from
1176
; the target frequency to get the absolute difference.
1177
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1178
add hl, bc
1179
ld d, [hl]
1180
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1181
add hl, bc
1182
ld e, [hl]
1183
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
1184
add hl, bc
1185
ld a, [hl]
1186
sub e
1187
ld e, a
1188
1189
; Bug. Instead of borrowing from the high byte of the target frequency as it
1190
; should, it borrows from the high byte of the current frequency instead.
1191
; This means that the result will be 0x200 greater than it should be if the
1192
; low byte of the current frequency is greater than the low byte of the
1193
; target frequency.
1194
ld a, d
1195
sbc b
1196
ld d, a
1197
1198
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
1199
add hl, bc
1200
ld a, [hl]
1201
sub d
1202
ld d, a
1203
ld b, 0
1204
ld hl, wChannelFlags1
1205
add hl, bc
1206
res BIT_PITCH_SLIDE_DECREASING, [hl]
1207
1208
.next2
1209
ld hl, wChannelPitchSlideLengthModifiers
1210
add hl, bc
1211
.divideLoop
1212
inc b
1213
ld a, e
1214
sub [hl]
1215
ld e, a
1216
jr nc, .divideLoop
1217
ld a, d
1218
and a
1219
jr z, .doneDividing
1220
dec a
1221
ld d, a
1222
jr .divideLoop
1223
.doneDividing
1224
ld a, e ; a = remainder - dividend
1225
add [hl]
1226
ld d, b ; d = quotient + 1
1227
ld b, 0
1228
ld hl, wChannelPitchSlideFrequencySteps
1229
add hl, bc
1230
ld [hl], d ; store quotient + 1
1231
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
1232
add hl, bc
1233
ld [hl], a ; store remainder - dividend
1234
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
1235
add hl, bc
1236
ld [hl], a ; store remainder - dividend
1237
ret
1238
1239
Audio1_ApplyDutyCyclePattern:
1240
ld b, 0
1241
ld hl, wChannelDutyCyclePatterns
1242
add hl, bc
1243
ld a, [hl]
1244
rlca
1245
rlca
1246
ld [hl], a
1247
and $c0
1248
ld d, a
1249
ld b, REG_DUTY_SOUND_LEN
1250
call Audio1_GetRegisterPointer
1251
ld a, [hl]
1252
and $3f
1253
or d
1254
ld [hl], a
1255
ret
1256
1257
Audio1_GetNextMusicByte:
1258
ld d, 0
1259
ld a, c
1260
add a
1261
ld e, a
1262
ld hl, wChannelCommandPointers
1263
add hl, de
1264
ld a, [hli]
1265
ld e, a
1266
ld a, [hld]
1267
ld d, a
1268
ld a, [de] ; get next music command
1269
inc de
1270
ld [hl], e ; store address of next command
1271
inc hl
1272
ld [hl], d
1273
ret
1274
1275
Audio1_GetRegisterPointer:
1276
; hl = address of hardware sound register b for software channel c
1277
ld a, c
1278
ld hl, Audio1_HWChannelBaseAddresses
1279
add l
1280
jr nc, .noCarry
1281
inc h
1282
.noCarry
1283
ld l, a
1284
ld a, [hl]
1285
add b
1286
ld l, a
1287
ld h, $ff
1288
ret
1289
1290
Audio1_MultiplyAdd:
1291
; hl = l + (a * de)
1292
ld h, 0
1293
.loop
1294
srl a
1295
jr nc, .skipAdd
1296
add hl, de
1297
.skipAdd
1298
sla e
1299
rl d
1300
and a
1301
jr z, .done
1302
jr .loop
1303
.done
1304
ret
1305
1306
Audio1_CalculateFrequency:
1307
; return the frequency for note a, octave b in de
1308
ld h, 0
1309
ld l, a
1310
add hl, hl
1311
ld d, h
1312
ld e, l
1313
ld hl, Audio1_Pitches
1314
add hl, de
1315
ld e, [hl]
1316
inc hl
1317
ld d, [hl]
1318
ld a, b
1319
.loop
1320
cp 7
1321
jr z, .done
1322
sra d
1323
rr e
1324
inc a
1325
jr .loop
1326
.done
1327
ld a, 8
1328
add d
1329
ld d, a
1330
ret
1331
1332
Audio1_PlaySound::
1333
ld [wSoundID], a
1334
cp SFX_STOP_ALL_MUSIC
1335
jp z, .stopAllAudio
1336
cp MAX_SFX_ID_1
1337
jp z, .playSfx
1338
jp c, .playSfx
1339
cp $fe
1340
jr z, .playMusic
1341
jp nc, .playSfx
1342
1343
.playMusic
1344
xor a
1345
ld [wUnusedMusicByte], a
1346
ld [wDisableChannelOutputWhenSfxEnds], a
1347
ld [wMusicTempo + 1], a
1348
ld [wMusicWaveInstrument], a
1349
ld [wSfxWaveInstrument], a
1350
ld d, NUM_CHANNELS
1351
ld hl, wChannelReturnAddresses
1352
call .FillMem
1353
ld hl, wChannelCommandPointers
1354
call .FillMem
1355
ld d, NUM_MUSIC_CHANS
1356
ld hl, wChannelSoundIDs
1357
call .FillMem
1358
ld hl, wChannelFlags1
1359
call .FillMem
1360
ld hl, wChannelDutyCycles
1361
call .FillMem
1362
ld hl, wChannelDutyCyclePatterns
1363
call .FillMem
1364
ld hl, wChannelVibratoDelayCounters
1365
call .FillMem
1366
ld hl, wChannelVibratoExtents
1367
call .FillMem
1368
ld hl, wChannelVibratoRates
1369
call .FillMem
1370
ld hl, wChannelFrequencyLowBytes
1371
call .FillMem
1372
ld hl, wChannelVibratoDelayCounterReloadValues
1373
call .FillMem
1374
ld hl, wChannelFlags2
1375
call .FillMem
1376
ld hl, wChannelPitchSlideLengthModifiers
1377
call .FillMem
1378
ld hl, wChannelPitchSlideFrequencySteps
1379
call .FillMem
1380
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
1381
call .FillMem
1382
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
1383
call .FillMem
1384
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1385
call .FillMem
1386
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1387
call .FillMem
1388
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
1389
call .FillMem
1390
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
1391
call .FillMem
1392
ld a, $1
1393
ld hl, wChannelLoopCounters
1394
call .FillMem
1395
ld hl, wChannelNoteDelayCounters
1396
call .FillMem
1397
ld hl, wChannelNoteSpeeds
1398
call .FillMem
1399
ld [wMusicTempo], a
1400
ld a, $ff
1401
ld [wStereoPanning], a
1402
xor a
1403
ldh [rAUDVOL], a
1404
ld a, AUD1SWEEP_DOWN
1405
ldh [rAUD1SWEEP], a
1406
ld a, 0
1407
ldh [rAUDTERM], a
1408
xor a
1409
ldh [rAUD3ENA], a
1410
ld a, AUD3ENA_ON
1411
ldh [rAUD3ENA], a
1412
ld a, $77
1413
ldh [rAUDVOL], a
1414
jp .playSoundCommon
1415
1416
.playSfx
1417
ld l, a
1418
ld e, a
1419
ld h, 0
1420
ld d, h
1421
add hl, hl
1422
add hl, de
1423
ld de, SFX_Headers_1
1424
add hl, de
1425
ld a, h
1426
ld [wSfxHeaderPointer], a
1427
ld a, l
1428
ld [wSfxHeaderPointer + 1], a
1429
ld a, [hl]
1430
and $c0
1431
rlca
1432
rlca
1433
ld c, a
1434
.sfxChannelLoop
1435
ld d, c
1436
ld a, c
1437
add a
1438
add c
1439
ld c, a
1440
ld b, 0
1441
ld a, [wSfxHeaderPointer]
1442
ld h, a
1443
ld a, [wSfxHeaderPointer + 1]
1444
ld l, a
1445
add hl, bc
1446
ld c, d
1447
ld a, [hl]
1448
and $f
1449
ld e, a ; software channel ID
1450
ld d, 0
1451
ld hl, wChannelSoundIDs
1452
add hl, de
1453
ld a, [hl]
1454
and a
1455
jr z, .playChannel
1456
ld a, e
1457
cp CHAN8
1458
jr nz, .notNoiseChannel
1459
ld a, [wSoundID]
1460
cp NOISE_INSTRUMENTS_END
1461
jr nc, .notNoiseInstrument
1462
ret
1463
.notNoiseInstrument
1464
ld a, [hl]
1465
cp NOISE_INSTRUMENTS_END
1466
jr z, .playChannel
1467
jr c, .playChannel
1468
.notNoiseChannel
1469
ld a, [wSoundID]
1470
cp [hl]
1471
jr z, .playChannel
1472
jr c, .playChannel
1473
ret
1474
.playChannel
1475
xor a
1476
push de
1477
ld h, d
1478
ld l, e
1479
add hl, hl
1480
ld d, h
1481
ld e, l
1482
ld hl, wChannelReturnAddresses
1483
add hl, de
1484
ld [hli], a
1485
ld [hl], a
1486
ld hl, wChannelCommandPointers
1487
add hl, de
1488
ld [hli], a
1489
ld [hl], a
1490
pop de
1491
ld hl, wChannelSoundIDs
1492
add hl, de
1493
ld [hl], a
1494
ld hl, wChannelFlags1
1495
add hl, de
1496
ld [hl], a
1497
ld hl, wChannelDutyCycles
1498
add hl, de
1499
ld [hl], a
1500
ld hl, wChannelDutyCyclePatterns
1501
add hl, de
1502
ld [hl], a
1503
ld hl, wChannelVibratoDelayCounters
1504
add hl, de
1505
ld [hl], a
1506
ld hl, wChannelVibratoExtents
1507
add hl, de
1508
ld [hl], a
1509
ld hl, wChannelVibratoRates
1510
add hl, de
1511
ld [hl], a
1512
ld hl, wChannelFrequencyLowBytes
1513
add hl, de
1514
ld [hl], a
1515
ld hl, wChannelVibratoDelayCounterReloadValues
1516
add hl, de
1517
ld [hl], a
1518
ld hl, wChannelPitchSlideLengthModifiers
1519
add hl, de
1520
ld [hl], a
1521
ld hl, wChannelPitchSlideFrequencySteps
1522
add hl, de
1523
ld [hl], a
1524
ld hl, wChannelPitchSlideFrequencyStepsFractionalPart
1525
add hl, de
1526
ld [hl], a
1527
ld hl, wChannelPitchSlideCurrentFrequencyFractionalPart
1528
add hl, de
1529
ld [hl], a
1530
ld hl, wChannelPitchSlideCurrentFrequencyHighBytes
1531
add hl, de
1532
ld [hl], a
1533
ld hl, wChannelPitchSlideCurrentFrequencyLowBytes
1534
add hl, de
1535
ld [hl], a
1536
ld hl, wChannelPitchSlideTargetFrequencyHighBytes
1537
add hl, de
1538
ld [hl], a
1539
ld hl, wChannelPitchSlideTargetFrequencyLowBytes
1540
add hl, de
1541
ld [hl], a
1542
ld hl, wChannelFlags2
1543
add hl, de
1544
ld [hl], a
1545
ld a, $1
1546
ld hl, wChannelLoopCounters
1547
add hl, de
1548
ld [hl], a
1549
ld hl, wChannelNoteDelayCounters
1550
add hl, de
1551
ld [hl], a
1552
ld hl, wChannelNoteSpeeds
1553
add hl, de
1554
ld [hl], a
1555
ld a, e
1556
cp CHAN5
1557
jr nz, .skipSweepDisable
1558
ld a, AUD1SWEEP_DOWN
1559
ldh [rAUD1SWEEP], a ; sweep off
1560
.skipSweepDisable
1561
ld a, c
1562
and a
1563
jp z, .playSoundCommon
1564
dec c
1565
jp .sfxChannelLoop
1566
1567
.stopAllAudio
1568
ld a, AUDENA_ON
1569
ldh [rAUDENA], a ; sound hardware on
1570
ldh [rAUD3ENA], a ; wave playback on
1571
xor a
1572
ldh [rAUDTERM], a ; no sound output
1573
ldh [rAUD3LEVEL], a ; mute channel 3 (wave channel)
1574
ld a, AUD1SWEEP_DOWN
1575
ldh [rAUD1SWEEP], a ; sweep off
1576
ldh [rAUD1ENV], a ; mute channel 1 (pulse channel 1)
1577
ldh [rAUD2ENV], a ; mute channel 2 (pulse channel 2)
1578
ldh [rAUD4ENV], a ; mute channel 4 (noise channel)
1579
ld a, AUD1HIGH_LENGTH_ON
1580
ldh [rAUD1HIGH], a ; counter mode
1581
ldh [rAUD2HIGH], a
1582
ldh [rAUD4GO], a
1583
ld a, $77
1584
ldh [rAUDVOL], a ; full volume
1585
xor a
1586
ld [wUnusedMusicByte], a
1587
ld [wDisableChannelOutputWhenSfxEnds], a
1588
ld [wMuteAudioAndPauseMusic], a
1589
ld [wMusicTempo + 1], a
1590
ld [wSfxTempo + 1], a
1591
ld [wMusicWaveInstrument], a
1592
ld [wSfxWaveInstrument], a
1593
ld d, $a0
1594
ld hl, wChannelCommandPointers
1595
call .FillMem
1596
ld a, $1
1597
ld d, $18
1598
ld hl, wChannelNoteDelayCounters
1599
call .FillMem
1600
ld [wMusicTempo], a
1601
ld [wSfxTempo], a
1602
ld a, $ff
1603
ld [wStereoPanning], a
1604
ret
1605
1606
; fills d bytes at hl with a
1607
.FillMem
1608
ld b, d
1609
.loop
1610
ld [hli], a
1611
dec b
1612
jr nz, .loop
1613
ret
1614
1615
.playSoundCommon
1616
ld a, [wSoundID]
1617
ld l, a
1618
ld e, a
1619
ld h, 0
1620
ld d, h
1621
add hl, hl
1622
add hl, de
1623
ld de, SFX_Headers_1
1624
add hl, de
1625
ld e, l
1626
ld d, h
1627
ld hl, wChannelCommandPointers
1628
ld a, [de] ; get channel number
1629
ld b, a
1630
rlca
1631
rlca
1632
and $3
1633
ld c, a
1634
ld a, b
1635
and $f
1636
ld b, c
1637
inc b
1638
inc de
1639
ld c, 0
1640
.commandPointerLoop
1641
cp c
1642
jr z, .next
1643
inc c
1644
inc hl
1645
inc hl
1646
jr .commandPointerLoop
1647
.next
1648
push hl
1649
push bc
1650
push af
1651
ld b, 0
1652
ld c, a
1653
ld hl, wChannelSoundIDs
1654
add hl, bc
1655
ld a, [wSoundID]
1656
ld [hl], a
1657
pop af
1658
cp CHAN4
1659
jr c, .skipSettingFlag
1660
ld hl, wChannelFlags1
1661
add hl, bc
1662
set BIT_NOISE_OR_SFX, [hl]
1663
.skipSettingFlag
1664
pop bc
1665
pop hl
1666
ld a, [de] ; get channel pointer
1667
ld [hli], a
1668
inc de
1669
ld a, [de]
1670
ld [hli], a
1671
inc de
1672
inc c
1673
dec b
1674
ld a, b
1675
and a
1676
ld a, [de]
1677
inc de
1678
jr nz, .commandPointerLoop
1679
ld a, [wSoundID]
1680
cp CRY_SFX_START
1681
jr nc, .maybeCry
1682
jr .done
1683
.maybeCry
1684
ld a, [wSoundID]
1685
cp CRY_SFX_END
1686
jr z, .done
1687
jr c, .cry
1688
jr .done
1689
.cry
1690
ld hl, wChannelSoundIDs + CHAN5
1691
ld [hli], a
1692
ld [hli], a
1693
ld [hli], a
1694
ld [hl], a
1695
ld hl, wChannelCommandPointers + CHAN7 * 2 ; sfx wave channel pointer
1696
ld de, Audio1_CryRet
1697
ld [hl], e
1698
inc hl
1699
ld [hl], d ; overwrite pointer to point to sound_ret
1700
ld a, [wSavedVolume]
1701
and a
1702
jr nz, .done
1703
ldh a, [rAUDVOL]
1704
ld [wSavedVolume], a
1705
ld a, $77
1706
ldh [rAUDVOL], a ; full volume
1707
.done
1708
ret
1709
1710
Audio1_CryRet:
1711
sound_ret
1712
1713
Audio1_HWChannelBaseAddresses:
1714
; the low bytes of each HW channel's base address
1715
db HW_CH1_BASE, HW_CH2_BASE, HW_CH3_BASE, HW_CH4_BASE ; channels 0-3
1716
db HW_CH1_BASE, HW_CH2_BASE, HW_CH3_BASE, HW_CH4_BASE ; channels 4-7
1717
1718
Audio1_HWChannelDisableMasks:
1719
db HW_CH1_DISABLE_MASK, HW_CH2_DISABLE_MASK, HW_CH3_DISABLE_MASK, HW_CH4_DISABLE_MASK ; channels 0-3
1720
db HW_CH1_DISABLE_MASK, HW_CH2_DISABLE_MASK, HW_CH3_DISABLE_MASK, HW_CH4_DISABLE_MASK ; channels 4-7
1721
1722
Audio1_HWChannelEnableMasks:
1723
db HW_CH1_ENABLE_MASK, HW_CH2_ENABLE_MASK, HW_CH3_ENABLE_MASK, HW_CH4_ENABLE_MASK ; channels 0-3
1724
db HW_CH1_ENABLE_MASK, HW_CH2_ENABLE_MASK, HW_CH3_ENABLE_MASK, HW_CH4_ENABLE_MASK ; channels 4-7
1725
1726
Audio1_Pitches:
1727
INCLUDE "audio/notes.asm"
1728
1729