marioparty4/src/msm/msmstream.c
2025-01-15 23:40:36 -06:00

1029 lines
32 KiB
C
Executable file

#include "msm/msmstream.h"
#include "msm/msmmem.h"
#include "msm/msmsys.h"
typedef struct {
/* 0x00 */ SND_STREAMID stid;
/* 0x04 */ s16 streamId;
/* 0x06 */ u8 status;
/* 0x07 */ u8 stereoF;
/* 0x08 */ u8 volBase;
/* 0x09 */ u8 vol;
/* 0x0A */ u8 volFade;
/* 0x0B */ u8 pauseVol;
/* 0x0C */ u8 panBase;
/* 0x0D */ u8 pan;
/* 0x0E */ s8 slotL;
/* 0x0F */ s8 slotR;
/* 0x10 */ u32 pauseLen;
/* 0x14 */ volatile s32 pauseTime;
/* 0x18 */ volatile s32 pauseTimeMax;
/* 0x1C */ s32 fadeVol;
/* 0x20 */ s32 unk20;
/* 0x24 */ volatile s32 fadeMaxTime;
/* 0x28 */ s32 fadeTime;
/* 0x2C */ s8 span;
/* 0x2D */ s8 auxA;
/* 0x2E */ s8 auxB;
/* 0x30 */ void* streamBuf;
/* 0x34 */ u32 streamBufSize;
/* 0x38 */ u32 streamFrq;
/* 0x3C */ struct {
volatile u8 bufNo : 1;
volatile u8 firstF : 1;
u8 streamOffF : 1;
u8 readBusyF : 1;
volatile u8 shutdownF : 1;
volatile u8 pauseF : 1;
volatile u8 updateAramF : 1;
};
s32 frq;
/* 0x44 */ SND_ADPCMSTREAM_INFO* adpcmInfo;
/* 0x48 */ s32 streamBaseOfs;
/* 0x4C */ u32 streamPos;
/* 0x50 */ u32 loopLen;
/* 0X54 */ s32 loopEndOfs;
/* 0x58 */ u32 streamReadSize;
/* 0x5C */ void* streamReadBuf;
/* 0X60 */ s32 streamPosStart;
/* 0x64 */ u32 unk64;
/* 0x68 */ s32 unk68;
/* 0x6C */ s32 unk6C;
/* 0x70 */ DVDFileInfo file;
} MSM_STREAM_SLOT; // Size 0xAC
static struct {
/* 0x00 */ s32 sampleFrq;
/* 0x04 */ u32 bufSize;
/* 0x08 */ s32 frq;
/* 0x0C */ s32 pdtEntryNum;
/* 0x10 */ s8 time;
/* 0x11 */ u8 masterVol;
/* 0x12 */ u8 outputMode;
/* 0x14 */ u32* streamPackList;
/* 0x18 */ s8* streamPackFlag;
/* 0x1C */ SND_ADPCMSTREAM_INFO* adpcmParam;
/* 0x20 */ MSM_STREAM_SLOT* slot;
MSM_STREAM_HEADER header ATTRIBUTE_ALIGN(32);
} StreamInfo; // Size 0x60
typedef struct {
/* 0x00 */ u8 vol;
/* 0x01 */ u8 pan;
/* 0x02 */ u8 span;
/* 0x03 */ u8 auxA;
/* 0x04 */ u8 auxB;
/* 0x08 */ s32 sampleOfs;
} STREAM_PARAM;
static void msmStreamPauseFade(s32 streamNo);
static void msmStreamFade(s32 streamNo);
static void msmStreamDvdCallback(s32 result, DVDFileInfo* fileInfo);
static void msmStreamStopSub(s32 streamNo, s32 speed);
static void msmStreamDvdCallback2(s32 result, DVDFileInfo* fileInfo);
static u32 msmStreamUpdateFunc(void* buffer1, u32 len1, void* buffer2, u32 len2, u32 user);
static s32 msmStreamSlotInit(MSM_STREAM_SLOT* arg0, MSM_STREAM_PACK* arg1, STREAM_PARAM* arg2, s32 arg3);
static void msmStreamPauseOff(s32 streamNo);
static void msmStreamPauseOn(s32 streamNo, s32 arg1);
static s32 msmStreamPackStartStereo(s32 streamId, MSM_STREAMPARAM *param, s32 sampleOfs);
static s32 msmStreamPackStartMono(s32 streamId, MSM_STREAMPARAM *param, s32 sampleOfs);
static void msmStreamSlotOff(s32 streamNo);
static inline void msmStreamClose(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
DVDClose(&slot->file);
slot->status = 0;
}
s32 msmStreamGetStatus(int streamNo) {
MSM_STREAM_SLOT* slot;
s32 status;
if (streamNo < 0 || streamNo >= StreamInfo.header.chanMax) {
return 0;
}
slot = &StreamInfo.slot[streamNo];
switch (slot->status) {
case 4:
status = MSM_STREAM_PLAY;
break;
case 2:
case 3:
status = MSM_STREAM_PAUSEOUT;
break;
case 5:
status = MSM_STREAM_STOP;
break;
default:
status = MSM_STREAM_DONE;
break;
}
if (slot->pauseF == TRUE) {
status = MSM_STREAM_PAUSEIN;
}
if (status == MSM_STREAM_DONE && slot->slotL != -1) {
status = msmStreamGetStatus(slot->slotL);
}
return status;
}
static void msmStreamUpdateBaseParam(MSM_STREAM_SLOT* slot) {
s32 pan;
s32 vol;
if (StreamInfo.outputMode != 0) {
pan = slot->panBase + slot->pan - 64;
if (pan < 0) {
pan = 0;
}
if (pan > 127) {
pan = 127;
}
} else {
pan = 64;
}
vol = slot->volBase * slot->vol * slot->volFade * slot->pauseVol / (127*127*127);
sndStreamMixParameterEx(slot->stid, vol * StreamInfo.masterVol / 127, pan, slot->span, slot->auxA, slot->auxB);
}
void msmStreamSetMasterVolume(s32 vol) {
s32 i;
StreamInfo.masterVol = vol & 127;
for (i = 0; i < StreamInfo.header.chanMax; i++) {
if (StreamInfo.slot[i].status != 0) {
msmStreamUpdateBaseParam(&StreamInfo.slot[i]);
}
}
}
static inline BOOL msmStreamIsPlay(MSM_STREAM_SLOT* slot) {
if (slot->status != 0 || slot->pauseF != 0) {
return TRUE;
} else {
return FALSE;
}
}
void msmStreamStopAll(s32 speed)
{
MSM_STREAM_SLOT* slot;
s32 i;
msmSysIrqDisable();
for (i = 0; i < StreamInfo.header.chanMax; i++) {
if (i >= 0 && i < StreamInfo.header.chanMax) {
slot = &StreamInfo.slot[i];
if (msmStreamIsPlay(slot)) {
msmSysIrqDisable();
msmStreamStopSub(i, speed);
if (slot->slotL != -1) {
msmStreamStopSub(slot->slotL, speed);
}
if (slot->slotR != -1) {
msmStreamStopSub(slot->slotR, speed);
}
msmSysIrqEnable();
}
}
}
msmSysIrqEnable();
}
static inline void msmStreamSetFade(int streamNo, s32 speed) {
MSM_STREAM_SLOT* slot = &StreamInfo.slot[streamNo];
if (slot->pauseF != 0) {
slot->pauseF = 0;
speed = 0;
}
slot->fadeMaxTime = speed / 15;
if (slot->fadeMaxTime != 0) {
slot->fadeTime = slot->fadeMaxTime;
slot->volFade = 127;
} else {
msmStreamSlotOff(streamNo);
}
}
s32 msmStreamStop(int streamNo, s32 speed) {
MSM_STREAM_SLOT* slot;
s32 unused;
if (streamNo < 0 || streamNo >= StreamInfo.header.chanMax) {
return MSM_ERR_RANGE_STREAM;
}
slot = &StreamInfo.slot[streamNo];
if (msmStreamIsPlay(slot)) {
msmSysIrqDisable();
msmStreamSetFade(streamNo, speed);
if (slot->slotL != -1) {
msmStreamSetFade(slot->slotL, speed);
}
if (slot->slotR != -1) {
msmStreamSetFade(slot->slotR, speed);
}
msmSysIrqEnable();
}
return 0;
}
int msmStreamPlay(int streamId, MSM_STREAMPARAM* streamParam) {
if (streamId < 0 || streamId >= StreamInfo.header.streamMax) {
return MSM_ERR_INVALIDID;
}
if (StreamInfo.streamPackList[streamId] == 0) {
return MSM_ERR_REMOVEDID;
}
if (StreamInfo.streamPackFlag[StreamInfo.streamPackList[streamId] - StreamInfo.header.streamPackOfs] & MSM_STREAM_FLAG_STEREO) {
return msmStreamPackStartStereo(streamId, streamParam, 0);
} else {
return msmStreamPackStartMono(streamId, streamParam, 0);
}
}
void msmStreamPeriodicProc(void) {
MSM_STREAM_SLOT* slot;
s32 i;
StreamInfo.time = 0;
for (i = 0; i < StreamInfo.header.chanMax; i++) {
slot = &StreamInfo.slot[i];
msmStreamFade(i);
msmStreamPauseOff(i);
msmStreamPauseFade(i);
if (slot->status != 0) {
StreamInfo.time++;
}
}
}
void msmStreamSetOutputMode(s32 outputMode) {
s32 i;
StreamInfo.outputMode = outputMode;
for (i = 0; i < StreamInfo.header.chanMax; i++) {
if (StreamInfo.slot[i].status != 0) {
msmStreamUpdateBaseParam(&StreamInfo.slot[i]);
}
}
}
void msmStreamAmemFree(void) {
u32 i;
for (i = 0; i < StreamInfo.header.chanMax; i++) {
sndStreamFree(StreamInfo.slot[i].stid);
}
}
s32 msmStreamAmemAlloc(void) {
u32 i;
MSM_STREAM_SLOT* slot;
for (i = 0; i < StreamInfo.header.chanMax; i++) {
slot = &StreamInfo.slot[i];
slot->status = 0;
slot->slotR = -1;
slot->slotL = -1;
slot->streamBuf = msmMemAlloc(StreamInfo.bufSize);
if (slot->streamBuf == NULL) {
return MSM_ERR_OUTOFMEM;
}
slot->streamBufSize = StreamInfo.bufSize;
slot->streamFrq = StreamInfo.frq;
slot->stid = sndStreamAllocEx(0xFF, slot->streamBuf, slot->streamFrq, StreamInfo.header.sampleFrq, 0, 64, 0, 0, 0, 0, 0x30001, msmStreamUpdateFunc, i, NULL);
if (slot->stid == -1) {
return MSM_ERR_STREAMALLOC_FAIL;
}
}
return StreamInfo.bufSize * StreamInfo.header.chanMax;
}
s32 msmStreamInit(char *pdtPath) {
DVDFileInfo file;
s32 size;
StreamInfo.header.streamMax = 0;
StreamInfo.header.chanMax = 0;
StreamInfo.masterVol = 127;
StreamInfo.time = 0;
if (pdtPath == NULL) {
return 0;
}
StreamInfo.pdtEntryNum = DVDConvertPathToEntrynum(pdtPath);
if (StreamInfo.pdtEntryNum == -1) {
return MSM_ERR_OPENFAIL;
}
if (!msmFioOpen(StreamInfo.pdtEntryNum, &file)) {
return MSM_ERR_OPENFAIL;
}
if (msmFioRead(&file, &StreamInfo.header, 0x20, 0) < 0) {
msmFioClose(&file);
return MSM_ERR_READFAIL;
}
if (StreamInfo.header.version != MSM_PDT_FILE_VERSION) {
msmFioClose(&file);
return MSM_ERR_INVALIDFILE;
}
if (StreamInfo.header.streamMax != 0) {
size = (StreamInfo.header.adpcmParamOfs - StreamInfo.header.streamPackListOfs + 0x1F) & ~0x1F;
StreamInfo.streamPackList = msmMemAlloc(size);
if (StreamInfo.streamPackList == NULL) {
msmFioClose(&file);
return MSM_ERR_OUTOFMEM;
}
if (msmFioRead(&file, StreamInfo.streamPackList, size, StreamInfo.header.streamPackListOfs) < 0) {
msmFioClose(&file);
return MSM_ERR_READFAIL;
}
size = (StreamInfo.header.sampleOfs - StreamInfo.header.streamPackOfs + 0x1F) & ~0x1F;
StreamInfo.streamPackFlag = msmMemAlloc(size);
if (StreamInfo.streamPackFlag == NULL) {
msmFioClose(&file);
return MSM_ERR_OUTOFMEM;
}
if (msmFioRead(&file, StreamInfo.streamPackFlag, size, StreamInfo.header.streamPackOfs) < 0) {
msmFioClose(&file);
return MSM_ERR_READFAIL;
}
size = StreamInfo.header.streamPackOfs - StreamInfo.header.adpcmParamOfs;
StreamInfo.adpcmParam = msmMemAlloc(size);
if (StreamInfo.adpcmParam == NULL) {
msmFioClose(&file);
return MSM_ERR_OUTOFMEM;
}
if (msmFioRead(&file, StreamInfo.adpcmParam, size, StreamInfo.header.adpcmParamOfs) < 0) {
msmFioClose(&file);
return MSM_ERR_READFAIL;
}
}
msmFioClose(&file);
StreamInfo.sampleFrq = (StreamInfo.header.sampleFrq + (SND_STREAM_ADPCM_BLKSIZE-1)) / SND_STREAM_ADPCM_BLKSIZE ;
StreamInfo.bufSize = (8 * StreamInfo.sampleFrq * StreamInfo.header.maxBufs + 0x3F) & ~0x3F;
StreamInfo.frq = (StreamInfo.bufSize / SND_STREAM_ADPCM_BLKBYTES ) * SND_STREAM_ADPCM_BLKSIZE;
StreamInfo.slot = msmMemAlloc(StreamInfo.header.chanMax * sizeof(*StreamInfo.slot));
memset(StreamInfo.slot, 0, StreamInfo.header.chanMax * sizeof(*StreamInfo.slot));
return 0;
}
static void msmStreamPauseOff(s32 streamNo) {
MSM_STREAM_SLOT* slot;
u32 ofs;
u32 readSize;
slot = &StreamInfo.slot[streamNo];
if (slot->pauseTime == 0) {
return;
}
if (slot->pauseF == 0) {
slot->pauseTime = 0;
return;
}
if (slot->pauseTimeMax != 0) {
slot->pauseTimeMax = -(slot->pauseTime + 1);
if (slot->pauseTimeMax == 0) {
slot->pauseVol = 127;
msmStreamUpdateBaseParam(slot);
}
slot->pauseTime = 0;
slot->pauseF = 0;
} else if (slot->status == 0 && DVDFastOpen(StreamInfo.pdtEntryNum, &slot->file) == TRUE) {
if (--slot->pauseTime != 0) {
slot->pauseTimeMax = -slot->pauseTime;
slot->fadeVol = 0;
slot->pauseVol = 0;
} else {
slot->pauseVol = 127;
}
slot->pauseTime = 0;
slot->firstF = TRUE;
slot->streamOffF = 0;
slot->shutdownF = 0;
slot->pauseF = 0;
slot->updateAramF = 0;
slot->bufNo = 1;
slot->unk64 = slot->unk68 = (slot->pauseLen / SND_STREAM_ADPCM_BLKBYTES) * SND_STREAM_ADPCM_BLKSIZE;
slot->unk6C = 0;
slot->streamPos = slot->pauseLen;
readSize = slot->streamBufSize / 2;
if ((ofs = slot->loopLen - slot->streamPos) < slot->streamBufSize / 2) {
readSize = ofs;
slot->streamReadSize = slot->streamBufSize / 2 - ofs;
slot->streamReadBuf = (void*) ((u32) slot->streamBuf + ofs);
memset(slot->streamReadBuf, 0, slot->streamReadSize);
}
slot->status = 2;
slot->streamPos += readSize;
slot->readBusyF = TRUE;
DVDReadAsync(&slot->file, slot->streamBuf, readSize, slot->streamBaseOfs + (slot->streamPos - readSize), msmStreamDvdCallback);
}
}
static inline void msmStreamOff(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
switch (slot->status) {
case 2:
slot->shutdownF = TRUE;
slot->status = 5;
break;
case 3:
msmStreamClose(streamNo);
break;
case 4:
if (slot->streamOffF == FALSE) {
sndStreamMixParameterEx(slot->stid, 0, 64, 0, 0, 0);
slot->streamOffF = TRUE;
slot->status = 5;
}
break;
}
}
static void msmStreamPauseOn(s32 streamNo, s32 speed) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
slot->pauseTime = 0;
if (slot->pauseF != 0) {
return;
}
slot->pauseF = TRUE;
slot->pauseTimeMax = speed / 15;
if (slot->pauseTimeMax != 0) {
slot->fadeVol = slot->pauseTimeMax;
slot->pauseVol = 127;
return;
}
slot->pauseLen = ((slot->unk64 / 7) * 4) & ~7;
if (slot->stereoF != 0) {
if (slot->pauseLen >= slot->loopLen - slot->streamBufSize / 4) {
slot->pauseLen = 0;
}
} else if (slot->pauseLen >= slot->loopLen) {
slot->pauseF = 0;
}
msmStreamOff(streamNo);
}
static void msmStreamPauseFade(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
if (slot->status != 4) {
return;
}
if (slot->pauseTimeMax > 0) {
if (--slot->fadeVol == 0) {
slot->pauseTimeMax = 0;
slot->pauseF = 0;
msmStreamPauseOn(streamNo, 0);
} else {
slot->pauseVol = slot->fadeVol * 127 / slot->pauseTimeMax;
msmStreamUpdateBaseParam(slot);
}
} else if (slot->pauseTimeMax < 0) {
if (++slot->fadeVol >= -slot->pauseTimeMax) {
slot->pauseTimeMax = 0;
slot->pauseVol = 127;
msmStreamUpdateBaseParam(slot);
} else {
slot->pauseVol = slot->fadeVol * 127 / -slot->pauseTimeMax;
msmStreamUpdateBaseParam(slot);
}
}
}
static void msmStreamFade(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
if (slot->status != 4) {
return;
}
if (slot->fadeMaxTime > 0) {
if (--slot->fadeTime == 0) {
slot->fadeMaxTime = 0;
msmStreamSetFade(streamNo, 0);
} else {
slot->volFade = slot->fadeTime * 127 / slot->fadeMaxTime;
msmStreamUpdateBaseParam(slot);
}
} else if (slot->fadeMaxTime < 0) {
if (++slot->fadeTime >= -slot->fadeMaxTime) {
slot->fadeMaxTime = 0;
slot->volFade = 127;
msmStreamUpdateBaseParam(slot);
} else {
slot->volFade = slot->fadeTime * 127 / -slot->fadeMaxTime;
msmStreamUpdateBaseParam(slot);
}
}
}
static void msmStreamStopSub(s32 streamNo, s32 speed) {
MSM_STREAM_SLOT* slot;
s32 time;
time = speed;
slot = &StreamInfo.slot[streamNo];
if (slot->pauseF != 0) {
slot->pauseF = 0;
time = 0;
}
slot->fadeMaxTime = time / 15;
if (slot->fadeMaxTime != 0) {
slot->fadeTime = slot->fadeMaxTime;
slot->volFade = 127;
return;
}
msmStreamOff(streamNo);
}
static void msmStreamSetParamSub(MSM_STREAM_SLOT* slot) {
int pan;
s32 vol;
if (StreamInfo.outputMode != 0) {
pan = slot->panBase + slot->pan - 64;
if (pan < 0) {
pan = 0;
}
if (pan > 127) {
pan = 127;
}
} else {
pan = 64;
}
vol = slot->volBase * slot->vol * slot->volFade * slot->pauseVol / (127*127*127);
sndStreamMixParameterEx(slot->stid, vol * StreamInfo.masterVol / 127, pan, slot->span, slot->auxA, slot->auxB);
}
static s32 msmStreamPackStartStereo(s32 streamId, MSM_STREAMPARAM *param, s32 sampleOfs) {
s32 flag;
s32 chanL;
s32 chanR;
u32 sizeL;
u32 sizeR;
STREAM_PARAM streamParam;
MSM_STREAM_SLOT* slotL;
MSM_STREAM_SLOT* slotR;
MSM_STREAM_PACK* pack;
flag = (param != NULL) ? param->flag : 0;
if (flag & MSM_STREAMPARAM_CHAN) {
chanL = param->chan;
chanR = param->chan + 1;
if (chanL < 0 || chanL >= StreamInfo.header.chanMax) {
return MSM_ERR_CHANLIMIT;
}
if (chanR < 0 || chanR >= StreamInfo.header.chanMax) {
return MSM_ERR_CHANLIMIT;
}
if (msmStreamIsPlay(&StreamInfo.slot[chanL])) {
return MSM_ERR_CHANLIMIT;
}
if (msmStreamIsPlay(&StreamInfo.slot[chanR])) {
return MSM_ERR_CHANLIMIT;
}
} else {
for (chanL = 0; chanL < StreamInfo.header.chanMax; chanL++) {
if (!msmStreamIsPlay(&StreamInfo.slot[chanL])) {
break;
}
}
for (chanR = chanL + 1; chanR < StreamInfo.header.chanMax; chanR++) {
if (!msmStreamIsPlay(&StreamInfo.slot[chanR])) {
break;
}
}
if (chanL == StreamInfo.header.chanMax || chanR == StreamInfo.header.chanMax) {
return MSM_ERR_CHANLIMIT;
}
}
slotL = &StreamInfo.slot[chanL];
slotR = &StreamInfo.slot[chanR];
pack = (MSM_STREAM_PACK*) ((u32) StreamInfo.streamPackFlag + (StreamInfo.streamPackList[streamId] - StreamInfo.header.streamPackOfs));
streamParam.vol = (flag & MSM_STREAMPARAM_VOL) ? param->vol : 127;
streamParam.span = (flag & MSM_STREAMPARAM_SPAN) ? param->span : (s32) pack->span;
streamParam.auxA = (flag & MSM_STREAMPARAM_AUXA) ? param->auxA : (s32) pack->auxA;
streamParam.auxB = (flag & MSM_STREAMPARAM_AUXB) ? param->auxB : (s32) pack->auxB;
streamParam.sampleOfs = sampleOfs;
msmSysIrqDisable();
streamParam.pan = 0;
sizeL = msmStreamSlotInit(slotL, pack, &streamParam, 0);
streamParam.pan = 127;
sizeR = msmStreamSlotInit(slotR, pack, &streamParam, 1);
slotL->streamId = streamId;
slotR->streamId = -1;
slotL->slotL = chanR;
slotR->slotR = chanL;
if ((flag & MSM_STREAMPARAM_FADESPEED) && param->fadeSpeed != 0) {
slotL->fadeMaxTime = slotR->fadeMaxTime = -param->fadeSpeed / 15;
slotL->fadeTime = slotR->fadeTime = 0;
slotL->volFade = slotR->volFade = 0;
}
msmSysIrqEnable();
if (sizeL == 0) {
return 0;
}
if (flag & MSM_STREAMPARAM_PAUSE) {
slotL->pauseF = slotR->pauseF = 1;
slotL->status = slotR->status = 0;
return chanL;
}
if (DVDFastOpen(StreamInfo.pdtEntryNum, &slotL->file) != 1) {
return MSM_ERR_OPENFAIL;
}
if (DVDFastOpen(StreamInfo.pdtEntryNum, &slotR->file) != 1) {
DVDClose(&slotL->file);
return MSM_ERR_OPENFAIL;
}
slotL->streamPos += sizeL;
slotR->streamPos += sizeR;
slotL->readBusyF = 1;
DVDReadAsync(&slotL->file, slotL->streamBuf, sizeL, slotL->streamBaseOfs + (slotL->streamPos - sizeL), msmStreamDvdCallback);
slotR->readBusyF = 1;
DVDReadAsync(&slotR->file, slotR->streamBuf, sizeR, slotR->streamBaseOfs + (slotR->streamPos - sizeR), msmStreamDvdCallback);
return chanL;
}
static s32 msmStreamPackStartMono(s32 streamId, MSM_STREAMPARAM *param, s32 sampleOfs) {
s32 flag;
s32 chan;
u32 size;
STREAM_PARAM streamParam;
MSM_STREAM_SLOT* slot;
MSM_STREAM_PACK* pack;
flag = (param != NULL) ? param->flag : 0;
if (flag & MSM_STREAMPARAM_CHAN) {
chan = param->chan;
if (chan < 0 || chan >= StreamInfo.header.chanMax) {
return MSM_ERR_CHANLIMIT;
}
if (msmStreamIsPlay(&StreamInfo.slot[chan])) {
return MSM_ERR_CHANLIMIT;
}
} else {
for (chan = 0; chan < StreamInfo.header.chanMax; chan++) {
if (!msmStreamIsPlay(&StreamInfo.slot[chan])) {
break;
}
}
if (chan == StreamInfo.header.chanMax) {
return MSM_ERR_CHANLIMIT;
}
}
slot = &StreamInfo.slot[chan];
pack = (MSM_STREAM_PACK*) ((u32) StreamInfo.streamPackFlag + (StreamInfo.streamPackList[streamId] - StreamInfo.header.streamPackOfs));
streamParam.vol = (flag & MSM_STREAMPARAM_VOL) ? param->vol : 127;
streamParam.pan = (flag & MSM_STREAMPARAM_PAN) ? param->pan : 64;
streamParam.span = (flag & MSM_STREAMPARAM_SPAN) ? param->span : (s32) pack->span;
streamParam.auxA = (flag & MSM_STREAMPARAM_AUXA) ? param->auxA : (s32) pack->auxA;
streamParam.auxB = (flag & MSM_STREAMPARAM_AUXB) ? param->auxB : (s32) pack->auxB;
streamParam.sampleOfs = sampleOfs;
msmSysIrqDisable();
size = msmStreamSlotInit(slot, pack, &streamParam, 0);
slot->streamId = streamId;
if ((flag & MSM_STREAMPARAM_FADESPEED) && param->fadeSpeed != 0) {
slot->fadeMaxTime = -param->fadeSpeed / 15;
slot->fadeTime = 0;
slot->volFade = 0;
}
msmSysIrqEnable();
if (size == 0) {
return 0;
}
if (flag & MSM_STREAMPARAM_PAUSE) {
slot->pauseF = TRUE;
slot->status = 0;
return chan;
}
if (DVDFastOpen(StreamInfo.pdtEntryNum, &slot->file) != 1) {
return MSM_ERR_OPENFAIL;
}
slot->streamPos += size;
slot->readBusyF = TRUE;
DVDReadAsync(&slot->file, slot->streamBuf, size, slot->streamBaseOfs + (slot->streamPos - size), msmStreamDvdCallback);
return chan;
}
// Note: identical to msmStreamOff.
static void msmStreamSlotOff(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
switch (slot->status) {
case 2:
slot->shutdownF = 1;
slot->status = 5;
break;
case 3:
msmStreamClose(streamNo);
break;
case 4:
if (slot->streamOffF == 0) {
sndStreamMixParameterEx(slot->stid, 0, 64, 0, 0, 0);
slot->streamOffF = TRUE;
slot->status = 5;
}
break;
}
}
static void msmStreamShutdown(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
msmStreamSlotOff(streamNo);
sndStreamDeactivate(slot->stid);
if (slot->readBusyF == 0) {
msmStreamClose(streamNo);
} else {
slot->shutdownF = 1;
}
}
static void msmStreamData(s32 streamNo) {
s32 dataSize;
u32 readSize;
void* dataPtr;
MSM_STREAM_SLOT* slot;
s32 off1;
slot = &StreamInfo.slot[streamNo];
readSize = dataSize = slot->streamBufSize / 2;
dataPtr = (slot->bufNo != 0)
? (void*) ((u32) slot->streamBuf + dataSize)
: slot->streamBuf;
slot->streamReadSize = off1 = 0;
if (slot->streamPos + readSize > slot->loopLen) {
if (slot->loopLen > slot->streamPos) {
readSize = slot->loopLen - slot->streamPos;
slot->streamReadSize = dataSize - readSize;
slot->streamReadBuf = (void*) ((u32) dataPtr + readSize);
} else if (slot->stereoF != 0) {
slot->streamPos = slot->streamPosStart;
} else {
memset(dataPtr, 0, dataSize);
if (slot->bufNo != 0) {
off1 = slot->streamFrq / 2;
}
sndStreamARAMUpdate(slot->stid, off1, slot->streamFrq / 2, 0, 0);
readSize = 0;
}
}
if (readSize != 0) {
if (DVDGetCommandBlockStatus(&slot->file.cb) != 0) {
if (slot->updateAramF != TRUE) {
slot->updateAramF = TRUE;
sndStreamMixParameterEx(slot->stid, 0, 64, 64, 0, 0);
memset(slot->streamBuf, 0, slot->streamBufSize);
sndStreamARAMUpdate(slot->stid, 0, slot->streamFrq, 0, 0);
}
} else {
if (slot->updateAramF == TRUE) {
slot->updateAramF = FALSE;
msmStreamUpdateBaseParam(slot);
}
slot->streamPos += readSize;
slot->readBusyF = 1;
DVDReadAsync(&slot->file, dataPtr, readSize, slot->streamBaseOfs + (slot->streamPos - readSize), msmStreamDvdCallback);
}
} else if (slot->firstF != 0) {
slot->firstF= 0;
} else {
msmStreamShutdown(streamNo);
}
slot->bufNo ^= 1;
}
static BOOL msmStreamActivateStream(s32 streamNo) {
MSM_STREAM_SLOT* slot;
slot = &StreamInfo.slot[streamNo];
msmStreamSetParamSub(slot);
sndStreamFrq(slot->stid, slot->frq);
sndStreamADPCMParameter(slot->stid, slot->adpcmInfo);
sndStreamARAMUpdate(slot->stid, 0, slot->streamFrq / 2, 0, 0);
if (sndStreamActivate(slot->stid)) {
slot->status = 4;
msmStreamData(streamNo);
return TRUE;
} else {
msmStreamClose(streamNo);
return FALSE;
}
}
static void msmStreamDvdCallback(s32 result, DVDFileInfo* fileInfo) {
s32 readSize;
MSM_STREAM_SLOT* slot;
for (readSize = 0; readSize < StreamInfo.header.chanMax; readSize++) {
if (&StreamInfo.slot[readSize].file == fileInfo) {
break;
}
}
if (readSize == StreamInfo.header.chanMax) {
return;
}
slot = &StreamInfo.slot[readSize];
slot->readBusyF = 0;
if (slot->shutdownF != 0) {
slot->shutdownF = 0;
msmStreamClose(readSize);
return;
}
if (DVDGetCommandBlockStatus(&fileInfo->cb) == 0) {
switch (slot->status) {
case 2:
if (slot->slotL != -1) {
if (StreamInfo.slot[slot->slotL].status != 3) {
slot->status = 3;
break;
}
if (!msmStreamActivateStream(slot->slotL)) {
slot->slotL = -1;
}
}
if (slot->slotR != -1) {
if (StreamInfo.slot[slot->slotR].status != 3) {
slot->status = 3;
break;
}
if (!msmStreamActivateStream(slot->slotR)) {
slot->slotR = -1;
}
}
if (!msmStreamActivateStream(readSize)) {
if (slot->slotL != -1) {
StreamInfo.slot[slot->slotL].slotR = -1;
}
if (slot->slotR != -1) {
StreamInfo.slot[slot->slotR].slotL = -1;
}
}
break;
case 4:
if (slot->streamPos >= slot->loopLen) {
if (slot->stereoF != 0) {
slot->streamPos = slot->streamPosStart;
if (slot->streamReadSize != 0) {
slot->readBusyF = 1;
DVDReadAsync(fileInfo, slot->streamReadBuf, slot->streamReadSize, slot->streamBaseOfs + slot->streamPos, msmStreamDvdCallback2);
slot->streamPos += slot->streamReadSize;
break;
}
} else if (slot->streamReadSize != 0) {
memset(slot->streamReadBuf, 0, slot->streamReadSize);
}
}
sndStreamARAMUpdate(slot->stid, (slot->bufNo != 0) ? 0 : slot->streamFrq / 2, slot->streamFrq / 2, 0, 0);
break;
case 5:
slot->shutdownF = 0;
msmStreamClose(readSize);
break;
}
} else {
if (slot->status == 4) {
sndStreamDeactivate(slot->stid);
}
msmStreamClose(readSize);
if (slot->slotL != -1) {
StreamInfo.slot[slot->slotL].slotR = -1;
}
if (slot->slotR != -1) {
StreamInfo.slot[slot->slotR].slotL = -1;
}
}
}
static void msmStreamDvdCallback2(s32 result, DVDFileInfo* fileInfo) {
MSM_STREAM_SLOT* slot;
s32 readSize;
for (readSize = 0; readSize < StreamInfo.header.chanMax; readSize++) {
slot = &StreamInfo.slot[readSize];
if (&slot->file == fileInfo) {
break;
}
}
if (readSize == StreamInfo.header.chanMax) {
return;
}
slot->readBusyF = FALSE;
if (slot->shutdownF != 0) {
slot->shutdownF = FALSE;
msmStreamClose(readSize);
} else if (DVDGetCommandBlockStatus(&fileInfo->cb) == 0) {
sndStreamARAMUpdate(slot->stid, (slot->bufNo != 0) ? 0 : slot->streamFrq / 2, slot->streamFrq / 2, 0, 0);
} else {
if (slot->status == 4) {
sndStreamDeactivate(slot->stid);
}
msmStreamClose(readSize);
if (slot->slotL != -1) {
StreamInfo.slot[slot->slotL].slotR = -1;
}
if (slot->slotR != -1) {
StreamInfo.slot[slot->slotR].slotL = -1;
}
}
}
static u32 msmStreamUpdateFunc(void* buffer1, u32 len1, void* buffer2, u32 len2, u32 user) {
MSM_STREAM_SLOT* slot;
s32 len3;
s32 updateLen;
s32 len;
slot = &StreamInfo.slot[user];
if (slot->streamOffF != 0) {
msmStreamShutdown(user);
return 0;
}
updateLen = slot->streamFrq / 2;
if (len1 < updateLen) {
len = 0;
slot->unk64 = slot->unk68 + (len1 - slot->unk6C);
} else {
msmStreamData(user);
len = updateLen;
len3 = slot->unk68 + (updateLen - slot->unk6C);
slot->unk68 = len3;
slot->unk64 = len3;
slot->unk6C = 0;
}
if (slot->unk64 >= slot->loopEndOfs) {
if (slot->stereoF != 0) {
slot->unk68 = 0;
slot->unk64 -= slot->loopEndOfs;
if (len1 < updateLen) {
slot->unk6C = len1 - slot->unk64;
}
} else {
slot->streamOffF = 1;
slot->pauseF = 0;
}
}
return len;
}
static s32 msmStreamSlotInit(MSM_STREAM_SLOT *slot, MSM_STREAM_PACK* pack, STREAM_PARAM* param, s32 no) {
MSM_STREAM *stream;
s32 temp_r3;
s32 ret;
stream = &pack->stream[no];
slot->volBase = pack->vol;
slot->vol = param->vol;
slot->volFade = slot->pauseVol = 127;
slot->panBase = pack->pan;
slot->pan = param->pan;
slot->span = param->span;
slot->auxA = param->auxA;
slot->auxB = param->auxB;
slot->stereoF = (pack->flag >> 1) & 1;
slot->streamBaseOfs = stream->sampleOfs;
slot->streamPosStart = (pack->loopOfsStart >> 1) & ~7;
slot->frq = pack->frq;
slot->adpcmInfo = &StreamInfo.adpcmParam[stream->adpcmParamIdx];
slot->fadeMaxTime = 0;
slot->pauseTimeMax = 0;
slot->pauseTime = 0;
slot->pauseLen = 0;
slot->firstF = 1;
slot->streamOffF = 0;
slot->shutdownF = 0;
slot->pauseF = 0;
slot->updateAramF = 0;
slot->bufNo = 1;
slot->streamBufSize = (StreamInfo.header.sampleFrq * StreamInfo.header.maxBufs * SND_STREAM_ADPCM_BLKBYTES / SND_STREAM_ADPCM_BLKSIZE + 0x3F) & ~0x3F;
if (slot->streamBufSize > StreamInfo.bufSize) {
slot->streamBufSize = StreamInfo.bufSize;
}
slot->streamFrq = (slot->streamBufSize / SND_STREAM_ADPCM_BLKBYTES) * SND_STREAM_ADPCM_BLKSIZE;
slot->loopLen = (pack->loopOfsEnd >> 1) & ~0x1F;
slot->loopEndOfs = (slot->loopLen / SND_STREAM_ADPCM_BLKBYTES) * SND_STREAM_ADPCM_BLKSIZE;
slot->unk64 = slot->unk68 = 0;
slot->unk6C = 0;
slot->slotL = -1;
slot->slotR = -1;
slot->streamPos = param->sampleOfs;
ret = slot->streamBufSize / 2;
if ((temp_r3 = slot->loopLen - slot->streamPos) < slot->streamBufSize / 2) {
ret = temp_r3;
slot->streamReadSize = slot->streamBufSize / 2 - temp_r3;
slot->streamReadBuf = (void*) ((u32) slot->streamBuf + temp_r3);
memset(slot->streamReadBuf, 0, slot->streamReadSize);
}
slot->status = 2;
return ret;
}