Improve sceAtracSetData() error handling.

This commit is contained in:
Unknown W. Brackets 2013-09-08 01:24:17 -07:00
parent d5a664a0fa
commit b7a2a92ebe

View File

@ -36,14 +36,17 @@
#define ATRAC_ERROR_NO_ATRACID 0x80630003
#define ATRAC_ERROR_INVALID_CODECTYPE 0x80630004
#define ATRAC_ERROR_BAD_ATRACID 0x80630005
#define ATRAC_ERROR_UNKNOWN_FORMAT 0x80630006
#define ATRAC_ERROR_WRONG_CODECTYPE 0x80630007
#define ATRAC_ERROR_ALL_DATA_LOADED 0x80630009
#define ATRAC_ERROR_NO_DATA 0x80630010
#define ATRAC_ERROR_SECOND_BUFFER_NEEDED 0x80630012
#define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013
#define ATRAC_ERROR_NO_DATA 0x80630010
#define ATRAC_ERROR_SIZE_TOO_SMALL 0x80630011
#define ATRAC_ERROR_SECOND_BUFFER_NEEDED 0x80630012
#define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013
#define ATRAC_ERROR_ADD_DATA_IS_TOO_BIG 0x80630018
#define ATRAC_ERROR_UNSET_PARAM 0x80630021
#define ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED 0x80630022
#define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023
#define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023
#define ATRAC_ERROR_ALL_DATA_DECODED 0x80630024
#define AT3_MAGIC 0x0270
@ -153,7 +156,7 @@ struct Atrac {
p.Do(atracID);
p.Do(first);
p.Do(atracBufSize);
p.Do(codeType);
p.Do(codecType);
p.Do(currentSample);
p.Do(endSample);
@ -190,9 +193,9 @@ struct Atrac {
p.DoMarker("Atrac");
}
void Analyze();
int Analyze();
u32 getDecodePosBySample(int sample) {
int atracSamplesPerFrame = (codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
return (u32)(firstSampleoffset + sample / atracSamplesPerFrame * atracBytesPerFrame );
}
@ -237,7 +240,7 @@ struct Atrac {
int loopEndSample;
int loopNum;
u32 codeType;
u32 codecType;
InputBuffer first;
InputBuffer second;
@ -365,7 +368,7 @@ int deleteAtrac(int atracID) {
return ATRAC_ERROR_BAD_ATRACID;
}
int getCodecType(int addr) {
int getCodecType(u32 addr) {
int at3magic = Memory::Read_U16(addr+20);
if (at3magic == AT3_MAGIC) {
return PSP_MODE_AT_3;
@ -375,9 +378,10 @@ int getCodecType(int addr) {
return 0;
}
void Atrac::Analyze()
int Atrac::Analyze()
{
// reset some values
codecType = 0;
currentSample = 0;
endSample = -1;
loopNum = 0;
@ -388,13 +392,13 @@ void Atrac::Analyze()
decodePos = 0;
if (first.size < 0x100) {
ERROR_LOG(ME, "Atrac buffer very small: %d", first.size);
return;
ERROR_LOG_REPORT(ME, "Atrac buffer very small: %d", first.size);
return ATRAC_ERROR_SIZE_TOO_SMALL;
}
if (!Memory::IsValidAddress(first.addr)) {
WARN_LOG(ME, "Atrac buffer at invalid address: %08x-%08x", first.addr, first.size);
return;
WARN_LOG_REPORT(ME, "Atrac buffer at invalid address: %08x-%08x", first.addr, first.size);
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
}
// TODO: Validate stuff.
@ -407,7 +411,7 @@ void Atrac::Analyze()
this->decodeEnd = first.filesize;
bool bfoundData = false;
while ((first.filesize - offset) >= 8 && !bfoundData) {
while (first.filesize >= offset + 8 && !bfoundData) {
int chunkMagic = Memory::Read_U32(first.addr + offset);
u32 chunkSize = Memory::Read_U32(first.addr + offset + 4);
offset += 8;
@ -419,11 +423,11 @@ void Atrac::Analyze()
if (chunkSize >= 16) {
int codeMagic = Memory::Read_U16(first.addr + offset);
if (codeMagic == AT3_MAGIC)
codeType = PSP_MODE_AT_3;
codecType = PSP_MODE_AT_3;
else if (codeMagic == AT3_PLUS_MAGIC)
codeType = PSP_MODE_AT_3_PLUS;
codecType = PSP_MODE_AT_3_PLUS;
else
codeType = 0;
codecType = 0;
atracChannels = Memory::Read_U16(first.addr + offset + 2);
// int atracSamplerate = Memory::Read_U32(first.addr + offset + 4); ;Should always be 44100Hz
int avgBytesPerSec = Memory::Read_U32(first.addr + offset + 8);
@ -473,6 +477,11 @@ void Atrac::Analyze()
offset += chunkSize;
}
if (codecType == 0) {
WARN_LOG_REPORT(ME, "Atrac buffer with unexpected or no magic bytes");
return ATRAC_ERROR_UNKNOWN_FORMAT;
}
// set the loopStartSample and loopEndSample by loopinfo
if (loopinfoNum > 0) {
loopStartSample = loopinfo[0].startSample;
@ -482,10 +491,12 @@ void Atrac::Analyze()
}
// if there is no correct endsample, try to guess it
if (endSample < 0) {
int atracSamplesPerFrame = (codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
if (endSample < 0 && atracBytesPerFrame != 0) {
int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
endSample = (first.filesize / atracBytesPerFrame) * atracSamplesPerFrame;
}
return 0;
}
u32 sceAtracGetAtracID(int codecType) {
@ -495,7 +506,7 @@ u32 sceAtracGetAtracID(int codecType) {
}
Atrac *atrac = new Atrac();
atrac->codeType = codecType;
atrac->codecType = codecType;
int atracID = createAtrac(atrac, codecType);
if (atracID < 0) {
ERROR_LOG_REPORT(ME, "sceAtracGetAtracID(%i): no free ID", codecType);
@ -571,9 +582,9 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int
} else {
// TODO: This isn't at all right, but at least it makes the music "last" some time.
u32 numSamples = 0;
u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
u32 atracSamplesPerFrame = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
#ifdef USE_FFMPEG
if (atrac->codeType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
if (atrac->codecType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample;
atrac->SeekToSample(forceseekSample);
atrac->SeekToSample(atrac->currentSample);
@ -752,7 +763,7 @@ u32 sceAtracGetBitrate(int atracID, u32 outBitrateAddr)
return -1;
} else {
atrac->atracBitrate = ( atrac->atracBytesPerFrame * 352800 ) / 1000;
if (atrac->codeType == PSP_MODE_AT_3_PLUS)
if (atrac->codecType == PSP_MODE_AT_3_PLUS)
atrac->atracBitrate = ((atrac->atracBitrate >> 11) + 8) & 0xFFFFFFF0;
else
atrac->atracBitrate = (atrac->atracBitrate + 511) >> 10;
@ -816,7 +827,7 @@ u32 sceAtracGetMaxSample(int atracID, u32 maxSamplesAddr)
//return -1;
} else {
if (Memory::IsValidAddress(maxSamplesAddr)) {
int atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
int atracSamplesPerFrame = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
Memory::Write_U32(atracSamplesPerFrame, maxSamplesAddr);
}
}
@ -851,7 +862,7 @@ u32 sceAtracGetNextSample(int atracID, u32 outNAddr)
Memory::Write_U32(0, outNAddr);
} else {
u32 numSamples = atrac->endSample - atrac->currentSample;
u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
u32 atracSamplesPerFrame = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
if (numSamples > atracSamplesPerFrame)
numSamples = atracSamplesPerFrame;
if (Memory::IsValidAddress(outNAddr))
@ -948,7 +959,7 @@ u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFirstBuf,
sceAtracAddStreamData(atracID, bytesWrittenFirstBuf);
atrac->currentSample = sample;
#ifdef USE_FFMPEG
if (atrac->codeType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
if (atrac->codecType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
atrac->SeekToSample(sample);
} else
#endif // USE_FFMPEG
@ -1034,7 +1045,7 @@ int __AtracUpdateOutputMode(Atrac *atrac, int wanted_channels) {
int __AtracSetContext(Atrac *atrac)
{
if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
if (atrac->codecType == PSP_MODE_AT_3_PLUS) {
atrac->decoder_context = Atrac3plus_Decoder::OpenContext();
return 0;
}
@ -1101,7 +1112,7 @@ int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize)
atrac->CleanStuff();
if (atrac->codeType == PSP_MODE_AT_3) {
if (atrac->codecType == PSP_MODE_AT_3) {
if (atrac->atracChannels == 1) {
WARN_LOG(ME, "This is an atrac3 mono audio");
} else {
@ -1114,7 +1125,7 @@ int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize)
return __AtracSetContext(atrac);
#endif // USE_FFMPEG
} else if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
} else if (atrac->codecType == PSP_MODE_AT_3_PLUS) {
if (atrac->atracChannels == 1) {
WARN_LOG(ME, "This is an atrac3+ mono audio");
} else {
@ -1171,17 +1182,25 @@ u32 sceAtracSetSecondBuffer(int atracID, u32 secondBuffer, u32 secondBufferSize)
u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize)
{
INFO_LOG(ME, "sceAtracSetData(%i, %08x, %08x)", atracID, buffer, bufferSize);
Atrac *atrac = getAtrac(atracID);
int ret = 0;
if (atrac != NULL) {
INFO_LOG(ME, "sceAtracSetData(%i, %08x, %08x)", atracID, buffer, bufferSize);
atrac->first.addr = buffer;
atrac->first.size = bufferSize;
atrac->Analyze();
atrac->atracOutputChannels = 2;
ret = _AtracSetData(atracID, buffer, bufferSize);
int ret = atrac->Analyze();
if (ret == 0 && atrac->codecType != atracIDTypes[atracID]) {
ERROR_LOG(ME, "sceAtracSetData(%i, %08x, %08x): atracID uses different codec type than data", atracID, buffer, bufferSize);
ret = ATRAC_ERROR_WRONG_CODECTYPE;
}
if (ret == 0) {
atrac->atracOutputChannels = 2;
ret = _AtracSetData(atracID, buffer, bufferSize);
}
return ret;
} else {
ERROR_LOG(ME, "sceAtracSetData(%i, %08x, %08x): bad atrac ID", atracID, buffer, bufferSize);
return ATRAC_ERROR_BAD_ATRACID;
}
return ret;
}
int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize)
@ -1191,7 +1210,11 @@ int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize)
Atrac *atrac = new Atrac();
atrac->first.addr = buffer;
atrac->first.size = bufferSize;
atrac->Analyze();
int ret = atrac->Analyze();
if (ret < 0) {
delete atrac;
return ret;
}
atrac->atracOutputChannels = 2;
int atracID = createAtrac(atrac, codecType);
if (atracID < 0) {
@ -1200,7 +1223,7 @@ int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize)
return atracID;
}
INFO_LOG(ME, "%d=sceAtracSetDataAndGetID(%08x, %08x)", atracID, buffer, bufferSize);
int ret = _AtracSetData(atracID, buffer, bufferSize, true);
ret = _AtracSetData(atracID, buffer, bufferSize, true);
if (ret < 0)
return ret;
return atracID;
@ -1436,7 +1459,7 @@ void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) {
context->info.bufferByte = atrac->atracBufSize;
context->info.secondBuffer = atrac->second.addr;
context->info.secondBufferByte = atrac->second.size;
context->info.codec = atrac->codeType;
context->info.codec = atrac->codecType;
context->info.loopNum = atrac->loopNum;
context->info.loopStart = atrac->loopStartSample > 0 ? atrac->loopStartSample : 0;
context->info.loopEnd = atrac->loopEndSample > 0 ? atrac->loopEndSample : 0;
@ -1453,7 +1476,7 @@ void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) {
// state 6, lack some data, has loop info
context->info.state = 6;
}
context->info.samplesPerChan = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
context->info.samplesPerChan = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
context->info.sampleSize = atrac->atracBytesPerFrame;
context->info.numChan = atrac->atracChannels;
context->info.dataOff = atrac->firstSampleoffset;
@ -1593,7 +1616,7 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr)
INFO_LOG(ME, "Channels: %i outputChannels: %i bytesperFrame: %x",
atrac->atracChannels, atrac->atracOutputChannels, atrac->atracBytesPerFrame);
#ifdef USE_FFMPEG
if (atrac->codeType == PSP_MODE_AT_3) {
if (atrac->codecType == PSP_MODE_AT_3) {
if (atrac->atracChannels == 1) {
WARN_LOG(ME, "This is an atrac3 mono audio (low level)");
} else {
@ -1612,7 +1635,7 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr)
}
#endif // USE_FFMPEG
if (atrac->codeType == PSP_MODE_AT_3_PLUS){
if (atrac->codecType == PSP_MODE_AT_3_PLUS){
if (atrac->atracChannels == 1) {
WARN_LOG(ME, "This is an atrac3+ mono audio (low level)");
} else {