2019-08-25 00:46:40 -04:00
|
|
|
#include <ultra64.h>
|
|
|
|
#include "sm64.h"
|
2020-03-01 22:42:52 -05:00
|
|
|
#include "heap.h"
|
2019-08-25 00:46:40 -04:00
|
|
|
#include "load.h"
|
|
|
|
#include "data.h"
|
|
|
|
#include "seqplayer.h"
|
|
|
|
#include "external.h"
|
|
|
|
#include "playback.h"
|
|
|
|
#include "synthesis.h"
|
|
|
|
#include "game/level_update.h"
|
2020-02-03 00:51:26 -05:00
|
|
|
#include "game/object_list_processor.h"
|
2019-08-25 00:46:40 -04:00
|
|
|
#include "game/camera.h"
|
|
|
|
#include "seq_ids.h"
|
2019-12-01 21:52:53 -05:00
|
|
|
#include "dialog_ids.h"
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
#define EU_FLOAT(x) x##f
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
|
|
|
#define EU_FLOAT(x) x
|
|
|
|
#endif
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
// N.B. sound banks are different from the audio banks referred to in other
|
|
|
|
// files. We should really fix our naming to be less ambiguous...
|
2020-12-03 14:26:38 -05:00
|
|
|
#define MAX_BACKGROUND_MUSIC_QUEUE_SIZE 6
|
|
|
|
#define MAX_CHANNELS_PER_SOUND_BANK 1
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
#define SEQUENCE_NONE 0xFF
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
#define SAMPLES_TO_OVERPRODUCE 0x10
|
|
|
|
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
struct Sound {
|
|
|
|
s32 soundBits;
|
|
|
|
f32 *position;
|
|
|
|
}; // size = 0x8
|
|
|
|
|
|
|
|
struct ChannelVolumeScaleFade {
|
|
|
|
f32 velocity;
|
|
|
|
u8 target;
|
|
|
|
f32 current;
|
2020-12-03 14:26:38 -05:00
|
|
|
u16 remainingFrames;
|
2019-08-25 00:46:40 -04:00
|
|
|
}; // size = 0x10
|
|
|
|
|
|
|
|
struct SoundCharacteristics {
|
|
|
|
f32 *x;
|
|
|
|
f32 *y;
|
|
|
|
f32 *z;
|
|
|
|
f32 distance;
|
|
|
|
u32 priority;
|
|
|
|
u32 soundBits; // packed bits, same as first arg to play_sound
|
|
|
|
u8 soundStatus;
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 freshness;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 prev;
|
|
|
|
u8 next;
|
|
|
|
}; // size = 0x1C
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Also the number of frames a discrete sound can be in the WAITING state before being deleted
|
|
|
|
#define SOUND_MAX_FRESHNESS 10
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SequenceQueueItem {
|
|
|
|
u8 seqId;
|
|
|
|
u8 priority;
|
|
|
|
}; // size = 0x2
|
|
|
|
|
|
|
|
// data
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
// moved to bss in data.c
|
|
|
|
s32 gAudioErrorFlags2 = 0;
|
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
s32 gAudioErrorFlags = 0;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
s32 sGameLoopTicked = 0;
|
|
|
|
|
|
|
|
// Dialog sounds
|
2019-12-01 21:52:53 -05:00
|
|
|
// The US difference is the sound for DIALOG_037 ("I win! You lose! Ha ha ha ha!
|
2019-08-25 00:46:40 -04:00
|
|
|
// You're no slouch, but I'm a better sledder! Better luck next time!"), spoken
|
|
|
|
// by Koopa instead of the penguin in JP.
|
|
|
|
|
|
|
|
#define UKIKI 0
|
|
|
|
#define TUXIE 1
|
|
|
|
#define BOWS1 2 // Bowser Intro / Doors Laugh
|
|
|
|
#define KOOPA 3
|
|
|
|
#define KBOMB 4
|
|
|
|
#define BOO 5
|
|
|
|
#define BOMB 6
|
|
|
|
#define BOWS2 7 // Bowser Battle Laugh
|
|
|
|
#define GRUNT 8
|
|
|
|
#define WIGLR 9
|
|
|
|
#define YOSHI 10
|
|
|
|
#define _ 0xFF
|
|
|
|
|
|
|
|
#ifdef VERSION_JP
|
|
|
|
#define DIFF KOOPA
|
|
|
|
#else
|
|
|
|
#define DIFF TUXIE
|
|
|
|
#endif
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
u8 sDialogSpeaker[] = {
|
2019-08-25 00:46:40 -04:00
|
|
|
// 0 1 2 3 4 5 6 7 8 9
|
|
|
|
/* 0*/ _, BOMB, BOMB, BOMB, BOMB, KOOPA, KOOPA, KOOPA, _, KOOPA,
|
|
|
|
/* 1*/ _, _, _, _, _, _, _, KBOMB, _, _,
|
|
|
|
/* 2*/ _, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1, BOWS1,
|
|
|
|
/* 3*/ _, _, _, _, _, _, _, DIFF, _, _,
|
|
|
|
/* 4*/ _, KOOPA, _, _, _, _, _, BOMB, _, _,
|
|
|
|
/* 5*/ _, _, _, _, _, TUXIE, TUXIE, TUXIE, TUXIE, TUXIE,
|
|
|
|
/* 6*/ _, _, _, _, _, _, _, BOWS2, _, _,
|
|
|
|
/* 7*/ _, _, _, _, _, _, _, _, _, UKIKI,
|
|
|
|
/* 8*/ UKIKI, _, _, _, _, BOO, _, _, _, _,
|
|
|
|
/* 9*/ BOWS2, _, BOWS2, BOWS2, _, _, _, _, BOO, BOO,
|
|
|
|
/*10*/ UKIKI, UKIKI, _, _, _, BOMB, BOMB, BOO, BOO, _,
|
|
|
|
/*11*/ _, _, _, _, GRUNT, GRUNT, KBOMB, GRUNT, GRUNT, _,
|
|
|
|
/*12*/ _, _, _, _, _, _, _, _, KBOMB, _,
|
|
|
|
/*13*/ _, _, TUXIE, _, _, _, _, _, _, _,
|
|
|
|
/*14*/ _, _, _, _, _, _, _, _, _, _,
|
|
|
|
/*15*/ WIGLR, WIGLR, WIGLR, _, _, _, _, _, _, _,
|
|
|
|
/*16*/ _, YOSHI, _, _, _, _, _, _, WIGLR, _
|
|
|
|
};
|
|
|
|
#undef _
|
2020-12-03 14:26:38 -05:00
|
|
|
STATIC_ASSERT(ARRAY_COUNT(sDialogSpeaker) == DIALOG_COUNT,
|
|
|
|
"change this array if you are adding dialogs");
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-02-03 00:51:26 -05:00
|
|
|
s32 sDialogSpeakerVoice[] = {
|
2019-10-05 15:08:05 -04:00
|
|
|
SOUND_OBJ_UKIKI_CHATTER_LONG,
|
|
|
|
SOUND_OBJ_BIG_PENGUIN_YELL,
|
|
|
|
SOUND_OBJ_BOWSER_INTRO_LAUGH,
|
|
|
|
SOUND_OBJ_KOOPA_TALK,
|
|
|
|
SOUND_OBJ_KING_BOBOMB_TALK,
|
|
|
|
SOUND_OBJ_BOO_LAUGH_LONG,
|
|
|
|
SOUND_OBJ_BOBOMB_BUDDY_TALK,
|
|
|
|
SOUND_OBJ_BOWSER_LAUGH,
|
|
|
|
SOUND_OBJ2_BOSS_DIALOG_GRUNT,
|
|
|
|
SOUND_OBJ_WIGGLER_TALK,
|
|
|
|
SOUND_GENERAL_YOSHI_TALK,
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
2019-08-25 00:46:40 -04:00
|
|
|
NO_SOUND,
|
|
|
|
NO_SOUND,
|
|
|
|
NO_SOUND,
|
|
|
|
NO_SOUND,
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
u8 sNumProcessedSoundRequests = 0;
|
|
|
|
u8 sSoundRequestCount = 0;
|
|
|
|
|
|
|
|
// Music dynamic tables. A dynamic describes which volumes to apply to which
|
|
|
|
// channels of a sequence (I think?), and different parts of a level can have
|
|
|
|
// different dynamics. Each table below specifies first the sequence to apply
|
|
|
|
// the dynamics to, then a bunch of conditions for when each dynamic applies
|
|
|
|
// (e.g. "only if Mario's X position is between 100 and 300"), and finally a
|
|
|
|
// fallback dynamic. Due to the encoding of the tables, the conditions must
|
|
|
|
// come in the same order as the macros.
|
|
|
|
// TODO: dynamic isn't a great term for this, it means other things in music...
|
|
|
|
|
|
|
|
#define MARIO_X_GE 0
|
|
|
|
#define MARIO_Y_GE 1
|
|
|
|
#define MARIO_Z_GE 2
|
|
|
|
#define MARIO_X_LT 3
|
|
|
|
#define MARIO_Y_LT 4
|
|
|
|
#define MARIO_Z_LT 5
|
|
|
|
#define MARIO_IS_IN_AREA 6
|
|
|
|
#define MARIO_IS_IN_ROOM 7
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
#define DYN1(cond1, val1, res) (s16)(1 << (15 - cond1) | res), val1
|
2020-02-03 00:51:26 -05:00
|
|
|
#define DYN2(cond1, val1, cond2, val2, res) \
|
2019-12-01 21:52:53 -05:00
|
|
|
(s16)(1 << (15 - cond1) | 1 << (15 - cond2) | res), val1, val2
|
2020-02-03 00:51:26 -05:00
|
|
|
#define DYN3(cond1, val1, cond2, val2, cond3, val3, res) \
|
2019-12-01 21:52:53 -05:00
|
|
|
(s16)(1 << (15 - cond1) | 1 << (15 - cond2) | 1 << (15 - cond3) | res), val1, val2, val3
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2019-09-01 15:50:50 -04:00
|
|
|
s16 sDynBbh[] = {
|
2020-12-03 14:26:38 -05:00
|
|
|
SEQ_LEVEL_SPOOKY, DYN1(MARIO_IS_IN_ROOM, BBH_OUTSIDE_ROOM, 6),
|
|
|
|
DYN1(MARIO_IS_IN_ROOM, BBH_NEAR_MERRY_GO_ROUND_ROOM, 6), 5,
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
2019-09-01 15:50:50 -04:00
|
|
|
s16 sDynDdd[] = {
|
|
|
|
SEQ_LEVEL_WATER,
|
|
|
|
DYN2(MARIO_X_LT, -800, MARIO_IS_IN_AREA, AREA_DDD_WHIRLPOOL & 0xf, 0),
|
2019-08-25 00:46:40 -04:00
|
|
|
DYN3(MARIO_Y_GE, -2000, MARIO_X_LT, 470, MARIO_IS_IN_AREA, AREA_DDD_WHIRLPOOL & 0xf, 0),
|
2019-09-01 15:50:50 -04:00
|
|
|
DYN2(MARIO_Y_GE, 100, MARIO_IS_IN_AREA, AREA_DDD_SUB & 0xf, 2),
|
|
|
|
1,
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
|
|
|
s16 sDynJrb[] = {
|
|
|
|
SEQ_LEVEL_WATER,
|
|
|
|
DYN2(MARIO_Y_GE, 945, MARIO_X_LT, -5260, 0),
|
|
|
|
DYN1(MARIO_IS_IN_AREA, AREA_JRB_SHIP & 0xf, 0),
|
|
|
|
DYN1(MARIO_Y_GE, 1000, 0),
|
|
|
|
DYN2(MARIO_Y_GE, -3100, MARIO_Z_LT, -900, 2),
|
|
|
|
1,
|
2019-09-01 15:50:50 -04:00
|
|
|
5, // bogus entry, ignored (was JRB originally intended to have spooky music?)
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
2019-09-01 15:50:50 -04:00
|
|
|
s16 sDynWdw[] = {
|
2020-12-03 14:26:38 -05:00
|
|
|
SEQ_LEVEL_UNDERGROUND, DYN2(MARIO_Y_LT, -670, MARIO_IS_IN_AREA, AREA_WDW_MAIN & 0xf, 4),
|
|
|
|
DYN1(MARIO_IS_IN_AREA, AREA_WDW_TOWN & 0xf, 4), 3,
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
2019-09-01 15:50:50 -04:00
|
|
|
s16 sDynHmc[] = {
|
2020-12-03 14:26:38 -05:00
|
|
|
SEQ_LEVEL_UNDERGROUND, DYN2(MARIO_X_GE, 0, MARIO_Y_LT, -203, 4),
|
|
|
|
DYN2(MARIO_X_LT, 0, MARIO_Y_LT, -2400, 4), 3,
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
2019-09-01 15:50:50 -04:00
|
|
|
s16 sDynUnk38[] = {
|
|
|
|
SEQ_LEVEL_UNDERGROUND,
|
|
|
|
DYN1(MARIO_IS_IN_AREA, 1, 3),
|
|
|
|
DYN1(MARIO_IS_IN_AREA, 2, 4),
|
|
|
|
DYN1(MARIO_IS_IN_AREA, 3, 7),
|
|
|
|
0,
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
2019-09-01 15:50:50 -04:00
|
|
|
s16 sDynNone[] = { SEQ_SOUND_PLAYER, 0 };
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
u8 sCurrentMusicDynamic = 0xff;
|
|
|
|
u8 sBackgroundMusicForDynamics = SEQUENCE_NONE;
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, leveldyn, _8) leveldyn,
|
|
|
|
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8, leveldyn, _10) leveldyn,
|
|
|
|
|
2019-09-01 15:50:50 -04:00
|
|
|
#define _ sDynNone
|
2019-12-01 21:52:53 -05:00
|
|
|
s16 *sLevelDynamics[LEVEL_COUNT] = {
|
2020-12-03 14:26:38 -05:00
|
|
|
_, // LEVEL_NONE
|
|
|
|
#include "levels/level_defines.h"
|
2019-09-01 15:50:50 -04:00
|
|
|
};
|
2019-08-25 00:46:40 -04:00
|
|
|
#undef _
|
2019-12-01 21:52:53 -05:00
|
|
|
#undef STUB_LEVEL
|
|
|
|
#undef DEFINE_LEVEL
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
struct MusicDynamic {
|
|
|
|
/*0x0*/ s16 bits1;
|
2019-12-01 21:52:53 -05:00
|
|
|
/*0x2*/ u16 volScale1;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0x4*/ s16 dur1;
|
|
|
|
/*0x6*/ s16 bits2;
|
2019-12-01 21:52:53 -05:00
|
|
|
/*0x8*/ u16 volScale2;
|
2019-08-25 00:46:40 -04:00
|
|
|
/*0xA*/ s16 dur2;
|
|
|
|
}; // size = 0xC
|
|
|
|
|
|
|
|
struct MusicDynamic sMusicDynamics[8] = {
|
2019-12-01 21:52:53 -05:00
|
|
|
{ 0x0000, 127, 100, 0x0e43, 0, 100 }, // SEQ_LEVEL_WATER
|
|
|
|
{ 0x0003, 127, 100, 0x0e40, 0, 100 }, // SEQ_LEVEL_WATER
|
|
|
|
{ 0x0e43, 127, 200, 0x0000, 0, 200 }, // SEQ_LEVEL_WATER
|
|
|
|
{ 0x02ff, 127, 100, 0x0100, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
|
|
|
|
{ 0x03f7, 127, 100, 0x0008, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
|
|
|
|
{ 0x0070, 127, 10, 0x0000, 0, 100 }, // SEQ_LEVEL_SPOOKY
|
|
|
|
{ 0x0000, 127, 100, 0x0070, 0, 10 }, // SEQ_LEVEL_SPOOKY
|
|
|
|
{ 0xffff, 127, 100, 0x0000, 0, 100 }, // any (unused)
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
#define STUB_LEVEL(_0, _1, _2, _3, echo1, echo2, echo3, _7, _8) { echo1, echo2, echo3 },
|
|
|
|
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, echo1, echo2, echo3, _9, _10) { echo1, echo2, echo3 },
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 sLevelAreaReverbs[LEVEL_COUNT][3] = {
|
2019-08-25 00:46:40 -04:00
|
|
|
{ 0x00, 0x00, 0x00 }, // LEVEL_NONE
|
2020-02-03 00:51:26 -05:00
|
|
|
#include "levels/level_defines.h"
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
2019-12-01 21:52:53 -05:00
|
|
|
#undef STUB_LEVEL
|
|
|
|
#undef DEFINE_LEVEL
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
#define STUB_LEVEL(_0, _1, _2, volume, _4, _5, _6, _7, _8) volume,
|
|
|
|
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, volume, _6, _7, _8, _9, _10) volume,
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
u16 sLevelAcousticReaches[LEVEL_COUNT] = {
|
|
|
|
20000, // LEVEL_NONE
|
|
|
|
#include "levels/level_defines.h"
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
#undef STUB_LEVEL
|
|
|
|
#undef DEFINE_LEVEL
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
#define AUDIO_MAX_DISTANCE US_FLOAT(22000.0)
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#ifdef VERSION_JP
|
|
|
|
#define LOW_VOLUME_REVERB 48.0
|
|
|
|
#else
|
|
|
|
#define LOW_VOLUME_REVERB 40.0f
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef VERSION_JP
|
|
|
|
#define VOLUME_RANGE_UNK1 0.8f
|
|
|
|
#define VOLUME_RANGE_UNK2 1.0f
|
|
|
|
#else
|
|
|
|
#define VOLUME_RANGE_UNK1 0.9f
|
|
|
|
#define VOLUME_RANGE_UNK2 0.8f
|
|
|
|
#endif
|
|
|
|
|
2019-09-01 15:50:50 -04:00
|
|
|
// Default volume for background music sequences (playing on player 0).
|
|
|
|
u8 sBackgroundMusicDefaultVolume[] = {
|
2019-08-25 00:46:40 -04:00
|
|
|
127, // SEQ_SOUND_PLAYER
|
|
|
|
80, // SEQ_EVENT_CUTSCENE_COLLECT_STAR
|
|
|
|
80, // SEQ_MENU_TITLE_SCREEN
|
|
|
|
75, // SEQ_LEVEL_GRASS
|
|
|
|
70, // SEQ_LEVEL_INSIDE_CASTLE
|
|
|
|
75, // SEQ_LEVEL_WATER
|
|
|
|
75, // SEQ_LEVEL_HOT
|
|
|
|
75, // SEQ_LEVEL_BOSS_KOOPA
|
|
|
|
70, // SEQ_LEVEL_SNOW
|
|
|
|
65, // SEQ_LEVEL_SLIDE
|
|
|
|
80, // SEQ_LEVEL_SPOOKY
|
|
|
|
65, // SEQ_EVENT_PIRANHA_PLANT
|
|
|
|
85, // SEQ_LEVEL_UNDERGROUND
|
|
|
|
75, // SEQ_MENU_STAR_SELECT
|
|
|
|
65, // SEQ_EVENT_POWERUP
|
|
|
|
70, // SEQ_EVENT_METAL_CAP
|
|
|
|
65, // SEQ_EVENT_KOOPA_MESSAGE
|
|
|
|
70, // SEQ_LEVEL_KOOPA_ROAD
|
|
|
|
70, // SEQ_EVENT_HIGH_SCORE
|
|
|
|
65, // SEQ_EVENT_MERRY_GO_ROUND
|
|
|
|
80, // SEQ_EVENT_RACE
|
|
|
|
70, // SEQ_EVENT_CUTSCENE_STAR_SPAWN
|
|
|
|
85, // SEQ_EVENT_BOSS
|
|
|
|
75, // SEQ_EVENT_CUTSCENE_COLLECT_KEY
|
|
|
|
75, // SEQ_EVENT_ENDLESS_STAIRS
|
|
|
|
85, // SEQ_LEVEL_BOSS_KOOPA_FINAL
|
|
|
|
70, // SEQ_EVENT_CUTSCENE_CREDITS
|
|
|
|
80, // SEQ_EVENT_SOLVE_PUZZLE
|
|
|
|
80, // SEQ_EVENT_TOAD_MESSAGE
|
|
|
|
70, // SEQ_EVENT_PEACH_MESSAGE
|
|
|
|
75, // SEQ_EVENT_CUTSCENE_INTRO
|
|
|
|
80, // SEQ_EVENT_CUTSCENE_VICTORY
|
|
|
|
70, // SEQ_EVENT_CUTSCENE_ENDING
|
|
|
|
65, // SEQ_MENU_FILE_SELECT
|
2019-09-01 15:50:50 -04:00
|
|
|
0, // SEQ_EVENT_CUTSCENE_LAKITU (not in JP)
|
2019-08-25 00:46:40 -04:00
|
|
|
};
|
|
|
|
|
2019-09-01 15:50:50 -04:00
|
|
|
STATIC_ASSERT(ARRAY_COUNT(sBackgroundMusicDefaultVolume) == SEQ_COUNT,
|
|
|
|
"change this array if you are adding sequences");
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 sMusicDynamicDelay = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 sSoundBankUsedListBack[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
u8 sSoundBankFreeListFront[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
|
|
|
u8 sNumSoundsInBank[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // only used for debugging
|
2019-12-01 21:52:53 -05:00
|
|
|
u8 sMaxChannelsForSoundBank[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
2019-09-01 15:50:50 -04:00
|
|
|
|
|
|
|
// Banks 2 and 7 both grew from 0x30 sounds to 0x40 in size in US.
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifdef VERSION_JP
|
2019-09-01 15:50:50 -04:00
|
|
|
#define BANK27_SIZE 0x30
|
2019-08-25 00:46:40 -04:00
|
|
|
#else
|
2019-09-01 15:50:50 -04:00
|
|
|
#define BANK27_SIZE 0x40
|
2019-08-25 00:46:40 -04:00
|
|
|
#endif
|
2019-09-01 15:50:50 -04:00
|
|
|
u8 sNumSoundsPerBank[SOUND_BANK_COUNT] = {
|
|
|
|
0x70, 0x30, BANK27_SIZE, 0x80, 0x20, 0x80, 0x20, BANK27_SIZE, 0x80, 0x80,
|
|
|
|
};
|
|
|
|
#undef BANK27_SIZE
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// sBackgroundMusicMaxTargetVolume and sBackgroundMusicTargetVolume use the 0x80
|
|
|
|
// bit to indicate that they are set, and the rest of the bits for the actual value
|
|
|
|
#define TARGET_VOLUME_IS_PRESENT_FLAG 0x80
|
|
|
|
#define TARGET_VOLUME_VALUE_MASK 0x7f
|
|
|
|
#define TARGET_VOLUME_UNSET 0x00
|
|
|
|
|
|
|
|
f32 gGlobalSoundSource[3] = { 0.0f, 0.0f, 0.0f };
|
2019-12-01 21:52:53 -05:00
|
|
|
f32 sUnusedSoundArgs[3] = { 1.0f, 1.0f, 1.0f };
|
|
|
|
u8 sSoundBankDisabled[16] = { 0 };
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 D_80332108 = 0;
|
|
|
|
u8 sHasStartedFadeOut = FALSE;
|
2020-12-03 14:26:38 -05:00
|
|
|
u16 sSoundBanksThatLowerBackgroundMusic = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 sUnused80332114 = 0; // never read, set to 0
|
|
|
|
u16 sUnused80332118 = 0; // never read, set to 0
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 D_80332120 = 0;
|
|
|
|
u8 D_80332124 = 0;
|
2020-02-03 00:51:26 -05:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
u8 D_EU_80300558 = 0;
|
|
|
|
#endif
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 sBackgroundMusicQueueSize = 0;
|
2020-02-03 00:51:26 -05:00
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifndef VERSION_JP
|
|
|
|
u8 sUnused8033323C = 0; // never read, set to 0
|
|
|
|
#endif
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
// bss
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
2020-06-02 12:44:34 -04:00
|
|
|
s16 *gCurrAiBuffer;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
#ifdef VERSION_SH
|
|
|
|
s8 D_SH_80343CD0_pad[0x20];
|
|
|
|
s32 D_SH_80343CF0;
|
|
|
|
s8 D_SH_80343CF8_pad[0x8];
|
|
|
|
struct UnkStruct80343D00 D_SH_80343D00;
|
|
|
|
s8 D_SH_8034DC8_pad[0x8];
|
|
|
|
OSPiHandle DriveRomHandle; // used in osDriveRomInit.c. Why here?
|
|
|
|
s8 D_SH_80343E48_pad[0x8];
|
|
|
|
#endif
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
struct Sound sSoundRequests[0x100];
|
2020-02-03 00:51:26 -05:00
|
|
|
// Curiously, this has size 3, despite SEQUENCE_PLAYERS == 4 on EU
|
|
|
|
struct ChannelVolumeScaleFade D_80360928[3][CHANNELS_MAX];
|
2019-12-01 21:52:53 -05:00
|
|
|
u8 sUsedChannelsForSoundBank[SOUND_BANK_COUNT];
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 sCurrentSound[SOUND_BANK_COUNT][MAX_CHANNELS_PER_SOUND_BANK]; // index into sSoundBanks
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For each sound bank, a pool containing the currently active sounds for that bank.
|
|
|
|
* The free and used slots in these pools are linked lists. The element sSoundBanks[bank][0]
|
|
|
|
* is used as a list header for the used list, and never holds an actual sound. See also
|
|
|
|
* sSoundBankUsedListBack and sSoundBankFreeListFront.
|
|
|
|
*/
|
|
|
|
struct SoundCharacteristics sSoundBanks[SOUND_BANK_COUNT][40];
|
|
|
|
|
|
|
|
u8 sSoundMovingSpeed[SOUND_BANK_COUNT];
|
|
|
|
u8 sBackgroundMusicTargetVolume;
|
|
|
|
static u8 sLowerBackgroundMusicVolume;
|
|
|
|
struct SequenceQueueItem sBackgroundMusicQueue[MAX_BACKGROUND_MUSIC_QUEUE_SIZE];
|
|
|
|
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
s32 unk_sh_8034754C;
|
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-02-03 00:51:26 -05:00
|
|
|
#ifdef VERSION_EU
|
|
|
|
OSMesgQueue OSMesgQueue0;
|
|
|
|
OSMesgQueue OSMesgQueue1;
|
|
|
|
OSMesgQueue OSMesgQueue2;
|
|
|
|
OSMesgQueue OSMesgQueue3;
|
|
|
|
extern OSMesgQueue *OSMesgQueues[];
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2020-02-03 00:51:26 -05:00
|
|
|
struct EuAudioCmd sAudioCmd[0x100];
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2020-02-03 00:51:26 -05:00
|
|
|
OSMesg OSMesg0;
|
|
|
|
s32 pad1; // why is there 1 s32 here
|
|
|
|
OSMesg OSMesg1;
|
2020-12-03 14:26:38 -05:00
|
|
|
s32 pad2[2]; // it's not just that the struct is bigger than we think, because there are 2 here
|
2020-02-03 00:51:26 -05:00
|
|
|
OSMesg OSMesg2; // and none here. wth nintendo
|
|
|
|
OSMesg OSMesg3;
|
2020-12-03 14:26:38 -05:00
|
|
|
#else // VERSION_SH
|
|
|
|
extern OSMesgQueue *D_SH_80350F88;
|
|
|
|
extern OSMesgQueue *D_SH_80350FA8;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifdef VERSION_JP
|
|
|
|
typedef u16 FadeT;
|
|
|
|
#else
|
|
|
|
typedef s32 FadeT;
|
|
|
|
#endif
|
|
|
|
|
2020-02-03 00:51:26 -05:00
|
|
|
// some sort of main thread -> sound thread dispatchers
|
|
|
|
extern void func_802ad728(u32 bits, f32 arg);
|
|
|
|
extern void func_802ad74c(u32 bits, u32 arg);
|
|
|
|
extern void func_802ad770(u32 bits, s8 arg);
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
static void update_background_music_after_sound(u8 bank, u8 soundIndex);
|
|
|
|
static void update_game_sound(void);
|
|
|
|
static void fade_channel_volume_scale(u8 player, u8 channelId, u8 targetScale, u16 fadeTimer);
|
2019-08-25 00:46:40 -04:00
|
|
|
void process_level_music_dynamics(void);
|
2020-12-03 14:26:38 -05:00
|
|
|
static u8 begin_background_music_fade(u16 fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
void func_80320ED8(void);
|
|
|
|
|
|
|
|
#ifndef VERSION_JP
|
|
|
|
void unused_8031E4F0(void) {
|
|
|
|
// This is a debug function which is almost entirely optimized away,
|
|
|
|
// except for loops, string literals, and a read of a volatile variable.
|
|
|
|
// The string literals have allowed it to be partially reconstructed.
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
stubbed_printf("AUTOSEQ ");
|
|
|
|
stubbed_printf("%2x %2x <%5x : %5x / %5x>\n", gSeqLoadedPool.temporary.entries[0].id,
|
|
|
|
gSeqLoadedPool.temporary.entries[1].id, gSeqLoadedPool.temporary.entries[0].size,
|
|
|
|
gSeqLoadedPool.temporary.entries[1].size, gSeqLoadedPool.temporary.pool.size);
|
|
|
|
|
|
|
|
stubbed_printf("AUTOBNK ");
|
|
|
|
stubbed_printf("%2x %3x <%5x : %5x / %5x>\n", gBankLoadedPool.temporary.entries[0].id,
|
|
|
|
gBankLoadedPool.temporary.entries[1].id, gBankLoadedPool.temporary.entries[0].size,
|
|
|
|
gBankLoadedPool.temporary.entries[1].size, gBankLoadedPool.temporary.pool.size);
|
|
|
|
|
|
|
|
stubbed_printf("STAYSEQ ");
|
|
|
|
stubbed_printf("[%2x] <%5x / %5x>\n", gSeqLoadedPool.persistent.numEntries,
|
|
|
|
gSeqLoadedPool.persistent.pool.cur - gSeqLoadedPool.persistent.pool.start,
|
|
|
|
gSeqLoadedPool.persistent.pool.size);
|
|
|
|
for (i = 0; (u32) i < gSeqLoadedPool.persistent.numEntries; i++) {
|
|
|
|
stubbed_printf("%2x ", gSeqLoadedPool.persistent.entries[i].id);
|
|
|
|
}
|
|
|
|
stubbed_printf("\n");
|
|
|
|
|
|
|
|
stubbed_printf("STAYBNK ");
|
|
|
|
stubbed_printf("[%2x] <%5x / %5x>\n", gBankLoadedPool.persistent.numEntries,
|
|
|
|
gBankLoadedPool.persistent.pool.cur - gBankLoadedPool.persistent.pool.start,
|
|
|
|
gBankLoadedPool.persistent.pool.size);
|
|
|
|
for (i = 0; (u32) i < gBankLoadedPool.persistent.numEntries; i++) {
|
|
|
|
stubbed_printf("%2x ", gBankLoadedPool.persistent.entries[i].id);
|
|
|
|
}
|
|
|
|
stubbed_printf("\n\n");
|
|
|
|
|
|
|
|
stubbed_printf(" 0123456789ABCDEF0123456789ABCDEF01234567\n");
|
|
|
|
stubbed_printf("--------------------------------------------\n");
|
|
|
|
|
|
|
|
// gSeqLoadStatus/gBankLoadStatus, 4 entries at a time?
|
|
|
|
stubbed_printf("SEQ ");
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
|
|
stubbed_printf("%1x", 0);
|
|
|
|
}
|
|
|
|
stubbed_printf("\n");
|
|
|
|
|
|
|
|
stubbed_printf("BNK ");
|
2020-12-03 14:26:38 -05:00
|
|
|
#ifdef VERSION_SH
|
|
|
|
#define count 1
|
|
|
|
#else
|
|
|
|
#define count 4
|
|
|
|
#endif
|
|
|
|
for (i = 0; i < 40; i += count) {
|
2019-08-25 00:46:40 -04:00
|
|
|
stubbed_printf("%1x", 0);
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#undef count
|
2019-08-25 00:46:40 -04:00
|
|
|
stubbed_printf("\n");
|
|
|
|
|
|
|
|
stubbed_printf("FIXHEAP ");
|
|
|
|
stubbed_printf("%4x / %4x\n", 0, 0);
|
|
|
|
stubbed_printf("DRVHEAP ");
|
|
|
|
stubbed_printf("%5x / %5x\n", 0, 0);
|
|
|
|
stubbed_printf("DMACACHE %4d Blocks\n", 0);
|
|
|
|
stubbed_printf("CHANNELS %2d / MAX %3d \n", 0, 0);
|
|
|
|
|
|
|
|
stubbed_printf("TEMPOMAX %d\n", gTempoInternalToExternal / TEMPO_SCALE);
|
2020-04-03 14:57:26 -04:00
|
|
|
stubbed_printf("TEMPO G0 %d\n", gSequencePlayers[SEQ_PLAYER_LEVEL].tempo / TEMPO_SCALE);
|
|
|
|
stubbed_printf("TEMPO G1 %d\n", gSequencePlayers[SEQ_PLAYER_ENV].tempo / TEMPO_SCALE);
|
|
|
|
stubbed_printf("TEMPO G2 %d\n", gSequencePlayers[SEQ_PLAYER_SFX].tempo / TEMPO_SCALE);
|
2019-08-25 00:46:40 -04:00
|
|
|
stubbed_printf("DEBUGFLAG %8x\n", gAudioErrorFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
void unused_8031E568(void) {
|
2019-12-01 21:52:53 -05:00
|
|
|
stubbed_printf("COUNT %8d\n", gAudioFrameCount);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
const char unusedErrorStr1[] = "Error : Queue is not empty ( %x ) \n";
|
|
|
|
const char unusedErrorStr2[] = "specchg error\n";
|
|
|
|
#endif
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
/**
|
|
|
|
* Fade out a sequence player
|
2020-12-03 14:26:38 -05:00
|
|
|
* Called from threads: thread5_game_loop
|
2019-08-25 00:46:40 -04:00
|
|
|
*/
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
void audio_reset_session_eu(s32 presetId) {
|
|
|
|
OSMesg mesg;
|
2020-12-03 14:26:38 -05:00
|
|
|
#ifdef VERSION_SH
|
|
|
|
osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_NOBLOCK);
|
|
|
|
osSendMesg(D_SH_80350F88, (OSMesg) presetId, OS_MESG_NOBLOCK);
|
|
|
|
osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_BLOCK);
|
|
|
|
if ((s32) mesg != presetId) {
|
|
|
|
osRecvMesg(D_SH_80350FA8, &mesg, OS_MESG_BLOCK);
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#else
|
2020-02-03 00:51:26 -05:00
|
|
|
osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_NOBLOCK);
|
|
|
|
osSendMesg(OSMesgQueues[2], (OSMesg) presetId, OS_MESG_NOBLOCK);
|
|
|
|
osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_BLOCK);
|
|
|
|
if ((s32) mesg != presetId) {
|
|
|
|
osRecvMesg(OSMesgQueues[3], &mesg, OS_MESG_BLOCK);
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#endif
|
2020-02-03 00:51:26 -05:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#endif
|
2020-02-03 00:51:26 -05:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void seq_player_fade_to_zero_volume(s32 player, FadeT fadeDuration) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifndef VERSION_JP
|
2020-12-03 14:26:38 -05:00
|
|
|
// fadeDuration is never 0 in practice
|
|
|
|
if (fadeDuration == 0) {
|
|
|
|
fadeDuration++;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeVelocity = -(seqPlayer->fadeVolume / fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->state = SEQUENCE_PLAYER_STATE_FADE_OUT;
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeRemainingFrames = fadeDuration;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void func_8031D690(s32 player, FadeT fadeInTime) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
|
|
|
|
|
|
|
|
if (fadeInTime == 0 || seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
seqPlayer->state = SEQUENCE_PLAYER_STATE_2;
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeRemainingFrames = fadeInTime;
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->fadeVolume = 0.0f;
|
|
|
|
seqPlayer->fadeVelocity = 0.0f;
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void seq_player_fade_to_percentage_of_volume(s32 player, FadeT fadeDuration, u8 percentage) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
|
2020-12-03 14:26:38 -05:00
|
|
|
f32 targetVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
if (seqPlayer->state == 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
|
|
|
|
return;
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
targetVolume = (FLOAT_CAST(percentage) / EU_FLOAT(100.0)) * seqPlayer->fadeVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->volume = seqPlayer->fadeVolume;
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
seqPlayer->fadeRemainingFrames = 0;
|
|
|
|
if (fadeDuration == 0) {
|
|
|
|
seqPlayer->fadeVolume = targetVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeVelocity = (targetVolume - seqPlayer->fadeVolume) / fadeDuration;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
seqPlayer->state = 0;
|
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->state = SEQUENCE_PLAYER_STATE_4;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
seqPlayer->fadeRemainingFrames = fadeDuration;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void seq_player_fade_to_normal_volume(s32 player, FadeT fadeDuration) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
if (seqPlayer->state == 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
|
|
|
|
return;
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeRemainingFrames = 0;
|
|
|
|
if (fadeDuration == 0) {
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->fadeVolume = seqPlayer->volume;
|
|
|
|
return;
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / fadeDuration;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
seqPlayer->state = 0;
|
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->state = SEQUENCE_PLAYER_STATE_2;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
seqPlayer->fadeRemainingFrames = fadeDuration;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void seq_player_fade_to_target_volume(s32 player, FadeT fadeDuration, u8 targetVolume) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
2019-08-25 00:46:40 -04:00
|
|
|
if (seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
|
|
|
|
return;
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
seqPlayer->fadeRemainingFrames = 0;
|
|
|
|
if (fadeDuration == 0) {
|
2020-02-03 00:51:26 -05:00
|
|
|
seqPlayer->fadeVolume = (FLOAT_CAST(targetVolume) / EU_FLOAT(127.0));
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->fadeVelocity =
|
2020-12-03 14:26:38 -05:00
|
|
|
(((f32)(FLOAT_CAST(targetVolume) / EU_FLOAT(127.0)) - seqPlayer->fadeVolume)
|
|
|
|
/ (f32) fadeDuration);
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
seqPlayer->state = 0;
|
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
seqPlayer->state = SEQUENCE_PLAYER_STATE_4;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
seqPlayer->fadeRemainingFrames = fadeDuration;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
#ifdef VERSION_EU
|
|
|
|
extern void func_802ad7a0(void);
|
2020-12-03 14:26:38 -05:00
|
|
|
#else
|
|
|
|
extern void func_sh_802F64C8(void);
|
|
|
|
#endif
|
2020-02-03 00:51:26 -05:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2020-03-01 22:42:52 -05:00
|
|
|
void maybe_tick_game_sound(void) {
|
|
|
|
if (sGameLoopTicked != 0) {
|
2020-02-03 00:51:26 -05:00
|
|
|
update_game_sound();
|
|
|
|
sGameLoopTicked = 0;
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#ifdef VERSION_EU
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad7a0();
|
2020-12-03 14:26:38 -05:00
|
|
|
#else
|
|
|
|
func_sh_802F64C8(); // moved in SH
|
|
|
|
#endif
|
2020-02-03 00:51:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void func_eu_802e9bec(s32 player, s32 channel, s32 arg2) {
|
2020-03-01 22:42:52 -05:00
|
|
|
// EU verson of unused_803209D8
|
2020-02-03 00:51:26 -05:00
|
|
|
// chan->stopSomething2 = arg2?
|
|
|
|
func_802ad770(0x08000000 | (player & 0xff) << 16 | (channel & 0xff) << 8, (s8) arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
struct SPTask *create_next_audio_frame_task(void) {
|
2019-12-01 21:52:53 -05:00
|
|
|
u32 samplesRemainingInAI;
|
2019-08-25 00:46:40 -04:00
|
|
|
s32 writtenCmds;
|
|
|
|
s32 index;
|
|
|
|
OSTask_t *task;
|
|
|
|
s32 oldDmaCount;
|
|
|
|
s32 flags;
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
gAudioFrameCount++;
|
2019-08-25 00:46:40 -04:00
|
|
|
if (gAudioLoadLock != AUDIO_LOCK_NOT_LOADING) {
|
|
|
|
stubbed_printf("DAC:Lost 1 Frame.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gAudioTaskIndex ^= 1;
|
|
|
|
gCurrAiBufferIndex++;
|
|
|
|
gCurrAiBufferIndex %= NUMAIBUFFERS;
|
|
|
|
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
|
2019-12-01 21:52:53 -05:00
|
|
|
samplesRemainingInAI = osAiGetLength() / 4;
|
|
|
|
|
|
|
|
// Audio is triple buffered; the audio interface reads from two buffers
|
|
|
|
// while the third is being written by the RSP. More precisely, the
|
|
|
|
// lifecycle is:
|
|
|
|
// - this function computes an audio command list
|
|
|
|
// - wait for vblank
|
|
|
|
// - the command list is sent to the RSP (we could have sent it to the
|
|
|
|
// RSP before the vblank, but that gives the RSP less time to finish)
|
|
|
|
// - wait for vblank
|
|
|
|
// - the RSP is now expected to be finished, and we can send its output
|
|
|
|
// on to the AI
|
|
|
|
// Here we thus send to the AI the sound that was generated two frames ago.
|
2019-08-25 00:46:40 -04:00
|
|
|
if (gAiBufferLengths[index] != 0) {
|
|
|
|
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
oldDmaCount = gCurrAudioFrameDmaCount;
|
|
|
|
// There has to be some sort of no-op if here, but it's not exactly clear
|
|
|
|
// how it should look... It's also very unclear why gCurrAudioFrameDmaQueue
|
|
|
|
// isn't read from here, despite gCurrAudioFrameDmaCount being reset.
|
|
|
|
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
|
|
|
|
stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
|
|
|
|
}
|
|
|
|
gCurrAudioFrameDmaCount = 0;
|
|
|
|
|
|
|
|
gAudioTask = &gAudioTasks[gAudioTaskIndex];
|
|
|
|
gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
|
|
|
|
|
|
|
|
index = gCurrAiBufferIndex;
|
|
|
|
gCurrAiBuffer = gAiBuffers[index];
|
2020-12-03 14:26:38 -05:00
|
|
|
gAiBufferLengths[index] =
|
|
|
|
((gSamplesPerFrameTarget - samplesRemainingInAI + EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf)
|
|
|
|
+ SAMPLES_TO_OVERPRODUCE;
|
2019-08-25 00:46:40 -04:00
|
|
|
if (gAiBufferLengths[index] < gMinAiBufferLength) {
|
|
|
|
gAiBufferLengths[index] = gMinAiBufferLength;
|
|
|
|
}
|
2019-12-01 21:52:53 -05:00
|
|
|
if (gAiBufferLengths[index] > gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE) {
|
|
|
|
gAiBufferLengths[index] = gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sGameLoopTicked != 0) {
|
|
|
|
update_game_sound();
|
|
|
|
sGameLoopTicked = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For the function to match we have to preserve some arbitrary variable
|
|
|
|
// across this function call.
|
|
|
|
flags = 0;
|
2019-11-03 14:36:27 -05:00
|
|
|
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, gCurrAiBuffer, gAiBufferLengths[index]);
|
2019-12-01 21:52:53 -05:00
|
|
|
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
index = gAudioTaskIndex;
|
|
|
|
gAudioTask->msgqueue = NULL;
|
|
|
|
gAudioTask->msg = NULL;
|
|
|
|
|
|
|
|
task = &gAudioTask->task.t;
|
|
|
|
task->type = M_AUDTASK;
|
|
|
|
task->flags = flags;
|
|
|
|
task->ucode_boot = rspF3DBootStart;
|
2019-10-05 15:08:05 -04:00
|
|
|
task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
|
2019-08-25 00:46:40 -04:00
|
|
|
task->ucode = rspAspMainStart;
|
2019-10-05 15:08:05 -04:00
|
|
|
task->ucode_size = 0x800; // (this size is ignored)
|
2019-08-25 00:46:40 -04:00
|
|
|
task->ucode_data = rspAspMainDataStart;
|
|
|
|
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
|
|
|
|
task->dram_stack = NULL;
|
|
|
|
task->dram_stack_size = 0;
|
|
|
|
task->output_buff = NULL;
|
|
|
|
task->output_buff_size = NULL;
|
|
|
|
task->data_ptr = gAudioCmdBuffers[index];
|
|
|
|
task->data_size = writtenCmds * sizeof(u64);
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// The audio task never yields, so having a yield buffer is pointless.
|
|
|
|
// This wastefulness was fixed in US.
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifdef VERSION_JP
|
|
|
|
task->yield_data_ptr = (u64 *) gAudioSPTaskYieldBuffer;
|
|
|
|
task->yield_data_size = OS_YIELD_AUDIO_SIZE;
|
|
|
|
#else
|
|
|
|
task->yield_data_ptr = NULL;
|
|
|
|
task->yield_data_size = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
decrease_sample_dma_ttls();
|
|
|
|
return gAudioTask;
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_sound(s32 soundBits, f32 *pos) {
|
|
|
|
sSoundRequests[sSoundRequestCount].soundBits = soundBits;
|
|
|
|
sSoundRequests[sSoundRequestCount].position = pos;
|
|
|
|
sSoundRequestCount++;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static void process_sound_request(u32 bits, f32 *pos) {
|
|
|
|
u8 bank;
|
|
|
|
u8 soundIndex;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 counter = 0;
|
|
|
|
u8 soundId;
|
|
|
|
f32 dist;
|
|
|
|
const f32 one = 1.0f;
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
bank = (bits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
|
2019-08-25 00:46:40 -04:00
|
|
|
soundId = (bits & SOUNDARGS_MASK_SOUNDID) >> SOUNDARGS_SHIFT_SOUNDID;
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
if (soundId >= sNumSoundsPerBank[bank] || sSoundBankDisabled[bank]) {
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
soundIndex = sSoundBanks[bank][0].next;
|
|
|
|
while (soundIndex != 0xff && soundIndex != 0) {
|
|
|
|
// If an existing sound from the same source exists in the bank, then we should either
|
|
|
|
// interrupt that sound and replace it with the new sound, or we should drop the new sound.
|
|
|
|
if (sSoundBanks[bank][soundIndex].x == pos) {
|
|
|
|
// If the existing sound has lower or equal priority, then we should replace it.
|
|
|
|
// Otherwise the new sound will be dropped.
|
|
|
|
if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_PRIORITY)
|
2019-08-25 00:46:40 -04:00
|
|
|
<= (bits & SOUNDARGS_MASK_PRIORITY)) {
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// If the existing sound is discrete or is a different continuous sound, then
|
|
|
|
// interrupt it and play the new sound instead.
|
|
|
|
// Otherwise the new sound is continuous and equals the existing sound, so we just
|
|
|
|
// need to update the sound's freshness.
|
|
|
|
if ((sSoundBanks[bank][soundIndex].soundBits & SOUND_DISCRETE) != 0
|
2019-08-25 00:46:40 -04:00
|
|
|
|| (bits & SOUNDARGS_MASK_SOUNDID)
|
2020-12-03 14:26:38 -05:00
|
|
|
!= (sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)) {
|
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = bits;
|
|
|
|
// In practice, the starting status is always WAITING
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = bits & SOUNDARGS_MASK_STATUS;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// Reset freshness:
|
|
|
|
// - For discrete sounds, this gives the sound SOUND_MAX_FRESHNESS frames to play
|
|
|
|
// before it gets deleted for being stale
|
|
|
|
// - For continuous sounds, this gives it another 2 frames before play_sound must
|
|
|
|
// be called again to keep it playing
|
|
|
|
sSoundBanks[bank][soundIndex].freshness = SOUND_MAX_FRESHNESS;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// Prevent allocating a new node - if the existing sound had higher piority, then the
|
|
|
|
// new sound will be dropped
|
|
|
|
soundIndex = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
soundIndex = sSoundBanks[bank][soundIndex].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
counter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (counter == 0) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundMovingSpeed[bank] = 32;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// If free list has more than one element remaining
|
|
|
|
if (sSoundBanks[bank][sSoundBankFreeListFront[bank]].next != 0xff && soundIndex != 0) {
|
|
|
|
// Allocate from free list
|
|
|
|
soundIndex = sSoundBankFreeListFront[bank];
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
dist = sqrtf(pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]) * one;
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBanks[bank][soundIndex].x = &pos[0];
|
|
|
|
sSoundBanks[bank][soundIndex].y = &pos[1];
|
|
|
|
sSoundBanks[bank][soundIndex].z = &pos[2];
|
|
|
|
sSoundBanks[bank][soundIndex].distance = dist;
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = bits;
|
|
|
|
// In practice, the starting status is always WAITING
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = bits & SOUNDARGS_MASK_STATUS;
|
|
|
|
sSoundBanks[bank][soundIndex].freshness = SOUND_MAX_FRESHNESS;
|
|
|
|
|
|
|
|
// Append to end of used list and pop from front of free list
|
|
|
|
sSoundBanks[bank][soundIndex].prev = sSoundBankUsedListBack[bank];
|
|
|
|
sSoundBanks[bank][sSoundBankUsedListBack[bank]].next = sSoundBankFreeListFront[bank];
|
|
|
|
sSoundBankUsedListBack[bank] = sSoundBankFreeListFront[bank];
|
|
|
|
sSoundBankFreeListFront[bank] = sSoundBanks[bank][sSoundBankFreeListFront[bank]].next;
|
|
|
|
sSoundBanks[bank][sSoundBankFreeListFront[bank]].prev = 0xff;
|
|
|
|
sSoundBanks[bank][soundIndex].next = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Processes all sound requests
|
2020-12-03 14:26:38 -05:00
|
|
|
*
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
2019-08-25 00:46:40 -04:00
|
|
|
*/
|
2020-12-03 14:26:38 -05:00
|
|
|
static void process_all_sound_requests(void) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct Sound *sound;
|
|
|
|
|
|
|
|
while (sSoundRequestCount != sNumProcessedSoundRequests) {
|
|
|
|
sound = &sSoundRequests[sNumProcessedSoundRequests];
|
|
|
|
process_sound_request(sound->soundBits, sound->position);
|
|
|
|
sNumProcessedSoundRequests++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static void delete_sound_from_bank(u8 bank, u8 soundIndex) {
|
|
|
|
if (sSoundBankUsedListBack[bank] == soundIndex) {
|
|
|
|
// Remove from end of used list
|
|
|
|
sSoundBankUsedListBack[bank] = sSoundBanks[bank][soundIndex].prev;
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
// Set sound.next.prev to sound.prev
|
|
|
|
sSoundBanks[bank][sSoundBanks[bank][soundIndex].next].prev = sSoundBanks[bank][soundIndex].prev;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Set sound.prev.next to sound.next
|
|
|
|
sSoundBanks[bank][sSoundBanks[bank][soundIndex].prev].next = sSoundBanks[bank][soundIndex].next;
|
|
|
|
|
|
|
|
// Push to front of free list
|
|
|
|
sSoundBanks[bank][soundIndex].next = sSoundBankFreeListFront[bank];
|
|
|
|
sSoundBanks[bank][soundIndex].prev = 0xff;
|
|
|
|
sSoundBanks[bank][sSoundBankFreeListFront[bank]].prev = soundIndex;
|
|
|
|
sSoundBankFreeListFront[bank] = soundIndex;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void update_background_music_after_sound(u8 bank, u8 soundIndex) {
|
|
|
|
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
|
|
|
|
sSoundBanksThatLowerBackgroundMusic &= (1 << bank) ^ 0xffff;
|
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static void select_current_sounds(u8 bank) {
|
|
|
|
u32 isDiscreteAndStatus;
|
|
|
|
u8 latestSoundIndex;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
u8 j;
|
|
|
|
u8 soundIndex;
|
2020-12-03 14:26:38 -05:00
|
|
|
u32 liveSoundPriorities[16] = { 0x10000000, 0x10000000, 0x10000000, 0x10000000,
|
|
|
|
0x10000000, 0x10000000, 0x10000000, 0x10000000,
|
|
|
|
0x10000000, 0x10000000, 0x10000000, 0x10000000,
|
|
|
|
0x10000000, 0x10000000, 0x10000000, 0x10000000 };
|
|
|
|
u8 liveSoundIndices[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
|
u8 liveSoundStatuses[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
|
u8 numSoundsInBank = 0;
|
|
|
|
u8 requestedPriority;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Delete stale sounds and prioritize remaining sounds into the liveSound arrays
|
|
|
|
//
|
|
|
|
soundIndex = sSoundBanks[bank][0].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
while (soundIndex != 0xff) {
|
2020-12-03 14:26:38 -05:00
|
|
|
latestSoundIndex = soundIndex;
|
|
|
|
|
|
|
|
// If a discrete sound goes 10 frames without being played (because it is too low
|
|
|
|
// priority), then mark it for deletion
|
|
|
|
if ((sSoundBanks[bank][soundIndex].soundBits & (SOUND_DISCRETE | SOUNDARGS_MASK_STATUS))
|
|
|
|
== (SOUND_DISCRETE | SOUND_STATUS_WAITING)) {
|
|
|
|
if (sSoundBanks[bank][soundIndex].freshness-- == 0) {
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
|
|
|
// If a continuous sound goes 2 frames without play_sound being called, then mark it for
|
|
|
|
// deletion
|
|
|
|
else if ((sSoundBanks[bank][soundIndex].soundBits & SOUND_DISCRETE) == 0) {
|
|
|
|
if (sSoundBanks[bank][soundIndex].freshness-- == SOUND_MAX_FRESHNESS - 2) {
|
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// If a sound was marked for deletion and hasn't started playing yet, delete it now
|
|
|
|
if (sSoundBanks[bank][soundIndex].soundBits == NO_SOUND
|
|
|
|
&& sSoundBanks[bank][soundIndex].soundStatus == SOUND_STATUS_WAITING) {
|
|
|
|
// Since the current sound will be deleted, the next iteration should process
|
|
|
|
// sound.prev.next
|
|
|
|
latestSoundIndex = sSoundBanks[bank][soundIndex].prev;
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
|
|
|
|
delete_sound_from_bank(bank, soundIndex);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// If the current sound was not just deleted, consider it as a candidate for the currently
|
|
|
|
// playing sound
|
|
|
|
if (sSoundBanks[bank][soundIndex].soundStatus != SOUND_STATUS_STOPPED
|
|
|
|
&& soundIndex == latestSoundIndex) {
|
|
|
|
|
|
|
|
// Recompute distance each frame since the sound's position may have changed
|
|
|
|
sSoundBanks[bank][soundIndex].distance =
|
|
|
|
sqrtf((*sSoundBanks[bank][soundIndex].x * *sSoundBanks[bank][soundIndex].x)
|
|
|
|
+ (*sSoundBanks[bank][soundIndex].y * *sSoundBanks[bank][soundIndex].y)
|
|
|
|
+ (*sSoundBanks[bank][soundIndex].z * *sSoundBanks[bank][soundIndex].z))
|
2019-08-25 00:46:40 -04:00
|
|
|
* 1;
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
requestedPriority = (sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_PRIORITY)
|
|
|
|
>> SOUNDARGS_SHIFT_PRIORITY;
|
|
|
|
|
|
|
|
// Recompute priority, possibly based on the sound's source position relative to the
|
|
|
|
// camera.
|
|
|
|
// (Note that the sound's priority is the opposite of requestedPriority; lower is
|
|
|
|
// more important)
|
|
|
|
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_PRIORITY_LOSS) {
|
|
|
|
sSoundBanks[bank][soundIndex].priority = 0x4c * (0xff - requestedPriority);
|
|
|
|
} else if (*sSoundBanks[bank][soundIndex].z > 0.0f) {
|
|
|
|
sSoundBanks[bank][soundIndex].priority =
|
|
|
|
(u32) sSoundBanks[bank][soundIndex].distance
|
|
|
|
+ (u32)(*sSoundBanks[bank][soundIndex].z / US_FLOAT(6.0))
|
|
|
|
+ 0x4c * (0xff - requestedPriority);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBanks[bank][soundIndex].priority =
|
|
|
|
(u32) sSoundBanks[bank][soundIndex].distance + 0x4c * (0xff - requestedPriority);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Insert the sound into the liveSound arrays, keeping the arrays sorted by priority.
|
|
|
|
// If more than sMaxChannelsForSoundBank[bank] sounds are live, then the
|
|
|
|
// sound with lowest priority will be removed from the arrays.
|
|
|
|
// In practice sMaxChannelsForSoundBank is always 1, so this code is overly general.
|
|
|
|
for (i = 0; i < sMaxChannelsForSoundBank[bank]; i++) {
|
|
|
|
// If the correct position is found
|
|
|
|
if (liveSoundPriorities[i] >= sSoundBanks[bank][soundIndex].priority) {
|
|
|
|
// Shift remaining sounds to the right
|
|
|
|
for (j = sMaxChannelsForSoundBank[bank] - 1; j > i; j--) {
|
|
|
|
liveSoundPriorities[j] = liveSoundPriorities[j - 1];
|
|
|
|
liveSoundIndices[j] = liveSoundIndices[j - 1];
|
|
|
|
liveSoundStatuses[j] = liveSoundStatuses[j - 1];
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
// Insert the sound at index i
|
|
|
|
liveSoundPriorities[i] = sSoundBanks[bank][soundIndex].priority;
|
|
|
|
liveSoundIndices[i] = soundIndex;
|
|
|
|
liveSoundStatuses[i] = sSoundBanks[bank][soundIndex].soundStatus; // unused
|
|
|
|
// Break
|
|
|
|
i = sMaxChannelsForSoundBank[bank];
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
numSoundsInBank++;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
soundIndex = sSoundBanks[bank][latestSoundIndex].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
sNumSoundsInBank[bank] = numSoundsInBank;
|
|
|
|
sUsedChannelsForSoundBank[bank] = sMaxChannelsForSoundBank[bank];
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
//
|
|
|
|
// Remove any sounds from liveSoundIndices that are already playing.
|
|
|
|
// Stop any currently playing sounds that are not in liveSoundIndices.
|
|
|
|
//
|
|
|
|
for (i = 0; i < sUsedChannelsForSoundBank[bank]; i++) {
|
|
|
|
// Check if sCurrentSound[bank][i] is present in the liveSound arrays.
|
|
|
|
for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bank]; soundIndex++) {
|
|
|
|
if (liveSoundIndices[soundIndex] != 0xff
|
|
|
|
&& sCurrentSound[bank][i] == liveSoundIndices[soundIndex]) {
|
|
|
|
// If found, remove it from liveSoundIndices
|
|
|
|
liveSoundIndices[soundIndex] = 0xff;
|
|
|
|
soundIndex = 0xfe; // Break. Afterward soundIndex will be 0xff
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// If it is not present in the liveSound arrays, then stop playing it
|
2019-08-25 00:46:40 -04:00
|
|
|
if (soundIndex != 0xff) {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sCurrentSound[bank][i] != 0xff) {
|
|
|
|
// If the sound was marked for deletion and is playing, delete it
|
|
|
|
if (sSoundBanks[bank][sCurrentSound[bank][i]].soundBits == NO_SOUND) {
|
|
|
|
if (sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus == SOUND_STATUS_PLAYING) {
|
|
|
|
sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_STOPPED;
|
|
|
|
delete_sound_from_bank(bank, sCurrentSound[bank][i]);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// If the sound is discrete and is playing, then delete it
|
|
|
|
isDiscreteAndStatus = sSoundBanks[bank][sCurrentSound[bank][i]].soundBits
|
|
|
|
& (SOUND_DISCRETE | SOUNDARGS_MASK_STATUS);
|
|
|
|
if (isDiscreteAndStatus >= (SOUND_DISCRETE | SOUND_STATUS_PLAYING)
|
|
|
|
&& sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus != SOUND_STATUS_STOPPED) {
|
|
|
|
//! @bug On JP, if a discrete sound that lowers the background music is
|
|
|
|
// interrupted in this way, it will keep the background music low afterward.
|
|
|
|
// There are only a few of these sounds, and it probably isn't possible to do
|
|
|
|
// it in practice without using a time stop glitch like triple star spawn.
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifndef VERSION_JP
|
2020-12-03 14:26:38 -05:00
|
|
|
update_background_music_after_sound(bank, sCurrentSound[bank][i]);
|
2019-08-25 00:46:40 -04:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
sSoundBanks[bank][sCurrentSound[bank][i]].soundBits = NO_SOUND;
|
|
|
|
sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_STOPPED;
|
|
|
|
delete_sound_from_bank(bank, sCurrentSound[bank][i]);
|
|
|
|
}
|
|
|
|
// If the sound is continuous and is playing, then stop playing it but don't delete
|
|
|
|
// it. (A continuous sound shouldn't be deleted until it stops being requested)
|
|
|
|
else {
|
|
|
|
if (isDiscreteAndStatus == SOUND_STATUS_PLAYING
|
|
|
|
&& sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus
|
2019-08-25 00:46:40 -04:00
|
|
|
!= SOUND_STATUS_STOPPED) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBanks[bank][sCurrentSound[bank][i]].soundStatus = SOUND_STATUS_WAITING;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
sCurrentSound[bank][i] = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
//
|
|
|
|
// Start playing the remaining sounds from liveSoundIndices.
|
|
|
|
//
|
|
|
|
for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bank]; soundIndex++) {
|
|
|
|
if (liveSoundIndices[soundIndex] != 0xff) {
|
|
|
|
for (i = 0; i < sUsedChannelsForSoundBank[bank]; i++) {
|
|
|
|
if (sCurrentSound[bank][i] == 0xff) {
|
|
|
|
sCurrentSound[bank][i] = liveSoundIndices[soundIndex];
|
|
|
|
|
|
|
|
// Set (soundBits & status) to WAITING (soundStatus will be updated
|
|
|
|
// shortly after in update_game_sound)
|
|
|
|
sSoundBanks[bank][liveSoundIndices[soundIndex]].soundBits =
|
|
|
|
(sSoundBanks[bank][liveSoundIndices[soundIndex]].soundBits
|
|
|
|
& ~SOUNDARGS_MASK_STATUS)
|
|
|
|
+ SOUND_STATUS_WAITING;
|
|
|
|
|
|
|
|
liveSoundIndices[i] = 0xff; // doesn't do anything
|
|
|
|
i = 0xfe; // break
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given an x and z coordinates, return the pan. This is a value between 0 and
|
|
|
|
* 1 that represents the audio direction.
|
|
|
|
*
|
|
|
|
* Pan:
|
|
|
|
* 0.0 - fully left
|
|
|
|
* 0.5 - center pan
|
|
|
|
* 1.0 - fully right
|
2020-12-03 14:26:38 -05:00
|
|
|
*
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
2019-08-25 00:46:40 -04:00
|
|
|
*/
|
2020-12-03 14:26:38 -05:00
|
|
|
static f32 get_sound_pan(f32 x, f32 z) {
|
2019-08-25 00:46:40 -04:00
|
|
|
f32 absX;
|
|
|
|
f32 absZ;
|
|
|
|
f32 pan;
|
|
|
|
|
|
|
|
absX = (x < 0 ? -x : x);
|
2019-09-01 15:50:50 -04:00
|
|
|
if (absX > AUDIO_MAX_DISTANCE) {
|
2019-08-25 00:46:40 -04:00
|
|
|
absX = AUDIO_MAX_DISTANCE;
|
2019-09-01 15:50:50 -04:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
absZ = (z < 0 ? -z : z);
|
2019-09-01 15:50:50 -04:00
|
|
|
if (absZ > AUDIO_MAX_DISTANCE) {
|
2019-08-25 00:46:40 -04:00
|
|
|
absZ = AUDIO_MAX_DISTANCE;
|
2019-09-01 15:50:50 -04:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
// There are 4 panning equations (12-hr clock used for angles)
|
|
|
|
// 1. (0,0) fully-centered pan
|
|
|
|
// 2. far right pan: between 1:30 and 4:30
|
|
|
|
// 3. far left pan: between 7:30 and 10:30
|
|
|
|
// 4. center pan: between 4:30 and 7:30 or between 10:30 and 1:30
|
|
|
|
if (x == US_FLOAT(0.0) && z == US_FLOAT(0.0)) {
|
2020-12-03 14:26:38 -05:00
|
|
|
// x and z being 0 results in a center pan
|
2019-08-25 00:46:40 -04:00
|
|
|
pan = US_FLOAT(0.5);
|
|
|
|
} else if (x >= US_FLOAT(0.0) && absX >= absZ) {
|
|
|
|
// far right pan
|
|
|
|
pan = US_FLOAT(1.0) - (US_FLOAT(44000.0) - absX) / (US_FLOAT(3.0) * (US_FLOAT(44000.0) - absZ));
|
|
|
|
} else if (x < 0 && absX > absZ) {
|
|
|
|
// far left pan
|
|
|
|
pan = (US_FLOAT(44000.0) - absX) / (US_FLOAT(3.0) * (US_FLOAT(44000.0) - absZ));
|
|
|
|
} else {
|
|
|
|
// center pan
|
|
|
|
pan = 0.5 + x / (US_FLOAT(6.0) * absZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pan;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static f32 get_sound_volume(u8 bank, u8 soundIndex, f32 volumeRange) {
|
|
|
|
f32 maxSoundDistance;
|
2019-08-25 00:46:40 -04:00
|
|
|
f32 intensity;
|
|
|
|
#ifndef VERSION_JP
|
2020-12-03 14:26:38 -05:00
|
|
|
s32 div = bank < 3 ? 2 : 3;
|
2019-08-25 00:46:40 -04:00
|
|
|
#endif
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_VOLUME_LOSS)) {
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifdef VERSION_JP
|
2020-12-03 14:26:38 -05:00
|
|
|
// Intensity linearly lowers from 1 at the camera to 0 at maxSoundDistance
|
|
|
|
maxSoundDistance = sLevelAcousticReaches[gCurrLevelNum];
|
|
|
|
if (maxSoundDistance < sSoundBanks[bank][soundIndex].distance) {
|
2019-08-25 00:46:40 -04:00
|
|
|
intensity = 0.0f;
|
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
intensity = 1.0 - sSoundBanks[bank][soundIndex].distance / maxSoundDistance;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
// Intensity linearly lowers from 1 at the camera to 1 - volumeRange at maxSoundDistance,
|
|
|
|
// then it goes from 1 - volumeRange at maxSoundDistance to 0 at AUDIO_MAX_DISTANCE
|
|
|
|
if (sSoundBanks[bank][soundIndex].distance > AUDIO_MAX_DISTANCE) {
|
2019-08-25 00:46:40 -04:00
|
|
|
intensity = 0.0f;
|
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
maxSoundDistance = sLevelAcousticReaches[gCurrLevelNum] / div;
|
|
|
|
if (maxSoundDistance < sSoundBanks[bank][soundIndex].distance) {
|
|
|
|
intensity = ((AUDIO_MAX_DISTANCE - sSoundBanks[bank][soundIndex].distance)
|
|
|
|
/ (AUDIO_MAX_DISTANCE - maxSoundDistance))
|
|
|
|
* (1.0f - volumeRange);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
intensity =
|
|
|
|
1.0f - sSoundBanks[bank][soundIndex].distance / maxSoundDistance * volumeRange;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_VIBRATO) {
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifdef VERSION_JP
|
|
|
|
if (intensity != 0.0)
|
|
|
|
#else
|
|
|
|
if (intensity >= 0.08f)
|
|
|
|
#endif
|
|
|
|
{
|
2019-12-01 21:52:53 -05:00
|
|
|
intensity -= (f32)(gAudioRandom & 0xf) / US_FLOAT(192.0);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
intensity = 1.0f;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Rise quadratically from 1 - volumeRange to 1
|
|
|
|
return volumeRange * intensity * intensity + 1.0f - volumeRange;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static f32 get_sound_freq_scale(u8 bank, u8 item) {
|
|
|
|
f32 amount;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (!(sSoundBanks[bank][item].soundBits & SOUND_CONSTANT_FREQUENCY)) {
|
|
|
|
amount = sSoundBanks[bank][item].distance / AUDIO_MAX_DISTANCE;
|
|
|
|
if (sSoundBanks[bank][item].soundBits & SOUND_VIBRATO) {
|
|
|
|
amount += (f32)(gAudioRandom & 0xff) / US_FLOAT(64.0);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
amount = 0.0f;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// Goes from 1 at the camera to 1 + 1/15 at AUDIO_MAX_DISTANCE (and continues rising
|
|
|
|
// farther than that)
|
|
|
|
return amount / US_FLOAT(15.0) + US_FLOAT(1.0);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static u8 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelIndex) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 area;
|
|
|
|
u8 level;
|
|
|
|
u8 reverb;
|
|
|
|
|
|
|
|
#ifndef VERSION_JP
|
2020-12-03 14:26:38 -05:00
|
|
|
// Disable level reverb if NO_ECHO is set
|
|
|
|
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO) {
|
2019-08-25 00:46:40 -04:00
|
|
|
level = 0;
|
|
|
|
area = 0;
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
level = (gCurrLevelNum > LEVEL_MAX ? LEVEL_MAX : gCurrLevelNum);
|
|
|
|
area = gCurrAreaIndex - 1;
|
2019-09-01 15:50:50 -04:00
|
|
|
if (area > 2) {
|
2019-08-25 00:46:40 -04:00
|
|
|
area = 2;
|
2019-09-01 15:50:50 -04:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifndef VERSION_JP
|
|
|
|
}
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// reverb = reverb adjustment + level reverb + a volume-dependent value
|
|
|
|
// The volume-dependent value is 0 when volume is at maximum, and raises to
|
|
|
|
// LOW_VOLUME_REVERB when the volume is 0
|
2020-04-03 14:57:26 -04:00
|
|
|
reverb = (u8)((u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5]
|
2020-12-03 14:26:38 -05:00
|
|
|
+ sLevelAreaReverbs[level][area]
|
|
|
|
+ (US_FLOAT(1.0) - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume)
|
|
|
|
* LOW_VOLUME_REVERB);
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
if (reverb > 0x7f) {
|
|
|
|
reverb = 0x7f;
|
|
|
|
}
|
|
|
|
return reverb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void noop_8031EEC8(void) {
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from the game loop thread to inform the audio thread that a new game
|
|
|
|
* frame has started.
|
|
|
|
*
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void audio_signal_game_loop_tick(void) {
|
|
|
|
sGameLoopTicked = 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
maybe_tick_game_sound();
|
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
noop_8031EEC8();
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU and SH only)
|
|
|
|
*/
|
|
|
|
static void update_game_sound(void) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 soundStatus;
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 i;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 soundId;
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 bank;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 channelIndex = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
u8 soundIndex;
|
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
|
|
|
f32 value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
process_all_sound_requests();
|
|
|
|
process_level_music_dynamics();
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2020-04-03 14:57:26 -04:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_SFX].channels[0] == &gSequenceChannelNone) {
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
for (bank = 0; bank < SOUND_BANK_COUNT; bank++) {
|
|
|
|
select_current_sounds(bank);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_CHANNELS_PER_SOUND_BANK; i++) {
|
|
|
|
soundIndex = sCurrentSound[bank][i];
|
|
|
|
|
|
|
|
if (soundIndex < 0xff
|
|
|
|
&& sSoundBanks[bank][soundIndex].soundStatus != SOUND_STATUS_STOPPED) {
|
|
|
|
soundStatus = sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_STATUS;
|
|
|
|
soundId = (sSoundBanks[bank][soundIndex].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
|
|
|
|
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = soundStatus;
|
|
|
|
|
|
|
|
if (soundStatus == SOUND_STATUS_WAITING) {
|
|
|
|
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
|
|
|
|
sSoundBanksThatLowerBackgroundMusic |= 1 << bank;
|
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Set sound status to PLAYING
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits++;
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_PLAYING;
|
|
|
|
|
|
|
|
// Begin playing the sound
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[4] = soundId;
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 1;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
switch (bank) {
|
|
|
|
case SOUND_BANK_MOVING:
|
|
|
|
if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_CONSTANT_FREQUENCY)) {
|
|
|
|
if (sSoundMovingSpeed[bank] > 8) {
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(
|
|
|
|
0x02020000 | ((channelIndex & 0xff) << 8),
|
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
|
|
|
value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1)
|
|
|
|
* ((sSoundMovingSpeed[bank] + 8.0f) / 16));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
2020-12-03 14:26:38 -05:00
|
|
|
(sSoundMovingSpeed[bank] + 8.0f) / 16 * value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
|
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)
|
2019-10-05 15:08:05 -04:00
|
|
|
== (SOUND_MOVING_FLYING & SOUNDARGS_MASK_SOUNDID)) {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(
|
|
|
|
0x04020000 | ((channelIndex & 0xff) << 8),
|
|
|
|
get_sound_freq_scale(bank, soundIndex)
|
|
|
|
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_freq_scale(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)) + value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(
|
|
|
|
0x04020000 | ((channelIndex & 0xff) << 8),
|
|
|
|
get_sound_freq_scale(bank, soundIndex)
|
|
|
|
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_freq_scale(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)) + value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverb =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fallthrough
|
2020-12-03 14:26:38 -05:00
|
|
|
case SOUND_BANK_MENU:
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8), 1);
|
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8), 64);
|
|
|
|
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume = 1.0f;
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan = 0.5f;
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale = 1.0f;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
2020-12-03 14:26:38 -05:00
|
|
|
case SOUND_BANK_ACTION:
|
|
|
|
case SOUND_BANK_VOICE:
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z)
|
|
|
|
* 127.0f
|
|
|
|
+ 0.5f);
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
|
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverb =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
2020-12-03 14:26:38 -05:00
|
|
|
case SOUND_BANK_GENERAL:
|
|
|
|
case SOUND_BANK_ENV:
|
|
|
|
case SOUND_BANK_OBJ:
|
|
|
|
case SOUND_BANK_AIR:
|
|
|
|
case SOUND_BANK_GENERAL2:
|
|
|
|
case SOUND_BANK_OBJ2:
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z)
|
|
|
|
* 127.0f
|
|
|
|
+ 0.5f);
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverb =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2);
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
|
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef VERSION_JP
|
2020-12-03 14:26:38 -05:00
|
|
|
// If the sound was marked for deletion (bits set to NO_SOUND), then stop playing it
|
|
|
|
// and delete it
|
2019-08-25 00:46:40 -04:00
|
|
|
else if (soundStatus == SOUND_STATUS_STOPPED) {
|
2020-12-03 14:26:38 -05:00
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
delete_sound_from_bank(bank, soundIndex);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
else if (gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->layers[0] == NULL) {
|
2020-12-03 14:26:38 -05:00
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
|
|
|
|
delete_sound_from_bank(bank, soundIndex);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else if (soundStatus == SOUND_STATUS_STOPPED
|
2020-12-03 14:26:38 -05:00
|
|
|
&& gSequencePlayers[SEQ_PLAYER_SFX]
|
|
|
|
.channels[channelIndex]
|
|
|
|
->layers[0]
|
|
|
|
->finished
|
2019-08-25 00:46:40 -04:00
|
|
|
== FALSE) {
|
2020-12-03 14:26:38 -05:00
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[0] = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
delete_sound_from_bank(bank, soundIndex);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
// If sound has finished playing, then delete it
|
|
|
|
else if (gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->layers[0]->enabled
|
|
|
|
== FALSE) {
|
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundStatus = SOUND_STATUS_STOPPED;
|
|
|
|
delete_sound_from_bank(bank, soundIndex);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
|
|
|
// Exactly the same code as before. Unfortunately we can't
|
|
|
|
// make a macro out of this, because then everything ends up
|
|
|
|
// on the same line after preprocessing, and the compiler,
|
|
|
|
// somehow caring about line numbers, makes it not match (it
|
|
|
|
// computes function arguments in the wrong order).
|
2020-12-03 14:26:38 -05:00
|
|
|
switch (bank) {
|
|
|
|
case SOUND_BANK_MOVING:
|
|
|
|
if (!(sSoundBanks[bank][soundIndex].soundBits & SOUND_CONSTANT_FREQUENCY)) {
|
|
|
|
if (sSoundMovingSpeed[bank] > 8) {
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(
|
|
|
|
0x02020000 | ((channelIndex & 0xff) << 8),
|
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
|
|
|
value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1)
|
|
|
|
* ((sSoundMovingSpeed[bank] + 8.0f) / 16));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
2020-12-03 14:26:38 -05:00
|
|
|
(sSoundMovingSpeed[bank] + 8.0f) / 16 * value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
|
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if ((sSoundBanks[bank][soundIndex].soundBits & SOUNDARGS_MASK_SOUNDID)
|
2019-10-05 15:08:05 -04:00
|
|
|
== (SOUND_MOVING_FLYING & SOUNDARGS_MASK_SOUNDID)) {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(
|
|
|
|
0x04020000 | ((channelIndex & 0xff) << 8),
|
|
|
|
get_sound_freq_scale(bank, soundIndex)
|
|
|
|
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_freq_scale(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
((f32) sSoundMovingSpeed[bank] / US_FLOAT(80.0)) + value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(
|
|
|
|
0x04020000 | ((channelIndex & 0xff) << 8),
|
|
|
|
get_sound_freq_scale(bank, soundIndex)
|
|
|
|
+ ((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
value = get_sound_freq_scale(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
((f32) sSoundMovingSpeed[bank] / US_FLOAT(400.0)) + value;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverb =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fallthrough
|
2020-12-03 14:26:38 -05:00
|
|
|
case SOUND_BANK_MENU:
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8), 1);
|
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8), 64);
|
|
|
|
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume = 1.0f;
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan = 0.5f;
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale = 1.0f;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
2020-12-03 14:26:38 -05:00
|
|
|
case SOUND_BANK_ACTION:
|
|
|
|
case SOUND_BANK_VOICE:
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z)
|
|
|
|
* 127.0f
|
|
|
|
+ 0.5f);
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK1);
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
|
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverb =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
2020-12-03 14:26:38 -05:00
|
|
|
case SOUND_BANK_GENERAL:
|
|
|
|
case SOUND_BANK_ENV:
|
|
|
|
case SOUND_BANK_OBJ:
|
|
|
|
case SOUND_BANK_AIR:
|
|
|
|
case SOUND_BANK_GENERAL2:
|
|
|
|
case SOUND_BANK_OBJ2:
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x05020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x02020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2));
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad770(0x03020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z)
|
|
|
|
* 127.0f
|
|
|
|
+ 0.5f);
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x04020000 | ((channelIndex & 0xff) << 8),
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex));
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->reverb =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_reverb(bank, soundIndex, channelIndex);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_volume(bank, soundIndex, VOLUME_RANGE_UNK2);
|
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->pan =
|
|
|
|
get_sound_pan(*sSoundBanks[bank][soundIndex].x,
|
|
|
|
*sSoundBanks[bank][soundIndex].z);
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->freqScale =
|
2020-12-03 14:26:38 -05:00
|
|
|
get_sound_freq_scale(bank, soundIndex);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
// Increment to the next channel that this bank owns
|
2019-08-25 00:46:40 -04:00
|
|
|
channelIndex++;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Increment to the first channel index of the next bank
|
|
|
|
// (In practice sUsedChannelsForSoundBank[i] = sMaxChannelsForSoundBank[i] = 1, so this
|
|
|
|
// doesn't do anything)
|
|
|
|
channelIndex += sMaxChannelsForSoundBank[bank] - sUsedChannelsForSoundBank[bank];
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) {
|
|
|
|
u8 targetVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (player == SEQ_PLAYER_LEVEL) {
|
|
|
|
sCurrentBackgroundMusicSeqId = seqId & SEQ_BASE_ID;
|
2019-08-25 00:46:40 -04:00
|
|
|
sBackgroundMusicForDynamics = SEQUENCE_NONE;
|
|
|
|
sCurrentMusicDynamic = 0xff;
|
|
|
|
sMusicDynamicDelay = 2;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
for (i = 0; i < CHANNELS_MAX; i++) {
|
|
|
|
D_80360928[player][i].remainingFrames = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad770(0x46000000 | ((u8)(u32) player) << 16, seqId & SEQ_VARIATION);
|
|
|
|
func_802ad74c(0x82000000 | ((u8)(u32) player) << 16 | ((u8)(seqId & SEQ_BASE_ID)) << 8, arg2);
|
2020-02-03 00:51:26 -05:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (player == SEQ_PLAYER_LEVEL) {
|
|
|
|
targetVolume = begin_background_music_fade(0);
|
|
|
|
if (targetVolume != 0xff) {
|
|
|
|
gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolumeScale = (f32) targetVolume / US_FLOAT(127.0);
|
2020-02-03 00:51:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
gSequencePlayers[player].seqVariation = seqId & SEQ_VARIATION;
|
|
|
|
load_sequence(player, seqId & SEQ_BASE_ID, 0);
|
|
|
|
|
|
|
|
if (player == SEQ_PLAYER_LEVEL) {
|
|
|
|
targetVolume = begin_background_music_fade(0);
|
|
|
|
if (targetVolume != 0xff) {
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_LEVEL].state = SEQUENCE_PLAYER_STATE_4;
|
2020-12-03 14:26:38 -05:00
|
|
|
gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolume = (f32) targetVolume / US_FLOAT(127.0);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
func_8031D690(player, arg2);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void seq_player_fade_out(u8 player, u16 fadeDuration) {
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
#ifdef VERSION_EU
|
2020-12-03 14:26:38 -05:00
|
|
|
u32 fd = fadeDuration;
|
|
|
|
#else
|
|
|
|
s32 fd = fadeDuration; // will also match if we change function signature func_802ad74c to use s32 as arg1
|
|
|
|
#endif
|
2020-02-03 00:51:26 -05:00
|
|
|
if (!player) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
|
2020-02-03 00:51:26 -05:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
func_802ad74c(0x83000000 | (player & 0xff) << 16, fd);
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
if (player == SEQ_PLAYER_LEVEL) {
|
|
|
|
sCurrentBackgroundMusicSeqId = SEQUENCE_NONE;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_zero_volume(player, fadeDuration);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
for (i = 0; i < CHANNELS_MAX; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
fade_channel_volume_scale(player, i, targetScale, fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) {
|
2019-08-25 00:46:40 -04:00
|
|
|
struct ChannelVolumeScaleFade *temp;
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
|
|
|
|
temp = &D_80360928[player][channelIndex];
|
|
|
|
temp->remainingFrames = fadeDuration;
|
2019-08-25 00:46:40 -04:00
|
|
|
temp->velocity = ((f32)(targetScale / US_FLOAT(127.0))
|
2020-12-03 14:26:38 -05:00
|
|
|
- gSequencePlayers[player].channels[channelIndex]->volumeScale)
|
|
|
|
/ fadeDuration;
|
2019-08-25 00:46:40 -04:00
|
|
|
temp->target = targetScale;
|
2020-12-03 14:26:38 -05:00
|
|
|
temp->current = gSequencePlayers[player].channels[channelIndex]->volumeScale;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
|
|
|
static void func_8031F96C(u8 player) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
|
|
|
|
// Loop over channels
|
|
|
|
for (i = 0; i < CHANNELS_MAX; i++) {
|
|
|
|
if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone
|
2020-12-03 14:26:38 -05:00
|
|
|
&& D_80360928[player][i].remainingFrames != 0) {
|
2019-08-25 00:46:40 -04:00
|
|
|
D_80360928[player][i].current += D_80360928[player][i].velocity;
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
|
|
|
|
D_80360928[player][i].current);
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
gSequencePlayers[player].channels[i]->volumeScale = D_80360928[player][i].current;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
D_80360928[player][i].remainingFrames--;
|
|
|
|
if (D_80360928[player][i].remainingFrames == 0) {
|
|
|
|
#if defined(VERSION_EU)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
|
2020-12-03 14:26:38 -05:00
|
|
|
FLOAT_CAST(D_80360928[player][i].target) / 127.0);
|
|
|
|
#elif defined(VERSION_SH)
|
|
|
|
func_802ad728(0x01000000 | (player & 0xff) << 16 | (i & 0xff) << 8,
|
|
|
|
FLOAT_CAST(D_80360928[player][i].target) / 127.0f);
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2019-08-25 00:46:40 -04:00
|
|
|
gSequencePlayers[player].channels[i]->volumeScale =
|
|
|
|
D_80360928[player][i].target / 127.0f;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void process_level_music_dynamics(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
u32 conditionBits;
|
|
|
|
u16 tempBits;
|
|
|
|
UNUSED u16 pad;
|
|
|
|
u8 musicDynIndex;
|
|
|
|
u8 condIndex;
|
|
|
|
u8 i;
|
|
|
|
u8 j;
|
|
|
|
s16 conditionValues[8];
|
|
|
|
u8 conditionTypes[8];
|
|
|
|
s16 dur1;
|
|
|
|
s16 dur2;
|
|
|
|
u16 bit;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
func_8031F96C(0);
|
|
|
|
func_8031F96C(2);
|
|
|
|
func_80320ED8();
|
|
|
|
if (sMusicDynamicDelay != 0) {
|
|
|
|
sMusicDynamicDelay--;
|
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
sBackgroundMusicForDynamics = sCurrentBackgroundMusicSeqId;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sBackgroundMusicForDynamics != sLevelDynamics[gCurrLevelNum][0]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
conditionBits = sLevelDynamics[gCurrLevelNum][1] & 0xff00;
|
|
|
|
musicDynIndex = (u8) sLevelDynamics[gCurrLevelNum][1] & 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
i = 2;
|
|
|
|
while (conditionBits & 0xff00) {
|
2020-04-03 14:57:26 -04:00
|
|
|
j = 0;
|
|
|
|
condIndex = 0;
|
|
|
|
bit = 0x8000;
|
|
|
|
while (j < 8) {
|
2019-08-25 00:46:40 -04:00
|
|
|
if (conditionBits & bit) {
|
2019-12-01 21:52:53 -05:00
|
|
|
conditionValues[condIndex] = sLevelDynamics[gCurrLevelNum][i++];
|
2019-08-25 00:46:40 -04:00
|
|
|
conditionTypes[condIndex] = j;
|
|
|
|
condIndex++;
|
|
|
|
}
|
2020-04-03 14:57:26 -04:00
|
|
|
|
|
|
|
j++;
|
|
|
|
bit = bit >> 1;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2019-10-05 15:08:05 -04:00
|
|
|
for (j = 0; j < condIndex; j++) {
|
2019-08-25 00:46:40 -04:00
|
|
|
switch (conditionTypes[j]) {
|
|
|
|
case MARIO_X_GE: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (((s16) gMarioStates[0].pos[0]) < conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_Y_GE: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (((s16) gMarioStates[0].pos[1]) < conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_Z_GE: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (((s16) gMarioStates[0].pos[2]) < conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_X_LT: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (((s16) gMarioStates[0].pos[0]) >= conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_Y_LT: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (((s16) gMarioStates[0].pos[1]) >= conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_Z_LT: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (((s16) gMarioStates[0].pos[2]) >= conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_IS_IN_AREA: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (gCurrAreaIndex != conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MARIO_IS_IN_ROOM: {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (gMarioCurrentRoom != conditionValues[j]) {
|
2019-10-05 15:08:05 -04:00
|
|
|
j = condIndex + 1;
|
2020-12-03 14:26:38 -05:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-05 15:08:05 -04:00
|
|
|
if (j == condIndex) {
|
2019-08-25 00:46:40 -04:00
|
|
|
// The area matches. Break out of the loop.
|
|
|
|
tempBits = 0;
|
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
tempBits = sLevelDynamics[gCurrLevelNum][i] & 0xff00;
|
|
|
|
musicDynIndex = sLevelDynamics[gCurrLevelNum][i] & 0xff;
|
2019-12-01 21:52:53 -05:00
|
|
|
i++;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
conditionBits = tempBits;
|
|
|
|
}
|
|
|
|
|
2020-04-03 14:57:26 -04:00
|
|
|
if (sCurrentMusicDynamic != musicDynIndex) {
|
2020-12-03 14:26:38 -05:00
|
|
|
tempBits = 1;
|
2019-08-25 00:46:40 -04:00
|
|
|
if (sCurrentMusicDynamic == 0xff) {
|
|
|
|
dur1 = 1;
|
|
|
|
dur2 = 1;
|
|
|
|
} else {
|
|
|
|
dur1 = sMusicDynamics[musicDynIndex].dur1;
|
|
|
|
dur2 = sMusicDynamics[musicDynIndex].dur2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < CHANNELS_MAX; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
conditionBits = tempBits;
|
|
|
|
tempBits = 0;
|
|
|
|
if (sMusicDynamics[musicDynIndex].bits1 & conditionBits) {
|
|
|
|
fade_channel_volume_scale(SEQ_PLAYER_LEVEL, i, sMusicDynamics[musicDynIndex].volScale1,
|
|
|
|
dur1);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sMusicDynamics[musicDynIndex].bits2 & conditionBits) {
|
|
|
|
fade_channel_volume_scale(SEQ_PLAYER_LEVEL, i, sMusicDynamics[musicDynIndex].volScale2,
|
|
|
|
dur2);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
tempBits = conditionBits << 1;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
sCurrentMusicDynamic = musicDynIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void unused_8031FED0(u8 player, u32 bits, s8 arg2) {
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
if (arg2 < 0) {
|
|
|
|
arg2 = -arg2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < CHANNELS_MAX; i++) {
|
|
|
|
if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone) {
|
|
|
|
if ((bits & 3) == 0) {
|
|
|
|
gSequencePlayers[player].channels[i]->volumeScale = 1.0f;
|
|
|
|
} else if ((bits & 1) != 0) {
|
|
|
|
gSequencePlayers[player].channels[i]->volumeScale = (f32) arg2 / US_FLOAT(127.0);
|
|
|
|
} else {
|
|
|
|
gSequencePlayers[player].channels[i]->volumeScale =
|
|
|
|
US_FLOAT(1.0) - (f32) arg2 / US_FLOAT(127.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bits >>= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Lower a sequence player's volume over fadeDuration frames.
|
|
|
|
* If player is SEQ_PLAYER_LEVEL (background music), the given percentage is ignored
|
|
|
|
* and a max target volume of 40 is used.
|
|
|
|
*
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) {
|
|
|
|
if (player == SEQ_PLAYER_LEVEL) {
|
|
|
|
sLowerBackgroundMusicVolume = TRUE;
|
|
|
|
begin_background_music_fade(fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else if (gSequencePlayers[player].enabled == TRUE) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_percentage_of_volume(player, fadeDuration, percentage);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Remove the lowered volume constraint set by seq_player_lower_volume.
|
|
|
|
* If player is SEQ_PLAYER_LEVEL (background music), the music won't necessarily
|
|
|
|
* raise back to normal volume if other constraints have been set, e.g.
|
|
|
|
* sBackgroundMusicTargetVolume.
|
|
|
|
*
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void seq_player_unlower_volume(u8 player, u16 fadeDuration) {
|
|
|
|
sLowerBackgroundMusicVolume = FALSE;
|
|
|
|
if (player == SEQ_PLAYER_LEVEL) {
|
2019-08-25 00:46:40 -04:00
|
|
|
if (gSequencePlayers[player].state != SEQUENCE_PLAYER_STATE_FADE_OUT) {
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (gSequencePlayers[player].enabled == TRUE) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_normal_volume(player, fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Begin a volume fade to adjust the background music to the correct volume.
|
|
|
|
* The target volume is determined by global variables like sBackgroundMusicTargetVolume
|
|
|
|
* and sLowerBackgroundMusicVolume.
|
|
|
|
* If none of the relevant global variables are set, then the default background music
|
|
|
|
* volume for the sequence is used.
|
|
|
|
*
|
|
|
|
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static u8 begin_background_music_fade(u16 fadeDuration) {
|
|
|
|
u8 targetVolume = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sCurrentBackgroundMusicSeqId == SEQUENCE_NONE
|
|
|
|
|| sCurrentBackgroundMusicSeqId == SEQ_EVENT_CUTSCENE_CREDITS) {
|
2019-08-25 00:46:40 -04:00
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_LEVEL].volume == 0.0f && fadeDuration) {
|
2020-04-03 14:57:26 -04:00
|
|
|
gSequencePlayers[SEQ_PLAYER_LEVEL].volume = gSequencePlayers[SEQ_PLAYER_LEVEL].fadeVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET) {
|
|
|
|
targetVolume = (sBackgroundMusicTargetVolume & TARGET_VOLUME_VALUE_MASK);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sBackgroundMusicMaxTargetVolume != TARGET_VOLUME_UNSET) {
|
|
|
|
u8 maxTargetVolume = (sBackgroundMusicMaxTargetVolume & TARGET_VOLUME_VALUE_MASK);
|
|
|
|
if (targetVolume > maxTargetVolume) {
|
|
|
|
targetVolume = maxTargetVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sLowerBackgroundMusicVolume && targetVolume > 40) {
|
|
|
|
targetVolume = 40;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sSoundBanksThatLowerBackgroundMusic != 0 && targetVolume > 20) {
|
|
|
|
targetVolume = 20;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-04-03 14:57:26 -04:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_LEVEL].enabled == TRUE) {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (targetVolume != 0xff) {
|
|
|
|
seq_player_fade_to_target_volume(SEQ_PLAYER_LEVEL, fadeDuration, targetVolume);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-02-03 00:51:26 -05:00
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
2020-12-03 14:26:38 -05:00
|
|
|
gSequencePlayers[SEQ_PLAYER_LEVEL].volume =
|
|
|
|
sBackgroundMusicDefaultVolume[sCurrentBackgroundMusicSeqId] / 127.0f;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_normal_volume(SEQ_PLAYER_LEVEL, fadeDuration);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
return targetVolume;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void set_audio_muted(u8 muted) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
|
|
|
|
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
if (muted)
|
2020-02-03 00:51:26 -05:00
|
|
|
func_802ad74c(0xf1000000, 0);
|
|
|
|
else
|
|
|
|
func_802ad74c(0xf2000000, 0);
|
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
gSequencePlayers[i].muted = muted;
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void sound_init(void) {
|
|
|
|
u8 i;
|
|
|
|
u8 j;
|
|
|
|
|
|
|
|
for (i = 0; i < SOUND_BANK_COUNT; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
// Set each sound in the bank to STOPPED
|
2019-08-25 00:46:40 -04:00
|
|
|
for (j = 0; j < 40; j++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBanks[i][j].soundStatus = SOUND_STATUS_STOPPED;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Remove current sounds
|
|
|
|
for (j = 0; j < MAX_CHANNELS_PER_SOUND_BANK; j++) {
|
2019-12-01 21:52:53 -05:00
|
|
|
sCurrentSound[i][j] = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBankUsedListBack[i] = 0;
|
|
|
|
sSoundBankFreeListFront[i] = 1;
|
|
|
|
sNumSoundsInBank[i] = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < SOUND_BANK_COUNT; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
// Set used list to empty
|
|
|
|
sSoundBanks[i][0].prev = 0xff;
|
|
|
|
sSoundBanks[i][0].next = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
// Set free list to contain every sound slot
|
2019-08-25 00:46:40 -04:00
|
|
|
for (j = 1; j < 40 - 1; j++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBanks[i][j].prev = j - 1;
|
|
|
|
sSoundBanks[i][j].next = j + 1;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
sSoundBanks[i][j].prev = j - 1;
|
|
|
|
sSoundBanks[i][j].next = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-02-03 00:51:26 -05:00
|
|
|
for (j = 0; j < 3; j++) {
|
2019-08-25 00:46:40 -04:00
|
|
|
for (i = 0; i < CHANNELS_MAX; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
D_80360928[j][i].remainingFrames = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
for (i = 0; i < MAX_BACKGROUND_MUSIC_QUEUE_SIZE; i++) {
|
2019-08-25 00:46:40 -04:00
|
|
|
sBackgroundMusicQueue[i].priority = 0;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
sound_banks_enable(SEQ_PLAYER_SFX, SOUND_BANKS_ALL_BITS);
|
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
sUnused80332118 = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
sBackgroundMusicTargetVolume = TARGET_VOLUME_UNSET;
|
|
|
|
sLowerBackgroundMusicVolume = FALSE;
|
|
|
|
sSoundBanksThatLowerBackgroundMusic = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
sUnused80332114 = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
sCurrentBackgroundMusicSeqId = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
gSoundMode = SOUND_MODE_STEREO;
|
|
|
|
sBackgroundMusicQueueSize = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
|
2019-08-25 00:46:40 -04:00
|
|
|
D_80332120 = 0;
|
|
|
|
D_80332124 = 0;
|
|
|
|
sNumProcessedSoundRequests = 0;
|
|
|
|
sSoundRequestCount = 0;
|
|
|
|
}
|
|
|
|
|
2019-12-01 21:52:53 -05:00
|
|
|
// (unused)
|
2020-12-03 14:26:38 -05:00
|
|
|
void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInBank, u8 *soundId) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
2019-12-01 21:52:53 -05:00
|
|
|
u8 count = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
for (i = 0; i < sMaxChannelsForSoundBank[bank]; i++) {
|
|
|
|
if (sCurrentSound[bank][i] != 0xff) {
|
2019-12-01 21:52:53 -05:00
|
|
|
count++;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
2019-12-01 21:52:53 -05:00
|
|
|
*numPlayingSounds = count;
|
2020-12-03 14:26:38 -05:00
|
|
|
|
|
|
|
*numSoundsInBank = sNumSoundsInBank[bank];
|
|
|
|
|
|
|
|
if (sCurrentSound[bank][0] != 0xff) {
|
|
|
|
*soundId = (u8)(sSoundBanks[bank][sCurrentSound[bank][0]].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2019-12-01 21:52:53 -05:00
|
|
|
*soundId = 0xff;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void stop_sound(u32 soundBits, f32 *pos) {
|
|
|
|
u8 bank = (soundBits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
|
|
|
|
u8 soundIndex = sSoundBanks[bank][0].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
while (soundIndex != 0xff) {
|
|
|
|
// If sound has same id and source position pointer
|
2019-08-25 00:46:40 -04:00
|
|
|
if ((u16)(soundBits >> SOUNDARGS_SHIFT_SOUNDID)
|
2020-12-03 14:26:38 -05:00
|
|
|
== (u16)(sSoundBanks[bank][soundIndex].soundBits >> SOUNDARGS_SHIFT_SOUNDID)
|
|
|
|
&& sSoundBanks[bank][soundIndex].x == pos) {
|
|
|
|
|
|
|
|
// Mark sound for deletion
|
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
|
|
|
|
soundIndex = 0xff; // break
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
soundIndex = sSoundBanks[bank][soundIndex].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void stop_sounds_from_source(f32 *pos) {
|
|
|
|
u8 bank;
|
|
|
|
u8 soundIndex;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
for (bank = 0; bank < SOUND_BANK_COUNT; bank++) {
|
|
|
|
soundIndex = sSoundBanks[bank][0].next;
|
|
|
|
while (soundIndex != 0xff) {
|
|
|
|
if (sSoundBanks[bank][soundIndex].x == pos) {
|
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
soundIndex = sSoundBanks[bank][soundIndex].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void stop_sounds_in_bank(u8 bank) {
|
|
|
|
u8 soundIndex = sSoundBanks[bank][0].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
while (soundIndex != 0xff) {
|
|
|
|
update_background_music_after_sound(bank, soundIndex);
|
|
|
|
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
|
|
|
|
soundIndex = sSoundBanks[bank][soundIndex].next;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Stops sounds in all of the sound banks that predominantly consist of continuous
|
|
|
|
* sounds. Misses some specific continuous sounds in other banks like bird chirping
|
|
|
|
* and the ticking sound after pressing a switch.
|
|
|
|
*
|
|
|
|
* Called from threads: thread3_main, thread5_game_loop
|
|
|
|
*/
|
|
|
|
void stop_sounds_in_continuous_banks(void) {
|
|
|
|
stop_sounds_in_bank(SOUND_BANK_MOVING);
|
|
|
|
stop_sounds_in_bank(SOUND_BANK_ENV);
|
|
|
|
stop_sounds_in_bank(SOUND_BANK_AIR);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void sound_banks_disable(UNUSED u8 player, u16 bankMask) {
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
for (i = 0; i < SOUND_BANK_COUNT; i++) {
|
|
|
|
if (bankMask & 1) {
|
2019-12-01 21:52:53 -05:00
|
|
|
sSoundBankDisabled[i] = TRUE;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
bankMask = bankMask >> 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
static void disable_all_sequence_players(void) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
|
|
|
|
for (i = 0; i < SEQUENCE_PLAYERS; i++) {
|
|
|
|
sequence_player_disable(&gSequencePlayers[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void sound_banks_enable(UNUSED u8 player, u16 bankMask) {
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
for (i = 0; i < SOUND_BANK_COUNT; i++) {
|
|
|
|
if (bankMask & 1) {
|
2019-12-01 21:52:53 -05:00
|
|
|
sSoundBankDisabled[i] = FALSE;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
bankMask = bankMask >> 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 unused_803209D8(u8 player, u8 channelIndex, u8 arg2) {
|
|
|
|
u8 ret = 0;
|
|
|
|
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
|
2019-12-01 21:52:53 -05:00
|
|
|
gSequencePlayers[player].channels[channelIndex]->stopSomething2 = arg2;
|
2019-08-25 00:46:40 -04:00
|
|
|
ret = arg2;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Set the moving speed for a sound bank, which may affect the volume and pitch
|
|
|
|
* of the sound.
|
|
|
|
*
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
|
|
|
void set_sound_moving_speed(u8 bank, u8 speed) {
|
|
|
|
sSoundMovingSpeed[bank] = speed;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-10-05 15:08:05 -04:00
|
|
|
void play_dialog_sound(u8 dialogID) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 speaker;
|
|
|
|
|
2020-07-04 11:18:55 -04:00
|
|
|
if (dialogID >= DIALOG_COUNT) {
|
2019-10-05 15:08:05 -04:00
|
|
|
dialogID = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2019-10-05 15:08:05 -04:00
|
|
|
speaker = sDialogSpeaker[dialogID];
|
2019-08-25 00:46:40 -04:00
|
|
|
if (speaker != 0xff) {
|
2020-12-03 14:26:38 -05:00
|
|
|
play_sound(sDialogSpeakerVoice[speaker], gGlobalSoundSource);
|
|
|
|
|
|
|
|
// Play music during bowser message that appears when first entering the
|
|
|
|
// castle or when trying to enter a door without enough stars
|
|
|
|
if (speaker == BOWS1) {
|
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_KOOPA_MESSAGE, 0);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef VERSION_JP
|
|
|
|
// "You've stepped on the (Wing|Metal|Vanish) Cap Switch"
|
2019-12-01 21:52:53 -05:00
|
|
|
if (dialogID == DIALOG_010 || dialogID == DIALOG_011 || dialogID == DIALOG_012) {
|
2019-08-25 00:46:40 -04:00
|
|
|
play_puzzle_jingle();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2020-02-03 00:51:26 -05:00
|
|
|
void play_music(u8 player, u16 seqArgs, u16 fadeTimer) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 seqId = seqArgs & 0xff;
|
|
|
|
u8 priority = seqArgs >> 8;
|
|
|
|
u8 i;
|
|
|
|
u8 foundIndex = 0;
|
|
|
|
|
|
|
|
// Except for the background music player, we don't support queued
|
|
|
|
// sequences. Just play them immediately, stopping any old sequence.
|
2020-12-03 14:26:38 -05:00
|
|
|
if (player != SEQ_PLAYER_LEVEL) {
|
|
|
|
seq_player_play_sequence(player, seqId, fadeTimer);
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Abort if the queue is already full.
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sBackgroundMusicQueueSize == MAX_BACKGROUND_MUSIC_QUEUE_SIZE) {
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
2019-09-01 15:50:50 -04:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
// If already in the queue, abort, after first restarting the sequence if
|
|
|
|
// it is first, and handling disabled music somehow.
|
|
|
|
// (That handling probably ought to occur even when the queue is full...)
|
|
|
|
for (i = 0; i < sBackgroundMusicQueueSize; i++) {
|
|
|
|
if (sBackgroundMusicQueue[i].seqId == seqId) {
|
|
|
|
if (i == 0) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_LEVEL, seqId, fadeTimer);
|
2020-04-03 14:57:26 -04:00
|
|
|
} else if (!gSequencePlayers[SEQ_PLAYER_LEVEL].enabled) {
|
2019-08-25 00:46:40 -04:00
|
|
|
stop_background_music(sBackgroundMusicQueue[0].seqId);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the next sequence slot by priority.
|
|
|
|
for (i = 0; i < sBackgroundMusicQueueSize; i++) {
|
|
|
|
if (sBackgroundMusicQueue[i].priority <= priority) {
|
|
|
|
foundIndex = i;
|
2020-12-03 14:26:38 -05:00
|
|
|
i = sBackgroundMusicQueueSize; // break
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the sequence ends up first in the queue, start it, and make space for
|
2020-12-03 14:26:38 -05:00
|
|
|
// one more entry in the queue.
|
2019-08-25 00:46:40 -04:00
|
|
|
if (foundIndex == 0) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_LEVEL, seqId, fadeTimer);
|
2019-08-25 00:46:40 -04:00
|
|
|
sBackgroundMusicQueueSize++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move all items up in queue, throwing away the last one if we didn't put
|
|
|
|
// the new sequence first.
|
|
|
|
for (i = sBackgroundMusicQueueSize - 1; i > foundIndex; i--) {
|
|
|
|
sBackgroundMusicQueue[i].priority = sBackgroundMusicQueue[i - 1].priority;
|
|
|
|
sBackgroundMusicQueue[i].seqId = sBackgroundMusicQueue[i - 1].seqId;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert item into queue.
|
|
|
|
sBackgroundMusicQueue[foundIndex].priority = priority;
|
|
|
|
sBackgroundMusicQueue[foundIndex].seqId = seqId;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void stop_background_music(u16 seqId) {
|
|
|
|
u8 foundIndex;
|
|
|
|
u8 i;
|
|
|
|
|
2019-09-01 15:50:50 -04:00
|
|
|
if (sBackgroundMusicQueueSize == 0) {
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
2019-09-01 15:50:50 -04:00
|
|
|
}
|
2019-08-25 00:46:40 -04:00
|
|
|
|
|
|
|
// If sequence is not found, remove an empty queue item (the next empty
|
|
|
|
// queue slot).
|
|
|
|
foundIndex = sBackgroundMusicQueueSize;
|
|
|
|
|
|
|
|
// Search for the sequence.
|
|
|
|
for (i = 0; i < sBackgroundMusicQueueSize; i++) {
|
|
|
|
if (sBackgroundMusicQueue[i].seqId == (u8)(seqId & 0xff)) {
|
|
|
|
// Remove sequence from queue. If it was first, play the next one,
|
|
|
|
// or fade out the music.
|
|
|
|
sBackgroundMusicQueueSize--;
|
|
|
|
if (i == 0) {
|
|
|
|
if (sBackgroundMusicQueueSize != 0) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_LEVEL, sBackgroundMusicQueue[1].seqId, 0);
|
2019-08-25 00:46:40 -04:00
|
|
|
} else {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_out(SEQ_PLAYER_LEVEL, 20);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
foundIndex = i;
|
|
|
|
i = sBackgroundMusicQueueSize; // "break;"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move later slots down.
|
|
|
|
for (i = foundIndex; i < sBackgroundMusicQueueSize; i++) {
|
|
|
|
sBackgroundMusicQueue[i].priority = sBackgroundMusicQueue[i + 1].priority;
|
|
|
|
sBackgroundMusicQueue[i].seqId = sBackgroundMusicQueue[i + 1].seqId;
|
|
|
|
}
|
|
|
|
|
|
|
|
// @bug? If the sequence queue is full and we attempt to stop a sequence
|
|
|
|
// that isn't in the queue, this writes out of bounds. Can that happen?
|
|
|
|
sBackgroundMusicQueue[i].priority = 0;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void fadeout_background_music(u16 seqId, u16 fadeOut) {
|
|
|
|
if (sBackgroundMusicQueueSize != 0 && sBackgroundMusicQueue[0].seqId == (u8)(seqId & 0xff)) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_out(SEQ_PLAYER_LEVEL, fadeOut);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void drop_queued_background_music(void) {
|
|
|
|
if (sBackgroundMusicQueueSize != 0) {
|
|
|
|
sBackgroundMusicQueueSize = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
u16 get_current_background_music(void) {
|
|
|
|
if (sBackgroundMusicQueueSize != 0) {
|
|
|
|
return (sBackgroundMusicQueue[0].priority << 8) + sBackgroundMusicQueue[0].seqId;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void func_80320ED8(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
if (D_EU_80300558 != 0) {
|
|
|
|
D_EU_80300558--;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_ENV].enabled
|
|
|
|
|| sBackgroundMusicMaxTargetVolume == TARGET_VOLUME_UNSET || D_EU_80300558 != 0) {
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_ENV].enabled
|
|
|
|
|| sBackgroundMusicMaxTargetVolume == TARGET_VOLUME_UNSET) {
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_UNSET;
|
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET
|
2019-08-25 00:46:40 -04:00
|
|
|
&& (D_80332120 == SEQ_EVENT_MERRY_GO_ROUND || D_80332120 == SEQ_EVENT_PIRANHA_PLANT)) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, D_80332120, 1);
|
2019-08-25 00:46:40 -04:00
|
|
|
if (D_80332124 != 0xff) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, 1, D_80332124);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer) {
|
|
|
|
UNUSED u32 dummy;
|
|
|
|
|
|
|
|
sUnused80332118 = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sCurrentBackgroundMusicSeqId == 0xff || sCurrentBackgroundMusicSeqId == SEQ_MENU_TITLE_SCREEN) {
|
2019-08-25 00:46:40 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sBackgroundMusicTargetVolume == TARGET_VOLUME_UNSET) {
|
|
|
|
sBackgroundMusicTargetVolume = bgMusicVolume + TARGET_VOLUME_IS_PRESENT_FLAG;
|
|
|
|
begin_background_music_fade(fadeTimer);
|
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, seqId, fadeTimer >> 1);
|
2019-08-25 00:46:40 -04:00
|
|
|
if (volume < 0x80) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
D_80332124 = volume;
|
|
|
|
D_80332120 = seqId;
|
|
|
|
} else if (volume != 0xff) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sBackgroundMusicTargetVolume = bgMusicVolume + TARGET_VOLUME_IS_PRESENT_FLAG;
|
|
|
|
begin_background_music_fade(fadeTimer);
|
|
|
|
seq_player_fade_to_target_volume(SEQ_PLAYER_ENV, fadeTimer, volume);
|
2019-08-25 00:46:40 -04:00
|
|
|
D_80332124 = volume;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void func_80321080(u16 fadeTimer) {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (sBackgroundMusicTargetVolume != TARGET_VOLUME_UNSET) {
|
|
|
|
sBackgroundMusicTargetVolume = TARGET_VOLUME_UNSET;
|
2019-08-25 00:46:40 -04:00
|
|
|
D_80332120 = 0;
|
|
|
|
D_80332124 = 0;
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(fadeTimer);
|
|
|
|
seq_player_fade_out(SEQ_PLAYER_ENV, fadeTimer);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread3_main, thread5_game_loop
|
|
|
|
*/
|
|
|
|
void func_803210D4(u16 fadeDuration) {
|
2019-08-25 00:46:40 -04:00
|
|
|
u8 i;
|
|
|
|
|
|
|
|
if (sHasStartedFadeOut) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-03 14:57:26 -04:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_LEVEL].enabled == TRUE) {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad74c(0x83000000, fadeDuration);
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_zero_volume(SEQ_PLAYER_LEVEL, fadeDuration);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2020-04-03 14:57:26 -04:00
|
|
|
if (gSequencePlayers[SEQ_PLAYER_ENV].enabled == TRUE) {
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
|
|
|
func_802ad74c(0x83010000, fadeDuration);
|
2020-02-03 00:51:26 -05:00
|
|
|
#else
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_fade_to_zero_volume(SEQ_PLAYER_ENV, fadeDuration);
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < SOUND_BANK_COUNT; i++) {
|
2020-12-03 14:26:38 -05:00
|
|
|
if (i != SOUND_BANK_MENU) {
|
|
|
|
fade_channel_volume_scale(SEQ_PLAYER_SFX, i, 0, fadeDuration / 16);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
|
2019-08-25 00:46:40 -04:00
|
|
|
sHasStartedFadeOut = TRUE;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_course_clear(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_CUTSCENE_COLLECT_STAR, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 0;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_peachs_jingle(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_PEACH_MESSAGE, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 0;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Plays the puzzle jingle. Plays the dadada dadada *dadada* jingle
|
|
|
|
* that usually plays when you solve a "puzzle", like chests, talking to
|
|
|
|
* yoshi, releasing chain chomp, opening the pyramid top, etc.
|
2020-12-03 14:26:38 -05:00
|
|
|
*
|
|
|
|
* Called from threads: thread5_game_loop
|
2019-08-25 00:46:40 -04:00
|
|
|
*/
|
|
|
|
void play_puzzle_jingle(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_SOLVE_PUZZLE, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_star_fanfare(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_HIGH_SCORE, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_power_star_jingle(u8 arg0) {
|
|
|
|
if (!arg0) {
|
2020-12-03 14:26:38 -05:00
|
|
|
sBackgroundMusicTargetVolume = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_CUTSCENE_STAR_SPAWN, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_race_fanfare(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_RACE, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void play_toads_jingle(void) {
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_ENV, SEQ_EVENT_TOAD_MESSAGE, 0);
|
|
|
|
sBackgroundMusicMaxTargetVolume = TARGET_VOLUME_IS_PRESENT_FLAG | 20;
|
|
|
|
#if defined(VERSION_EU) || defined(VERSION_SH)
|
2020-02-03 00:51:26 -05:00
|
|
|
D_EU_80300558 = 2;
|
|
|
|
#endif
|
2020-12-03 14:26:38 -05:00
|
|
|
begin_background_music_fade(50);
|
2019-08-25 00:46:40 -04:00
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2020-02-03 00:51:26 -05:00
|
|
|
void sound_reset(u8 presetId) {
|
2019-08-25 00:46:40 -04:00
|
|
|
#ifndef VERSION_JP
|
2020-02-03 00:51:26 -05:00
|
|
|
if (presetId >= 8) {
|
|
|
|
presetId = 0;
|
2019-08-25 00:46:40 -04:00
|
|
|
sUnused8033323C = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
sGameLoopTicked = 0;
|
|
|
|
disable_all_sequence_players();
|
|
|
|
sound_init();
|
2020-12-03 14:26:38 -05:00
|
|
|
#ifdef VERSION_SH
|
|
|
|
func_802ad74c(0xF2000000, 0);
|
|
|
|
#endif
|
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
2020-02-03 00:51:26 -05:00
|
|
|
audio_reset_session(&gAudioSessionPresets[presetId]);
|
|
|
|
#else
|
|
|
|
audio_reset_session_eu(presetId);
|
|
|
|
#endif
|
2019-08-25 00:46:40 -04:00
|
|
|
osWritebackDCacheAll();
|
2020-02-03 00:51:26 -05:00
|
|
|
if (presetId != 7) {
|
2019-08-25 00:46:40 -04:00
|
|
|
preload_sequence(SEQ_EVENT_SOLVE_PUZZLE, PRELOAD_BANKS | PRELOAD_SEQUENCE);
|
|
|
|
preload_sequence(SEQ_EVENT_PEACH_MESSAGE, PRELOAD_BANKS | PRELOAD_SEQUENCE);
|
|
|
|
preload_sequence(SEQ_EVENT_CUTSCENE_STAR_SPAWN, PRELOAD_BANKS | PRELOAD_SEQUENCE);
|
|
|
|
}
|
2020-12-03 14:26:38 -05:00
|
|
|
seq_player_play_sequence(SEQ_PLAYER_SFX, SEQ_SOUND_PLAYER, 0);
|
2020-02-03 00:51:26 -05:00
|
|
|
D_80332108 = (D_80332108 & 0xf0) + presetId;
|
2019-08-25 00:46:40 -04:00
|
|
|
gSoundMode = D_80332108 >> 4;
|
|
|
|
sHasStartedFadeOut = FALSE;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
/**
|
|
|
|
* Called from threads: thread5_game_loop
|
|
|
|
*/
|
2019-08-25 00:46:40 -04:00
|
|
|
void audio_set_sound_mode(u8 soundMode) {
|
|
|
|
D_80332108 = (D_80332108 & 0xf) + (soundMode << 4);
|
|
|
|
gSoundMode = soundMode;
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:26:38 -05:00
|
|
|
#if defined(VERSION_JP) || defined(VERSION_US)
|
2019-08-25 00:46:40 -04:00
|
|
|
void unused_80321460(UNUSED s32 arg0, UNUSED s32 arg1, UNUSED s32 arg2, UNUSED s32 arg3) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void unused_80321474(UNUSED s32 arg0) {
|
|
|
|
}
|
2020-02-03 00:51:26 -05:00
|
|
|
#endif
|