From 58afdfac60135ed74cefa4f1a90d8d443c6a7fda Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Sep 2014 20:24:14 -0700 Subject: [PATCH 1/3] Return an error for MOut on a stereo stream. It seems like it won't downmix, it returns an error. --- Core/HLE/sceAtrac.cpp | 80 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index dbb76ce76..d7da4f523 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -59,6 +59,7 @@ #define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013 #define ATRAC_ERROR_BAD_SAMPLE 0x80630015 #define ATRAC_ERROR_ADD_DATA_IS_TOO_BIG 0x80630018 +#define ATRAC_ERROR_NOT_MONO 0x80630019 #define ATRAC_ERROR_NO_LOOP_INFORMATION 0x80630021 #define ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED 0x80630022 #define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023 @@ -1533,43 +1534,73 @@ int sceAtracIsSecondBufferNeeded(int atracID) { return 0; } -int sceAtracSetMOutHalfwayBuffer(int atracID, u32 MOutHalfBuffer, u32 readSize, u32 MOutHalfBufferSize) { +int sceAtracSetMOutHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u32 bufferSize) { Atrac *atrac = getAtrac(atracID); if (!atrac) { - ERROR_LOG(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): bad atrac ID", atracID, MOutHalfBuffer, readSize, MOutHalfBufferSize); + ERROR_LOG(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): bad atrac ID", atracID, buffer, readSize, bufferSize); return ATRAC_ERROR_BAD_ATRACID; } - INFO_LOG(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x)", atracID, MOutHalfBuffer, readSize, MOutHalfBufferSize); - if (readSize > MOutHalfBufferSize) + INFO_LOG(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x)", atracID, buffer, readSize, bufferSize); + if (readSize > bufferSize) return ATRAC_ERROR_INCORRECT_READ_SIZE; int ret = 0; if (atrac != NULL) { - atrac->first.addr = MOutHalfBuffer; + atrac->first.addr = buffer; atrac->first.size = readSize; ret = atrac->Analyze(); if (ret < 0) { - ERROR_LOG_REPORT(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): bad data", atracID, MOutHalfBuffer, readSize, MOutHalfBufferSize); + ERROR_LOG_REPORT(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): bad data", atracID, buffer, readSize, bufferSize); return ret; } - atrac->atracOutputChannels = 1; - ret = _AtracSetData(atracID, MOutHalfBuffer, MOutHalfBufferSize); + if (atrac->atracChannels != 1) { + ERROR_LOG_REPORT(ME, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): not mono data", atracID, buffer, readSize, bufferSize); + ret = ATRAC_ERROR_NOT_MONO; + // It seems it still sets the data. + atrac->atracOutputChannels = 2; + _AtracSetData(atrac, buffer, bufferSize); + return ret; + } else { + atrac->atracOutputChannels = 1; + ret = _AtracSetData(atracID, buffer, bufferSize); + } } return ret; } + u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) { - INFO_LOG(ME, "sceAtracSetMOutData(%i, %08x, %08x)", atracID, buffer, bufferSize); Atrac *atrac = getAtrac(atracID); + if (!atrac) { + ERROR_LOG(ME, "sceAtracSetMOutData(%i, %08x, %08x): bad atrac ID", atracID, buffer, bufferSize); + return ATRAC_ERROR_BAD_ATRACID; + } + + // This doesn't seem to be part of any available libatrac3plus library. + WARN_LOG_REPORT(ME, "sceAtracSetMOutData(%i, %08x, %08x)", atracID, buffer, bufferSize); + // TODO: What is the proper error code here? int ret = 0; if (atrac != NULL) { atrac->first.addr = buffer; atrac->first.size = bufferSize; - // TODO: Error code for bad data (probably yes)? - atrac->Analyze(); - atrac->atracOutputChannels = 1; - ret = _AtracSetData(atracID, buffer, bufferSize); + ret = atrac->Analyze(); + if (ret < 0) { + ERROR_LOG_REPORT(ME, "sceAtracSetMOutData(%i, %08x, %08x): bad data", atracID, buffer, bufferSize); + return ret; + } + if (atrac->atracChannels != 1) { + ERROR_LOG_REPORT(ME, "sceAtracSetMOutData(%i, %08x, %08x): not mono data", atracID, buffer, bufferSize); + ret = ATRAC_ERROR_NOT_MONO; + // It seems it still sets the data. + atrac->atracOutputChannels = 2; + _AtracSetData(atrac, buffer, bufferSize); + // Not sure of the real delay time. + return ret; + } else { + atrac->atracOutputChannels = 1; + ret = _AtracSetData(atracID, buffer, bufferSize); + } } return ret; } @@ -1583,8 +1614,17 @@ int sceAtracSetMOutDataAndGetID(u32 buffer, u32 bufferSize) { Atrac *atrac = new Atrac(); atrac->first.addr = buffer; atrac->first.size = bufferSize; - // TODO: Error code for bad data (probably yes)? - atrac->Analyze(); + int ret = atrac->Analyze(); + if (ret < 0) { + ERROR_LOG_REPORT(ME, "sceAtracSetMOutDataAndGetID(%08x, %08x): bad data", buffer, bufferSize); + delete atrac; + return ret; + } + if (atrac->atracChannels != 1) { + ERROR_LOG_REPORT(ME, "sceAtracSetMOutDataAndGetID(%08x, %08x): not mono data", buffer, bufferSize); + delete atrac; + return ATRAC_ERROR_NOT_MONO; + } atrac->atracOutputChannels = 1; int atracID = createAtrac(atrac, codecType); if (atracID < 0) { @@ -1592,8 +1632,9 @@ int sceAtracSetMOutDataAndGetID(u32 buffer, u32 bufferSize) { delete atrac; return atracID; } - INFO_LOG(ME, "%d=sceAtracSetMOutDataAndGetID(%08x, %08x)", atracID, buffer, bufferSize); - int ret = _AtracSetData(atracID, buffer, bufferSize, true); + // This doesn't seem to be part of any available libatrac3plus library. + WARN_LOG_REPORT(ME, "%d=sceAtracSetMOutDataAndGetID(%08x, %08x)", atracID, buffer, bufferSize); + ret = _AtracSetData(atracID, buffer, bufferSize, true); if (ret < 0) return ret; return atracID; @@ -1618,6 +1659,11 @@ int sceAtracSetMOutHalfwayBufferAndGetID(u32 halfBuffer, u32 readSize, u32 halfB delete atrac; return ret; } + if (atrac->atracChannels != 1) { + ERROR_LOG_REPORT(ME, "sceAtracSetMOutHalfwayBufferAndGetID(%08x, %08x, %08x): not mono data", halfBuffer, readSize, halfBufferSize); + delete atrac; + return ATRAC_ERROR_NOT_MONO; + } atrac->atracOutputChannels = 1; int atracID = createAtrac(atrac, codecType); if (atracID < 0) { From 3856a535032ac0d3d4eff82e9a1060d7495449d7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Sep 2014 20:24:50 -0700 Subject: [PATCH 2/3] Handle atrac files with larger "fact" chunks. Ends up with the a separate offset for loops, it seems like. This corrects looping information for these files. --- Core/HLE/sceAtrac.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index d7da4f523..cd8b78ea1 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -440,6 +440,7 @@ int Atrac::Analyze() { first.filesize = Memory::Read_U32(first.addr + 4) + 8; u32 offset = 12; + int loopFirstSampleOffset = 0; firstSampleoffset = 0; this->decodeEnd = first.filesize; @@ -471,9 +472,13 @@ int Atrac::Analyze() { break; case FACT_CHUNK_MAGIC: { - if (chunkSize >= 8) { - endSample = Memory::Read_U32(first.addr + offset); - firstSampleoffset = Memory::Read_U32(first.addr + offset + 4); + endSample = Memory::Read_U32(first.addr + offset); + firstSampleoffset = Memory::Read_U32(first.addr + offset + 4); + if (chunkSize >= 12) { + // Seems like this indicates it's got a separate offset for loops. + loopFirstSampleOffset = Memory::Read_U32(first.addr + offset + 8); + } else if (chunkSize >= 8) { + loopFirstSampleOffset = firstSampleoffset; } } break; @@ -489,8 +494,8 @@ int Atrac::Analyze() { for (int i = 0; i < loopinfoNum; i++, loopinfoAddr += 24) { loopinfo[i].cuePointID = Memory::Read_U32(loopinfoAddr); loopinfo[i].type = Memory::Read_U32(loopinfoAddr + 4); - loopinfo[i].startSample = Memory::Read_U32(loopinfoAddr + 8) - firstSampleoffset; - loopinfo[i].endSample = Memory::Read_U32(loopinfoAddr + 12) - firstSampleoffset; + loopinfo[i].startSample = Memory::Read_U32(loopinfoAddr + 8) - loopFirstSampleOffset; + loopinfo[i].endSample = Memory::Read_U32(loopinfoAddr + 12) - loopFirstSampleOffset; loopinfo[i].fraction = Memory::Read_U32(loopinfoAddr + 16); loopinfo[i].playCount = Memory::Read_U32(loopinfoAddr + 20); From 2221951cd9803c1c21a46eaba4dd79313a176fcd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Sep 2014 20:52:44 -0700 Subject: [PATCH 3/3] Correct atrac looping offset by one frame. --- Core/HLE/sceAtrac.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index cd8b78ea1..9bf7151de 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -737,7 +737,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample); int finishFlag = 0; - if (atrac->loopNum != 0 && (atrac->currentSample + (int)atracSamplesPerFrame > atrac->loopEndSample || + if (atrac->loopNum != 0 && (atrac->currentSample > atrac->loopEndSample || (numSamples == 0 && atrac->first.size >= atrac->first.filesize))) { atrac->currentSample = atrac->loopStartSample; if (atrac->loopNum > 0)