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