1029 lines
32 KiB
C
Executable file
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;
|
|
}
|