Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 245 additions & 16 deletions src/SB/Core/gc/iSnd.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,112 @@
#include "iSnd.h"

#include <types.h>
#include "xSnd.h"
#include "xstransvc.h"
#include "xMath.h"

#include <dolphin/ar.h>
#include <dolphin/ax.h>
#include <dolphin/dvd/dvd.h>
#include <dolphin/mix.h>

#include "intrin.h"
#include <types.h>

#include "xCutscene.h"
#include "xSnd.h"
#include "xMath.h"
// Size: 0x10c
struct UNK_STREAMS
{
AXVPB* voice;
U32 x4;
U32 x8;
U8 pad[0x8C];
DVDCommandBlock cb;
U8 pad3[0x20];
ARQRequest request;
U8 pad2[0x4];
};

UNK_STREAMS streams[6];

vinfo voices[58];

S32 SoundFlags;
volatile S32 fc;
static char soundInited;
U32 houston_we_have_a_problem;

struct UNK_USERDATA
{
U32 x0;
U32 flags;
U32 aid;
U8 pad5[0xC];
U32 x18;
U8 pad[0x6C];
U32 x88;
U32 x8c;
U32 x90;
U8 pad3[0x40];
U32 source;
U32 dest_a;
U32 dest_b;
U32 xe0;
U32 xe4;
ARQRequest request;
};
ARQRequest* last_ar;

static void dv_callback(void* userdata)
{
struct UNK_VOIDSTAR
{
U8 pad[0x14];
U32 stream;
};

UNK_VOIDSTAR* data = (UNK_VOIDSTAR*)userdata;

if (!soundInited)
{
return;
}

U32 stream = data->stream;
xSndVoiceInfo* info = &gSnd.voice[stream];
info->sndID = 0;
info->flags = 0;
if (stream < sizeof(streams) / sizeof(UNK_STREAMS))
{
U32 idx = stream;
if (streams[idx].voice == NULL)
{
return;
}

DVDCancelAsync(&streams[idx].cb, NULL);
ARQRemoveRequest(&streams[idx].request);
AXSetVoiceState(streams[idx].voice, 0);
MIXReleaseChannel(streams[idx].voice);

extern vinfo voices[58];
extern char soundInited;
extern S32 SoundFlags;
extern F32 _1262;
extern F32 _1263;
extern volatile S32 fc;
streams[idx].voice = NULL;
streams[idx].x4 = 0x40000;
streams[idx].x8 = 0;
}
else
{
U32 idx = stream - sizeof(streams) / sizeof(UNK_STREAMS);
if (voices[idx].voice == NULL)
{
return;
}
MIXReleaseChannel(voices[idx].voice);
AXSetVoiceState(voices[idx].voice, 0);

voices[idx].voice = NULL;
voices[idx].x4 = 0;
voices[idx].x8 = 0;
}
}

void arq_callback(long)
static void arq_callback(u32)
{
if (!soundInited)
{
Expand All @@ -25,6 +115,144 @@ void arq_callback(long)
SoundFlags = 0;
}

static const char* dump_flags(U32 flags)
{
static char str[0x40];
memset(str, 0, sizeof(str));

// TODO:

return str;
}

static void arqcb(u32 pointerToARQRequest);

// FIXME: param name
static void dvdcb(s32 r3, DVDFileInfo* info)
{
if (!soundInited)
{
return;
}

UNK_USERDATA* data = (UNK_USERDATA*)info->cb.userData;
xSTAssetName(data->aid);
dump_flags(data->flags);
if (data->x0 == 0)
{
return;
}

if (r3 <= 0)
{
return;
}

data->x88 += r3;
data->x90 += r3;
data->flags |= 0x800;
data->flags &= ~0x100;
if (data->flags & (0x200 | 0x400))
{
houston_we_have_a_problem = TRUE;
}
if ((data->flags & 0x4) == 0)
{
return;
}

U32 dest = 0;
if ((data->flags & 0x1000) == 0)
{
data->flags |= 0x200;
dest = data->dest_a;
}
else if ((data->flags & 0x2000) == 0)
{
data->flags |= 0x400;
dest = data->dest_b;
}

if (dest != 0)
{
ARQPostRequest(&data->request, (u32)data, 0, 1, data->source, dest, 0x4000, arqcb);
}
}

static void arqcb(u32 pointerToARQRequest)
{
if (!soundInited)
{
return;
}

UNK_USERDATA* data = (UNK_USERDATA*)((ARQRequest*)pointerToARQRequest)->owner;

xSTAssetName(data->aid);
dump_flags(data->flags);
last_ar = (ARQRequest*)pointerToARQRequest;
if (last_ar->length == 0)
{
return;
}

//FIXME: Missing redundant branch instruction here
if (data->x0 == 0)
{
return;
}

if (data->flags & 0x100)
{
houston_we_have_a_problem = TRUE;
}
if (data->flags & 0x1000000)
{
if (data->flags & 0x200)
{
data->flags |= 0x1000;
data->flags &= ~0x200;
}
if (data->flags & 0x400)
{
data->flags |= 0x2000;
data->flags &= ~0x400;
}

data->x90 += data->xe4;
data->xe4 = 0;
data->xe0 = 0;
}
else if (data->flags & 0x200)
{
data->flags |= 0x1000;
data->flags &= ~0x200;
}
else if (data->flags & 0x400)
{
data->flags |= 0x2000;
data->flags &= ~0x400;
}

if (data->x8c - data->x90 == 0)
{
xSTAssetName(data->aid);
data->flags |= 0x20;
}
else if ((data->flags & 0x1000000) == 0)
{
data->flags |= 0x200000;
}

data->flags &= ~0x800;
data->flags &= ~0x4000000;
data->flags &= ~0x400000;
if(data->flags & 0x4) {
data->flags &= ~4;
data->flags |= 0x8;
}
}

void iSndExit()
{
soundInited = 0;
Expand Down Expand Up @@ -109,13 +337,14 @@ void iSndStereo(U32 i)
void iSndWaitForDeadSounds()
{
fc = 0;
int i = 0;
// Can't get 0x8c to get stored in r31
while ((i = fc) < 0x8c) //for (int i = 0; (i = fc) < 0x8c; )
for (int i = 0x8c; fc < i;)
{
// `i` is weird, it's stored in a saved register but never mutated. However it needs to be mutated to put it in a saved register
i = fc;
while (fc < i + 0xe)
;
// This adds the nonmatching instruction, but get's us back to the state `i`'s register should be in.
i = 0x8c;
iSndUpdate();
}
}
Expand Down Expand Up @@ -150,7 +379,7 @@ void sndloadcb(tag_xFile* tag)
SoundFlags = 0;
}

void iSndSetExternalCallback(void (*func_ptr)(U32))
void iSndSetExternalCallback(iSndExternalCallback callback)
{
}

Expand Down
54 changes: 34 additions & 20 deletions src/SB/Core/gc/iSnd.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ struct iSndFileInfo
struct vinfo
{
_AXVPB* voice;
S32 buffer[4];
U32 x4;
U32 x8;
S32 buffer[2];
U32 _0x14;
S32 buffer2[2];
};
Expand All @@ -69,35 +71,47 @@ enum isound_effect
iSND_EFFECT_CAVE
};

void arq_callback(long);
typedef void (*iSndExternalCallback)(U32);

void iSndInit();
void iSndExit();

void iSndPause(U32 snd, U32 pause);
void iSndSetEnvironmentalEffect(isound_effect);
void iSndInit();
void iSndCalcVol(xSndVoiceInfo* xSndVoiceInfo, vinfo* vinfo);
void iSndCalcVol3d(xSndVoiceInfo* xSndVoiceInfo, vinfo* vinfo);
void iSndVolUpdate(xSndVoiceInfo* info, vinfo* vinfo);
void iSndUpdateSounds();
void iSndUpdate();
void iSndSuspendCD(U32);
void iSndMessWithEA(sDSPADPCM* param1);
U32 SampleToNybbleAddress(U32 sample);
void iSndInitSceneLoaded();

S32 iSndIsPlaying(U32 assetID);
S32 iSndIsPlaying(U32 assetID, U32 parid);
S32 iSndIsPlayingByHandle(U32 handle);
iSndFileInfo* iSndLookup(U32 id);
void iSndWaitForDeadSounds();
void iSndSceneExit();
void sndloadcb(tag_xFile* tag);
S32 iSndLoadSounds(void*);
void iSndSetExternalCallback(void (*func_ptr)(U32));
void iSndAXFree(_AXVPB** param1);
void iSndStartStereo(U32 id1, U32 id2, F32 pitch);

void iSndPause(U32 snd, U32 pause);
void iSndStop(U32 snd);
void iSndUpdate();

void iSndFindFreeVoice(U32 priority, U32 flags, U32 owner);

void iSndPlay(xSndVoiceInfo* vp);
void iSndSetVol(U32 snd, F32 vol);
void iSndSetPitch(U32 snd, F32 pitch);
F32 iSndGetVol(U32 snd);
void iSndStartStereo(U32 id1, U32 id2, F32 pitch);
void iSndStereo(U32 stereo);

void iSndWaitForDeadSounds();
void iSndSuspendCD(U32);

void iSndSceneExit();

S32 iSndLoadSounds(void*);
void iSndDIEDIEDIE();
void iSndSetExternalCallback(iSndExternalCallback callback);

void iSndSuspend();
void iSndResume();

F32 iSndGetVol(U32 snd);

// FIXME: delete these
U32 SampleToNybbleAddress(U32 sample);
void iSndCalcVol(xSndVoiceInfo* xSndVoiceInfo, vinfo* vinfo);
void iSndCalcVol3d(xSndVoiceInfo* xSndVoiceInfo, vinfo* vinfo);
#endif