$42B3: Handle audio { If [audio pause control] = pause: $4801: Audio pause { Mute sound channels (call to $47B3) Clear sound channel 1/2/4 sound effects playing Audio pause sound effect timer = 40h ; Go to $4819 Set noise channel registers to [$487C..7F] (call to $47F1) ; Go to $476A Clear sound channel 1/2/4 sound effect requests Clear audio pause control Return } If [audio pause control] = unpause: { Audio pause sound effect timer = 0 Tone/sweep channel sound effect request = unpaused } Else if [audio pause sound effect timer] != 0: $4852: Handle audio - paused { Decrement audio pause sound effect timer If [audio pause sound effect timer] = 3Fh: $482E: Handle audio - paused - frame 3Fh { ; Go to $4831 Set tone/sweep channel registers to [$4884..88] (call to $47D9) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 3Dh: $481F: Handle audio - paused - frame 3Dh { ; Go to $4819 Set noise channel registers to [$4880..83] (call to $47F1) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 3Ah: $4837: Handle audio - paused - frame 3Ah { ; Go to $4831 Set tone/sweep channel registers to [$4889..8D] (call to $47D9) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 32h: $4824: Handle audio - paused - frame 32h { ; Go to $4819 Set noise channel registers to [$488E..91] (call to $47F1) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 2Fh: $483C: Handle audio - paused - frame 2Fh { ; Go to $4831 Set tone/sweep channel registers to [$4892..96] (call to $47D9) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 27h: $4829: Handle audio - paused - frame 27h { ; Go to $4819 Set noise channel registers to [$4897..9A] (call to $47F1) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 24h: $4841: Handle audio - paused - frame 24h { ; Go to $4831 Set tone/sweep channel registers to [$489B..9F] (call to $47D9) ; Go to $476A Clear sound channel 1/2/4 sound effect requests } If [audio pause sound effect timer] = 10h: Increment audio pause sound effect timer ; Go to $476A Clear sound channel 1/2/4 sound effect requests Clear audio pause control Return } $42C7: Handle audio - handle song interruption request { If [song interruption request] = 0: $42EA: Handle song interruption playing { If [song interruption playing] = 2: $43C4: Finish ending song interruption { Disable wave channel Write out wave pattern RAM If [song playing] != earthquake: Low health beep sound effect playing = [$CFE7] Audio channel output stereo flags = [$CFED] Update IO audio channel output stereo flags Tone/sweep channel sweep = [$CFC9] Song interruption playing = 0 $CFEB = 0 Song playing = [$CFC5] Return } If [song interruption playing] = 8: $4418: Handle audio - handle fading out music { Decrement song fadeout timer If [song fadeout timer] = A0h: Sound channel sound envelopes = 65h Else if [song fadeout timer] = 70h: { $CF07 = 0 (disable noise channel?) Wave volume = 60h Sound channel sound envelopes = 45h } Else if [song fadeout timer] = 30h: Sound channel sound envelopes = 25h Else if [song fadeout timer] = 10h: Sound channel sound envelopes = 13h Else if [song fadeout timer] = 0: { Song playing = song interruption request = 0 Disable sound channels Return } } } If [song interruption request] = 1: ; Go to $432B Play song interruption - item-get { Song interruption playing = 1 Song request = item-get Go to play song interruption } If [song interruption request] = 3: ; Go to $4390 Start ending song interruption { Song interruption playing = 2 Song processing state = [backup of song processing state] Set IO audio channel options Song interruption request = 0 Sound effects request = 0 Return } If [song interruption request] = 5: ; Go to $4335 Play song interruption - missile pickup { Song interruption playing = 5 Song request = missile pickup Go to play song interruption } If [song interruption request] = 8: ; Go to $43FB Handle audio - initiate fading out music { Song interruption playing = 8 Song fadeout timer = D0h $CF5D = [tone/sweep sound envelope] $CF5E = [tone sound envelope] $CF5F = [wave volume] Go to handle song and sound effects } If [song interruption request] = Eh: ; Go to $433F Play song interruption - earthquake { Song request = song interruption playing = earthquake Go to play song interruption } If [song interruption request] = FFh: $4323: Clear song interruption { Clear song interruption request Clear song interruption playing Return } Go to handle song and sound effects } $4345: Play song interruption { Backup of song playing = [song playing] If [song interruption request] != earthquake: $CFE7 = [low health beep sound effect playing] Low health beep sound effect playing = 0 $CFED = [audio channel output stereo flags] $CFC9 = [tone/sweep channel sweep] $CF61..$CFC1 = [song processing state] Mute sound channels Clear song interruption request Clear tone/sweep channel sound effect request Clear tone/sweep channel sound effect playing Clear noise channel sound effect request Clear noise channel sound effect playing Clear noise channel sound effect is playing flag Return } $42FA: Handle song and sound effects { $457C: Handle song { If [song request] = FFh: Go to disable sound channels { Song tone/sweep channel enable = 0 Song tone channel enable = 0 Song wave channel enable = 0 Song noise channel enable = 0 Disable tone/sweep channel Disable tone channel Disable wave channel Disable noise channel } If [song request] = killed metroid: Clear tone/sweep channel sound effect Clear noise channel sound effect If [song request] != 0 and [song request] < 21h: { Song playing = [song request] Audio channel output stereo flags = [$5F70 + [song request] - 1] hl = [$5F30 + ([song request] - 1) * 2] Go to load song header ; Reset song state, load song header, load initial song channel instruction pointers { Reset song sound channel options { Clear song channel processing states ($CF2F..5B) Clear channel sound effect is playing flags Clear tone channel frequency tweak Clear tone/sweep channel sweep Disable wave channel Disable sound channel envelopes Restart tone/sweep channel Restart tone channel Restart noise channel } ; Decode header a = [[hl++]] If [a] & 1: Tone channel frequency tweak = 1 Song transpose = [a] & ~1 Song instruction timer array pointer = [[hl++]] Song tone/sweep channel instruction pointer list = [[hl++]] Song tone channel instruction pointer list = [[hl++]] Song wave channel instruction pointer list = [[hl++]] Song noise channel instruction pointer list = [[hl]] ; Tone/sweep channel If [song tone/sweep channel instruction pointer list] = 0: Song tone/sweep channel enable = 0 Disable tone/sweep channel envelope Restart tone/sweep channel Else: Song tone/sweep channel enable = 1 Song tone/sweep channel instruction pointer = [[song tone/sweep channel instruction pointer list]] ; Tone channel If [song tone channel instruction pointer list] = 0: Song tone channel enable = 0 Disable tone channel envelope Restart tone channel Else: Song tone channel enable = 2 Song tone channel instruction pointer = [[song tone channel instruction pointer list]] ; Wave channel If [song wave channel instruction pointer list] = 0: Song wave channel enable = 0 Disable wave channel Else: Song wave channel enable = 3 Song wave channel instruction pointer = [[song wave channel instruction pointer list]] ; Noise channel If [song noise channel instruction pointer list] = 0: Song noise channel enable = 0 Else: Song noise channel enable = 4 Song noise channel instruction pointer = [[song noise channel instruction pointer list]] Song tone/sweep channel instruction timer = 1 Song tone channel instruction timer = 1 Song wave channel instruction timer = 1 Song noise channel instruction timer = 1 } } ; Handle song playing If [song playing] = 0: Return If [song playing] >= 21h: Go to clear song playing ; Tone/sweep channel $CF08 = 0 If [song tone/sweep channel enable] != 0: { Song working sound channel = 1 Song working channel instruction timer = [song tone/sweep channel instruction timer] If [song tone/sweep channel instruction timer] = 1: Handle song - load next tone/sweep channel sound { Working channel song processing state = [tone/sweep channel song processing state] hl = [song tone/sweep channel instruction pointer] a = 1 Load next sound Song tone/sweep channel enable = [song working sound channel] If [song tone/sweep channel enable] = 0: Reset tone/sweep channel options { Song tone/sweep channel enable = 0 Disable tone/sweep channel envelope Restart tone/sweep channel } Else: { Song tone/sweep channel instruction pointer = [hl] Tone/sweep channel song processing state = [working channel song processing state] If [$CF08] = 1: Tone/sweep channel sweep = [working sound channel sweep] Tone/sweep channel sound length / wave pattern duty = [working sound channel sound length / wave pattern duty] Tone/sweep channel envelope = [working sound channel envelope] Tone/sweep channel frequency = [working sound channel frequency] If [tone/sweep channel sound effect is playing flag] = 0: Set IO tone/sweep channel registers } } Else: { Decrement song tone/sweep channel instruction timer If [tone/sweep channel sound effect is playing flag] = 0: { Song working channel effect index = [song tone/sweep channel effect index] If [song working channel effect index] != 0: bc = [song tone/sweep channel frequency] Handle song sound channel effect IO tone/sweep channel frequency = [song working sound channel frequency] } } } ; Tone channel $CF08 = 0 If [song tone channel enable] != 0: { Song working sound channel = 2 Song working channel instruction timer = [song tone channel instruction timer] If [song tone channel instruction timer] = 1: Handle song - load next tone channel sound { Working channel song processing state = [tone channel song processing state] hl = [song tone channel instruction pointer] a = 2 Load next sound Song tone channel enable = [song working sound channel] If [song tone channel enable] = 0: Reset tone channel options { Song tone channel enable = 0 Disable tone channel envelope Restart tone channel } Else: { Song tone channel instruction pointer = [hl] Tone channel song processing state = [working channel song processing state] If [$CF08] = 2: Tone channel sound length / wave pattern duty = [working sound channel sound length / wave pattern duty] Tone channel envelope = [working sound channel envelope] Tone channel frequency = [working sound channel frequency] If [tone channel sound effect is playing flag] = 0: { If [tone channel frequency tweak] = 1: { If [tone channel frequency] < 8700h: Tone channel frequency += 2 Else: Tone channel frequency += 1 } Set IO tone channel registers } } } Else: { Decrement song tone channel instruction timer If [tone channel sound effect is playing flag] = 0: { Song working channel effect index = [song tone channel effect index] If [song working channel effect index] != 0: bc = [song tone channel frequency] Handle song sound channel effect IO tone channel frequency = [song working sound channel frequency] } } } ; Wave channel $CF08 = 0 If [song wave channel enable] != 0: { Song working sound channel = 3 Song working channel instruction timer = [song wave channel instruction timer] If [song wave channel instruction timer] = 1: Handle song - load next wave channel sound { Working channel song processing state = [tone channel song processing state] hl = [song wave channel instruction pointer] a = 3 Load next sound Song wave channel enable = [song working sound channel] If [song wave channel enable] = 0: Reset wave channel options { Song wave channel enable = 0 Disable wave channel } Else: { Song wave channel instruction pointer = [hl] Wave channel song processing state = [working channel song processing state] Wave channel enable = [Working sound channel enable] Wave channel sound length = [working sound channel sound length] Wave channel volume = [working sound channel volume] Wave channel frequency = [working sound channel frequency] If [wave channel sound effect is playing flag] = 0: Set wave channel registers } Else: { Decrement song wave channel instruction timer If [wave channel sound effect is playing flag] = 0: { Song working channel effect index = [song wave channel effect index] If [song working channel effect index] != 0: bc = [song wave channel frequency] Handle song sound channel effect IO wave channel frequency = [song working sound channel frequency] & 7FFFh } } } ; Noise channel $CF08 = 0 If [song noise channel enable] != 0: { Song working sound channel = 4 Song working channel instruction timer = [song noise channel instruction timer] If [song noise channel instruction timer] = 1: Go to handle song - load next noise channel sound { Working channel song processing state = [noise channel song processing state] hl = [song noise channel instruction pointer] a = 4 Load next sound Song noise channel enable = [song working sound channel] If [song noise channel enable] = 0: Reset noise channel options { Song tone/sweep channel enable = 0 Disable tone/sweep channel envelope Restart tone/sweep channel } Else: { Song noise channel instruction pointer = [hl] Noise channel song processing state = [working channel song processing state] If [noise channel sound effect is playing flag] = 0: { IO noise channel sound length = [working sound channel sound length] IO noise channel envelope = [working sound channel envelope] Noise channel polynomial counter = [working sound channel polynomial counter] Noise channel counter control = [working sound channel counter control] Set IO noise channel polynomial counter / counter control } } } Decrement song noise channel instruction timer } ; Finish If [song tone/sweep channel enable] != 0 or [song tone channel enable] != 0 or [song wave channel enable] != 0 or [song noise channel enable] != 0: Return Song playing = 0 Song interruption playing = 0 } ; For the most part, these sound effect handlers just sets a channel option set based on the sound effect timer ; Wave channel also sets the wave pattern RAM, and restores it *and* the wave channel registers when it's done $44CF: Handle noise channel sound effect { ; Handle noise channel sound effect request If [noise channel sound effect request] = FFh: Go to clear noise channel sound effect If [noise channel sound effect request] != 0: and [noise channel sound effect request] < 1Bh: { If [song playing] = earthquake: Return If [noise channel sound effect playing] != metroid killed and [noise channel sound effect playing] != Eh and [noise channel sound effect playing] != cleared save file: Go to [$56CC + ([noise channel sound effect request] - 1) * 2] ; Noise channel sound effect initialisation { ; Some sound effects play accompanying an sound effect on another channel Set noise channel sound effect is playing flag Noise channel sound effect playing = [noise channel sound effect request] Set noise channel sound effect timer = [custom] Set noise channel option set [custom] } } ; Handle noise channel sound effect playing If [noise channel sound effect playing] = 0: Return If [noise channel sound effect playing] < 1Bh: Go to [$5700 + ([noise channel sound effect playing] - 1) * 2] ; Noise channel sound effect playback { Decrement noise channel sound effect timer or clear noise channel sound effect ; Some sound effects set a noise channel option set depending on the noise channel sound effect timer ; Some sound effects set a noise channel polynomial counter depending on the noise channel sound effect timer } } $446B: Handle tone/sweep channel sound effect { ; Handle tone/sweep channel sound effect request If [tone/sweep channel sound effect request] = FFh: Go to clear tone/sweep channel sound effect If [tone/sweep channel sound effect request] != 0 and [tone/sweep channel sound effect request] < 1Fh and [tone/sweep channel sound effect playing] != picked up missile drop and [tone/sweep channel sound effect playing] != Samus' health changed: Go to [$4EC4 + ([tone/sweep channel sound effect request] - 1) * 2] ; Tone/sweep channel sound effect initialisation { ; Some sound effects nope out under some conditions and go to handle sound effect playing ; Otherwise: ; Some sound effects set the variable tone/sweep channel frequency low byte ; Some sound effects (picked up energy drop) remember if screw attack was playing ; Samus' health changed sets an option set index Set tone/sweep channel sound effect is playing flag Tone/sweep channel sound effect playing = [tone/sweep channel sound effect request] Set tone/sweep channel sound effect timer = [custom] Set tone/sweep channel option set [custom] } ; Handle tone/sweep channel sound effect playing If [tone/sweep channel sound effect playing] = 0: Return If [tone/sweep channel sound effect playing] < 1Fh: Go to [$4F00 + ([tone/sweep channel sound effect playing] - 1) * 2] ; Tone/sweep channel sound effect playback Tone/sweep channel sound effect playing = 0 } $44A4: Handle tone channel sound effect { If [tone channel sound effect request] = FFh: Go to clear tone channel sound effect ; Handle tone channel sound effect request If [tone channel sound effect request] != 0 and [tone channel sound effect request] < 8: Go to [$55F2 + ([tone channel sound effect request] - 1) * 2] ; Tone channel sound effect initialisation ; Handle tone channel sound effect playing If [tone channel sound effect playing] = 0: Return If [tone channel sound effect playing] < 8: Go to [$5600 + ([tone channel sound effect playing] - 1) * 2] ; Tone channel sound effect playback Tone channel sound effect playing = 0 } $4512: Handle wave channel sound effect { ; Handle wave channel sound effect request If [wave channel sound effect request] = FFh: { Disable wave channel de = [pointer to wave pattern data] Write [[de]..[de]+Fh] to wave pattern RAM ; Restore song wave pattern Clear wave channel sound effect is playing flag Wave channel sound effect request = 0 Wave channel sound effect playing = 0 If [song playing] = earthquake: Return Write wave channel registers ; Restore song wave channel registers Return } If [wave channel sound effect request] != 0: { If [wave channel sound effect request] >= 6: Return Set wave channel sound effect is playing flag Wave channel sound effect playing = [wave channel sound effect request] Go to [$5D3F + ([wave channel sound effect request] - 1) * 2] ; Wave channel sound effect initialisation { Disable wave channel Write [$418B..9A] to wave pattern RAM Loud low health beep timer = Ch/6/6/6 Set wave sound effect timer Eh/13h/16h/18h and option set $5EFF/$5F09/$5F13/$5F1D } } ; Handle wave channel sound effect playing If [wave channel sound effect playing] = 0: Return If [wave channel sound effect playing] < 6: Go to [$5D49 + ([wave channel sound effect playing] - 1) * 2] ; Wave channel sound effect playback { Set wave channel sound effect is playing flag Decrement wave channel sound effect timer If [wave channel sound effect timer] = Ah/9/9/Bh: { If [loud low health beep timer] != 0: Decrement loud low health beep timer Write [$418B..9A] to wave pattern RAM Else: Disable wave channel Write [$419B..AA] to wave pattern RAM Go to set wave channel option set $5F04/$5F0E/$5F18/$5F22 } If [wave channel sound effect timer] = 0: { If [loud low health beep timer] != 0: Write [$418B..9A] to wave pattern RAM Else: Write [$419B..AA] to wave pattern RAM Wave channel sound effect timer = [wave channel sound effect length] Go to set wave channel option set $5EFF/$5F09/$5F13/$5F1D } } Wave channel sound effect playing = 0 } Clear song request Clear sound effect requests Clear song interruption request Clear low health beep sound effect request Clear audio pause control Return } } $4B47: Load next sound { ;; Parameters: ;; a: Working sound channel ;; hl: Song instruction pointer list ;; Returns: ;; a: Working sound channel frequency / polynomial counter Song working sound channel = [a] If [[hl]] != 0: Go to LOOP ; BRANCH_NEXT_INSTRUCTION_LIST Song instruction pointer list += 2 If [[song instruction pointer list]] = 0: Song working sound channel = 0 Return If [[song instruction pointer list]] = 00F0h: Song instruction pointer list = [[song instruction pointer list] + 2] hl = [[song instruction pointer list]] ; LOOP Do: { ; The song instructions set hl to point to the next instruction and a = [[hl]] If [[hl]] = F1h: Set working sound channel options { ++hl $CF08 = [song working sound channel] If [working sound channel] = wave channel: { Pointer to wave pattern data = $CFE3 = [[hl++]] If [wave channel sound effect is playing flag] = 0: Disable wave channel Write wave pattern RAM } If [song interruption playing] = fade out music: Working sound channel envelope / volume = [[hl++]] Else: Working song sound channel envelope / volume = working sound channel envelope / volume = [[hl++]] If [working sound channel] = wave channel: Working song sound channel effect index = [working sound channel volume] & ~60h Else: { Working sound channel sweep = [[hl++]] Working sound channel sound length / wave pattern duty = [[hl++]] Working song sound channel effect index = working sound channel sound length (specifically) } } If [[hl]] = F2h: Set tempo { ++hl $CF01 = [[hl++]] } If [[hl]] = F3h: Set music note offset { ++hl Music note offset = [[hl++]] } If [[hl]] = F4h: Mark repeat point { ++hl Repeat count = [[hl++]] Repeat point = [hl] } If [[hl]] = F5h: Repeat { Decrement repeat count If [repeat count] = 0: ++hl Else: hl = [repeat point] } If [[hl]] = 0: Go to BRANCH_NEXT_INSTRUCTION_LIST If [[hl]] >= F6h: Go to clear sound effects and song } While [[hl]] >= F1h If [[hl]] >= 9Fh: Instruction length = instruction timer = [[$CF01] + ([[hl++]] & ~A0h)] Instruction timer = [instruction length] a = [[hl++]] If [a] = 1: { ; Rest If [song working sound channel] != wave channel: Mute working sound channel Restart working sound channel Else: Clear working sound channel enable Clear working sound channel volume Return } If [song working sound channel] = noise channel: { Working sound channel sound length = [$41BB + [a]] Working sound channel envelope = [$41BB + [a] + 1] Working sound channel polynomial counter = [$41BB + [a] + 2] Working sound channel counter control = [$41BB + [a] + 3] Return } If [a] = 3: Working sound channel envelope / volume = 66h ; Echo quiet for wave, loud for tone... Else if [a] = 5: Working sound channel envelope / volume = 46h ; Echo loud for wave, quiet for tone... Else: { If [song working sound channel] = wave channel and [wave channel sound effect is playing flag] = 0: Enable IO wave sound output Working sound channel sweep / enable = 80h a += [music note offset] Working sound channel envelope / volume = [working song sound channel envelope] Working sound channel frequency = [music notes + [a]] Return } If [song interruption playing] = fade out music: Mute working sound channel If [song working sound channel] = tone/sweep: Working sound channel frequency = [tone/sweep channel frequency] Return If [song working sound channel] = tone: Working sound channel frequency = [tone channel frequency] Return If [song working sound channel] = wave and [wave channel sound effect is playing flag] = 0: Enable working sound channel Working sound channel frequency = [wave channel frequency] } $4D75: Handle song sound channel effect { ;; Parameters: ;; bc: Working sound channel's frequency If [song working channel effect index] = 6: Working sound channel's frequency += 1 Return Else if [song working channel effect index] = 7: Working sound channel's frequency += 4 Return Else if [song working channel effect index] = 8: Working sound channel's frequency -= 3 Return If [song working channel effect index] = 9: Working sound channel frequency = [bc] + 1 Return Else if [song working channel effect index] = Ah: Working sound channel frequency = [bc] + 3 Return If [song working channel effect index] = 2: hl = $4263 ; 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 Else if [song working channel effect index] = 3: hl = $4273 ; 08 10 18 20 28 30 38 40 38 30 28 20 18 10 08 00 Else if [song working channel effect index] = 4: hl = $4283 ; 00 05 00 05 00 05 00 05 05 00 05 00 05 00 05 00 Song sound channel effect timer = ([song sound channel effect timer] - 1) % 11h Working sound channel frequency = [bc] + [[hl] + [song sound channel effect timer]] }