sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

external.c (105277B)


      1 #include <ultra64.h>
      2 #include "sm64.h"
      3 #include "heap.h"
      4 #include "load.h"
      5 #include "data.h"
      6 #include "seqplayer.h"
      7 #include "external.h"
      8 #include "playback.h"
      9 #include "synthesis.h"
     10 #include "game/level_update.h"
     11 #include "game/object_list_processor.h"
     12 #include "game/camera.h"
     13 #include "seq_ids.h"
     14 #include "dialog_ids.h"
     15 
     16 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
     17 #define EU_FLOAT(x) x##f
     18 #else
     19 #define EU_FLOAT(x) x
     20 #endif
     21 
     22 // N.B. sound banks are different from the audio banks referred to in other
     23 // files. We should really fix our naming to be less ambiguous...
     24 #define MAX_BACKGROUND_MUSIC_QUEUE_SIZE 6
     25 #define MAX_CHANNELS_PER_SOUND_BANK 1
     26 
     27 #define SEQUENCE_NONE 0xFF
     28 
     29 #define SAMPLES_TO_OVERPRODUCE 0x10
     30 #define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40
     31 
     32 struct Sound {
     33     s32 soundBits;
     34     f32 *position;
     35 }; // size = 0x8
     36 
     37 struct ChannelVolumeScaleFade {
     38     f32 velocity;
     39     u8 target;
     40     f32 current;
     41     u16 remainingFrames;
     42 }; // size = 0x10
     43 
     44 struct SoundCharacteristics {
     45     f32 *x;
     46     f32 *y;
     47     f32 *z;
     48     f32 distance;
     49     u32 priority;
     50     u32 soundBits; // packed bits, same as first arg to play_sound
     51     u8 soundStatus;
     52     u8 freshness;
     53     u8 prev;
     54     u8 next;
     55 }; // size = 0x1C
     56 
     57 // Also the number of frames a discrete sound can be in the WAITING state before being deleted
     58 #define SOUND_MAX_FRESHNESS 10
     59 
     60 struct SequenceQueueItem {
     61     u8 seqId;
     62     u8 priority;
     63 }; // size = 0x2
     64 
     65 // data
     66 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
     67 // moved to bss in data.c
     68 s32 gAudioErrorFlags2 = 0;
     69 #else
     70 s32 gAudioErrorFlags = 0;
     71 #endif
     72 s32 sGameLoopTicked = 0;
     73 
     74 // Dialog sounds
     75 // The US difference is the sound for DIALOG_037 ("I win! You lose! Ha ha ha ha!
     76 // You're no slouch, but I'm a better sledder! Better luck next time!"), spoken
     77 // by Koopa instead of the penguin in JP.
     78 
     79 #define UKIKI 0
     80 #define TUXIE 1
     81 #define BOWS1 2 // Bowser Intro / Doors Laugh
     82 #define KOOPA 3
     83 #define KBOMB 4
     84 #define BOO 5
     85 #define BOMB 6
     86 #define BOWS2 7 // Bowser Battle Laugh
     87 #define GRUNT 8
     88 #define WIGLR 9
     89 #define YOSHI 10
     90 #define _ 0xFF
     91 
     92 #ifdef VERSION_JP
     93 #define DIFF KOOPA
     94 #else
     95 #define DIFF TUXIE
     96 #endif
     97 
     98 u8 sDialogSpeaker[] = {
     99     //       0      1      2      3      4      5      6      7      8      9
    100     /* 0*/ _,     BOMB,  BOMB,  BOMB,  BOMB,  KOOPA, KOOPA, KOOPA, _,     KOOPA,
    101     /* 1*/ _,     _,     _,     _,     _,     _,     _,     KBOMB, _,     _,
    102     /* 2*/ _,     BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1,
    103     /* 3*/ _,     _,     _,     _,     _,     _,     _,     DIFF,  _,     _,
    104     /* 4*/ _,     KOOPA, _,     _,     _,     _,     _,     BOMB,  _,     _,
    105     /* 5*/ _,     _,     _,     _,     _,     TUXIE, TUXIE, TUXIE, TUXIE, TUXIE,
    106     /* 6*/ _,     _,     _,     _,     _,     _,     _,     BOWS2, _,     _,
    107     /* 7*/ _,     _,     _,     _,     _,     _,     _,     _,     _,     UKIKI,
    108     /* 8*/ UKIKI, _,     _,     _,     _,     BOO,   _,     _,     _,     _,
    109     /* 9*/ BOWS2, _,     BOWS2, BOWS2, _,     _,     _,     _,     BOO,   BOO,
    110     /*10*/ UKIKI, UKIKI, _,     _,     _,     BOMB,  BOMB,  BOO,   BOO,   _,
    111     /*11*/ _,     _,     _,     _,     GRUNT, GRUNT, KBOMB, GRUNT, GRUNT, _,
    112     /*12*/ _,     _,     _,     _,     _,     _,     _,     _,     KBOMB, _,
    113     /*13*/ _,     _,     TUXIE, _,     _,     _,     _,     _,     _,     _,
    114     /*14*/ _,     _,     _,     _,     _,     _,     _,     _,     _,     _,
    115     /*15*/ WIGLR, WIGLR, WIGLR, _,     _,     _,     _,     _,     _,     _,
    116     /*16*/ _,     YOSHI, _,     _,     _,     _,     _,     _,     WIGLR, _
    117 };
    118 #undef _
    119 STATIC_ASSERT(ARRAY_COUNT(sDialogSpeaker) == DIALOG_COUNT,
    120               "change this array if you are adding dialogs");
    121 
    122 s32 sDialogSpeakerVoice[] = {
    123     SOUND_OBJ_UKIKI_CHATTER_LONG,
    124     SOUND_OBJ_BIG_PENGUIN_YELL,
    125     SOUND_OBJ_BOWSER_INTRO_LAUGH,
    126     SOUND_OBJ_KOOPA_TALK,
    127     SOUND_OBJ_KING_BOBOMB_TALK,
    128     SOUND_OBJ_BOO_LAUGH_LONG,
    129     SOUND_OBJ_BOBOMB_BUDDY_TALK,
    130     SOUND_OBJ_BOWSER_LAUGH,
    131     SOUND_OBJ2_BOSS_DIALOG_GRUNT,
    132     SOUND_OBJ_WIGGLER_TALK,
    133     SOUND_GENERAL_YOSHI_TALK,
    134 #if defined(VERSION_JP) || defined(VERSION_US)
    135     NO_SOUND,
    136     NO_SOUND,
    137     NO_SOUND,
    138     NO_SOUND,
    139 #endif
    140 };
    141 
    142 u8 sNumProcessedSoundRequests = 0;
    143 u8 sSoundRequestCount = 0;
    144 
    145 // Music dynamic tables. A dynamic describes which volumes to apply to which
    146 // channels of a sequence (I think?), and different parts of a level can have
    147 // different dynamics. Each table below specifies first the sequence to apply
    148 // the dynamics to, then a bunch of conditions for when each dynamic applies
    149 // (e.g. "only if Mario's X position is between 100 and 300"), and finally a
    150 // fallback dynamic. Due to the encoding of the tables, the conditions must
    151 // come in the same order as the macros.
    152 // TODO: dynamic isn't a great term for this, it means other things in music...
    153 
    154 #define MARIO_X_GE 0
    155 #define MARIO_Y_GE 1
    156 #define MARIO_Z_GE 2
    157 #define MARIO_X_LT 3
    158 #define MARIO_Y_LT 4
    159 #define MARIO_Z_LT 5
    160 #define MARIO_IS_IN_AREA 6
    161 #define MARIO_IS_IN_ROOM 7
    162 
    163 #define DYN1(cond1, val1, res) (s16)(1 << (15 - cond1) | res), val1
    164 #define DYN2(cond1, val1, cond2, val2, res)                                                            \
    165     (s16)(1 << (15 - cond1) | 1 << (15 - cond2) | res), val1, val2
    166 #define DYN3(cond1, val1, cond2, val2, cond3, val3, res)                                               \
    167     (s16)(1 << (15 - cond1) | 1 << (15 - cond2) | 1 << (15 - cond3) | res), val1, val2, val3
    168 
    169 s16 sDynBBH[] = {
    170     SEQ_LEVEL_SPOOKY, DYN1(MARIO_IS_IN_ROOM, BBH_OUTSIDE_ROOM, 6),
    171     DYN1(MARIO_IS_IN_ROOM, BBH_NEAR_MERRY_GO_ROUND_ROOM, 6), 5,
    172 };
    173 s16 sDynDDD[] = {
    174     SEQ_LEVEL_WATER,
    175     DYN2(MARIO_X_LT, -800, MARIO_IS_IN_AREA, AREA_DDD_WHIRLPOOL & 0xf, 0),
    176     DYN3(MARIO_Y_GE, -2000, MARIO_X_LT, 470, MARIO_IS_IN_AREA, AREA_DDD_WHIRLPOOL & 0xf, 0),
    177     DYN2(MARIO_Y_GE, 100, MARIO_IS_IN_AREA, AREA_DDD_SUB & 0xf, 2),
    178     1,
    179 };
    180 s16 sDynJRB[] = {
    181     SEQ_LEVEL_WATER,
    182     DYN2(MARIO_Y_GE, 945, MARIO_X_LT, -5260, 0),
    183     DYN1(MARIO_IS_IN_AREA, AREA_JRB_SHIP & 0xf, 0),
    184     DYN1(MARIO_Y_GE, 1000, 0),
    185     DYN2(MARIO_Y_GE, -3100, MARIO_Z_LT, -900, 2),
    186     1,
    187     5, // bogus entry, ignored (was JRB originally intended to have spooky music?)
    188 };
    189 s16 sDynWDW[] = {
    190     SEQ_LEVEL_UNDERGROUND, DYN2(MARIO_Y_LT, -670, MARIO_IS_IN_AREA, AREA_WDW_MAIN & 0xf, 4),
    191     DYN1(MARIO_IS_IN_AREA, AREA_WDW_TOWN & 0xf, 4), 3,
    192 };
    193 s16 sDynHMC[] = {
    194     SEQ_LEVEL_UNDERGROUND, DYN2(MARIO_X_GE, 0, MARIO_Y_LT, -203, 4),
    195     DYN2(MARIO_X_LT, 0, MARIO_Y_LT, -2400, 4), 3,
    196 };
    197 s16 sDynUnk38[] = {
    198     SEQ_LEVEL_UNDERGROUND,
    199     DYN1(MARIO_IS_IN_AREA, 1, 3),
    200     DYN1(MARIO_IS_IN_AREA, 2, 4),
    201     DYN1(MARIO_IS_IN_AREA, 3, 7),
    202     0,
    203 };
    204 s16 sDynNone[] = { SEQ_SOUND_PLAYER, 0 };
    205 
    206 u8 sCurrentMusicDynamic = 0xff;
    207 u8 sBackgroundMusicForDynamics = SEQUENCE_NONE;
    208 
    209 #define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, leveldyn, _8) leveldyn,
    210 #define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8, leveldyn, _10) leveldyn,
    211 
    212 #define _ sDynNone
    213 s16 *sLevelDynamics[LEVEL_COUNT] = {
    214     _, // LEVEL_NONE
    215 #include "levels/level_defines.h"
    216 };
    217 #undef _
    218 #undef STUB_LEVEL
    219 #undef DEFINE_LEVEL
    220 
    221 struct MusicDynamic {
    222     /*0x0*/ s16 bits1;
    223     /*0x2*/ u16 volScale1;
    224     /*0x4*/ s16 dur1;
    225     /*0x6*/ s16 bits2;
    226     /*0x8*/ u16 volScale2;
    227     /*0xA*/ s16 dur2;
    228 }; // size = 0xC
    229 
    230 struct MusicDynamic sMusicDynamics[8] = {
    231     { 0x0000, 127, 100, 0x0e43, 0, 100 }, // SEQ_LEVEL_WATER
    232     { 0x0003, 127, 100, 0x0e40, 0, 100 }, // SEQ_LEVEL_WATER
    233     { 0x0e43, 127, 200, 0x0000, 0, 200 }, // SEQ_LEVEL_WATER
    234     { 0x02ff, 127, 100, 0x0100, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
    235     { 0x03f7, 127, 100, 0x0008, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
    236     { 0x0070, 127, 10, 0x0000, 0, 100 },  // SEQ_LEVEL_SPOOKY
    237     { 0x0000, 127, 100, 0x0070, 0, 10 },  // SEQ_LEVEL_SPOOKY
    238     { 0xffff, 127, 100, 0x0000, 0, 100 }, // any (unused)
    239 };
    240 
    241 #define STUB_LEVEL(_0, _1, _2, _3, echo1, echo2, echo3, _7, _8) { echo1, echo2, echo3 },
    242 #define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, echo1, echo2, echo3, _9, _10) { echo1, echo2, echo3 },
    243 
    244 u8 sLevelAreaReverbs[LEVEL_COUNT][3] = {
    245     { 0x00, 0x00, 0x00 }, // LEVEL_NONE
    246 #include "levels/level_defines.h"
    247 };
    248 #undef STUB_LEVEL
    249 #undef DEFINE_LEVEL
    250 
    251 #define STUB_LEVEL(_0, _1, _2, volume, _4, _5, _6, _7, _8) volume,
    252 #define DEFINE_LEVEL(_0, _1, _2, _3, _4, volume, _6, _7, _8, _9, _10) volume,
    253 
    254 u16 sLevelAcousticReaches[LEVEL_COUNT] = {
    255     20000, // LEVEL_NONE
    256 #include "levels/level_defines.h"
    257 };
    258 
    259 #undef STUB_LEVEL
    260 #undef DEFINE_LEVEL
    261 
    262 #define AUDIO_MAX_DISTANCE US_FLOAT(22000.0)
    263 
    264 #ifdef VERSION_JP
    265 #define LOW_VOLUME_REVERB 48.0
    266 #else
    267 #define LOW_VOLUME_REVERB 40.0f
    268 #endif
    269 
    270 #ifdef VERSION_JP
    271 #define VOLUME_RANGE_UNK1 0.8f
    272 #define VOLUME_RANGE_UNK2 1.0f
    273 #else
    274 #define VOLUME_RANGE_UNK1 0.9f
    275 #define VOLUME_RANGE_UNK2 0.8f
    276 #endif
    277 
    278 // Default volume for background music sequences (playing on player 0).
    279 u8 sBackgroundMusicDefaultVolume[] = {
    280     127, // SEQ_SOUND_PLAYER
    281     80,  // SEQ_EVENT_CUTSCENE_COLLECT_STAR
    282     80,  // SEQ_MENU_TITLE_SCREEN
    283     75,  // SEQ_LEVEL_GRASS
    284     70,  // SEQ_LEVEL_INSIDE_CASTLE
    285     75,  // SEQ_LEVEL_WATER
    286     75,  // SEQ_LEVEL_HOT
    287     75,  // SEQ_LEVEL_BOSS_KOOPA
    288     70,  // SEQ_LEVEL_SNOW
    289     65,  // SEQ_LEVEL_SLIDE
    290     80,  // SEQ_LEVEL_SPOOKY
    291     65,  // SEQ_EVENT_PIRANHA_PLANT
    292     85,  // SEQ_LEVEL_UNDERGROUND
    293     75,  // SEQ_MENU_STAR_SELECT
    294     65,  // SEQ_EVENT_POWERUP
    295     70,  // SEQ_EVENT_METAL_CAP
    296     65,  // SEQ_EVENT_KOOPA_MESSAGE
    297     70,  // SEQ_LEVEL_KOOPA_ROAD
    298     70,  // SEQ_EVENT_HIGH_SCORE
    299     65,  // SEQ_EVENT_MERRY_GO_ROUND
    300     80,  // SEQ_EVENT_RACE
    301     70,  // SEQ_EVENT_CUTSCENE_STAR_SPAWN
    302     85,  // SEQ_EVENT_BOSS
    303     75,  // SEQ_EVENT_CUTSCENE_COLLECT_KEY
    304     75,  // SEQ_EVENT_ENDLESS_STAIRS
    305     85,  // SEQ_LEVEL_BOSS_KOOPA_FINAL
    306     70,  // SEQ_EVENT_CUTSCENE_CREDITS
    307     80,  // SEQ_EVENT_SOLVE_PUZZLE
    308     80,  // SEQ_EVENT_TOAD_MESSAGE
    309     70,  // SEQ_EVENT_PEACH_MESSAGE
    310     75,  // SEQ_EVENT_CUTSCENE_INTRO
    311     80,  // SEQ_EVENT_CUTSCENE_VICTORY
    312     70,  // SEQ_EVENT_CUTSCENE_ENDING
    313     65,  // SEQ_MENU_FILE_SELECT
    314     0,   // SEQ_EVENT_CUTSCENE_LAKITU (not in JP)
    315 };
    316 
    317 STATIC_ASSERT(ARRAY_COUNT(sBackgroundMusicDefaultVolume) == SEQ_COUNT,
    318               "change this array if you are adding sequences");
    319 
    320 u8 sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
    321 u8 sMusicDynamicDelay = 0;
    322 u8 sSoundBankUsedListBack[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    323 u8 sSoundBankFreeListFront[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    324 u8 sNumSoundsInBank[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // only used for debugging
    325 u8 sMaxChannelsForSoundBank[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    326 
    327 // Banks 2 and 7 both grew from 0x30 sounds to 0x40 in size in US.
    328 #ifdef VERSION_JP
    329 #define BANK27_SIZE 0x30
    330 #else
    331 #define BANK27_SIZE 0x40
    332 #endif
    333 u8 sNumSoundsPerBank[SOUND_BANK_COUNT] = {
    334     0x70, 0x30, BANK27_SIZE, 0x80, 0x20, 0x80, 0x20, BANK27_SIZE, 0x80, 0x80,
    335 };
    336 #undef BANK27_SIZE
    337 
    338 // sBackgroundMusicMaxTargetVolume and sBackgroundMusicTargetVolume use the 0x80
    339 // bit to indicate that they are set, and the rest of the bits for the actual value
    340 #define TARGET_VOLUME_IS_PRESENT_FLAG 0x80
    341 #define TARGET_VOLUME_VALUE_MASK 0x7f
    342 #define TARGET_VOLUME_UNSET 0x00
    343 
    344 f32 gGlobalSoundSource[3] = { 0.0f, 0.0f, 0.0f };
    345 f32 sUnusedSoundArgs[3] = { 1.0f, 1.0f, 1.0f };
    346 u8 sSoundBankDisabled[16] = { 0 };
    347 u8 D_80332108 = 0;
    348 u8 sHasStartedFadeOut = FALSE;
    349 u16 sSoundBanksThatLowerBackgroundMusic = 0;
    350 u8 sUnused80332114 = 0;  // never read, set to 0
    351 u16 sUnused80332118 = 0; // never read, set to 0
    352 u8 sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
    353 u8 D_80332120 = 0;
    354 u8 D_80332124 = 0;
    355 
    356 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    357 u8 D_EU_80300558 = 0;
    358 #endif
    359 
    360 u8 sBackgroundMusicQueueSize = 0;
    361 
    362 #ifndef VERSION_JP
    363 u8 sUnused8033323C = 0; // never read, set to 0
    364 #endif
    365 
    366 
    367 // bss
    368 #if defined(VERSION_JP) || defined(VERSION_US)
    369 s16 *gCurrAiBuffer;
    370 #endif
    371 #if defined(VERSION_SH) || defined(VERSION_CN)
    372 s8 D_SH_80343CD0_pad[0x20];
    373 s32 D_SH_80343CF0;
    374 s8 D_SH_80343CF8_pad[0x8];
    375 struct UnkStruct80343D00 D_SH_80343D00;
    376 s8 D_SH_8034DC8_pad[0x8];
    377 OSPiHandle DriveRomHandle; // used in osDriveRomInit.c. Why here?
    378 s8 D_SH_80343E48_pad[0x8];
    379 #endif
    380 
    381 struct Sound sSoundRequests[0x100];
    382 // Curiously, this has size 3, despite SEQUENCE_PLAYERS == 4 on EU
    383 struct ChannelVolumeScaleFade D_80360928[3][CHANNELS_MAX];
    384 u8 sUsedChannelsForSoundBank[SOUND_BANK_COUNT];
    385 u8 sCurrentSound[SOUND_BANK_COUNT][MAX_CHANNELS_PER_SOUND_BANK]; // index into sSoundBanks
    386 
    387 /**
    388  * For each sound bank, a pool containing the currently active sounds for that bank.
    389  * The free and used slots in these pools are linked lists. The element sSoundBanks[bank][0]
    390  * is used as a list header for the used list, and never holds an actual sound. See also
    391  * sSoundBankUsedListBack and sSoundBankFreeListFront.
    392  */
    393 struct SoundCharacteristics sSoundBanks[SOUND_BANK_COUNT][40];
    394 
    395 u8 sSoundMovingSpeed[SOUND_BANK_COUNT];
    396 u8 sBackgroundMusicTargetVolume;
    397 static u8 sLowerBackgroundMusicVolume;
    398 struct SequenceQueueItem sBackgroundMusicQueue[MAX_BACKGROUND_MUSIC_QUEUE_SIZE];
    399 
    400 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    401 s32 unk_sh_8034754C;
    402 #endif
    403 
    404 #ifdef VERSION_EU
    405 OSMesgQueue OSMesgQueue0;
    406 OSMesgQueue OSMesgQueue1;
    407 OSMesgQueue OSMesgQueue2;
    408 OSMesgQueue OSMesgQueue3;
    409 extern OSMesgQueue *OSMesgQueues[];
    410 
    411 struct EuAudioCmd sAudioCmd[0x100];
    412 
    413 OSMesg OSMesg0;
    414 s32 pad1; // why is there 1 s32 here
    415 OSMesg OSMesg1;
    416 s32 pad2[2];    // it's not just that the struct is bigger than we think, because there are 2 here
    417 OSMesg OSMesg2; // and none here. wth nintendo
    418 OSMesg OSMesg3;
    419 #else // VERSION_SH
    420 extern OSMesgQueue *D_SH_80350F88;
    421 extern OSMesgQueue *D_SH_80350FA8;
    422 #endif
    423 
    424 #ifdef VERSION_JP
    425 typedef u16 FadeT;
    426 #else
    427 typedef s32 FadeT;
    428 #endif
    429 
    430 // some sort of main thread -> sound thread dispatchers
    431 extern void func_802ad728(u32 bits, f32 arg);
    432 extern void func_802ad74c(u32 bits, u32 arg);
    433 extern void func_802ad770(u32 bits, s8 arg);
    434 
    435 static void update_background_music_after_sound(u8 bank, u8 soundIndex);
    436 static void update_game_sound(void);
    437 static void fade_channel_volume_scale(u8 player, u8 channelId, u8 targetScale, u16 fadeTimer);
    438 void process_level_music_dynamics(void);
    439 static u8 begin_background_music_fade(u16 fadeDuration);
    440 void func_80320ED8(void);
    441 
    442 #ifndef VERSION_JP
    443 void unused_8031E4F0(void) {
    444     // This is a debug function which is almost entirely optimized away,
    445     // except for loops, string literals, and a read of a volatile variable.
    446     // The string literals have allowed it to be partially reconstructed.
    447     s32 i;
    448 
    449     stubbed_printf("AUTOSEQ ");
    450     stubbed_printf("%2x %2x <%5x : %5x / %5x>\n", gSeqLoadedPool.temporary.entries[0].id,
    451                    gSeqLoadedPool.temporary.entries[1].id, gSeqLoadedPool.temporary.entries[0].size,
    452                    gSeqLoadedPool.temporary.entries[1].size, gSeqLoadedPool.temporary.pool.size);
    453 
    454     stubbed_printf("AUTOBNK ");
    455     stubbed_printf("%2x %3x <%5x : %5x / %5x>\n", gBankLoadedPool.temporary.entries[0].id,
    456                    gBankLoadedPool.temporary.entries[1].id, gBankLoadedPool.temporary.entries[0].size,
    457                    gBankLoadedPool.temporary.entries[1].size, gBankLoadedPool.temporary.pool.size);
    458 
    459     stubbed_printf("STAYSEQ ");
    460     stubbed_printf("[%2x] <%5x / %5x>\n", gSeqLoadedPool.persistent.numEntries,
    461                    gSeqLoadedPool.persistent.pool.cur - gSeqLoadedPool.persistent.pool.start,
    462                    gSeqLoadedPool.persistent.pool.size);
    463     for (i = 0; (u32) i < gSeqLoadedPool.persistent.numEntries; i++) {
    464         stubbed_printf("%2x ", gSeqLoadedPool.persistent.entries[i].id);
    465     }
    466     stubbed_printf("\n");
    467 
    468     stubbed_printf("STAYBNK ");
    469     stubbed_printf("[%2x] <%5x / %5x>\n", gBankLoadedPool.persistent.numEntries,
    470                    gBankLoadedPool.persistent.pool.cur - gBankLoadedPool.persistent.pool.start,
    471                    gBankLoadedPool.persistent.pool.size);
    472     for (i = 0; (u32) i < gBankLoadedPool.persistent.numEntries; i++) {
    473         stubbed_printf("%2x ", gBankLoadedPool.persistent.entries[i].id);
    474     }
    475     stubbed_printf("\n\n");
    476 
    477     stubbed_printf("    0123456789ABCDEF0123456789ABCDEF01234567\n");
    478     stubbed_printf("--------------------------------------------\n");
    479 
    480     // gSeqLoadStatus/gBankLoadStatus, 4 entries at a time?
    481     stubbed_printf("SEQ ");
    482     for (i = 0; i < 40; i++) {
    483         stubbed_printf("%1x", 0);
    484     }
    485     stubbed_printf("\n");
    486 
    487     stubbed_printf("BNK ");
    488     for (i = 0; i < 40; i += 4) {
    489         stubbed_printf("%1x", 0);
    490     }
    491     stubbed_printf("\n");
    492 
    493     stubbed_printf("FIXHEAP ");
    494     stubbed_printf("%4x / %4x\n", 0, 0);
    495     stubbed_printf("DRVHEAP ");
    496     stubbed_printf("%5x / %5x\n", 0, 0);
    497     stubbed_printf("DMACACHE  %4d Blocks\n", 0);
    498     stubbed_printf("CHANNELS  %2d / MAX %3d \n", 0, 0);
    499 
    500     stubbed_printf("TEMPOMAX  %d\n", gTempoInternalToExternal / TEMPO_SCALE);
    501     stubbed_printf("TEMPO G0  %d\n", gSequencePlayers[SEQ_PLAYER_LEVEL].tempo / TEMPO_SCALE);
    502     stubbed_printf("TEMPO G1  %d\n", gSequencePlayers[SEQ_PLAYER_ENV].tempo / TEMPO_SCALE);
    503     stubbed_printf("TEMPO G2  %d\n", gSequencePlayers[SEQ_PLAYER_SFX].tempo / TEMPO_SCALE);
    504     stubbed_printf("DEBUGFLAG  %8x\n", gAudioErrorFlags);
    505 }
    506 
    507 void unused_8031E568(void) {
    508     stubbed_printf("COUNT %8d\n", gAudioFrameCount);
    509 }
    510 #endif
    511 
    512 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    513 const char unusedErrorStr1[] = "Error : Queue is not empty ( %x ) \n";
    514 const char unusedErrorStr2[] = "specchg error\n";
    515 #endif
    516 
    517 /**
    518  * Fade out a sequence player
    519  * Called from threads: thread5_game_loop
    520  */
    521 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    522 void audio_reset_session_eu(s32 presetId) {
    523     OSMesg mesg;
    524 #if defined(VERSION_SH) || defined(VERSION_CN)
    525     osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_NOBLOCK);
    526     osSendMesg(D_SH_80350F88, (OSMesg) presetId, OS_MESG_NOBLOCK);
    527     osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_BLOCK);
    528     if ((s32) mesg != presetId) {
    529         osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_BLOCK);
    530     }
    531 
    532 #else
    533     osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_NOBLOCK);
    534     osSendMesg(OSMesgQueues[2], (OSMesg) presetId, OS_MESG_NOBLOCK);
    535     osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_BLOCK);
    536     if ((s32) mesg != presetId) {
    537         osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_BLOCK);
    538     }
    539 #endif
    540 }
    541 #endif
    542 
    543 #if defined(VERSION_JP) || defined(VERSION_US)
    544 /**
    545  * Called from threads: thread3_main, thread5_game_loop
    546  */
    547 static void seq_player_fade_to_zero_volume(s32 player, FadeT fadeDuration) {
    548     struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
    549 
    550 #ifndef VERSION_JP
    551     // fadeDuration is never 0 in practice
    552     if (fadeDuration == 0) {
    553         fadeDuration++;
    554     }
    555 #endif
    556 
    557     seqPlayer->fadeVelocity = -(seqPlayer->fadeVolume / fadeDuration);
    558     seqPlayer->state = SEQUENCE_PLAYER_STATE_FADE_OUT;
    559     seqPlayer->fadeRemainingFrames = fadeDuration;
    560 }
    561 
    562 /**
    563  * Called from threads: thread4_sound, thread5_game_loop
    564  */
    565 static void func_8031D690(s32 player, FadeT fadeInTime) {
    566     struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
    567 
    568     if (fadeInTime == 0 || seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
    569         return;
    570     }
    571 
    572     seqPlayer->state = SEQUENCE_PLAYER_STATE_2;
    573     seqPlayer->fadeRemainingFrames = fadeInTime;
    574     seqPlayer->fadeVolume = 0.0f;
    575     seqPlayer->fadeVelocity = 0.0f;
    576 }
    577 #endif
    578 
    579 /**
    580  * Called from threads: thread5_game_loop
    581  */
    582 static void seq_player_fade_to_percentage_of_volume(s32 player, FadeT fadeDuration, u8 percentage) {
    583     struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
    584     f32 targetVolume;
    585 
    586 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    587     if (seqPlayer->state == 2) {
    588         return;
    589     }
    590 #else
    591     if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
    592         return;
    593     }
    594 #endif
    595 
    596     targetVolume = (FLOAT_CAST(percentage) / EU_FLOAT(100.0)) * seqPlayer->fadeVolume;
    597     seqPlayer->volume = seqPlayer->fadeVolume;
    598 
    599     seqPlayer->fadeRemainingFrames = 0;
    600     if (fadeDuration == 0) {
    601         seqPlayer->fadeVolume = targetVolume;
    602         return;
    603     }
    604     seqPlayer->fadeVelocity = (targetVolume - seqPlayer->fadeVolume) / fadeDuration;
    605 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    606     seqPlayer->state = 0;
    607 #else
    608     seqPlayer->state = SEQUENCE_PLAYER_STATE_4;
    609 #endif
    610 
    611     seqPlayer->fadeRemainingFrames = fadeDuration;
    612 }
    613 
    614 /**
    615  * Called from threads: thread3_main, thread4_sound, thread5_game_loop
    616  */
    617 static void seq_player_fade_to_normal_volume(s32 player, FadeT fadeDuration) {
    618     struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
    619 
    620 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    621     if (seqPlayer->state == 2) {
    622         return;
    623     }
    624 #else
    625     if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
    626         return;
    627     }
    628 #endif
    629 
    630     seqPlayer->fadeRemainingFrames = 0;
    631     if (fadeDuration == 0) {
    632         seqPlayer->fadeVolume = seqPlayer->volume;
    633         return;
    634     }
    635     seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / fadeDuration;
    636 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    637     seqPlayer->state = 0;
    638 #else
    639     seqPlayer->state = SEQUENCE_PLAYER_STATE_2;
    640 #endif
    641 
    642     seqPlayer->fadeRemainingFrames = fadeDuration;
    643 }
    644 
    645 /**
    646  * Called from threads: thread3_main, thread4_sound, thread5_game_loop
    647  */
    648 static void seq_player_fade_to_target_volume(s32 player, FadeT fadeDuration, u8 targetVolume) {
    649     struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
    650 
    651 #if defined(VERSION_JP) || defined(VERSION_US)
    652     if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
    653         return;
    654     }
    655 #endif
    656 
    657     seqPlayer->fadeRemainingFrames = 0;
    658     if (fadeDuration == 0) {
    659         seqPlayer->fadeVolume = (FLOAT_CAST(targetVolume) / EU_FLOAT(127.0));
    660         return;
    661     }
    662 
    663     seqPlayer->fadeVelocity =
    664         (((f32)(FLOAT_CAST(targetVolume) / EU_FLOAT(127.0)) - seqPlayer->fadeVolume)
    665          / (f32) fadeDuration);
    666 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    667     seqPlayer->state = 0;
    668 #else
    669     seqPlayer->state = SEQUENCE_PLAYER_STATE_4;
    670 #endif
    671 
    672     seqPlayer->fadeRemainingFrames = fadeDuration;
    673 }
    674 
    675 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
    676 #ifdef VERSION_EU
    677 extern void func_802ad7a0(void);
    678 #else
    679 extern void func_sh_802F64C8(void);
    680 #endif
    681 
    682 /**
    683  * Called from threads: thread5_game_loop
    684  */
    685 void maybe_tick_game_sound(void) {
    686     if (sGameLoopTicked != 0) {
    687         update_game_sound();
    688         sGameLoopTicked = 0;
    689     }
    690 #ifdef VERSION_EU
    691     func_802ad7a0();
    692 #else
    693     func_sh_802F64C8(); // moved in SH
    694 #endif
    695 }
    696 
    697 void func_eu_802e9bec(s32 player, s32 channel, s32 arg2) {
    698     // EU verson of unused_803209D8
    699     // chan->stopSomething2 = arg2?
    700     func_802ad770(0x08000000 | (player & 0xff) << 16 | (channel & 0xff) << 8, (s8) arg2);
    701 }
    702 
    703 #else
    704 
    705 /**
    706  * Called from threads: thread4_sound
    707  */
    708 struct SPTask *create_next_audio_frame_task(void) {
    709     u32 samplesRemainingInAI;
    710     s32 writtenCmds;
    711     s32 index;
    712     OSTask_t *task;
    713     s32 oldDmaCount;
    714     s32 flags;
    715 
    716     gAudioFrameCount++;
    717     if (gAudioLoadLock != AUDIO_LOCK_NOT_LOADING) {
    718         stubbed_printf("DAC:Lost 1 Frame.\n");
    719         return NULL;
    720     }
    721 
    722     gAudioTaskIndex ^= 1;
    723     gCurrAiBufferIndex++;
    724     gCurrAiBufferIndex %= NUMAIBUFFERS;
    725     index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
    726     samplesRemainingInAI = osAiGetLength() / 4;
    727 
    728     // Audio is triple buffered; the audio interface reads from two buffers
    729     // while the third is being written by the RSP. More precisely, the
    730     // lifecycle is:
    731     // - this function computes an audio command list
    732     // - wait for vblank
    733     // - the command list is sent to the RSP (we could have sent it to the
    734     //   RSP before the vblank, but that gives the RSP less time to finish)
    735     // - wait for vblank
    736     // - the RSP is now expected to be finished, and we can send its output
    737     //   on to the AI
    738     // Here we thus send to the AI the sound that was generated two frames ago.
    739     if (gAiBufferLengths[index] != 0) {
    740         osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
    741     }
    742 
    743     oldDmaCount = gCurrAudioFrameDmaCount;
    744     // There has to be some sort of no-op if here, but it's not exactly clear
    745     // how it should look... It's also very unclear why gCurrAudioFrameDmaQueue
    746     // isn't read from here, despite gCurrAudioFrameDmaCount being reset.
    747     if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
    748         stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
    749     }
    750     gCurrAudioFrameDmaCount = 0;
    751 
    752     gAudioTask = &gAudioTasks[gAudioTaskIndex];
    753     gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
    754 
    755     index = gCurrAiBufferIndex;
    756     gCurrAiBuffer = gAiBuffers[index];
    757     gAiBufferLengths[index] =
    758         ((gSamplesPerFrameTarget - samplesRemainingInAI + EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf)
    759         + SAMPLES_TO_OVERPRODUCE;
    760     if (gAiBufferLengths[index] < gMinAiBufferLength) {
    761         gAiBufferLengths[index] = gMinAiBufferLength;
    762     }
    763     if (gAiBufferLengths[index] > gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE) {
    764         gAiBufferLengths[index] = gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE;
    765     }
    766 
    767     if (sGameLoopTicked != 0) {
    768         update_game_sound();
    769         sGameLoopTicked = 0;
    770     }
    771 
    772     // For the function to match we have to preserve some arbitrary variable
    773     // across this function call.
    774     flags = 0;
    775     gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, gCurrAiBuffer, gAiBufferLengths[index]);
    776     gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
    777 
    778     index = gAudioTaskIndex;
    779     gAudioTask->msgqueue = NULL;
    780     gAudioTask->msg = NULL;
    781 
    782     task = &gAudioTask->task.t;
    783     task->type = M_AUDTASK;
    784     task->flags = flags;
    785     task->ucode_boot = rspF3DBootStart;
    786     task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
    787     task->ucode = rspAspMainStart;
    788     task->ucode_size = 0x800; // (this size is ignored)
    789     task->ucode_data = rspAspMainDataStart;
    790     task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
    791     task->dram_stack = NULL;
    792     task->dram_stack_size = 0;
    793     task->output_buff = NULL;
    794     task->output_buff_size = NULL;
    795     task->data_ptr = gAudioCmdBuffers[index];
    796     task->data_size = writtenCmds * sizeof(u64);
    797 
    798 // The audio task never yields, so having a yield buffer is pointless.
    799 // This wastefulness was fixed in US.
    800 #ifdef VERSION_JP
    801     task->yield_data_ptr = (u64 *) gAudioSPTaskYieldBuffer;
    802     task->yield_data_size = OS_YIELD_AUDIO_SIZE;
    803 #else
    804     task->yield_data_ptr = NULL;
    805     task->yield_data_size = 0;
    806 #endif
    807 
    808     decrease_sample_dma_ttls();
    809     return gAudioTask;
    810 }
    811 #endif
    812 
    813 /**
    814  * Called from threads: thread5_game_loop
    815  */
    816 void play_sound(s32 soundBits, f32 *pos) {
    817     sSoundRequests[sSoundRequestCount].soundBits = soundBits;
    818     sSoundRequests[sSoundRequestCount].position = pos;
    819     sSoundRequestCount++;
    820 }
    821 
    822 /**
    823  * Called from threads: thread4_sound, thread5_game_loop (EU only)
    824  */
    825 static void process_sound_request(u32 bits, f32 *pos) {
    826     u8 bank;
    827     u8 soundIndex;
    828     u8 counter = 0;
    829     u8 soundId;
    830     f32 dist;
    831     const f32 one = 1.0f;
    832 
    833     bank = (bits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
    834     soundId = (bits & SOUNDARGS_MASK_SOUNDID) >> SOUNDARGS_SHIFT_SOUNDID;
    835 
    836     if (soundId >= sNumSoundsPerBank[bank] || sSoundBankDisabled[bank]) {
    837         return;
    838     }
    839 
    840     soundIndex = sSoundBanks[bank][0].next;
    841     while (soundIndex != 0xff && soundIndex != 0) {
    842         // If an existing sound from the same source exists in the bank, then we should either
    843         // interrupt that sound and replace it with the new sound, or we should drop the new sound.
    844         if (sSoundBanks[bank][soundIndex].x == pos) {
    845             // If the existing sound has lower or equal priority, then we should replace it.
    846             // Otherwise the new sound will be dropped.
    847             if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_PRIORITY)
    848                 <= (bits & SOUNDARGS_MASK_PRIORITY)) {
    849 
    850                 // If the existing sound is discrete or is a different continuous sound, then
    851                 // interrupt it and play the new sound instead.
    852                 // Otherwise the new sound is continuous and equals the existing sound, so we just
    853                 // need to update the sound's freshness.
    854                 if ((sSoundBanks[bank][soundIndex].soundBits & SOUND_DISCRETE) != 0
    855                     || (bits & SOUNDARGS_MASK_SOUNDID)
    856                            != (sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)) {
    857                     update_background_music_after_sound(bank, soundIndex);
    858                     sSoundBanks[bank][soundIndex].soundBits = bits;
    859                     // In practice, the starting status is always WAITING
    860                     sSoundBanks[bank][soundIndex].soundStatus = bits & SOUNDARGS_MASK_STATUS;
    861                 }
    862 
    863                 // Reset freshness:
    864                 // - For discrete sounds, this gives the sound SOUND_MAX_FRESHNESS frames to play
    865                 //   before it gets deleted for being stale
    866                 // - For continuous sounds, this gives it another 2 frames before play_sound must
    867                 //   be called again to keep it playing
    868                 sSoundBanks[bank][soundIndex].freshness = SOUND_MAX_FRESHNESS;
    869             }
    870 
    871             // Prevent allocating a new node - if the existing sound had higher piority, then the
    872             // new sound will be dropped
    873             soundIndex = 0;
    874         } else {
    875             soundIndex = sSoundBanks[bank][soundIndex].next;
    876         }
    877         counter++;
    878     }
    879 
    880     if (counter == 0) {
    881         sSoundMovingSpeed[bank] = 32;
    882     }
    883 
    884     // If free list has more than one element remaining
    885     if (sSoundBanks[bank][sSoundBankFreeListFront[bank]].next != 0xff && soundIndex != 0) {
    886         // Allocate from free list
    887         soundIndex = sSoundBankFreeListFront[bank];
    888 
    889         dist = sqrtf(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]) * one;
    890         sSoundBanks[bank][soundIndex].x = &pos[0];
    891         sSoundBanks[bank][soundIndex].y = &pos[1];
    892         sSoundBanks[bank][soundIndex].z = &pos[2];
    893         sSoundBanks[bank][soundIndex].distance = dist;
    894         sSoundBanks[bank][soundIndex].soundBits = bits;
    895         // In practice, the starting status is always WAITING
    896         sSoundBanks[bank][soundIndex].soundStatus = bits & SOUNDARGS_MASK_STATUS;
    897         sSoundBanks[bank][soundIndex].freshness = SOUND_MAX_FRESHNESS;
    898 
    899         // Append to end of used list and pop from front of free list
    900         sSoundBanks[bank][soundIndex].prev = sSoundBankUsedListBack[bank];
    901         sSoundBanks[bank][sSoundBankUsedListBack[bank]].next = sSoundBankFreeListFront[bank];
    902         sSoundBankUsedListBack[bank] = sSoundBankFreeListFront[bank];
    903         sSoundBankFreeListFront[bank] = sSoundBanks[bank][sSoundBankFreeListFront[bank]].next;
    904         sSoundBanks[bank][sSoundBankFreeListFront[bank]].prev = 0xff;
    905         sSoundBanks[bank][soundIndex].next = 0xff;
    906     }
    907 }
    908 
    909 /**
    910  * Processes all sound requests
    911  *
    912  * Called from threads: thread4_sound, thread5_game_loop (EU only)
    913  */
    914 static void process_all_sound_requests(void) {
    915     struct Sound *sound;
    916 
    917     while (sSoundRequestCount != sNumProcessedSoundRequests) {
    918         sound = &sSoundRequests[sNumProcessedSoundRequests];
    919         process_sound_request(sound->soundBits, sound->position);
    920         sNumProcessedSoundRequests++;
    921     }
    922 }
    923 
    924 /**
    925  * Called from threads: thread4_sound, thread5_game_loop (EU only)
    926  */
    927 static void delete_sound_from_bank(u8 bank, u8 soundIndex) {
    928     if (sSoundBankUsedListBack[bank] == soundIndex) {
    929         // Remove from end of used list
    930         sSoundBankUsedListBack[bank] = sSoundBanks[bank][soundIndex].prev;
    931     } else {
    932         // Set sound.next.prev to sound.prev
    933         sSoundBanks[bank][sSoundBanks[bank][soundIndex].next].prev = sSoundBanks[bank][soundIndex].prev;
    934     }
    935 
    936     // Set sound.prev.next to sound.next
    937     sSoundBanks[bank][sSoundBanks[bank][soundIndex].prev].next = sSoundBanks[bank][soundIndex].next;
    938 
    939     // Push to front of free list
    940     sSoundBanks[bank][soundIndex].next = sSoundBankFreeListFront[bank];
    941     sSoundBanks[bank][soundIndex].prev = 0xff;
    942     sSoundBanks[bank][sSoundBankFreeListFront[bank]].prev = soundIndex;
    943     sSoundBankFreeListFront[bank] = soundIndex;
    944 }
    945 
    946 /**
    947  * Called from threads: thread3_main, thread4_sound, thread5_game_loop
    948  */
    949 static void update_background_music_after_sound(u8 bank, u8 soundIndex) {
    950     if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
    951         sSoundBanksThatLowerBackgroundMusic &= (1 << bank) ^ 0xffff;
    952         begin_background_music_fade(50);
    953     }
    954 }
    955 
    956 /**
    957  * Called from threads: thread4_sound, thread5_game_loop (EU only)
    958  */
    959 static void select_current_sounds(u8 bank) {
    960     u32 isDiscreteAndStatus;
    961     u8 latestSoundIndex;
    962     u8 i;
    963     u8 j;
    964     u8 soundIndex;
    965     u32 liveSoundPriorities[16] = { 0x10000000, 0x10000000, 0x10000000, 0x10000000,
    966                                     0x10000000, 0x10000000, 0x10000000, 0x10000000,
    967                                     0x10000000, 0x10000000, 0x10000000, 0x10000000,
    968                                     0x10000000, 0x10000000, 0x10000000, 0x10000000 };
    969     u8 liveSoundIndices[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    970                                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    971     u8 liveSoundStatuses[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    972                                  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    973     u8 numSoundsInBank = 0;
    974     u8 requestedPriority;
    975 
    976     //
    977     // Delete stale sounds and prioritize remaining sounds into the liveSound arrays
    978     //
    979     soundIndex = sSoundBanks[bank][0].next;
    980     while (soundIndex != 0xff) {
    981         latestSoundIndex = soundIndex;
    982 
    983         // If a discrete sound goes 10 frames without being played (because it is too low
    984         // priority), then mark it for deletion
    985         if ((sSoundBanks[bank][soundIndex].soundBits & (SOUND_DISCRETE | SOUNDARGS_MASK_STATUS))
    986             == (SOUND_DISCRETE | SOUND_STATUS_WAITING)) {
    987             if (sSoundBanks[bank][soundIndex].freshness-- == 0) {
    988                 sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
    989             }
    990         }
    991         // If a continuous sound goes 2 frames without play_sound being called, then mark it for
    992         // deletion
    993         else if ((sSoundBanks[bank][soundIndex].soundBits & SOUND_DISCRETE) == 0) {
    994             if (sSoundBanks[bank][soundIndex].freshness-- == SOUND_MAX_FRESHNESS - 2) {
    995                 update_background_music_after_sound(bank, soundIndex);
    996                 sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
    997             }
    998         }
    999 
   1000         // If a sound was marked for deletion and hasn't started playing yet, delete it now
   1001         if (sSoundBanks[bank][soundIndex].soundBits == NO_SOUND
   1002             && sSoundBanks[bank][soundIndex].soundStatus == SOUND_STATUS_WAITING) {
   1003             // Since the current sound will be deleted, the next iteration should process
   1004             // sound.prev.next
   1005             latestSoundIndex = sSoundBanks[bank][soundIndex].prev;
   1006             sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
   1007             delete_sound_from_bank(bank, soundIndex);
   1008         }
   1009 
   1010         // If the current sound was not just deleted, consider it as a candidate for the currently
   1011         // playing sound
   1012         if (sSoundBanks[bank][soundIndex].soundStatus != SOUND_STATUS_STOPPED
   1013             && soundIndex == latestSoundIndex) {
   1014 
   1015             // Recompute distance each frame since the sound's position may have changed
   1016             sSoundBanks[bank][soundIndex].distance =
   1017                 sqrtf((*sSoundBanks[bank][soundIndex].x * *sSoundBanks[bank][soundIndex].x)
   1018                       + (*sSoundBanks[bank][soundIndex].y * *sSoundBanks[bank][soundIndex].y)
   1019                       + (*sSoundBanks[bank][soundIndex].z * *sSoundBanks[bank][soundIndex].z))
   1020                 * 1;
   1021 
   1022             requestedPriority = (sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_PRIORITY)
   1023                                 >> SOUNDARGS_SHIFT_PRIORITY;
   1024 
   1025             // Recompute priority, possibly based on the sound's source position relative to the
   1026             // camera.
   1027             // (Note that the sound's priority is the opposite of requestedPriority; lower is
   1028             // more important)
   1029             if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_PRIORITY_LOSS) {
   1030                 sSoundBanks[bank][soundIndex].priority = 0x4c * (0xff - requestedPriority);
   1031             } else if (*sSoundBanks[bank][soundIndex].z > 0.0f) {
   1032                 sSoundBanks[bank][soundIndex].priority =
   1033                     (u32) sSoundBanks[bank][soundIndex].distance
   1034                     + (u32)(*sSoundBanks[bank][soundIndex].z / US_FLOAT(6.0))
   1035                     + 0x4c * (0xff - requestedPriority);
   1036             } else {
   1037                 sSoundBanks[bank][soundIndex].priority =
   1038                     (u32) sSoundBanks[bank][soundIndex].distance + 0x4c * (0xff - requestedPriority);
   1039             }
   1040 
   1041             // Insert the sound into the liveSound arrays, keeping the arrays sorted by priority.
   1042             // If more than sMaxChannelsForSoundBank[bank] sounds are live, then the
   1043             // sound with lowest priority will be removed from the arrays.
   1044             // In practice sMaxChannelsForSoundBank is always 1, so this code is overly general.
   1045             for (i = 0; i < sMaxChannelsForSoundBank[bank]; i++) {
   1046                 // If the correct position is found
   1047                 if (liveSoundPriorities[i] >= sSoundBanks[bank][soundIndex].priority) {
   1048                     // Shift remaining sounds to the right
   1049                     for (j = sMaxChannelsForSoundBank[bank] - 1; j > i; j--) {
   1050                         liveSoundPriorities[j] = liveSoundPriorities[j - 1];
   1051                         liveSoundIndices[j] = liveSoundIndices[j - 1];
   1052                         liveSoundStatuses[j] = liveSoundStatuses[j - 1];
   1053                     }
   1054                     // Insert the sound at index i
   1055                     liveSoundPriorities[i] = sSoundBanks[bank][soundIndex].priority;
   1056                     liveSoundIndices[i] = soundIndex;
   1057                     liveSoundStatuses[i] = sSoundBanks[bank][soundIndex].soundStatus; // unused
   1058                     // Break
   1059                     i = sMaxChannelsForSoundBank[bank];
   1060                 }
   1061             }
   1062 
   1063             numSoundsInBank++;
   1064         }
   1065 
   1066         soundIndex = sSoundBanks[bank][latestSoundIndex].next;
   1067     }
   1068 
   1069     sNumSoundsInBank[bank] = numSoundsInBank;
   1070     sUsedChannelsForSoundBank[bank] = sMaxChannelsForSoundBank[bank];
   1071 
   1072     //
   1073     // Remove any sounds from liveSoundIndices that are already playing.
   1074     // Stop any currently playing sounds that are not in liveSoundIndices.
   1075     //
   1076     for (i = 0; i < sUsedChannelsForSoundBank[bank]; i++) {
   1077         // Check if sCurrentSound[bank][i] is present in the liveSound arrays.
   1078         for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bank]; soundIndex++) {
   1079             if (liveSoundIndices[soundIndex] != 0xff
   1080                 && sCurrentSound[bank][i] == liveSoundIndices[soundIndex]) {
   1081                 // If found, remove it from liveSoundIndices
   1082                 liveSoundIndices[soundIndex] = 0xff;
   1083                 soundIndex = 0xfe; // Break. Afterward soundIndex will be 0xff
   1084             }
   1085         }
   1086 
   1087         // If it is not present in the liveSound arrays, then stop playing it
   1088         if (soundIndex != 0xff) {
   1089             if (sCurrentSound[bank][i] != 0xff) {
   1090                 // If the sound was marked for deletion and is playing, delete it
   1091                 if (sSoundBanks[bank][sCurrentSound[bank][i]].soundBits == NO_SOUND) {
   1092                     if (sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus == SOUND_STATUS_PLAYING) {
   1093                         sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_STOPPED;
   1094                         delete_sound_from_bank(bank, sCurrentSound[bank][i]);
   1095                     }
   1096                 }
   1097 
   1098                 // If the sound is discrete and is playing, then delete it
   1099                 isDiscreteAndStatus = sSoundBanks[bank][sCurrentSound[bank][i]].soundBits
   1100                                       & (SOUND_DISCRETE | SOUNDARGS_MASK_STATUS);
   1101                 if (isDiscreteAndStatus >= (SOUND_DISCRETE | SOUND_STATUS_PLAYING)
   1102                     && sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus != SOUND_STATUS_STOPPED) {
   1103 //! @bug On JP, if a discrete sound that lowers the background music is
   1104 //  interrupted in this way, it will keep the background music low afterward.
   1105 //  There are only a few of these sounds, and it probably isn't possible to do
   1106 //  it in practice without using a time stop glitch like triple star spawn.
   1107 #ifndef VERSION_JP
   1108                     update_background_music_after_sound(bank, sCurrentSound[bank][i]);
   1109 #endif
   1110 
   1111                     sSoundBanks[bank][sCurrentSound[bank][i]].soundBits = NO_SOUND;
   1112                     sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_STOPPED;
   1113                     delete_sound_from_bank(bank, sCurrentSound[bank][i]);
   1114                 }
   1115                 // If the sound is continuous and is playing, then stop playing it but don't delete
   1116                 // it. (A continuous sound shouldn't be deleted until it stops being requested)
   1117                 else {
   1118                     if (isDiscreteAndStatus == SOUND_STATUS_PLAYING
   1119                         && sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus
   1120                                != SOUND_STATUS_STOPPED) {
   1121                         sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_WAITING;
   1122                     }
   1123                 }
   1124             }
   1125             sCurrentSound[bank][i] = 0xff;
   1126         }
   1127     }
   1128 
   1129     //
   1130     // Start playing the remaining sounds from liveSoundIndices.
   1131     //
   1132     for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bank]; soundIndex++) {
   1133         if (liveSoundIndices[soundIndex] != 0xff) {
   1134             for (i = 0; i < sUsedChannelsForSoundBank[bank]; i++) {
   1135                 if (sCurrentSound[bank][i] == 0xff) {
   1136                     sCurrentSound[bank][i] = liveSoundIndices[soundIndex];
   1137 
   1138                     // Set (soundBits & status) to WAITING (soundStatus will be updated
   1139                     // shortly after in update_game_sound)
   1140                     sSoundBanks[bank][liveSoundIndices[soundIndex]].soundBits =
   1141                         (sSoundBanks[bank][liveSoundIndices[soundIndex]].soundBits
   1142                          & ~SOUNDARGS_MASK_STATUS)
   1143                         + SOUND_STATUS_WAITING;
   1144 
   1145                     liveSoundIndices[i] = 0xff; // doesn't do anything
   1146                     i = 0xfe;                   // break
   1147                 }
   1148             }
   1149         }
   1150     }
   1151 }
   1152 
   1153 /**
   1154  * Given x and z coordinates, return the pan. This is a value nominally between
   1155  * 0 and 1 that represents the audio direction.
   1156  *
   1157  * Pan:
   1158  * 0.0 - fully left
   1159  * 0.5 - center pan
   1160  * 1.0 - fully right
   1161  *
   1162  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   1163  */
   1164 static f32 get_sound_pan(f32 x, f32 z) {
   1165     f32 absX;
   1166     f32 absZ;
   1167     f32 pan;
   1168 
   1169     absX = (x < 0 ? -x : x);
   1170     if (absX > AUDIO_MAX_DISTANCE) {
   1171         absX = AUDIO_MAX_DISTANCE;
   1172     }
   1173 
   1174     absZ = (z < 0 ? -z : z);
   1175     if (absZ > AUDIO_MAX_DISTANCE) {
   1176         absZ = AUDIO_MAX_DISTANCE;
   1177     }
   1178 
   1179     // There are 4 panning equations (12-hr clock used for angles)
   1180     // 1. (0,0) fully-centered pan
   1181     // 2. far right pan: between 1:30 and 4:30
   1182     // 3. far left pan: between 7:30 and 10:30
   1183     // 4. center pan: between 4:30 and 7:30 or between 10:30 and 1:30
   1184     if (x == US_FLOAT(0.0) && z == US_FLOAT(0.0)) {
   1185         // x and z being 0 results in a center pan
   1186         pan = US_FLOAT(0.5);
   1187     } else if (x >= US_FLOAT(0.0) && absX >= absZ) {
   1188         // far right pan
   1189         pan = US_FLOAT(1.0) - (2 * AUDIO_MAX_DISTANCE - absX) / (US_FLOAT(3.0) * (2 * AUDIO_MAX_DISTANCE - absZ));
   1190     } else if (x < 0 && absX > absZ) {
   1191         // far left pan
   1192         pan = (2 * AUDIO_MAX_DISTANCE - absX) / (US_FLOAT(3.0) * (2 * AUDIO_MAX_DISTANCE - absZ));
   1193     } else {
   1194         // center pan
   1195         //! @bug (JP PU sound glitch) If |x|, |z| > AUDIO_MAX_DISTANCE, we'll
   1196         // end up in this case, and pan may be set to something outside of [0,1]
   1197         // since x is not clamped. On JP, this can lead to an out-of-bounds
   1198         // float read in note_set_vel_pan_reverb when x is highly negative,
   1199         // causing console crashes when that float is a nan or denormal.
   1200         pan = 0.5 + x / (US_FLOAT(6.0) * absZ);
   1201     }
   1202 
   1203     return pan;
   1204 }
   1205 
   1206 /**
   1207  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   1208  */
   1209 static f32 get_sound_volume(u8 bank, u8 soundIndex, f32 volumeRange) {
   1210     f32 maxSoundDistance;
   1211     f32 intensity;
   1212 #ifndef VERSION_JP
   1213     s32 div = bank < 3 ? 2 : 3;
   1214 #endif
   1215 
   1216     if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_VOLUME_LOSS)) {
   1217 #ifdef VERSION_JP
   1218         // Intensity linearly lowers from 1 at the camera to 0 at maxSoundDistance
   1219         maxSoundDistance = sLevelAcousticReaches[gCurrLevelNum];
   1220         if (maxSoundDistance < sSoundBanks[bank][soundIndex].distance) {
   1221             intensity = 0.0f;
   1222         } else {
   1223             intensity = 1.0 - sSoundBanks[bank][soundIndex].distance / maxSoundDistance;
   1224         }
   1225 #else
   1226         // Intensity linearly lowers from 1 at the camera to 1 - volumeRange at maxSoundDistance,
   1227         // then it goes from 1 - volumeRange at maxSoundDistance to 0 at AUDIO_MAX_DISTANCE
   1228         if (sSoundBanks[bank][soundIndex].distance > AUDIO_MAX_DISTANCE) {
   1229             intensity = 0.0f;
   1230         } else {
   1231             maxSoundDistance = sLevelAcousticReaches[gCurrLevelNum] / div;
   1232             if (maxSoundDistance < sSoundBanks[bank][soundIndex].distance) {
   1233                 intensity = ((AUDIO_MAX_DISTANCE - sSoundBanks[bank][soundIndex].distance)
   1234                              / (AUDIO_MAX_DISTANCE - maxSoundDistance))
   1235                             * (1.0f - volumeRange);
   1236             } else {
   1237                 intensity =
   1238                     1.0f - sSoundBanks[bank][soundIndex].distance / maxSoundDistance * volumeRange;
   1239             }
   1240         }
   1241 #endif
   1242 
   1243         if (sSoundBanks[bank][soundIndex].soundBits & SOUND_VIBRATO) {
   1244 #ifdef VERSION_JP
   1245             //! @bug Intensity is 0 when the sound is far away. Due to the subtraction below, it is possible to end up with a negative intensity.
   1246             // When it is, objects with a volumeRange of 1 can still occasionally be lightly heard.
   1247             if (intensity != 0.0)
   1248 #else
   1249             if (intensity >= 0.08f)
   1250 #endif
   1251             {
   1252                 intensity -= (f32)(gAudioRandom & 0xf) / US_FLOAT(192.0);
   1253             }
   1254         }
   1255     } else {
   1256         intensity = 1.0f;
   1257     }
   1258 
   1259     // Rise quadratically from 1 - volumeRange to 1
   1260     return volumeRange * intensity * intensity + 1.0f - volumeRange;
   1261 }
   1262 
   1263 /**
   1264  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   1265  */
   1266 static f32 get_sound_freq_scale(u8 bank, u8 item) {
   1267     f32 amount;
   1268 
   1269     if (!(sSoundBanks[bank][item].soundBits & SOUND_CONSTANT_FREQUENCY)) {
   1270         amount = sSoundBanks[bank][item].distance / AUDIO_MAX_DISTANCE;
   1271         if (sSoundBanks[bank][item].soundBits & SOUND_VIBRATO) {
   1272             amount += (f32)(gAudioRandom & 0xff) / US_FLOAT(64.0);
   1273         }
   1274     } else {
   1275         amount = 0.0f;
   1276     }
   1277 
   1278     // Goes from 1 at the camera to 1 + 1/15 at AUDIO_MAX_DISTANCE (and continues rising
   1279     // farther than that)
   1280     return amount / US_FLOAT(15.0) + US_FLOAT(1.0);
   1281 }
   1282 
   1283 /**
   1284  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   1285  */
   1286 static u8 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelIndex) {
   1287     u8 area;
   1288     u8 level;
   1289     u8 reverb;
   1290 
   1291 #ifndef VERSION_JP
   1292     // Disable level reverb if NO_ECHO is set
   1293     if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO) {
   1294         level = 0;
   1295         area = 0;
   1296     } else {
   1297 #endif
   1298         level = (gCurrLevelNum > LEVEL_MAX ? LEVEL_MAX : gCurrLevelNum);
   1299         area = gCurrAreaIndex - 1;
   1300         if (area > 2) {
   1301             area = 2;
   1302         }
   1303 #ifndef VERSION_JP
   1304     }
   1305 #endif
   1306 
   1307     // reverb = reverb adjustment + level reverb + a volume-dependent value
   1308     // The volume-dependent value is 0 when volume is at maximum, and raises to
   1309     // LOW_VOLUME_REVERB when the volume is 0
   1310     reverb = (u8)((u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5]
   1311                   + sLevelAreaReverbs[level][area]
   1312                   + (US_FLOAT(1.0) - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume)
   1313                         * LOW_VOLUME_REVERB);
   1314 
   1315     if (reverb > 0x7f) {
   1316         reverb = 0x7f;
   1317     }
   1318     return reverb;
   1319 }
   1320 
   1321 static void noop_8031EEC8(void) {
   1322 }
   1323 
   1324 /**
   1325  * Called from the game loop thread to inform the audio thread that a new game
   1326  * frame has started.
   1327  *
   1328  * Called from threads: thread5_game_loop
   1329  */
   1330 void audio_signal_game_loop_tick(void) {
   1331     sGameLoopTicked = 1;
   1332 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1333     maybe_tick_game_sound();
   1334 #endif
   1335     noop_8031EEC8();
   1336 }
   1337 
   1338 /**
   1339  * Called from threads: thread4_sound, thread5_game_loop (EU and SH only)
   1340  */
   1341 static void update_game_sound(void) {
   1342     u8 soundStatus;
   1343     u8 i;
   1344     u8 soundId;
   1345     u8 bank;
   1346     u8 channelIndex = 0;
   1347     u8 soundIndex;
   1348 #if defined(VERSION_JP) || defined(VERSION_US)
   1349     f32 value;
   1350 #endif
   1351 
   1352     process_all_sound_requests();
   1353     process_level_music_dynamics();
   1354 
   1355     if (gSequencePlayers[SEQ_PLAYER_SFX].channels[0] == &gSequenceChannelNone) {
   1356         return;
   1357     }
   1358 
   1359     for (bank = 0; bank < SOUND_BANK_COUNT; bank++) {
   1360         select_current_sounds(bank);
   1361 
   1362         for (i = 0; i < MAX_CHANNELS_PER_SOUND_BANK; i++) {
   1363             soundIndex = sCurrentSound[bank][i];
   1364 
   1365             if (soundIndex < 0xff
   1366                 && sSoundBanks[bank][soundIndex].soundStatus != SOUND_STATUS_STOPPED) {
   1367                 soundStatus = sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_STATUS;
   1368                 soundId = (sSoundBanks[bank][soundIndex].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
   1369 
   1370                 sSoundBanks[bank][soundIndex].soundStatus = soundStatus;
   1371 
   1372                 if (soundStatus == SOUND_STATUS_WAITING) {
   1373                     if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
   1374                         sSoundBanksThatLowerBackgroundMusic |= 1 << bank;
   1375                         begin_background_music_fade(50);
   1376                     }
   1377 
   1378                     // Set sound status to PLAYING
   1379                     sSoundBanks[bank][soundIndex].soundBits++;
   1380                     sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_PLAYING;
   1381 
   1382                     // Begin playing the sound
   1383                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[4] = soundId;
   1384                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 1;
   1385 
   1386                     switch (bank) {
   1387                         case SOUND_BANK_MOVING:
   1388                             if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_CONSTANT_FREQUENCY)) {
   1389                                 if (sSoundMovingSpeed[bank] > 8) {
   1390 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1391                                     func_802ad728(
   1392                                         0x02020000 | ((channelIndex & 0xff) << 8),
   1393                                         get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
   1394 #else
   1395                                     value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
   1396                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1397                                         value;
   1398 #endif
   1399                                 } else {
   1400 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1401                                     func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
   1402                                                   get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1)
   1403                                                       * ((sSoundMovingSpeed[bank] + 8.0f) / 16));
   1404 #else
   1405                                     value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
   1406                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1407                                         (sSoundMovingSpeed[bank] + 8.0f) / 16 * value;
   1408 #endif
   1409                                 }
   1410 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1411                                 func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
   1412                                               get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1413                                                             *sSoundBanks[bank][soundIndex].z));
   1414 #else
   1415                                 gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
   1416                                     get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1417                                                   *sSoundBanks[bank][soundIndex].z);
   1418 #endif
   1419 
   1420                                 if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)
   1421                                     == (SOUND_MOVING_FLYING & SOUNDARGS_MASK_SOUNDID)) {
   1422 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1423                                     func_802ad728(
   1424                                         0x04020000 | ((channelIndex & 0xff) << 8),
   1425                                         get_sound_freq_scale(bank, soundIndex)
   1426                                             + ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)));
   1427 #else
   1428                                     value = get_sound_freq_scale(bank, soundIndex);
   1429                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1430                                         ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)) + value;
   1431 #endif
   1432                                 } else {
   1433 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1434                                     func_802ad728(
   1435                                         0x04020000 | ((channelIndex & 0xff) << 8),
   1436                                         get_sound_freq_scale(bank, soundIndex)
   1437                                             + ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)));
   1438 #else
   1439                                     value = get_sound_freq_scale(bank, soundIndex);
   1440                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1441                                         ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)) + value;
   1442 #endif
   1443                                 }
   1444 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1445                                 func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
   1446                                               get_sound_reverb(bank, soundIndex, channelIndex));
   1447 #else
   1448                                 gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
   1449                                     get_sound_reverb(bank, soundIndex, channelIndex);
   1450 #endif
   1451 
   1452                                 break;
   1453                             }
   1454                         // fallthrough
   1455                         case SOUND_BANK_MENU:
   1456 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1457                             func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8), 1);
   1458                             func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8), 64);
   1459                             func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
   1460                                           get_sound_freq_scale(bank, soundIndex));
   1461 #else
   1462                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume = 1.0f;
   1463                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan = 0.5f;
   1464                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale = 1.0f;
   1465 #endif
   1466                             break;
   1467                         case SOUND_BANK_ACTION:
   1468                         case SOUND_BANK_VOICE:
   1469 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1470                             func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
   1471                                           get_sound_reverb(bank, soundIndex, channelIndex));
   1472                             func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
   1473                                           get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
   1474                             func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
   1475                                           get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1476                                                         *sSoundBanks[bank][soundIndex].z)
   1477                                                   * 127.0f
   1478                                               + 0.5f);
   1479                             func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
   1480                                           get_sound_freq_scale(bank, soundIndex));
   1481 #else
   1482                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1483                                 get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
   1484                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
   1485                                 get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1486                                               *sSoundBanks[bank][soundIndex].z);
   1487                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1488                                 get_sound_freq_scale(bank, soundIndex);
   1489                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
   1490                                 get_sound_reverb(bank, soundIndex, channelIndex);
   1491 #endif
   1492                             break;
   1493                         case SOUND_BANK_GENERAL:
   1494                         case SOUND_BANK_ENV:
   1495                         case SOUND_BANK_OBJ:
   1496                         case SOUND_BANK_AIR:
   1497                         case SOUND_BANK_GENERAL2:
   1498                         case SOUND_BANK_OBJ2:
   1499 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1500                             func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
   1501                                           get_sound_reverb(bank, soundIndex, channelIndex));
   1502                             func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
   1503                                           get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2));
   1504                             func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
   1505                                           get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1506                                                         *sSoundBanks[bank][soundIndex].z)
   1507                                                   * 127.0f
   1508                                               + 0.5f);
   1509                             func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
   1510                                           get_sound_freq_scale(bank, soundIndex));
   1511 #else
   1512                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
   1513                                 get_sound_reverb(bank, soundIndex, channelIndex);
   1514                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1515                                 get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2);
   1516                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
   1517                                 get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1518                                               *sSoundBanks[bank][soundIndex].z);
   1519                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1520                                 get_sound_freq_scale(bank, soundIndex);
   1521 #endif
   1522                             break;
   1523                     }
   1524                 }
   1525 #ifdef VERSION_JP
   1526                 // If the sound was marked for deletion (bits set to NO_SOUND), then stop playing it
   1527                 // and delete it
   1528                 // @bug (JP double red coin sound) If the sound finished within the same frame as
   1529                 // being marked for deletion, the signal to stop playing will be interpreted as a
   1530                 // signal to *start* playing, as .main_loop_023589 in 00_sound_player does not check
   1531                 // for soundScriptIO[0] being zero. This happens most commonly for red coin sounds
   1532                 // whose sound spawners deactivate 30 frames after the sound starts to play, while
   1533                 // the sound itself runs for 1.20 seconds. With enough lag these may coincide.
   1534                 // Fixed on US by checking that layer0->finished is FALSE.
   1535                 else if (soundStatus == SOUND_STATUS_STOPPED) {
   1536                     update_background_music_after_sound(bank, soundIndex);
   1537                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 0;
   1538                     delete_sound_from_bank(bank, soundIndex);
   1539                 }
   1540 #else
   1541                 else if (gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->layers[0] == NULL) {
   1542                     update_background_music_after_sound(bank, soundIndex);
   1543                     sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
   1544                     delete_sound_from_bank(bank, soundIndex);
   1545                 } else if (soundStatus == SOUND_STATUS_STOPPED
   1546                            && gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]
   1547                                       ->layers[0]->finished == FALSE) {
   1548                     update_background_music_after_sound(bank, soundIndex);
   1549                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 0;
   1550                     delete_sound_from_bank(bank, soundIndex);
   1551                 }
   1552 #endif
   1553                 // If sound has finished playing, then delete it
   1554                 // @bug (JP sound glitch) On JP, ...->layers[0] has not been checked for null,
   1555                 // so this access can crash if an earlier layer allocation failed due to too
   1556                 // many sounds playing at once. This crash is comparatively common; RTA
   1557                 // speedrunners even have a setup for avoiding it within the SSL pyramid:
   1558                 // https://www.youtube.com/watch?v=QetyTgbQxcw
   1559                 else if (gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->layers[0]->enabled
   1560                          == FALSE) {
   1561                     update_background_music_after_sound(bank, soundIndex);
   1562                     sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
   1563                     delete_sound_from_bank(bank, soundIndex);
   1564                 } else {
   1565                     // Exactly the same code as before. Unfortunately we can't
   1566                     // make a macro out of this, because then everything ends up
   1567                     // on the same line after preprocessing, and the compiler,
   1568                     // somehow caring about line numbers, makes it not match (it
   1569                     // computes function arguments in the wrong order).
   1570                     switch (bank) {
   1571                         case SOUND_BANK_MOVING:
   1572                             if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_CONSTANT_FREQUENCY)) {
   1573                                 if (sSoundMovingSpeed[bank] > 8) {
   1574 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1575                                     func_802ad728(
   1576                                         0x02020000 | ((channelIndex & 0xff) << 8),
   1577                                         get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
   1578 #else
   1579                                     value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
   1580                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1581                                         value;
   1582 #endif
   1583                                 } else {
   1584 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1585                                     func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
   1586                                                   get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1)
   1587                                                       * ((sSoundMovingSpeed[bank] + 8.0f) / 16));
   1588 #else
   1589                                     value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
   1590                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1591                                         (sSoundMovingSpeed[bank] + 8.0f) / 16 * value;
   1592 #endif
   1593                                 }
   1594 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1595                                 func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
   1596                                               get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1597                                                             *sSoundBanks[bank][soundIndex].z));
   1598 #else
   1599                                 gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
   1600                                     get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1601                                                   *sSoundBanks[bank][soundIndex].z);
   1602 #endif
   1603 
   1604                                 if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)
   1605                                     == (SOUND_MOVING_FLYING & SOUNDARGS_MASK_SOUNDID)) {
   1606 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1607                                     func_802ad728(
   1608                                         0x04020000 | ((channelIndex & 0xff) << 8),
   1609                                         get_sound_freq_scale(bank, soundIndex)
   1610                                             + ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)));
   1611 #else
   1612                                     value = get_sound_freq_scale(bank, soundIndex);
   1613                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1614                                         ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)) + value;
   1615 #endif
   1616                                 } else {
   1617 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1618                                     func_802ad728(
   1619                                         0x04020000 | ((channelIndex & 0xff) << 8),
   1620                                         get_sound_freq_scale(bank, soundIndex)
   1621                                             + ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)));
   1622 #else
   1623                                     value = get_sound_freq_scale(bank, soundIndex);
   1624                                     gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1625                                         ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)) + value;
   1626 #endif
   1627                                 }
   1628 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1629                                 func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
   1630                                               get_sound_reverb(bank, soundIndex, channelIndex));
   1631 #else
   1632                                 gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
   1633                                     get_sound_reverb(bank, soundIndex, channelIndex);
   1634 #endif
   1635 
   1636                                 break;
   1637                             }
   1638                         // fallthrough
   1639                         case SOUND_BANK_MENU:
   1640 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1641                             func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8), 1);
   1642                             func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8), 64);
   1643                             func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
   1644                                           get_sound_freq_scale(bank, soundIndex));
   1645 #else
   1646                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume = 1.0f;
   1647                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan = 0.5f;
   1648                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale = 1.0f;
   1649 #endif
   1650                             break;
   1651                         case SOUND_BANK_ACTION:
   1652                         case SOUND_BANK_VOICE:
   1653 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1654                             func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
   1655                                           get_sound_reverb(bank, soundIndex, channelIndex));
   1656                             func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
   1657                                           get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
   1658                             func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
   1659                                           get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1660                                                         *sSoundBanks[bank][soundIndex].z)
   1661                                                   * 127.0f
   1662                                               + 0.5f);
   1663                             func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
   1664                                           get_sound_freq_scale(bank, soundIndex));
   1665 #else
   1666                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1667                                 get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
   1668                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
   1669                                 get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1670                                               *sSoundBanks[bank][soundIndex].z);
   1671                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1672                                 get_sound_freq_scale(bank, soundIndex);
   1673                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
   1674                                 get_sound_reverb(bank, soundIndex, channelIndex);
   1675 #endif
   1676                             break;
   1677                         case SOUND_BANK_GENERAL:
   1678                         case SOUND_BANK_ENV:
   1679                         case SOUND_BANK_OBJ:
   1680                         case SOUND_BANK_AIR:
   1681                         case SOUND_BANK_GENERAL2:
   1682                         case SOUND_BANK_OBJ2:
   1683 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1684                             func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
   1685                                           get_sound_reverb(bank, soundIndex, channelIndex));
   1686                             func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
   1687                                           get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2));
   1688                             func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
   1689                                           get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1690                                                         *sSoundBanks[bank][soundIndex].z)
   1691                                                   * 127.0f
   1692                                               + 0.5f);
   1693                             func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
   1694                                           get_sound_freq_scale(bank, soundIndex));
   1695 #else
   1696                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverbVol =
   1697                                 get_sound_reverb(bank, soundIndex, channelIndex);
   1698                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
   1699                                 get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2);
   1700                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
   1701                                 get_sound_pan(*sSoundBanks[bank][soundIndex].x,
   1702                                               *sSoundBanks[bank][soundIndex].z);
   1703                             gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
   1704                                 get_sound_freq_scale(bank, soundIndex);
   1705 #endif
   1706                             break;
   1707                     }
   1708                 }
   1709             }
   1710 
   1711             // Increment to the next channel that this bank owns
   1712             channelIndex++;
   1713         }
   1714 
   1715         // Increment to the first channel index of the next bank
   1716         // (In practice sUsedChannelsForSoundBank[i] = sMaxChannelsForSoundBank[i] = 1, so this
   1717         // doesn't do anything)
   1718         channelIndex += sMaxChannelsForSoundBank[bank] - sUsedChannelsForSoundBank[bank];
   1719     }
   1720 }
   1721 
   1722 /**
   1723  * Called from threads: thread4_sound, thread5_game_loop
   1724  */
   1725 static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) {
   1726     u8 targetVolume;
   1727     u8 i;
   1728 
   1729     if (player == SEQ_PLAYER_LEVEL) {
   1730         sCurrentBackgroundMusicSeqId = seqId & SEQ_BASE_ID;
   1731         sBackgroundMusicForDynamics = SEQUENCE_NONE;
   1732         sCurrentMusicDynamic = 0xff;
   1733         sMusicDynamicDelay = 2;
   1734     }
   1735 
   1736     for (i = 0; i < CHANNELS_MAX; i++) {
   1737         D_80360928[player][i].remainingFrames = 0;
   1738     }
   1739 
   1740 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1741     func_802ad770(0x46000000 | ((u8)(u32) player) << 16, seqId & SEQ_VARIATION);
   1742     func_802ad74c(0x82000000 | ((u8)(u32) player) << 16 | ((u8)(seqId & SEQ_BASE_ID)) << 8, arg2);
   1743 
   1744     if (player == SEQ_PLAYER_LEVEL) {
   1745         targetVolume = begin_background_music_fade(0);
   1746         if (targetVolume != 0xff) {
   1747             gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolumeScale = (f32) targetVolume / US_FLOAT(127.0);
   1748         }
   1749     }
   1750 #else
   1751 
   1752     gSequencePlayers[player].seqVariation = seqId & SEQ_VARIATION;
   1753     load_sequence(player, seqId & SEQ_BASE_ID, 0);
   1754 
   1755     if (player == SEQ_PLAYER_LEVEL) {
   1756         targetVolume = begin_background_music_fade(0);
   1757         if (targetVolume != 0xff) {
   1758             gSequencePlayers[SEQ_PLAYER_LEVEL].state = SEQUENCE_PLAYER_STATE_4;
   1759             gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolume = (f32) targetVolume / US_FLOAT(127.0);
   1760         }
   1761     } else {
   1762         func_8031D690(player, arg2);
   1763     }
   1764 #endif
   1765 }
   1766 
   1767 /**
   1768  * Called from threads: thread5_game_loop
   1769  */
   1770 void seq_player_fade_out(u8 player, u16 fadeDuration) {
   1771 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1772 #ifdef VERSION_EU
   1773     u32 fd = fadeDuration;
   1774 #else
   1775     s32 fd = fadeDuration; // will also match if we change function signature func_802ad74c to use s32 as arg1
   1776 #endif
   1777     if (!player) {
   1778         sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
   1779     }
   1780     func_802ad74c(0x83000000 | (player & 0xff) << 16, fd);
   1781 #else
   1782     if (player == SEQ_PLAYER_LEVEL) {
   1783         sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
   1784     }
   1785     seq_player_fade_to_zero_volume(player, fadeDuration);
   1786 #endif
   1787 }
   1788 
   1789 /**
   1790  * Called from threads: thread5_game_loop
   1791  */
   1792 void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration) {
   1793     u8 i;
   1794     for (i = 0; i < CHANNELS_MAX; i++) {
   1795         fade_channel_volume_scale(player, i, targetScale, fadeDuration);
   1796     }
   1797 }
   1798 
   1799 /**
   1800  * Called from threads: thread3_main, thread4_sound, thread5_game_loop
   1801  */
   1802 static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) {
   1803     struct ChannelVolumeScaleFade *temp;
   1804 
   1805     if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
   1806         temp = &D_80360928[player][channelIndex];
   1807         temp->remainingFrames = fadeDuration;
   1808         temp->velocity = ((f32)(targetScale / US_FLOAT(127.0))
   1809                           - gSequencePlayers[player].channels[channelIndex]->volumeScale)
   1810                          / fadeDuration;
   1811         temp->target = targetScale;
   1812         temp->current = gSequencePlayers[player].channels[channelIndex]->volumeScale;
   1813     }
   1814 }
   1815 
   1816 /**
   1817  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   1818  */
   1819 static void func_8031F96C(u8 player) {
   1820     u8 i;
   1821 
   1822     // Loop over channels
   1823     for (i = 0; i < CHANNELS_MAX; i++) {
   1824         if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone
   1825             && D_80360928[player][i].remainingFrames != 0) {
   1826             D_80360928[player][i].current += D_80360928[player][i].velocity;
   1827 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   1828             func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
   1829                           D_80360928[player][i].current);
   1830 #else
   1831             gSequencePlayers[player].channels[i]->volumeScale = D_80360928[player][i].current;
   1832 #endif
   1833             D_80360928[player][i].remainingFrames--;
   1834             if (D_80360928[player][i].remainingFrames == 0) {
   1835 #if defined(VERSION_EU)
   1836                 func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
   1837                               FLOAT_CAST(D_80360928[player][i].target) / 127.0);
   1838 #elif defined(VERSION_SH) || defined(VERSION_CN)
   1839                 func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
   1840                               FLOAT_CAST(D_80360928[player][i].target) / 127.0f);
   1841 #else
   1842                 gSequencePlayers[player].channels[i]->volumeScale =
   1843                     D_80360928[player][i].target / 127.0f;
   1844 #endif
   1845             }
   1846         }
   1847     }
   1848 }
   1849 
   1850 /**
   1851  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   1852  */
   1853 void process_level_music_dynamics(void) {
   1854     u32 conditionBits;
   1855     u16 tempBits;
   1856     UNUSED u16 pad;
   1857     u8 musicDynIndex;
   1858     u8 condIndex;
   1859     u8 i;
   1860     u8 j;
   1861     s16 conditionValues[8];
   1862     u8 conditionTypes[8];
   1863     s16 dur1;
   1864     s16 dur2;
   1865     u16 bit;
   1866 
   1867     func_8031F96C(0);
   1868     func_8031F96C(2);
   1869     func_80320ED8();
   1870     if (sMusicDynamicDelay != 0) {
   1871         sMusicDynamicDelay--;
   1872     } else {
   1873         sBackgroundMusicForDynamics = sCurrentBackgroundMusicSeqId;
   1874     }
   1875 
   1876     if (sBackgroundMusicForDynamics != sLevelDynamics[gCurrLevelNum][0]) {
   1877         return;
   1878     }
   1879 
   1880     conditionBits = sLevelDynamics[gCurrLevelNum][1] & 0xff00;
   1881     musicDynIndex = (u8) sLevelDynamics[gCurrLevelNum][1] & 0xff;
   1882     i = 2;
   1883     while (conditionBits & 0xff00) {
   1884         j = 0;
   1885         condIndex = 0;
   1886         bit = 0x8000;
   1887         while (j < 8) {
   1888             if (conditionBits & bit) {
   1889                 conditionValues[condIndex] = sLevelDynamics[gCurrLevelNum][i++];
   1890                 conditionTypes[condIndex] = j;
   1891                 condIndex++;
   1892             }
   1893 
   1894             j++;
   1895             bit = bit >> 1;
   1896         }
   1897 
   1898         for (j = 0; j < condIndex; j++) {
   1899             switch (conditionTypes[j]) {
   1900                 case MARIO_X_GE: {
   1901                     if (((s16) gMarioStates[0].pos[0]) < conditionValues[j]) {
   1902                         j = condIndex + 1;
   1903                     }
   1904                     break;
   1905                 }
   1906                 case MARIO_Y_GE: {
   1907                     if (((s16) gMarioStates[0].pos[1]) < conditionValues[j]) {
   1908                         j = condIndex + 1;
   1909                     }
   1910                     break;
   1911                 }
   1912                 case MARIO_Z_GE: {
   1913                     if (((s16) gMarioStates[0].pos[2]) < conditionValues[j]) {
   1914                         j = condIndex + 1;
   1915                     }
   1916                     break;
   1917                 }
   1918                 case MARIO_X_LT: {
   1919                     if (((s16) gMarioStates[0].pos[0]) >= conditionValues[j]) {
   1920                         j = condIndex + 1;
   1921                     }
   1922                     break;
   1923                 }
   1924                 case MARIO_Y_LT: {
   1925                     if (((s16) gMarioStates[0].pos[1]) >= conditionValues[j]) {
   1926                         j = condIndex + 1;
   1927                     }
   1928                     break;
   1929                 }
   1930                 case MARIO_Z_LT: {
   1931                     if (((s16) gMarioStates[0].pos[2]) >= conditionValues[j]) {
   1932                         j = condIndex + 1;
   1933                     }
   1934                     break;
   1935                 }
   1936                 case MARIO_IS_IN_AREA: {
   1937                     if (gCurrAreaIndex != conditionValues[j]) {
   1938                         j = condIndex + 1;
   1939                     }
   1940                     break;
   1941                 }
   1942                 case MARIO_IS_IN_ROOM: {
   1943                     if (gMarioCurrentRoom != conditionValues[j]) {
   1944                         j = condIndex + 1;
   1945                     }
   1946                     break;
   1947                 }
   1948             }
   1949         }
   1950 
   1951         if (j == condIndex) {
   1952             // The area matches. Break out of the loop.
   1953             tempBits = 0;
   1954         } else {
   1955             tempBits      = sLevelDynamics[gCurrLevelNum][i] & 0xff00;
   1956             musicDynIndex = sLevelDynamics[gCurrLevelNum][i] & 0xff;
   1957             i++;
   1958         }
   1959 
   1960         conditionBits = tempBits;
   1961     }
   1962 
   1963     if (sCurrentMusicDynamic != musicDynIndex) {
   1964         tempBits = 1;
   1965         if (sCurrentMusicDynamic == 0xff) {
   1966             dur1 = 1;
   1967             dur2 = 1;
   1968         } else {
   1969             dur1 = sMusicDynamics[musicDynIndex].dur1;
   1970             dur2 = sMusicDynamics[musicDynIndex].dur2;
   1971         }
   1972 
   1973         for (i = 0; i < CHANNELS_MAX; i++) {
   1974             conditionBits = tempBits;
   1975             tempBits = 0;
   1976             if (sMusicDynamics[musicDynIndex].bits1 & conditionBits) {
   1977                 fade_channel_volume_scale(SEQ_PLAYER_LEVEL, i, sMusicDynamics[musicDynIndex].volScale1,
   1978                                           dur1);
   1979             }
   1980             if (sMusicDynamics[musicDynIndex].bits2 & conditionBits) {
   1981                 fade_channel_volume_scale(SEQ_PLAYER_LEVEL, i, sMusicDynamics[musicDynIndex].volScale2,
   1982                                           dur2);
   1983             }
   1984             tempBits = conditionBits << 1;
   1985         }
   1986 
   1987         sCurrentMusicDynamic = musicDynIndex;
   1988     }
   1989 }
   1990 
   1991 void unused_8031FED0(u8 player, u32 bits, s8 arg2) {
   1992     u8 i;
   1993 
   1994     if (arg2 < 0) {
   1995         arg2 = -arg2;
   1996     }
   1997 
   1998     for (i = 0; i < CHANNELS_MAX; i++) {
   1999         if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone) {
   2000             if ((bits & 3) == 0) {
   2001                 gSequencePlayers[player].channels[i]->volumeScale = 1.0f;
   2002             } else if ((bits & 1) != 0) {
   2003                 gSequencePlayers[player].channels[i]->volumeScale = (f32) arg2 / US_FLOAT(127.0);
   2004             } else {
   2005                 gSequencePlayers[player].channels[i]->volumeScale =
   2006                     US_FLOAT(1.0) - (f32) arg2 / US_FLOAT(127.0);
   2007             }
   2008         }
   2009         bits >>= 2;
   2010     }
   2011 }
   2012 
   2013 /**
   2014  * Lower a sequence player's volume over fadeDuration frames.
   2015  * If player is SEQ_PLAYER_LEVEL (background music), the given percentage is ignored
   2016  * and a max target volume of 40 is used.
   2017  *
   2018  * Called from threads: thread5_game_loop
   2019  */
   2020 void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) {
   2021     if (player == SEQ_PLAYER_LEVEL) {
   2022         sLowerBackgroundMusicVolume = TRUE;
   2023         begin_background_music_fade(fadeDuration);
   2024     } else if (gSequencePlayers[player].enabled == TRUE) {
   2025         seq_player_fade_to_percentage_of_volume(player, fadeDuration, percentage);
   2026     }
   2027 }
   2028 
   2029 /**
   2030  * Remove the lowered volume constraint set by seq_player_lower_volume.
   2031  * If player is SEQ_PLAYER_LEVEL (background music), the music won't necessarily
   2032  * raise back to normal volume if other constraints have been set, e.g.
   2033  * sBackgroundMusicTargetVolume.
   2034  *
   2035  * Called from threads: thread5_game_loop
   2036  */
   2037 void seq_player_unlower_volume(u8 player, u16 fadeDuration) {
   2038     sLowerBackgroundMusicVolume = FALSE;
   2039     if (player == SEQ_PLAYER_LEVEL) {
   2040         if (gSequencePlayers[player].state != SEQUENCE_PLAYER_STATE_FADE_OUT) {
   2041             begin_background_music_fade(fadeDuration);
   2042         }
   2043     } else {
   2044         if (gSequencePlayers[player].enabled == TRUE) {
   2045             seq_player_fade_to_normal_volume(player, fadeDuration);
   2046         }
   2047     }
   2048 }
   2049 
   2050 /**
   2051  * Begin a volume fade to adjust the background music to the correct volume.
   2052  * The target volume is determined by global variables like sBackgroundMusicTargetVolume
   2053  * and sLowerBackgroundMusicVolume.
   2054  * If none of the relevant global variables are set, then the default background music
   2055  * volume for the sequence is used.
   2056  *
   2057  * Called from threads: thread3_main, thread4_sound, thread5_game_loop
   2058  */
   2059 static u8 begin_background_music_fade(u16 fadeDuration) {
   2060     u8 targetVolume = 0xff;
   2061 
   2062     if (sCurrentBackgroundMusicSeqId == SEQUENCE_NONE
   2063         || sCurrentBackgroundMusicSeqId == SEQ_EVENT_CUTSCENE_CREDITS) {
   2064         return 0xff;
   2065     }
   2066 
   2067     if (gSequencePlayers[SEQ_PLAYER_LEVEL].volume == 0.0f && fadeDuration) {
   2068         gSequencePlayers[SEQ_PLAYER_LEVEL].volume = gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolume;
   2069     }
   2070 
   2071     if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET) {
   2072         targetVolume = (sBackgroundMusicTargetVolume & TARGET_VOLUME_VALUE_MASK);
   2073     }
   2074 
   2075     if (sBackgroundMusicMaxTargetVolume != TARGET_VOLUME_UNSET) {
   2076         u8 maxTargetVolume = (sBackgroundMusicMaxTargetVolume & TARGET_VOLUME_VALUE_MASK);
   2077         if (targetVolume > maxTargetVolume) {
   2078             targetVolume = maxTargetVolume;
   2079         }
   2080     }
   2081 
   2082     if (sLowerBackgroundMusicVolume && targetVolume > 40) {
   2083         targetVolume = 40;
   2084     }
   2085 
   2086     if (sSoundBanksThatLowerBackgroundMusic != 0 && targetVolume > 20) {
   2087         targetVolume = 20;
   2088     }
   2089 
   2090     if (gSequencePlayers[SEQ_PLAYER_LEVEL].enabled == TRUE) {
   2091         if (targetVolume != 0xff) {
   2092             seq_player_fade_to_target_volume(SEQ_PLAYER_LEVEL, fadeDuration, targetVolume);
   2093         } else {
   2094 #if defined(VERSION_JP) || defined(VERSION_US)
   2095             gSequencePlayers[SEQ_PLAYER_LEVEL].volume =
   2096                 sBackgroundMusicDefaultVolume[sCurrentBackgroundMusicSeqId] / 127.0f;
   2097 #endif
   2098             seq_player_fade_to_normal_volume(SEQ_PLAYER_LEVEL, fadeDuration);
   2099         }
   2100     }
   2101 
   2102     return targetVolume;
   2103 }
   2104 
   2105 /**
   2106  * Called from threads: thread5_game_loop
   2107  */
   2108 void set_audio_muted(u8 muted) {
   2109     u8 i;
   2110 
   2111     for (i = 0; i < SEQUENCE_PLAYERS; i++) {
   2112 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2113         if (muted) {
   2114             func_802ad74c(0xf1000000, 0);
   2115         } else {
   2116             func_802ad74c(0xf2000000, 0);
   2117         }
   2118 #else
   2119         gSequencePlayers[i].muted = muted;
   2120 #endif
   2121     }
   2122 }
   2123 
   2124 /**
   2125  * Called from threads: thread4_sound
   2126  */
   2127 void sound_init(void) {
   2128     u8 i;
   2129     u8 j;
   2130 
   2131     for (i = 0; i < SOUND_BANK_COUNT; i++) {
   2132         // Set each sound in the bank to STOPPED
   2133         for (j = 0; j < 40; j++) {
   2134             sSoundBanks[i][j].soundStatus = SOUND_STATUS_STOPPED;
   2135         }
   2136 
   2137         // Remove current sounds
   2138         for (j = 0; j < MAX_CHANNELS_PER_SOUND_BANK; j++) {
   2139             sCurrentSound[i][j] = 0xff;
   2140         }
   2141 
   2142         sSoundBankUsedListBack[i] = 0;
   2143         sSoundBankFreeListFront[i] = 1;
   2144         sNumSoundsInBank[i] = 0;
   2145     }
   2146 
   2147     for (i = 0; i < SOUND_BANK_COUNT; i++) {
   2148         // Set used list to empty
   2149         sSoundBanks[i][0].prev = 0xff;
   2150         sSoundBanks[i][0].next = 0xff;
   2151 
   2152         // Set free list to contain every sound slot
   2153         for (j = 1; j < 40 - 1; j++) {
   2154             sSoundBanks[i][j].prev = j - 1;
   2155             sSoundBanks[i][j].next = j + 1;
   2156         }
   2157         sSoundBanks[i][j].prev = j - 1;
   2158         sSoundBanks[i][j].next = 0xff;
   2159     }
   2160 
   2161     for (j = 0; j < 3; j++) {
   2162         for (i = 0; i < CHANNELS_MAX; i++) {
   2163             D_80360928[j][i].remainingFrames = 0;
   2164         }
   2165     }
   2166 
   2167     for (i = 0; i < MAX_BACKGROUND_MUSIC_QUEUE_SIZE; i++) {
   2168         sBackgroundMusicQueue[i].priority = 0;
   2169     }
   2170 
   2171     sound_banks_enable(SEQ_PLAYER_SFX, SOUND_BANKS_ALL_BITS);
   2172 
   2173     sUnused80332118 = 0;
   2174     sBackgroundMusicTargetVolume = TARGET_VOLUME_UNSET;
   2175     sLowerBackgroundMusicVolume = FALSE;
   2176     sSoundBanksThatLowerBackgroundMusic = 0;
   2177     sUnused80332114 = 0;
   2178     sCurrentBackgroundMusicSeqId = 0xff;
   2179     gSoundMode = SOUND_MODE_STEREO;
   2180     sBackgroundMusicQueueSize = 0;
   2181     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
   2182     D_80332120 = 0;
   2183     D_80332124 = 0;
   2184     sNumProcessedSoundRequests = 0;
   2185     sSoundRequestCount = 0;
   2186 }
   2187 
   2188 // (unused)
   2189 void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInBank, u8 *soundId) {
   2190     u8 i;
   2191     u8 count = 0;
   2192 
   2193     for (i = 0; i < sMaxChannelsForSoundBank[bank]; i++) {
   2194         if (sCurrentSound[bank][i] != 0xff) {
   2195             count++;
   2196         }
   2197     }
   2198     *numPlayingSounds = count;
   2199 
   2200     *numSoundsInBank = sNumSoundsInBank[bank];
   2201 
   2202     if (sCurrentSound[bank][0] != 0xff) {
   2203         *soundId = (u8)(sSoundBanks[bank][sCurrentSound[bank][0]].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
   2204     } else {
   2205         *soundId = 0xff;
   2206     }
   2207 }
   2208 
   2209 /**
   2210  * Called from threads: thread5_game_loop
   2211  */
   2212 void stop_sound(u32 soundBits, f32 *pos) {
   2213     u8 bank = (soundBits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
   2214     u8 soundIndex = sSoundBanks[bank][0].next;
   2215 
   2216     while (soundIndex != 0xff) {
   2217         // If sound has same id and source position pointer
   2218         if ((u16)(soundBits >> SOUNDARGS_SHIFT_SOUNDID)
   2219                 == (u16)(sSoundBanks[bank][soundIndex].soundBits >> SOUNDARGS_SHIFT_SOUNDID)
   2220             && sSoundBanks[bank][soundIndex].x == pos) {
   2221 
   2222             // Mark sound for deletion
   2223             update_background_music_after_sound(bank, soundIndex);
   2224             sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
   2225             soundIndex = 0xff; // break
   2226         } else {
   2227             soundIndex = sSoundBanks[bank][soundIndex].next;
   2228         }
   2229     }
   2230 }
   2231 
   2232 /**
   2233  * Called from threads: thread5_game_loop
   2234  */
   2235 void stop_sounds_from_source(f32 *pos) {
   2236     u8 bank;
   2237     u8 soundIndex;
   2238 
   2239     for (bank = 0; bank < SOUND_BANK_COUNT; bank++) {
   2240         soundIndex = sSoundBanks[bank][0].next;
   2241         while (soundIndex != 0xff) {
   2242             if (sSoundBanks[bank][soundIndex].x == pos) {
   2243                 update_background_music_after_sound(bank, soundIndex);
   2244                 sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
   2245             }
   2246             soundIndex = sSoundBanks[bank][soundIndex].next;
   2247         }
   2248     }
   2249 }
   2250 
   2251 /**
   2252  * Called from threads: thread3_main, thread5_game_loop
   2253  */
   2254 static void stop_sounds_in_bank(u8 bank) {
   2255     u8 soundIndex = sSoundBanks[bank][0].next;
   2256 
   2257     while (soundIndex != 0xff) {
   2258         update_background_music_after_sound(bank, soundIndex);
   2259         sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
   2260         soundIndex = sSoundBanks[bank][soundIndex].next;
   2261     }
   2262 }
   2263 
   2264 /**
   2265  * Stops sounds in all of the sound banks that predominantly consist of continuous
   2266  * sounds. Misses some specific continuous sounds in other banks like bird chirping
   2267  * and the ticking sound after pressing a switch.
   2268  *
   2269  * Called from threads: thread3_main, thread5_game_loop
   2270  */
   2271 void stop_sounds_in_continuous_banks(void) {
   2272     stop_sounds_in_bank(SOUND_BANK_MOVING);
   2273     stop_sounds_in_bank(SOUND_BANK_ENV);
   2274     stop_sounds_in_bank(SOUND_BANK_AIR);
   2275 }
   2276 
   2277 /**
   2278  * Called from threads: thread3_main, thread5_game_loop
   2279  */
   2280 void sound_banks_disable(UNUSED u8 player, u16 bankMask) {
   2281     u8 i;
   2282 
   2283     for (i = 0; i < SOUND_BANK_COUNT; i++) {
   2284         if (bankMask & 1) {
   2285             sSoundBankDisabled[i] = TRUE;
   2286         }
   2287         bankMask = bankMask >> 1;
   2288     }
   2289 }
   2290 
   2291 /**
   2292  * Called from threads: thread5_game_loop
   2293  */
   2294 static void disable_all_sequence_players(void) {
   2295     u8 i;
   2296 
   2297     for (i = 0; i < SEQUENCE_PLAYERS; i++) {
   2298         sequence_player_disable(&gSequencePlayers[i]);
   2299     }
   2300 }
   2301 
   2302 /**
   2303  * Called from threads: thread5_game_loop
   2304  */
   2305 void sound_banks_enable(UNUSED u8 player, u16 bankMask) {
   2306     u8 i;
   2307 
   2308     for (i = 0; i < SOUND_BANK_COUNT; i++) {
   2309         if (bankMask & 1) {
   2310             sSoundBankDisabled[i] = FALSE;
   2311         }
   2312         bankMask = bankMask >> 1;
   2313     }
   2314 }
   2315 
   2316 u8 unused_803209D8(u8 player, u8 channelIndex, u8 arg2) {
   2317     u8 ret = 0;
   2318     if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
   2319         gSequencePlayers[player].channels[channelIndex]->stopSomething2 = arg2;
   2320         ret = arg2;
   2321     }
   2322     return ret;
   2323 }
   2324 
   2325 /**
   2326  * Set the moving speed for a sound bank, which may affect the volume and pitch
   2327  * of the sound.
   2328  *
   2329  * Called from threads: thread5_game_loop
   2330  */
   2331 void set_sound_moving_speed(u8 bank, u8 speed) {
   2332     sSoundMovingSpeed[bank] = speed;
   2333 }
   2334 
   2335 /**
   2336  * Called from threads: thread5_game_loop
   2337  */
   2338 void play_dialog_sound(u8 dialogID) {
   2339     u8 speaker;
   2340 
   2341     if (dialogID >= DIALOG_COUNT) {
   2342         dialogID = 0;
   2343     }
   2344 
   2345     speaker = sDialogSpeaker[dialogID];
   2346     if (speaker != 0xff) {
   2347         play_sound(sDialogSpeakerVoice[speaker], gGlobalSoundSource);
   2348 
   2349         // Play music during bowser message that appears when first entering the
   2350         // castle or when trying to enter a door without enough stars
   2351         if (speaker == BOWS1) {
   2352             seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_KOOPA_MESSAGE, 0);
   2353         }
   2354     }
   2355 
   2356 #ifndef VERSION_JP
   2357     // "You've stepped on the (Wing|Metal|Vanish) Cap Switch"
   2358     if (dialogID == DIALOG_010 || dialogID == DIALOG_011 || dialogID == DIALOG_012) {
   2359         play_puzzle_jingle();
   2360     }
   2361 #endif
   2362 }
   2363 
   2364 /**
   2365  * Called from threads: thread5_game_loop
   2366  */
   2367 void play_music(u8 player, u16 seqArgs, u16 fadeTimer) {
   2368     u8 seqId = seqArgs & 0xff;
   2369     u8 priority = seqArgs >> 8;
   2370     u8 i;
   2371     u8 foundIndex = 0;
   2372 
   2373     // Except for the background music player, we don't support queued
   2374     // sequences. Just play them immediately, stopping any old sequence.
   2375     if (player != SEQ_PLAYER_LEVEL) {
   2376         seq_player_play_sequence(player, seqId, fadeTimer);
   2377         return;
   2378     }
   2379 
   2380     // Abort if the queue is already full.
   2381     if (sBackgroundMusicQueueSize == MAX_BACKGROUND_MUSIC_QUEUE_SIZE) {
   2382         return;
   2383     }
   2384 
   2385     // If already in the queue, abort, after first restarting the sequence if
   2386     // it is first, and handling disabled music somehow.
   2387     // (That handling probably ought to occur even when the queue is full...)
   2388     for (i = 0; i < sBackgroundMusicQueueSize; i++) {
   2389         if (sBackgroundMusicQueue[i].seqId == seqId) {
   2390             if (i == 0) {
   2391                 seq_player_play_sequence(SEQ_PLAYER_LEVEL, seqId, fadeTimer);
   2392             } else if (!gSequencePlayers[SEQ_PLAYER_LEVEL].enabled) {
   2393                 stop_background_music(sBackgroundMusicQueue[0].seqId);
   2394             }
   2395             return;
   2396         }
   2397     }
   2398 
   2399     // Find the next sequence slot by priority.
   2400     for (i = 0; i < sBackgroundMusicQueueSize; i++) {
   2401         if (sBackgroundMusicQueue[i].priority <= priority) {
   2402             foundIndex = i;
   2403             i = sBackgroundMusicQueueSize; // break
   2404         }
   2405     }
   2406 
   2407     // If the sequence ends up first in the queue, start it, and make space for
   2408     // one more entry in the queue.
   2409     if (foundIndex == 0) {
   2410         seq_player_play_sequence(SEQ_PLAYER_LEVEL, seqId, fadeTimer);
   2411         sBackgroundMusicQueueSize++;
   2412     }
   2413 
   2414     // Move all items up in queue, throwing away the last one if we didn't put
   2415     // the new sequence first.
   2416     for (i = sBackgroundMusicQueueSize - 1; i > foundIndex; i--) {
   2417         sBackgroundMusicQueue[i].priority = sBackgroundMusicQueue[i - 1].priority;
   2418         sBackgroundMusicQueue[i].seqId = sBackgroundMusicQueue[i - 1].seqId;
   2419     }
   2420 
   2421     // Insert item into queue.
   2422     sBackgroundMusicQueue[foundIndex].priority = priority;
   2423     sBackgroundMusicQueue[foundIndex].seqId = seqId;
   2424 }
   2425 
   2426 /**
   2427  * Called from threads: thread5_game_loop
   2428  */
   2429 void stop_background_music(u16 seqId) {
   2430     u8 foundIndex;
   2431     u8 i;
   2432 
   2433     if (sBackgroundMusicQueueSize == 0) {
   2434         return;
   2435     }
   2436 
   2437     // If sequence is not found, remove an empty queue item (the next empty
   2438     // queue slot).
   2439     foundIndex = sBackgroundMusicQueueSize;
   2440 
   2441     // Search for the sequence.
   2442     for (i = 0; i < sBackgroundMusicQueueSize; i++) {
   2443         if (sBackgroundMusicQueue[i].seqId == (u8)(seqId & 0xff)) {
   2444             // Remove sequence from queue. If it was first, play the next one,
   2445             // or fade out the music.
   2446             sBackgroundMusicQueueSize--;
   2447             if (i == 0) {
   2448                 if (sBackgroundMusicQueueSize != 0) {
   2449                     seq_player_play_sequence(SEQ_PLAYER_LEVEL, sBackgroundMusicQueue[1].seqId, 0);
   2450                 } else {
   2451                     seq_player_fade_out(SEQ_PLAYER_LEVEL, 20);
   2452                 }
   2453             }
   2454             foundIndex = i;
   2455             i = sBackgroundMusicQueueSize; // "break;"
   2456         }
   2457     }
   2458 
   2459     // Move later slots down.
   2460     for (i = foundIndex; i < sBackgroundMusicQueueSize; i++) {
   2461         sBackgroundMusicQueue[i].priority = sBackgroundMusicQueue[i + 1].priority;
   2462         sBackgroundMusicQueue[i].seqId = sBackgroundMusicQueue[i + 1].seqId;
   2463     }
   2464 
   2465     // @bug? If the sequence queue is full and we attempt to stop a sequence
   2466     // that isn't in the queue, this writes out of bounds. Can that happen?
   2467     sBackgroundMusicQueue[i].priority = 0;
   2468 }
   2469 
   2470 /**
   2471  * Called from threads: thread5_game_loop
   2472  */
   2473 void fadeout_background_music(u16 seqId, u16 fadeOut) {
   2474     if (sBackgroundMusicQueueSize != 0 && sBackgroundMusicQueue[0].seqId == (u8)(seqId & 0xff)) {
   2475         seq_player_fade_out(SEQ_PLAYER_LEVEL, fadeOut);
   2476     }
   2477 }
   2478 
   2479 /**
   2480  * Called from threads: thread5_game_loop
   2481  */
   2482 void drop_queued_background_music(void) {
   2483     if (sBackgroundMusicQueueSize != 0) {
   2484         sBackgroundMusicQueueSize = 1;
   2485     }
   2486 }
   2487 
   2488 /**
   2489  * Called from threads: thread5_game_loop
   2490  */
   2491 u16 get_current_background_music(void) {
   2492     if (sBackgroundMusicQueueSize != 0) {
   2493         return (sBackgroundMusicQueue[0].priority << 8) + sBackgroundMusicQueue[0].seqId;
   2494     }
   2495     return -1;
   2496 }
   2497 
   2498 /**
   2499  * Called from threads: thread4_sound, thread5_game_loop (EU only)
   2500  */
   2501 void func_80320ED8(void) {
   2502 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2503     if (D_EU_80300558 != 0) {
   2504         D_EU_80300558--;
   2505     }
   2506 
   2507     if (gSequencePlayers[SEQ_PLAYER_ENV].enabled
   2508         || sBackgroundMusicMaxTargetVolume == TARGET_VOLUME_UNSET || D_EU_80300558 != 0) {
   2509 #else
   2510     if (gSequencePlayers[SEQ_PLAYER_ENV].enabled
   2511         || sBackgroundMusicMaxTargetVolume == TARGET_VOLUME_UNSET) {
   2512 #endif
   2513         return;
   2514     }
   2515 
   2516     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
   2517     begin_background_music_fade(50);
   2518 
   2519     if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET
   2520         && (D_80332120 == SEQ_EVENT_MERRY_GO_ROUND || D_80332120 == SEQ_EVENT_PIRANHA_PLANT)) {
   2521         seq_player_play_sequence(SEQ_PLAYER_ENV, D_80332120, 1);
   2522         if (D_80332124 != 0xff) {
   2523             seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, 1, D_80332124);
   2524         }
   2525     }
   2526 }
   2527 
   2528 /**
   2529  * Called from threads: thread5_game_loop
   2530  */
   2531 void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer) {
   2532     UNUSED u32 dummy;
   2533 
   2534     sUnused80332118 = 0;
   2535     if (sCurrentBackgroundMusicSeqId == 0xff || sCurrentBackgroundMusicSeqId == SEQ_MENU_TITLE_SCREEN) {
   2536         return;
   2537     }
   2538 
   2539     if (sBackgroundMusicTargetVolume == TARGET_VOLUME_UNSET) {
   2540         sBackgroundMusicTargetVolume = bgMusicVolume + TARGET_VOLUME_IS_PRESENT_FLAG;
   2541         begin_background_music_fade(fadeTimer);
   2542         seq_player_play_sequence(SEQ_PLAYER_ENV, seqId, fadeTimer >> 1);
   2543         if (volume < 0x80) {
   2544             seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume);
   2545         }
   2546         D_80332124 = volume;
   2547         D_80332120 = seqId;
   2548     } else if (volume != 0xff) {
   2549         sBackgroundMusicTargetVolume = bgMusicVolume + TARGET_VOLUME_IS_PRESENT_FLAG;
   2550         begin_background_music_fade(fadeTimer);
   2551         seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume);
   2552         D_80332124 = volume;
   2553     }
   2554 }
   2555 
   2556 /**
   2557  * Called from threads: thread5_game_loop
   2558  */
   2559 void func_80321080(u16 fadeTimer) {
   2560     if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET) {
   2561         sBackgroundMusicTargetVolume = TARGET_VOLUME_UNSET;
   2562         D_80332120 = 0;
   2563         D_80332124 = 0;
   2564         begin_background_music_fade(fadeTimer);
   2565         seq_player_fade_out(SEQ_PLAYER_ENV, fadeTimer);
   2566     }
   2567 }
   2568 
   2569 /**
   2570  * Called from threads: thread3_main, thread5_game_loop
   2571  */
   2572 void func_803210D4(u16 fadeDuration) {
   2573     u8 i;
   2574 
   2575     if (sHasStartedFadeOut) {
   2576         return;
   2577     }
   2578 
   2579     if (gSequencePlayers[SEQ_PLAYER_LEVEL].enabled == TRUE) {
   2580 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2581         func_802ad74c(0x83000000, fadeDuration);
   2582 #else
   2583         seq_player_fade_to_zero_volume(SEQ_PLAYER_LEVEL, fadeDuration);
   2584 #endif
   2585     }
   2586 
   2587     if (gSequencePlayers[SEQ_PLAYER_ENV].enabled == TRUE) {
   2588 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2589         func_802ad74c(0x83010000, fadeDuration);
   2590 #else
   2591         seq_player_fade_to_zero_volume(SEQ_PLAYER_ENV, fadeDuration);
   2592 #endif
   2593     }
   2594 
   2595     for (i = 0; i < SOUND_BANK_COUNT; i++) {
   2596         if (i != SOUND_BANK_MENU) {
   2597             fade_channel_volume_scale(SEQ_PLAYER_SFX, i, 0, fadeDuration / 16);
   2598         }
   2599     }
   2600 
   2601     sHasStartedFadeOut = TRUE;
   2602 }
   2603 
   2604 /**
   2605  * Called from threads: thread5_game_loop
   2606  */
   2607 void play_course_clear(void) {
   2608     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_CUTSCENE_COLLECT_STAR, 0);
   2609     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 0;
   2610 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2611     D_EU_80300558 = 2;
   2612 #endif
   2613     begin_background_music_fade(50);
   2614 }
   2615 
   2616 /**
   2617  * Called from threads: thread5_game_loop
   2618  */
   2619 void play_peachs_jingle(void) {
   2620     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_PEACH_MESSAGE, 0);
   2621     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 0;
   2622 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2623     D_EU_80300558 = 2;
   2624 #endif
   2625     begin_background_music_fade(50);
   2626 }
   2627 
   2628 /**
   2629  * Plays the puzzle jingle. Plays the dadada dadada *dadada* jingle
   2630  * that usually plays when you solve a "puzzle", like chests, talking to
   2631  * yoshi, releasing chain chomp, opening the pyramid top, etc.
   2632  *
   2633  * Called from threads: thread5_game_loop
   2634  */
   2635 void play_puzzle_jingle(void) {
   2636     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_SOLVE_PUZZLE, 0);
   2637     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
   2638 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2639     D_EU_80300558 = 2;
   2640 #endif
   2641     begin_background_music_fade(50);
   2642 }
   2643 
   2644 /**
   2645  * Called from threads: thread5_game_loop
   2646  */
   2647 void play_star_fanfare(void) {
   2648     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_HIGH_SCORE, 0);
   2649     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
   2650 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2651     D_EU_80300558 = 2;
   2652 #endif
   2653     begin_background_music_fade(50);
   2654 }
   2655 
   2656 /**
   2657  * Called from threads: thread5_game_loop
   2658  */
   2659 void play_power_star_jingle(u8 arg0) {
   2660     if (!arg0) {
   2661         sBackgroundMusicTargetVolume = 0;
   2662     }
   2663     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_CUTSCENE_STAR_SPAWN, 0);
   2664     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
   2665 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2666     D_EU_80300558 = 2;
   2667 #endif
   2668     begin_background_music_fade(50);
   2669 }
   2670 
   2671 /**
   2672  * Called from threads: thread5_game_loop
   2673  */
   2674 void play_race_fanfare(void) {
   2675     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_RACE, 0);
   2676     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
   2677 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2678     D_EU_80300558 = 2;
   2679 #endif
   2680     begin_background_music_fade(50);
   2681 }
   2682 
   2683 /**
   2684  * Called from threads: thread5_game_loop
   2685  */
   2686 void play_toads_jingle(void) {
   2687     seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_TOAD_MESSAGE, 0);
   2688     sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
   2689 #if defined(VERSION_EU) || defined(VERSION_SH) || defined(VERSION_CN)
   2690     D_EU_80300558 = 2;
   2691 #endif
   2692     begin_background_music_fade(50);
   2693 }
   2694 
   2695 /**
   2696  * Called from threads: thread5_game_loop
   2697  */
   2698 void sound_reset(u8 presetId) {
   2699 #ifndef VERSION_JP
   2700     if (presetId >= 8) {
   2701         presetId = 0;
   2702         sUnused8033323C = 0;
   2703     }
   2704 #endif
   2705     sGameLoopTicked = 0;
   2706     disable_all_sequence_players();
   2707     sound_init();
   2708 #if defined(VERSION_SH) || defined(VERSION_CN)
   2709     func_802ad74c(0xF2000000, 0);
   2710 #endif
   2711 #if defined(VERSION_JP) || defined(VERSION_US)
   2712     audio_reset_session(&gAudioSessionPresets[presetId]);
   2713 #else
   2714     audio_reset_session_eu(presetId);
   2715 #endif
   2716     osWritebackDCacheAll();
   2717     if (presetId != 7) {
   2718         preload_sequence(SEQ_EVENT_SOLVE_PUZZLE, PRELOAD_BANKS | PRELOAD_SEQUENCE);
   2719         preload_sequence(SEQ_EVENT_PEACH_MESSAGE, PRELOAD_BANKS | PRELOAD_SEQUENCE);
   2720         preload_sequence(SEQ_EVENT_CUTSCENE_STAR_SPAWN, PRELOAD_BANKS | PRELOAD_SEQUENCE);
   2721     }
   2722     seq_player_play_sequence(SEQ_PLAYER_SFX, SEQ_SOUND_PLAYER, 0);
   2723     D_80332108 = (D_80332108 & 0xf0) + presetId;
   2724     gSoundMode = D_80332108 >> 4;
   2725     sHasStartedFadeOut = FALSE;
   2726 }
   2727 
   2728 /**
   2729  * Called from threads: thread5_game_loop
   2730  */
   2731 void audio_set_sound_mode(u8 soundMode) {
   2732     D_80332108 = (D_80332108 & 0xf) + (soundMode << 4);
   2733     gSoundMode = soundMode;
   2734 }
   2735 
   2736 #if defined(VERSION_JP) || defined(VERSION_US)
   2737 void unused_80321460(UNUSED s32 arg0, UNUSED s32 arg1, UNUSED s32 arg2, UNUSED s32 arg3) {
   2738 }
   2739 
   2740 void unused_80321474(UNUSED s32 arg0) {
   2741 }
   2742 #endif