mirror of
https://gitlab.com/ryandwyer/perfect-dark
synced 2026-09-02 09:51:37 -04:00
1205 lines
26 KiB
C
1205 lines
26 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/chraicommands.h"
|
|
#include "game/dlights.h"
|
|
#include "game/propsnd.h"
|
|
#include "game/atan2f.h"
|
|
#include "game/hudmsg.h"
|
|
#include "game/file.h"
|
|
#include "game/lv.h"
|
|
#include "game/mplayer/mplayer.h"
|
|
#include "game/pad.h"
|
|
#include "bss.h"
|
|
#include "lib/snd.h"
|
|
#include "lib/rng.h"
|
|
#include "lib/mtx.h"
|
|
#include "lib/lib_317f0.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
struct audiochannel *g_AudioChannels = NULL;
|
|
|
|
u32 g_AudioPrevUuid = 0x00000000;
|
|
|
|
s8 var8006ae18 = 0;
|
|
s8 var8006ae1c = 0;
|
|
s8 var8006ae20 = 0;
|
|
s8 var8006ae24 = 0;
|
|
s8 var8006ae28 = 0;
|
|
u32 var8006ae2c = 0x00000000;
|
|
u32 var8006ae30 = 0x00000000;
|
|
u32 var8006ae34 = 0x00000000;
|
|
u32 var8006ae38 = 0x00000000;
|
|
|
|
u32 var8006ae40 = 0x00000000;
|
|
bool var8006ae44 = false;
|
|
u32 var8006ae48 = 0x00000001;
|
|
u32 var8006ae4c = 0x00000000;
|
|
s16 var8006ae50 = -1;
|
|
u32 var8006ae54 = 0x000003e7;
|
|
|
|
bool func0f092610(struct prop *prop, s32 arg1)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
if ((g_AudioChannels[i].flags & AUDIOCHANNELFLAG_IDLE) == 0
|
|
&& prop == g_AudioChannels[i].prop
|
|
&& (arg1 == g_AudioChannels[i].unk28 || arg1 == 1)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void func0f0926bc(struct prop *prop, s32 arg1, u16 arg2)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
struct audiochannel *channel = &g_AudioChannels[i];
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_IDLE) == 0 && channel->prop == prop) {
|
|
if (!channel->flags || !arg2 || (arg2 & channel->flags)) {
|
|
if (channel->unk28 == arg1 || arg1 == 1) {
|
|
func0f092a98(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
s32 func0f0927d4(f32 arg0, f32 arg1, f32 arg2, f32 arg3, s32 arg4)
|
|
{
|
|
s32 result = 0;
|
|
|
|
if (arg0 < arg3) {
|
|
if (arg1 > 5501) {
|
|
arg1 = 5501;
|
|
}
|
|
|
|
if (arg2 > 5801) {
|
|
arg2 = 5801;
|
|
}
|
|
|
|
if (arg3 > 6000) {
|
|
arg3 = 6000;
|
|
}
|
|
|
|
if (arg1 > arg0) {
|
|
result = arg4;
|
|
} else {
|
|
if (arg2 > arg0) {
|
|
result = arg4 - (s32)(sqrtf((arg0 - arg1) / (arg2 - arg1)) * (arg4 - 1000.0f));
|
|
} else {
|
|
result = (((arg3 - arg0) * 1000.0f) / (arg3 - arg2));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result > 0x7fff) {
|
|
result = 0x7fff;
|
|
}
|
|
|
|
if (result < 40) {
|
|
result = 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void propsnd0f09294c(struct prop *prop, s16 soundnum, s32 arg2)
|
|
{
|
|
s32 i;
|
|
|
|
if (propsnd0f0946b0(&prop->pos, 400, 2500, 3000, prop->rooms, soundnum, 0x7fff, 0)) {
|
|
// Return if this prop is already playing a sound
|
|
for (i = 8; i < 40; i++) {
|
|
if ((g_AudioChannels[i].flags & AUDIOCHANNELFLAG_IDLE) == 0
|
|
&& g_AudioChannels[i].prop == prop
|
|
&& g_AudioChannels[i].unk28 == arg2) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
propsnd0f0939f8(NULL, prop, soundnum, -1, -1, 2, 0, arg2, 0, -1.0f, 0, -1, -1.0f, -1.0f, -1.0f);
|
|
}
|
|
}
|
|
|
|
void func0f092a98(s32 channelnum)
|
|
{
|
|
struct audiochannel *channel = &g_AudioChannels[channelnum];
|
|
|
|
channel->flags2 |= 0x80;
|
|
|
|
if (channel->flags & AUDIOCHANNELFLAG_FORHUDMSG) {
|
|
hudmsgsHideByChannel(channelnum);
|
|
}
|
|
|
|
if (channel->flags & AUDIOCHANNELFLAG_FORPROP) {
|
|
propDecrementSoundCount(channel->prop);
|
|
}
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_ISMP3)) {
|
|
snd0000fbc4(channel->soundnum26);
|
|
} else if (channel->audiohandle && sndGetState(channel->audiohandle) != AL_STOPPED) {
|
|
audioStop(channel->audiohandle);
|
|
}
|
|
}
|
|
|
|
s32 propsndGetSubtitleOpacity(s32 channelnum)
|
|
{
|
|
if (channelnum == -1) {
|
|
return 1;
|
|
}
|
|
|
|
if ((g_AudioChannels[channelnum].flags & AUDIOCHANNELFLAG_IDLE) == 0) {
|
|
s32 value = g_AudioChannels[channelnum].unk06;
|
|
|
|
if (value == -1 || value > 200) {
|
|
s32 tmp = g_AudioChannels[channelnum].unk06 - 200;
|
|
s32 opacity = tmp * 255 / 15800;
|
|
|
|
if (opacity > 255) {
|
|
opacity = 255;
|
|
}
|
|
|
|
return opacity;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void propsndTickChannel(s32 channelnum)
|
|
{
|
|
struct audiochannel *channel = &g_AudioChannels[channelnum];
|
|
|
|
if ((channel->flags2 & AUDIOCHANNELFLAG2_0080) == 0
|
|
&& channel->unk28 != 11
|
|
&& ((channel->audiohandle != NULL && sndGetState(channel->audiohandle) != AL_STOPPED)
|
|
|| (channel->flags & AUDIOCHANNELFLAG_0002)
|
|
|| (channel->flags & AUDIOCHANNELFLAG_1000)
|
|
|| ((channel->flags & AUDIOCHANNELFLAG_ISMP3) && sndIsPlayingMp3()))) {
|
|
struct coord *pos = NULL; // 50
|
|
s16 *rooms = NULL; // 4c
|
|
s32 sp48;
|
|
s32 sp44;
|
|
s32 sp40;
|
|
f32 sp3c;
|
|
|
|
if (channel->prop) {
|
|
pos = &channel->prop->pos;
|
|
rooms = channel->prop->rooms;
|
|
} else if (channel->rooms[0] != -1) {
|
|
rooms = channel->rooms;
|
|
}
|
|
|
|
if (channel->posptr != NULL) {
|
|
pos = channel->posptr;
|
|
}
|
|
|
|
if (1);
|
|
|
|
if (g_Vars.langfilteron && (channel->flags2 & AUDIOCHANNELFLAG2_OFFENSIVE)) {
|
|
channel->unk04 = 0;
|
|
} else if (channel->flags2 & AUDIOCHANNELFLAG2_0010) {
|
|
if ((channel->flags & AUDIOCHANNELFLAG_1000) == 0) {
|
|
return;
|
|
}
|
|
|
|
channel->unk04 = channel->unk10;
|
|
} else {
|
|
if (pos && rooms) {
|
|
s16 *tmprooms;
|
|
|
|
if (channel->flags & AUDIOCHANNELFLAG_8000) {
|
|
tmprooms = NULL;
|
|
} else {
|
|
tmprooms = rooms;
|
|
}
|
|
|
|
var8006ae50 = channel->unk2c;
|
|
|
|
channel->unk04 = propsnd0f0946b0(pos, channel->unk34, channel->unk38, channel->unk3c,
|
|
tmprooms, channel->soundnum26, channel->unk10, &channel->unk4c);
|
|
}
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_0020) == 0) {
|
|
channel->unk0a = propsnd0f094d78(pos, channel->unk34, channel->unk38, channel->unk3c,
|
|
channel->unk4c, channel->flags & AUDIOCHANNELFLAG_0800, channel);
|
|
}
|
|
}
|
|
|
|
if (rooms != NULL && rooms[0] != -1) {
|
|
channel->unk0c = 0;
|
|
channel->unk1a = 1;
|
|
} else {
|
|
channel->unk0c = 0;
|
|
channel->unk1a = 1;
|
|
}
|
|
|
|
if (channel->audiohandle != NULL && channel->unk44 > 0.0f) {
|
|
if (channel->unk48 < 0.0f) {
|
|
sp3c = channel->unk44;
|
|
} else if (channel->unk20 > 0.0f) {
|
|
sp3c = channel->unk48 + (channel->unk44 - channel->unk48) * g_Vars.lvupdate240 / channel->unk20;
|
|
} else {
|
|
sp3c = channel->unk44;
|
|
}
|
|
} else {
|
|
sp3c = -1.0f;
|
|
}
|
|
|
|
sp44 = channel->unk0a;
|
|
sp48 = channel->unk06;
|
|
sp40 = channel->unk0c;
|
|
|
|
if (channel->unk06 == -1) {
|
|
sp48 = channel->unk04;
|
|
} else if (channel->unk1c >= 0) {
|
|
if (channel->unk1c > g_Vars.lvupdate60) {
|
|
sp48 = channel->unk06 + (channel->unk04 - channel->unk06) * g_Vars.lvupdate60 / channel->unk1c;
|
|
}
|
|
|
|
channel->unk1c -= g_Vars.lvupdate60;
|
|
} else if (channel->unk18 && channel->unk06 != channel->unk04) {
|
|
f32 f12 = channel->unk04 - channel->unk06;
|
|
f32 f14 = g_Vars.lvupdate60 * (1.0f / 6000.0f) * channel->unk18;
|
|
|
|
if (ABS(f12) > 1.0f) {
|
|
if (f14 > 1.0f) {
|
|
f14 = 1.0f;
|
|
}
|
|
|
|
if (ABS(f14 * f12) > 1.0f) {
|
|
sp48 = channel->unk06 + (s32) (f14 * f12);
|
|
}
|
|
}
|
|
} else {
|
|
sp48 = channel->unk04;
|
|
}
|
|
|
|
if (lvIsPaused()
|
|
|| (mpIsPaused() && (channel->flags2 & AUDIOCHANNELFLAG2_0002))
|
|
|| (mpIsPaused() && PLAYERCOUNT() == 1)) {
|
|
channel->unk06 = -1;
|
|
sp48 = 0;
|
|
}
|
|
|
|
if (sp48 != channel->unk06) {
|
|
channel->unk06 = sp48;
|
|
} else {
|
|
sp48 = -1;
|
|
}
|
|
|
|
if (channel->unk0a != channel->unk08) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_1000) {
|
|
channel->unk08 = channel->unk0a;
|
|
sp44 = channel->unk08;
|
|
} else {
|
|
s32 diff = channel->unk0a - channel->unk08;
|
|
s32 lvupdate = g_Vars.lvupdate240 * 512 / 240;
|
|
s32 dir = diff < 0 ? -1 : 1;
|
|
s32 absdiff = ABS(diff);
|
|
s32 amount = absdiff < lvupdate ? absdiff : lvupdate;
|
|
|
|
channel->unk08 += amount * dir;
|
|
sp44 = channel->unk08;
|
|
}
|
|
|
|
channel->flags |= AUDIOCHANNELFLAG_4000;
|
|
} else {
|
|
sp44 = -1;
|
|
}
|
|
|
|
if (sp40 != channel->unk0e) {
|
|
channel->unk0e = sp40;
|
|
} else {
|
|
sp40 = -1;
|
|
}
|
|
|
|
if (sp3c > 0.0f && ABS(sp3c - channel->unk48) > 0.01f) {
|
|
channel->unk48 = sp3c;
|
|
} else {
|
|
sp3c = -1.0f;
|
|
}
|
|
|
|
if (channel->flags & AUDIOCHANNELFLAG_0002) {
|
|
if (channel->unk06 > 0) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_2000) {
|
|
channel->flags &= ~AUDIOCHANNELFLAG_2000;
|
|
channel->flags |= AUDIOCHANNELFLAG_1000;
|
|
}
|
|
} else {
|
|
if ((channel->flags & AUDIOCHANNELFLAG_2000) == 0) {
|
|
if (channel->audiohandle != NULL && sndGetState(channel->audiohandle) != AL_STOPPED) {
|
|
audioStop(channel->audiohandle);
|
|
}
|
|
|
|
channel->flags |= AUDIOCHANNELFLAG_2000;
|
|
}
|
|
|
|
channel->flags &= ~AUDIOCHANNELFLAG_1000;
|
|
}
|
|
}
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_2000) == 0) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_1000) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_ISMP3) {
|
|
sndStartMp3(channel->soundnum26, sp48, sp44, (channel->flags2 & AUDIOCHANNELFLAG2_0001) ? 1 : 0);
|
|
} else {
|
|
if (channel->flags & AUDIOCHANNELFLAG_0400) {
|
|
if (sp48) {
|
|
snd00010718(&channel->audiohandle, channel->flags & AUDIOCHANNELFLAG_ISMP3, sp48, sp44,
|
|
channel->soundnum26, sp3c, channel->unk1a, sp40, 1);
|
|
}
|
|
} else {
|
|
if (sp48) {
|
|
snd00010718(&channel->audiohandle, channel->flags & AUDIOCHANNELFLAG_ISMP3, sp48, sp44,
|
|
channel->soundnum26, sp3c, channel->unk1a, sp40, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
channel->flags &= ~AUDIOCHANNELFLAG_1000;
|
|
} else {
|
|
sndAdjust(&channel->audiohandle, channel->flags & AUDIOCHANNELFLAG_ISMP3, sp48, sp44,
|
|
channel->soundnum26, sp3c, channel->unk1a, sp40, channel->flags & AUDIOCHANNELFLAG_4000);
|
|
}
|
|
}
|
|
} else {
|
|
if (channel->unk28 != 11) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_ISMP3) {
|
|
if (!sndIsPlayingMp3()) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_FORPROP) {
|
|
propDecrementSoundCount(channel->prop);
|
|
}
|
|
|
|
if (channel->flags & AUDIOCHANNELFLAG_FORHUDMSG) {
|
|
hudmsgsHideByChannel(channelnum);
|
|
}
|
|
}
|
|
|
|
channel->flags = AUDIOCHANNELFLAG_IDLE;
|
|
} else if (channel->audiohandle == NULL) {
|
|
if (channel->flags & AUDIOCHANNELFLAG_FORPROP) {
|
|
propDecrementSoundCount(channel->prop);
|
|
}
|
|
|
|
channel->flags = AUDIOCHANNELFLAG_IDLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
channel->flags &= ~AUDIOCHANNELFLAG_1000;
|
|
channel->flags &= ~AUDIOCHANNELFLAG_4000;
|
|
}
|
|
|
|
void propsndTick(void)
|
|
{
|
|
static s32 g_PropsndMaxActiveChannels = 0;
|
|
s32 count = 0;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
struct audiochannel *channel = &g_AudioChannels[i];
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_IDLE) == 0) {
|
|
propsndTickChannel(i);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (g_PropsndMaxActiveChannels < count) {
|
|
g_PropsndMaxActiveChannels = count;
|
|
}
|
|
}
|
|
|
|
void func0f093630(struct prop *prop, f32 arg1, s32 arg2)
|
|
{
|
|
OSPri prevpri;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
if ((g_AudioChannels[i].flags & AUDIOCHANNELFLAG_IDLE) == 0 && g_AudioChannels[i].prop == prop) {
|
|
g_AudioChannels[i].unk44 = arg1;
|
|
|
|
if (arg2 > 0) {
|
|
g_AudioChannels[i].unk20 = arg2 * 4;
|
|
} else {
|
|
g_AudioChannels[i].unk20 = -1;
|
|
}
|
|
|
|
prevpri = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
propsndTickChannel(i);
|
|
osSetThreadPri(0, prevpri);
|
|
}
|
|
}
|
|
}
|
|
|
|
void func0f093790(struct prop *prop, s32 arg1)
|
|
{
|
|
OSPri prevpri;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
if ((g_AudioChannels[i].flags & AUDIOCHANNELFLAG_IDLE) == 0 && prop == g_AudioChannels[i].prop) {
|
|
if (arg1 > 100) {
|
|
arg1 = 100;
|
|
}
|
|
|
|
prevpri = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
|
|
g_AudioChannels[i].unk10 = arg1 * 32767 / 100;
|
|
propsndTickChannel(i);
|
|
|
|
osSetThreadPri(0, prevpri);
|
|
}
|
|
}
|
|
}
|
|
|
|
void func0f0938ec(struct prop *prop)
|
|
{
|
|
s32 lowestuuid = -1;
|
|
s32 count = 0;
|
|
s32 bestindex = -1;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
struct audiochannel *channel = &g_AudioChannels[i];
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_IDLE) == 0
|
|
&& (channel->flags2 & AUDIOCHANNELFLAG2_0080) == 0
|
|
&& prop == channel->prop
|
|
&& channel->unk28 == 0x11) {
|
|
count++;
|
|
|
|
if (channel->uuid < lowestuuid) {
|
|
lowestuuid = channel->uuid;
|
|
bestindex = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (1);
|
|
|
|
if (count >= 2 && bestindex != -1) {
|
|
func0f092a98(bestindex);
|
|
}
|
|
}
|
|
|
|
s16 propsnd0f0939f8(
|
|
struct audiochannel *channel,
|
|
struct prop *prop,
|
|
s16 soundnum,
|
|
s16 padnum,
|
|
s32 arg4,
|
|
u16 flags,
|
|
u16 flags2,
|
|
s32 arg7,
|
|
struct coord *pos,
|
|
f32 arg9,
|
|
s16 *rooms,
|
|
s32 room,
|
|
f32 arg12,
|
|
f32 arg13,
|
|
f32 arg14)
|
|
{
|
|
union soundnumhack spac;
|
|
OSPri prevpri;
|
|
u32 stack[2];
|
|
s32 tmp;
|
|
|
|
struct pad pad;
|
|
s32 i;
|
|
s32 j;
|
|
|
|
if (arg7 == 0x11) {
|
|
func0f0938ec(prop);
|
|
}
|
|
|
|
spac.packed = soundnum;
|
|
|
|
if (channel == NULL) {
|
|
if (arg7 != 16 && var8005ddd4 > 12) {
|
|
return -1;
|
|
}
|
|
|
|
for (i = 8; i < 40; i++) {
|
|
if (g_AudioChannels[i].flags & AUDIOCHANNELFLAG_IDLE) {
|
|
channel = &g_AudioChannels[i];
|
|
channel->channelnum = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (padnum >= 0) {
|
|
pos = &g_Pads[padnum].pos;
|
|
room = g_Pads[padnum].room;
|
|
prop = NULL;
|
|
}
|
|
|
|
if (channel == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (g_AudioPrevUuid < 0xffffffff) {
|
|
g_AudioPrevUuid++;
|
|
} else {
|
|
g_AudioPrevUuid = 0;
|
|
}
|
|
|
|
channel->flags = flags;
|
|
channel->flags2 = flags2;
|
|
channel->audiohandle = NULL;
|
|
channel->unk06 = -1;
|
|
channel->unk08 = -1;
|
|
channel->unk0e = -1;
|
|
channel->unk04 = (arg4 != -1) ? arg4 : -1;
|
|
channel->unk0a = 64;
|
|
channel->unk0c = 0;
|
|
channel->unk10 = 0x7fff;
|
|
channel->unk1a = 1;
|
|
channel->unk44 = (arg9 > 0) ? arg9 : -1;
|
|
channel->unk48 = channel->unk44;
|
|
channel->unk20 = -1;
|
|
channel->unk1c = -1;
|
|
channel->padnum = padnum;
|
|
channel->prop = prop;
|
|
channel->unk28 = arg7;
|
|
channel->unk12 = arg4;
|
|
channel->unk40 = -1;
|
|
channel->unk34 = (arg12 > 0) ? arg12 : 400;
|
|
channel->unk38 = (arg13 > 0) ? arg13 : 2500;
|
|
channel->unk3c = (arg14 > 0) ? arg14 : 3000;
|
|
channel->unk18 = 0;
|
|
channel->uuid = g_AudioPrevUuid;
|
|
|
|
if (spac.hasconfig) {
|
|
s32 id = spac.confignum;
|
|
s32 confignum = g_AudioRussMappings[id].audioconfig_index;
|
|
s32 newid = g_AudioRussMappings[id].soundnum;
|
|
|
|
channel->unk34 = g_AudioConfigs[confignum].unk00;
|
|
channel->unk38 = g_AudioConfigs[confignum].unk04;
|
|
channel->unk3c = g_AudioConfigs[confignum].unk08;
|
|
channel->unk18 = g_AudioConfigs[confignum].unk18;
|
|
|
|
if (g_AudioConfigs[confignum].unk10 != 100) {
|
|
channel->unk10 = g_AudioConfigs[confignum].unk10 * 327;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].unk0c > 0) {
|
|
channel->unk44 = g_AudioConfigs[confignum].unk0c;
|
|
}
|
|
|
|
tmp = g_AudioConfigs[confignum].unk14;
|
|
|
|
if (tmp != -1) {
|
|
channel->unk0a = tmp;
|
|
channel->flags |= AUDIOCHANNELFLAG_0020;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].flags & AUDIOCONFIGFLAG_01) {
|
|
channel->flags |= AUDIOCHANNELFLAG_0800;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].flags & AUDIOCONFIGFLAG_04) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_0001;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].flags & AUDIOCONFIGFLAG_08) {
|
|
if (channel->unk04 == -1) {
|
|
channel->unk04 = channel->unk10;
|
|
}
|
|
|
|
channel->flags |= AUDIOCHANNELFLAG_8000;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].flags & AUDIOCONFIGFLAG_OFFENSIVE) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_OFFENSIVE;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].flags & AUDIOCONFIGFLAG_20) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_0010;
|
|
}
|
|
|
|
if (g_AudioConfigs[confignum].flags & AUDIOCONFIGFLAG_40) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_0040;
|
|
}
|
|
|
|
channel->flags |= AUDIOCHANNELFLAG_0040;
|
|
|
|
spac.packed = newid;
|
|
spac.hasconfig = false;
|
|
soundnum = spac.packed;
|
|
}
|
|
|
|
if (channel->unk18) {
|
|
channel->flags |= AUDIOCHANNELFLAG_0002;
|
|
}
|
|
|
|
channel->soundnum26 = spac.packed;
|
|
channel->unk2c = spac.id;
|
|
|
|
if (sndIsFiltered(channel->unk2c)) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_OFFENSIVE;
|
|
}
|
|
|
|
if (spac.unk02) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_0010;
|
|
}
|
|
|
|
if (pos) {
|
|
channel->pos = *pos;
|
|
channel->posptr = &channel->pos;
|
|
} else {
|
|
channel->posptr = NULL;
|
|
}
|
|
|
|
if (rooms) {
|
|
// @dangerous: Array overflow will occur if rooms has more than 8 elements
|
|
for (j = 0; rooms[j] != -1; j++) {
|
|
channel->rooms[j] = rooms[j];
|
|
}
|
|
|
|
channel->rooms[j] = -1;
|
|
} else if (room != -1) {
|
|
channel->rooms[0] = room;
|
|
channel->rooms[1] = -1;
|
|
} else {
|
|
channel->rooms[0] = -1;
|
|
}
|
|
|
|
if (!pos && !channel->prop) {
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_0010;
|
|
}
|
|
|
|
if ((channel->flags2 & AUDIOCHANNELFLAG2_0010) && channel->unk04 == -1) {
|
|
channel->unk04 = channel->unk10;
|
|
}
|
|
|
|
channel->flags |= AUDIOCHANNELFLAG_1000;
|
|
|
|
if (sndIsMp3(soundnum)) {
|
|
channel->flags |= AUDIOCHANNELFLAG_ISMP3;
|
|
|
|
prevpri = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
propsndTickChannel(channel->channelnum);
|
|
osSetThreadPri(0, prevpri);
|
|
} else {
|
|
prevpri = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
propsndTickChannel(channel->channelnum);
|
|
osSetThreadPri(0, prevpri);
|
|
}
|
|
|
|
if (channel->flags & AUDIOCHANNELFLAG_0400) {
|
|
channel->flags &= ~AUDIOCHANNELFLAG_0400;
|
|
channel->flags2 |= AUDIOCHANNELFLAG2_0010;
|
|
}
|
|
|
|
channel->flags &= ~AUDIOCHANNELFLAG_1000;
|
|
|
|
return channel->channelnum;
|
|
}
|
|
|
|
s32 audioPlayFromProp(s32 channelnum, s16 soundnum, s32 arg2, struct prop *prop, s16 arg4, u16 arg5)
|
|
{
|
|
s32 retchannelnum = -1;
|
|
|
|
if (arg4 == 11) {
|
|
if (channelnum >= 0 && channelnum <= 7) {
|
|
if (g_AudioChannels[channelnum].flags & AUDIOCHANNELFLAG_IDLE) {
|
|
g_AudioChannels[channelnum].soundnum26 = soundnum;
|
|
g_AudioChannels[channelnum].unk28 = 11;
|
|
g_AudioChannels[channelnum].flags &= ~AUDIOCHANNELFLAG_IDLE;
|
|
retchannelnum = channelnum;
|
|
} else {
|
|
g_AudioChannels[channelnum].soundnum26 = soundnum;
|
|
g_AudioChannels[channelnum].unk28 = 11;
|
|
g_AudioChannels[channelnum].flags &= ~AUDIOCHANNELFLAG_IDLE;
|
|
retchannelnum = channelnum;
|
|
}
|
|
} else {
|
|
// empty
|
|
}
|
|
} else if (channelnum == 10) {
|
|
retchannelnum = propsnd0f0939f8(NULL, prop, soundnum, -1,
|
|
(arg2 ? 0 : -1), arg5 | 0x0080, 0, arg4, 0, -1, 0, -1, -1, -1, -1);
|
|
} else if (channelnum < 0 || channelnum >= 8 || channelnum == 9) {
|
|
retchannelnum = propsnd0f0939f8(NULL, prop, soundnum, -1,
|
|
(arg2 ? 0 : -1), arg5, 0, arg4, 0, -1, 0, -1, -1, -1, -1);
|
|
} else {
|
|
if ((g_AudioChannels[channelnum].flags & AUDIOCHANNELFLAG_IDLE) == 0) {
|
|
func0f092a98(channelnum);
|
|
}
|
|
|
|
g_AudioChannels[channelnum].channelnum = channelnum;
|
|
|
|
propsnd0f0939f8(&g_AudioChannels[channelnum], prop, soundnum, -1,
|
|
(arg2 ? 0 : -1), arg5, 0, arg4, 0, -1, 0, -1, -1, -1, -1);
|
|
|
|
retchannelnum = channelnum;
|
|
}
|
|
|
|
return retchannelnum;
|
|
}
|
|
|
|
void audioMuteChannel(s32 channelnum)
|
|
{
|
|
if (channelnum == 10) {
|
|
s32 i;
|
|
|
|
for (i = 8; i < 40; i++) {
|
|
if ((g_AudioChannels[i].flags & AUDIOCHANNELFLAG_IDLE) == 0
|
|
&& (g_AudioChannels[i].flags & AUDIOCHANNELFLAG_0080)) {
|
|
func0f092a98(i);
|
|
}
|
|
}
|
|
} else if (channelnum >= 0 && channelnum <= 7) {
|
|
func0f092a98(channelnum);
|
|
}
|
|
}
|
|
|
|
bool audioIsChannelIdle(s32 channelnum)
|
|
{
|
|
if (channelnum >= 0 && channelnum <= 7) {
|
|
return (g_AudioChannels[channelnum].flags & AUDIOCHANNELFLAG_IDLE) ? true : false;
|
|
}
|
|
|
|
if (channelnum == 10) {
|
|
s32 i;
|
|
|
|
for (i = 8; i < 40; i++) {
|
|
if (g_AudioChannels[i].flags & AUDIOCHANNELFLAG_0080) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void audioPlayFromProp2(s32 channelnum, s32 arg1, s16 padnum, struct prop *prop, s32 arg4, s32 arg5, s32 arg6, u16 arg7)
|
|
{
|
|
struct audiochannel *channel = &g_AudioChannels[channelnum];
|
|
bool a1 = (arg4 >= 6) ? true : false;
|
|
bool a0 = (arg7 & 2) ? true : false;
|
|
|
|
if (channelnum >= 0 && channelnum <= 7) {
|
|
if (channel->unk28 == 11) {
|
|
g_AudioChannels[channelnum].channelnum = (u16)channelnum;
|
|
|
|
propsnd0f0939f8(&g_AudioChannels[channelnum], prop, channel->soundnum26, -1,
|
|
-1, arg7, 0, 0, 0, -1, 0, -1, 400, arg5, arg6);
|
|
} else {
|
|
if ((channel->flags & AUDIOCHANNELFLAG_2000) == 0 && arg1 >= 0) {
|
|
channel->unk04 = arg1;
|
|
}
|
|
|
|
if (a1) {
|
|
channel->unk1c = TICKS(arg4);
|
|
}
|
|
|
|
if (padnum != -1) {
|
|
channel->padnum = padnum;
|
|
}
|
|
|
|
if (prop) {
|
|
channel->prop = prop;
|
|
}
|
|
|
|
if (a0) {
|
|
channel->flags |= AUDIOCHANNELFLAG_0002;
|
|
}
|
|
|
|
if ((channel->flags & AUDIOCHANNELFLAG_0040) == 0) {
|
|
channel->unk34 = 400;
|
|
channel->unk38 = arg5;
|
|
channel->unk3c = arg6;
|
|
channel->unk18 = 0;
|
|
}
|
|
|
|
if (!a1 || channel->unk1c == 0) {
|
|
OSPri prevpri = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
propsndTickChannel(channelnum);
|
|
osSetThreadPri(0, prevpri);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
s32 propsnd0f0946b0(struct coord *pos, f32 arg1, f32 arg2, f32 arg3, s16 *rooms, s16 soundnum, s32 arg6, f32 *arg7)
|
|
{
|
|
union soundnumhack sp6c;
|
|
union soundnumhack sp68;
|
|
f32 sp64;
|
|
s16 sp62;
|
|
s32 s0;
|
|
s32 i;
|
|
|
|
sp64 = arg3 + 10.0f;
|
|
|
|
if (rooms != NULL) {
|
|
sp62 = *rooms;
|
|
} else {
|
|
sp62 = -1;
|
|
}
|
|
|
|
sp68.packed = soundnum;
|
|
sp6c.packed = soundnum;
|
|
|
|
if (sp68.hasconfig) {
|
|
s32 confignum = sp68.confignum;
|
|
s32 index = g_AudioRussMappings[confignum].audioconfig_index;
|
|
|
|
sp6c.packed = g_AudioRussMappings[confignum].soundnum;
|
|
|
|
arg1 = g_AudioConfigs[index].unk00;
|
|
arg2 = g_AudioConfigs[index].unk04;
|
|
arg3 = g_AudioConfigs[index].unk08;
|
|
|
|
if (arg3 < sp64) {
|
|
sp64 = arg3;
|
|
}
|
|
}
|
|
|
|
if (var8006ae34 && var8006ae2c == sp6c.id) {
|
|
s0 = 1;
|
|
} else {
|
|
s0 = 0;
|
|
}
|
|
|
|
for (i = 0; i < PLAYERCOUNT(); i++) {
|
|
struct player *player = g_Vars.players[i];
|
|
s32 camroom;
|
|
|
|
if (sp6c.unk02 == 0) {
|
|
camroom = player->cam_room;
|
|
} else {
|
|
camroom = -1;
|
|
}
|
|
|
|
func0f0056f4(camroom, &player->cam_pos, sp62, pos, 0, &sp64, s0);
|
|
}
|
|
|
|
if (arg7 != NULL) {
|
|
*arg7 = sp64;
|
|
}
|
|
|
|
return func0f0927d4(sp64, arg1, arg2, arg3, arg6);
|
|
}
|
|
|
|
s32 propsnd0f094940(s32 degrees, f32 arg1, struct audiochannel *channel)
|
|
{
|
|
s32 result;
|
|
|
|
while (degrees >= 180) {
|
|
degrees -= 360;
|
|
}
|
|
|
|
while (degrees < -180) {
|
|
degrees += 360;
|
|
}
|
|
|
|
switch (g_SoundMode) {
|
|
default:
|
|
{
|
|
s32 absdegrees = degrees > 0 ? degrees : -degrees;
|
|
s32 dir;
|
|
s32 v1;
|
|
|
|
if (absdegrees > 90) {
|
|
absdegrees = 180 - absdegrees;
|
|
}
|
|
|
|
v1 = absdegrees && absdegrees;
|
|
dir = (degrees > 0) ? (1) : (-1);
|
|
|
|
if (v1);
|
|
|
|
degrees = dir * absdegrees;
|
|
}
|
|
break;
|
|
case SOUNDMODE_SURROUND:
|
|
if (degrees > -45 && degrees < 45) {
|
|
degrees *= 2;
|
|
} else {
|
|
s32 dir = degrees > 0 ? 1 : -1;
|
|
s32 v1 = dir && dir;
|
|
s32 absdegrees = degrees > 0 ? degrees : -degrees;
|
|
s32 t4 = (180 - absdegrees) * 0.6666667f;
|
|
|
|
if (v1);
|
|
|
|
degrees = (180 - t4) * dir;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (degrees >= -90 && degrees <= 90) {
|
|
result = degrees * 0.7f + 64.0f;
|
|
} else {
|
|
s32 v0;
|
|
s32 dir = degrees > 0 ? 1 : -1;
|
|
s32 absdegrees = ABS(degrees);
|
|
|
|
result = (s32) ((180 - absdegrees) * dir * 0.7f + 64.0f) + 128;
|
|
}
|
|
|
|
if (channel != NULL) {
|
|
channel->unk14 = degrees;
|
|
channel->unk16 = 100.0f * arg1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
s32 propsnd0f094b1c(struct coord *pos, s32 arg1, f32 arg2, struct audiochannel *channel)
|
|
{
|
|
s32 result = 64;
|
|
u32 stack[4];
|
|
s32 a0;
|
|
f32 f2;
|
|
|
|
if (PLAYERCOUNT() < 2) {
|
|
struct coord *campos = &g_Vars.currentplayer->cam_pos;
|
|
f32 sp3c;
|
|
f32 sp38;
|
|
|
|
f2 = -(atan2f(pos->x - campos->x, pos->z - campos->z) * 180.0f / M_PI + g_Vars.currentplayer->vv_theta);
|
|
|
|
if (arg2 >= 0.0f) {
|
|
sp3c = sinf(0.017453292f * f2);
|
|
sp38 = cosf(0.017453292f * f2);
|
|
|
|
sp3c *= arg2;
|
|
|
|
f2 = atan2f(ABSF(sp3c), ABSF(sp38));
|
|
|
|
if (!(sp3c >= 0.0f) || !(sp38 >= 0.0f)) {
|
|
if (sp3c >= 0.0f) {
|
|
f2 = M_PI - f2;
|
|
} else if (sp38 >= 0.0f) {
|
|
f2 = -f2;
|
|
} else {
|
|
f2 = -(M_PI - f2);
|
|
}
|
|
}
|
|
|
|
a0 = (f2 * 57.295776f);
|
|
} else {
|
|
a0 = f2;
|
|
}
|
|
|
|
if (channel != NULL) {
|
|
channel->unk14 = a0;
|
|
channel->unk16 = 100.0f * arg2;
|
|
}
|
|
|
|
result = propsnd0f094940(a0, arg2, channel);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
s32 propsnd0f094d78(struct coord *pos, f32 arg1, f32 arg2, f32 arg3, f32 arg4, bool arg5, struct audiochannel *channel)
|
|
{
|
|
s32 result = 0x40;
|
|
|
|
if (pos != NULL && arg4 > 0) {
|
|
if (arg1 < 0) {
|
|
arg1 = 400;
|
|
}
|
|
|
|
if (arg2 < 0) {
|
|
arg2 = 2500;
|
|
}
|
|
|
|
if (arg3 < 0) {
|
|
arg3 = 3000;
|
|
}
|
|
|
|
if (arg4 < arg3) {
|
|
if (arg1 > 5501) {
|
|
arg1 = 5501;
|
|
}
|
|
|
|
if (arg2 > 5801) {
|
|
arg2 = 5801;
|
|
}
|
|
|
|
if (arg5 != 0) {
|
|
if (!(arg4 < arg1)) {
|
|
if (arg4 < arg2) {
|
|
f32 f2 = (arg4 - arg1) / (arg2 - arg1);
|
|
|
|
if (f2 < 0) {
|
|
f2 = 0;
|
|
}
|
|
|
|
if (f2 > 1) {
|
|
f2 = 1;
|
|
}
|
|
|
|
result = propsnd0f094b1c(pos, 0, f2, channel);
|
|
} else {
|
|
result = propsnd0f094b1c(pos, 0, -1, NULL);
|
|
}
|
|
}
|
|
} else {
|
|
result = propsnd0f094b1c(pos, 0, -1, channel);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void propsnd0f094ef4(struct coord *pos, s16 *rooms, s16 soundnum, s32 *arg3, s32 *arg4)
|
|
{
|
|
f32 sp5c;
|
|
f32 sp58;
|
|
f32 sp54;
|
|
struct audiorussmapping *russ;
|
|
struct audioconfig *config;
|
|
union soundnumhack sp48;
|
|
union soundnumhack sp44;
|
|
f32 sp40;
|
|
bool sp3c;
|
|
s32 index;
|
|
s32 confignum;
|
|
s32 zero = 0;
|
|
|
|
sp5c = 400;
|
|
sp58 = 2500;
|
|
sp54 = 3000;
|
|
if (1);
|
|
sp44.packed = soundnum;
|
|
sp40 = 9999999;
|
|
sp3c = false;
|
|
|
|
// To make this match, sp40 must be reloaded from the stack rather than
|
|
// reuse its register. Calling a function invalidates the register, thus
|
|
// forcing the compiler to emit code that reloads it from stack. Then an
|
|
// optimisation pass in the compiler removes this branch and function call,
|
|
// leaving the reload from stack in place.
|
|
if (zero) {
|
|
random();
|
|
}
|
|
|
|
if (sp44.hasconfig) {
|
|
confignum = sp44.confignum;
|
|
russ = &g_AudioRussMappings[confignum];
|
|
index = russ->audioconfig_index;
|
|
config = &g_AudioConfigs[index];
|
|
sp5c = config->unk00;
|
|
sp58 = config->unk04;
|
|
sp54 = config->unk08;
|
|
sp48.packed = russ->soundnum;
|
|
|
|
if (config->flags & AUDIOCONFIGFLAG_01) {
|
|
sp3c = true;
|
|
}
|
|
|
|
if (sp54 < sp40) {
|
|
sp40 = sp54;
|
|
}
|
|
|
|
sp48.hasconfig = false;
|
|
soundnum = sp48.packed;
|
|
}
|
|
|
|
*arg3 = propsnd0f0946b0(pos, sp5c, sp58, sp54, rooms, soundnum, 0x7fff, &sp40);
|
|
*arg4 = propsnd0f094d78(pos, sp5c, sp58, sp54, sp40, sp3c, 0);
|
|
}
|
|
|
|
void func0f09505c(struct sndstate *handle, struct coord *pos, f32 arg2, f32 arg3, f32 arg4, s16 *rooms, s16 soundnum, s32 arg7, f32 *arg8)
|
|
{
|
|
union soundnumhack sp5c;
|
|
union soundnumhack sp58;
|
|
f32 sp54;
|
|
bool sp50;
|
|
s32 sp4c;
|
|
s32 pan;
|
|
|
|
sp50 = false;
|
|
sp54 = 9999999;
|
|
sp58.packed = soundnum;
|
|
|
|
if (arg8 == NULL) {
|
|
arg8 = &sp54;
|
|
}
|
|
|
|
if (sp58.hasconfig) {
|
|
s32 confignum = sp58.confignum;
|
|
s32 index = g_AudioRussMappings[confignum].audioconfig_index;
|
|
|
|
arg2 = g_AudioConfigs[index].unk00;
|
|
arg3 = g_AudioConfigs[index].unk04;
|
|
arg4 = g_AudioConfigs[index].unk08;
|
|
sp5c.packed = g_AudioRussMappings[confignum].soundnum;
|
|
|
|
if (g_AudioConfigs[index].flags & AUDIOCONFIGFLAG_01) {
|
|
sp50 = true;
|
|
}
|
|
|
|
if (arg4 < *arg8) {
|
|
*arg8 = arg4;
|
|
}
|
|
|
|
sp5c.hasconfig = false;
|
|
soundnum = sp5c.packed;
|
|
}
|
|
|
|
sp4c = propsnd0f0946b0(pos, arg2, arg3, arg4, rooms, soundnum, arg7, arg8);
|
|
pan = propsnd0f094d78(pos, arg2, arg3, arg4, *arg8, sp50, 0);
|
|
sndAdjust(&handle, sndIsMp3(soundnum), sp4c, pan, soundnum, 1.0f, 1, -1, 1);
|
|
}
|
|
|
|
s32 propsndGetRandomSparkSound(void)
|
|
{
|
|
s32 index = random() % 6;
|
|
|
|
s16 sounds[] = {
|
|
SFX_80B0,
|
|
SFX_80B1,
|
|
SFX_80B2,
|
|
SFX_80B3,
|
|
SFX_80B4,
|
|
SFX_80B5,
|
|
};
|
|
|
|
return sounds[index];
|
|
}
|
|
|
|
/**
|
|
* Get the duration for an MP3 file by channel number.
|
|
*
|
|
* All MP3 files are 24 kilobits per second
|
|
* so this is just math based on the filesize.
|
|
*/
|
|
s32 propsndGetDuration60(s32 channelnum)
|
|
{
|
|
struct audiochannel *channel = &g_AudioChannels[channelnum];
|
|
|
|
if (channelnum >= 0 && channelnum < 40
|
|
&& (channel->flags & AUDIOCHANNELFLAG_IDLE) == 0
|
|
&& (channel->flags & AUDIOCHANNELFLAG_ISMP3)) {
|
|
union soundnumhack soundnum;
|
|
soundnum.packed = channel->soundnum26;
|
|
|
|
return fileGetRomSize(soundnum.id) * 60 / (1024 * 24 / 8);
|
|
}
|
|
|
|
return -1;
|
|
}
|