From 8b0276670273fd1e31896ff407c50ff2aa659e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 11 Mar 2025 20:46:35 +0100 Subject: [PATCH] Some cleanup and refactor. --- Core/HLE/AtracCtx.h | 3 +- Core/HLE/AtracCtx2.cpp | 78 +++++++++++++++++++++--------------------- Core/HLE/AtracCtx2.h | 4 +-- Core/HLE/sceAtrac.cpp | 12 ++++--- 4 files changed, 51 insertions(+), 46 deletions(-) diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 972dfcae9a..386b25b9bc 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -239,7 +239,6 @@ public: protected: Track track_{}; u16 outputChannels_ = 2; - int loopNum_ = 0; // TODO: Save the internal state of this, now technically possible. AudioDecoder *decoder_ = nullptr; @@ -288,6 +287,7 @@ public: return loopNum_; } int LoopStatus() const override { + // This doesn't match tests. if (track_.loopinfo.size() > 0) return 1; else @@ -355,6 +355,7 @@ private: int currentSample_ = 0; u32 decodePos_ = 0; u32 bufferMaxSize_ = 0; + int loopNum_ = 0; // Used to track streaming. u32 bufferPos_ = 0; diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 82d2e30b8d..ffd7cb6f9c 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -86,7 +86,7 @@ int Atrac2::RemainingFrames() const { // No longer looping in this case, outside the loop. return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY; } - if (loopNum_ == 0) { + if (info.loopNum == 0) { return PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY; } return info.streamDataByte / info.sampleSize; @@ -131,53 +131,27 @@ int Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWri return SCE_ERROR_ATRAC_BAD_SECOND_RESET_SIZE; } - const SceAtracIdInfo &info = context_->info; + SceAtracIdInfo &info = context_->info; if (info.state == ATRAC_STATUS_ALL_DATA_LOADED) { // Always adds zero bytes. } else if (info.state == ATRAC_STATUS_HALFWAY_BUFFER) { - /* - // Okay, it's a valid number of bytes. Let's set them up. - if (bytesWrittenFirstBuf != 0) { - first_.fileoffset += bytesWrittenFirstBuf; - first_.size += bytesWrittenFirstBuf; - first_.offset += bytesWrittenFirstBuf; + // Just reinitialize the context at the start. + _dbg_assert_(info.dataOff + info.streamDataByte == bufferInfo.first.filePos); + int readSize = info.dataOff + info.streamDataByte + bytesWrittenFirstBuf; + InitContext(0, info.buffer, readSize, info.bufferByte); + if (readSize == info.dataEnd) { + // Now, it's possible we'll transition to a full buffer here, if all the bytes were written. Let's do it. + info.state = ATRAC_STATUS_ALL_DATA_LOADED; } - - // Did we transition to a full buffer? - if (first_.size >= track_.fileSize) { - first_.size = track_.fileSize; - bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; - } - */ } else { if (bufferInfo.first.filePos > track_.fileSize) { *delay = true; return SCE_ERROR_ATRAC_API_FAIL; } - /* - - // Move the offset to the specified position. - first_.fileoffset = bufferInfo.first.filePos; - - if (bytesWrittenFirstBuf != 0) { - if (!ignoreDataBuf_) { - Memory::Memcpy(dataBuf_ + first_.fileoffset, first_.addr, bytesWrittenFirstBuf, "AtracResetPlayPosition"); - } - first_.fileoffset += bytesWrittenFirstBuf; - } - first_.size = first_.fileoffset; - first_.offset = bytesWrittenFirstBuf; - - bufferHeaderSize_ = 0; - bufferPos_ = track_.bytesPerFrame; - bufferValidBytes_ = bytesWrittenFirstBuf - bufferPos_; - */ + InitContext((bufferInfo.first.writePosPtr - info.buffer) + info.dataOff, info.buffer, bytesWrittenFirstBuf, info.bufferByte); } - // _dbg_assert_(track_.codecType == PSP_MODE_AT_3 || track_.codecType == PSP_MODE_AT_3_PLUS); - // SeekToSample(sample); - return 0; } @@ -206,6 +180,7 @@ void Atrac2::SeekToSample(int sample) { for (u32 pos = start; pos < off; pos += track_.bytesPerFrame) { decoder_->Decode(Memory::GetPointer(info.buffer + pos), track_.bytesPerFrame, nullptr, 2, nullptr, nullptr); + _dbg_assert_(decodeTemp_[track_.SamplesPerFrame() * track_.channels] == 1337); // Sentinel } } @@ -281,6 +256,15 @@ int Atrac2::SetLoopNum(int loopNum) { return 0; } +int Atrac2::LoopNum() const { + return context_->info.loopNum; +} + +int Atrac2::LoopStatus() const { + // ???? + return context_->info.loopEnd > 0; +} + u32 Atrac2::GetNextSamples() { SceAtracIdInfo &info = context_->info; // TODO: Handle end-of-track short block. @@ -345,6 +329,7 @@ void Atrac2::GetStreamDataInfo(u32 *writePtr, u32 *bytesToRead, u32 *readFileOff *readFileOffset = 0; return; } + // Just ask for the rest of the data. The game can supply as much of it as it wants at a time. *writePtr = info.buffer + fileOffset; *readFileOffset = fileOffset; @@ -457,6 +442,7 @@ u32 Atrac2::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, context_->codec.inBuf = inAddr; // just because. int bytesConsumed = 0; int outSamples = 0; + _dbg_assert_(decodeTemp_[track_.SamplesPerFrame() * track_.channels] == 1337); // Sentinel if (!decoder_->Decode(Memory::GetPointer(inAddr), track_.bytesPerFrame, &bytesConsumed, outputChannels_, decodeTemp_, &outSamples)) { // Decode failed. *SamplesNum = 0; @@ -464,10 +450,15 @@ u32 Atrac2::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, context_->codec.err = 0x20b; // checked on hardware for 0xFF corruption. it's possible that there are more codes. return SCE_ERROR_ATRAC_API_FAIL; // tested. } + if (bytesConsumed != info.sampleSize) { + WARN_LOG(Log::ME, "bytesConsumed mismatch: %d vs %d", bytesConsumed, info.sampleSize); + } + _dbg_assert_(decodeTemp_[track_.SamplesPerFrame() * track_.channels] == 1337); // Sentinel // Write the decoded samples to memory. // TODO: We can detect cases where we can safely just decode directly into output (full samplesToWrite, outbuf != nullptr) if (outbuf) { + _dbg_assert_(samplesToWrite <= track_.SamplesPerFrame()); memcpy(outbuf, decodeTemp_, samplesToWrite * outputChannels_ * sizeof(int16_t)); } @@ -517,7 +508,9 @@ int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 buffer CreateDecoder(); if (!decodeTemp_) { - decodeTemp_ = new int16_t[track_.SamplesPerFrame() * track_.channels]; + _dbg_assert_(track_.channels <= 2); + decodeTemp_ = new int16_t[track_.SamplesPerFrame() * track_.channels + 1]; + decodeTemp_[track_.SamplesPerFrame() * track_.channels] = 1337; // Sentinel } context_->codec.inBuf = bufferAddr; @@ -546,6 +539,8 @@ int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 buffer } } + INFO_LOG(Log::ME, "Atrac streaming mode setup: %s", AtracStatusToString(info.state)); + InitContext(0, bufferAddr, readSize, bufferSize); return 0; } @@ -567,8 +562,8 @@ void Atrac2::InitContext(int offset, u32 bufferAddr, u32 readSize, u32 bufferSiz info.numFrame = 0; info.dataOff = track_.dataByteOffset; info.curOff = track_.dataByteOffset; // Note: This and streamOff get incremented by bytesPerFrame before the return from this function by skipping frames. - info.streamOff = track_.dataByteOffset; - info.streamDataByte = readSize - track_.dataByteOffset; + info.streamOff = track_.dataByteOffset - offset; + info.streamDataByte = readSize - info.streamOff; info.dataEnd = track_.fileSize; info.decodePos = track_.FirstSampleOffsetFull(); discardedSamples_ = track_.FirstSampleOffsetFull(); @@ -582,6 +577,11 @@ void Atrac2::InitContext(int offset, u32 bufferAddr, u32 readSize, u32 bufferSiz if (!decoder_->Decode(Memory::GetPointer(info.buffer + info.streamOff), info.sampleSize, &bytesConsumed, track_.channels, decodeTemp_, &outSamples)) { ERROR_LOG(Log::ME, "Error decoding the 'dummy' buffer at offset %d in the buffer", info.streamOff); } + if (bytesConsumed != info.sampleSize) { + WARN_LOG(Log::ME, "bytesConsumed mismatch: %d vs %d", bytesConsumed, info.sampleSize); + } + _dbg_assert_(decodeTemp_[track_.SamplesPerFrame() * track_.channels] == 1337); // Sentinel + info.curOff += track_.bytesPerFrame; if (AtracStatusIsStreaming(info.state)) { info.streamOff += track_.bytesPerFrame; diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index 400f433071..f137f1d5e3 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -22,9 +22,9 @@ public: int GetNextDecodePosition(int *pos) const override; int RemainingFrames() const override; - int LoopStatus() const override { return 0; } + int LoopStatus() const override; int Bitrate() const override; - int LoopNum() const override { return context_->info.loopNum; } + int LoopNum() const override; int SamplesPerFrame() const override { return context_->info.codec == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES; } int Channels() const override { return context_->info.numChan; } int BytesPerFrame() const override { return context_->info.sampleSize; } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index be4f293f47..25f4291104 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -393,13 +393,16 @@ static u32 sceAtracGetInternalErrorInfo(int atracID, u32 errorAddr) { if (err != 0) { return hleLogError(Log::ME, err); } - u32 errorCode = atrac->GetInternalCodecError(); - if (Memory::IsValidAddress(errorAddr)) + + const u32 errorCode = atrac->GetInternalCodecError(); + if (Memory::IsValidAddress(errorAddr)) { Memory::WriteUnchecked_U32(errorCode, errorAddr); + } + if (errorCode) { - return hleLogError(Log::ME, 0, "code: %08x", errorCode); + return hleLogWarning(Log::ME, 0, "code: %08x", errorCode); } else { - return hleLogInfo(Log::ME, 0); + return hleLogDebug(Log::ME, 0); } } @@ -710,6 +713,7 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { if (err != 0) { return hleLogError(Log::ME, err); } + int ret = atrac->SetLoopNum(loopNum); if (ret == SCE_ERROR_ATRAC_NO_LOOP_INFORMATION && loopNum == -1) { // Not really an issue