From 4c25072328d872b63752ec1f2a267363fa48dc86 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 17:06:52 -0800 Subject: [PATCH 1/7] Atrac: Never ask for more bytes than filesize. --- Core/HLE/sceAtrac.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 3de58f617..79fe70e1f 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -717,7 +717,7 @@ int Atrac::Analyze(u32 addr, u32 size) { // TODO: Validate stuff. if (Memory::Read_U32(first_.addr) != RIFF_CHUNK_MAGIC) { - return hleReportError(ME, ATRAC_ERROR_UNKNOWN_FORMAT, "invalid RIF header"); + return hleReportError(ME, ATRAC_ERROR_UNKNOWN_FORMAT, "invalid RIFF header"); } u32 offset = 8; @@ -1028,13 +1028,6 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) { first_.writableBytes = bufferPos_ - bufferStartUsed; } - // If you don't think this should be here, remove it. It's just a temporary safety check. - if (first_.offset + first_.writableBytes > bufferMaxSize_) { - ERROR_LOG_REPORT(ME, "Somehow calculated too many writable bytes: %d + %d > %d", first_.offset, first_.writableBytes, bufferMaxSize_); - first_.offset = 0; - first_.writableBytes = bufferMaxSize_; - } - if (readOffset >= first_.filesize) { if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) { readOffset = 0; @@ -1042,6 +1035,18 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) { readOffset = dataOff_; } } + + if (readOffset + first_.writableBytes > first_.filesize) { + // Never ask for past the end of file, even when the space is free. + first_.writableBytes = first_.filesize - readOffset; + } + + // If you don't think this should be here, remove it. It's just a temporary safety check. + if (first_.offset + first_.writableBytes > bufferMaxSize_) { + ERROR_LOG_REPORT(ME, "Somehow calculated too many writable bytes: %d + %d > %d", first_.offset, first_.writableBytes, bufferMaxSize_); + first_.offset = 0; + first_.writableBytes = bufferMaxSize_; + } } if (outReadOffset) { From 036c965cf51ef61e6fdee57788dde8cac5697ba1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 17:12:46 -0800 Subject: [PATCH 2/7] Atrac: Correct stream write offset after seek. --- 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 79fe70e1f..f9850950c 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1697,7 +1697,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi atrac->bufferHeaderSize_ = 0; atrac->bufferPos_ = atrac->bytesPerFrame_; - atrac->bufferValidBytes_ = bytesWrittenFirstBuf; + atrac->bufferValidBytes_ = bytesWrittenFirstBuf - atrac->bufferPos_; } if (atrac->codecType_ == PSP_MODE_AT_3 || atrac->codecType_ == PSP_MODE_AT_3_PLUS) { From 3130b7a4899509add29c58da0fa7cd91f88aca56 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 17:17:14 -0800 Subject: [PATCH 3/7] Atrac: Correct stream offset after non-loop end. --- Core/HLE/sceAtrac.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index f9850950c..b2dceba0c 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1030,7 +1030,10 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) { if (readOffset >= first_.filesize) { if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) { + // We don't need anything more, so all 0s. readOffset = 0; + first_.offset = 0; + first_.writableBytes = 0; } else { readOffset = dataOff_; } From e2f2c1af900afa49cf02e0a7f2f89cb9acb0aeb1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 17:46:18 -0800 Subject: [PATCH 4/7] Atrac: Mark the leading frame consumed on loop. This is the frame we skip samples from. Might need smarter logic. --- Core/HLE/sceAtrac.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index b2dceba0c..fad2c8808 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -563,13 +563,27 @@ struct Atrac { void CalculateStreamInfo(u32 *readOffset); - u32 StreamBufferEnd() { + u32 StreamBufferEnd() const { // The buffer is always aligned to a frame in size, not counting an optional header. // The header will only initially exist after the data is first set. u32 framesAfterHeader = (bufferMaxSize_ - bufferHeaderSize_) / bytesPerFrame_; return framesAfterHeader * bytesPerFrame_ + bufferHeaderSize_; } + void ConsumeFrame() { + bufferPos_ += bytesPerFrame_; + if (bufferValidBytes_ > bytesPerFrame_) { + bufferValidBytes_ -= bytesPerFrame_; + } else { + bufferValidBytes_ = 0; + } + if (bufferPos_ >= StreamBufferEnd()) { + // Wrap around... theoretically, this should only happen at exactly StreamBufferEnd. + bufferPos_ -= StreamBufferEnd(); + bufferHeaderSize_ = 0; + } + } + private: void AnalyzeReset(); }; @@ -1141,6 +1155,12 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 skipSamples = unalignedSamples; } + if (skipSamples != 0 && atrac->bufferHeaderSize_ == 0) { + // Skip the initial frame used to load state for the looped frame. + // TODO: We will want to actually read this in. + atrac->ConsumeFrame(); + } + if (!atrac->failedDecode_ && (atrac->codecType_ == PSP_MODE_AT_3 || atrac->codecType_ == PSP_MODE_AT_3_PLUS)) { atrac->SeekToSample(atrac->currentSample_); @@ -1217,17 +1237,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 atrac->currentSample_ += numSamples; atrac->decodePos_ = atrac->DecodePosBySample(atrac->currentSample_); - atrac->bufferPos_ += atrac->bytesPerFrame_; - if (atrac->bufferValidBytes_ > atrac->bytesPerFrame_) { - atrac->bufferValidBytes_ -= atrac->bytesPerFrame_; - } else { - atrac->bufferValidBytes_ = 0; - } - if (atrac->bufferPos_ >= atrac->StreamBufferEnd()) { - // Wrap around... theoretically, this should only happen at exactly StreamBufferEnd. - atrac->bufferPos_ -= atrac->StreamBufferEnd(); - atrac->bufferHeaderSize_ = 0; - } + atrac->ConsumeFrame(); int finishFlag = 0; // TODO: Verify. From 3466fb17554fd33f1af9c17040e5f2a971c6a507 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 17:57:45 -0800 Subject: [PATCH 5/7] Atrac: Adjust loop/nonloop remaining full values. These are tricky, but it seems like this is right. --- Core/HLE/sceAtrac.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index fad2c8808..61f28f71f 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -365,16 +365,18 @@ struct Atrac { } u32 currentFileOffset = FileOffsetBySample(currentSample_ - SamplesPerFrame() + FirstOffsetExtra()); - if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { - if (currentFileOffset > first_.fileoffset) { - // We've looped in the data we added. - return PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY; - } - - if (first_.fileoffset >= first_.filesize && loopNum_ == 0) { - // We don't need anything more; we're not planning to loop again. + if (first_.fileoffset >= first_.filesize) { + if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) { return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; } + int loopEndAdjusted = loopEndSample_ - FirstOffsetExtra() - firstSampleOffset_; + if (bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && currentSample_ > loopEndAdjusted) { + // No longer looping in this case, outside the loop. + return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; + } + if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { + return PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY; + } } // Since the first frame is shorter by this offset, add to round up at this offset. @@ -1249,6 +1251,11 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 if (atrac->loopNum_ > 0) atrac->loopNum_--; } + if ((atrac->bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { + // Whatever bytes we have left were added from the loop. + atrac->first_.fileoffset = atrac->dataOff_; + // Skip the initial frame at the start. + } } else if (hitEnd) { finishFlag = 1; From 600df17eb67887963664c763d96876d057cfbe64 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 18:11:25 -0800 Subject: [PATCH 6/7] Atrac: Correct loop read pos with offset. In case it doesn't loop from the start. --- Core/HLE/sceAtrac.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 61f28f71f..869e1515d 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1051,7 +1051,7 @@ void Atrac::CalculateStreamInfo(u32 *outReadOffset) { first_.offset = 0; first_.writableBytes = 0; } else { - readOffset = dataOff_; + readOffset = FileOffsetBySample(loopStartSample_ - FirstOffsetExtra() - firstSampleOffset_ - SamplesPerFrame() * 2); } } @@ -1253,7 +1253,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 } if ((atrac->bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { // Whatever bytes we have left were added from the loop. - atrac->first_.fileoffset = atrac->dataOff_; + atrac->first_.fileoffset = atrac->FileOffsetBySample(atrac->loopStartSample_ - atrac->FirstOffsetExtra() - atrac->firstSampleOffset_ - atrac->SamplesPerFrame() * 2); // Skip the initial frame at the start. } } else if (hitEnd) { From 1b72d3a67a527230c494c0b1c774648403c3cd9e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 18 Jan 2016 22:05:01 -0800 Subject: [PATCH 7/7] Atrac: Correct remaining frame count for streaming. This makes more sense, I think this is the right value. --- Core/HLE/sceAtrac.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 869e1515d..f8c312e5a 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -374,11 +374,16 @@ struct Atrac { // No longer looping in this case, outside the loop. return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; } - if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { + if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK && loopNum_ == 0) { return PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY; } } + if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { + // Since we're streaming, the remaining frames are what's valid in the buffer. + return bufferValidBytes_ / bytesPerFrame_; + } + // Since the first frame is shorter by this offset, add to round up at this offset. const int remainingBytes = first_.fileoffset - currentFileOffset; if (remainingBytes < 0) {