diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index c6cccacabb..30dddc3ed2 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -554,6 +554,16 @@ int Atrac::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSamp return 0; } +int Atrac::GetNextDecodePosition(int *pos) const { + if (currentSample_ >= track_.endSample) { + *pos = 0; + return SCE_ERROR_ATRAC_ALL_DATA_DECODED; + } else { + *pos = currentSample_; + return 0; + } +} + void Atrac::CalculateStreamInfo(u32 *outReadOffset) { u32 readOffset = first_.fileoffset; if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { @@ -860,7 +870,7 @@ u32 Atrac::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) { } u32 Atrac::GetNextSamples() { - if (CurrentSample() >= track_.endSample) { + if (currentSample_ >= track_.endSample) { return 0; } @@ -1114,16 +1124,24 @@ void AtracBase::SetLoopNum(int loopNum) { WriteContextToPSPMem(); } -u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) { +int Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) { + *delay = false; + if (BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && SecondBufferSize() == 0) { + return SCE_ERROR_ATRAC_SECOND_BUFFER_NEEDED; + } else if ((u32)sample + GetTrack().firstSampleOffset > (u32)GetTrack().endSample + GetTrack().firstSampleOffset) { + // NOTE: Above we have to add firstSampleOffset to both sides - we seem to rely on wraparound. + return SCE_ERROR_ATRAC_BAD_SAMPLE; + } + // Reuse the same calculation as before. AtracResetBufferInfo bufferInfo; GetResetBufferInfo(&bufferInfo, sample); if ((u32)bytesWrittenFirstBuf < bufferInfo.first.minWriteBytes || (u32)bytesWrittenFirstBuf > bufferInfo.first.writableBytes) { - return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_FIRST_RESET_SIZE, "first byte count not in valid range"); + return SCE_ERROR_ATRAC_BAD_FIRST_RESET_SIZE; } if ((u32)bytesWrittenSecondBuf < bufferInfo.second.minWriteBytes || (u32)bytesWrittenSecondBuf > bufferInfo.second.writableBytes) { - return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_SECOND_RESET_SIZE, "second byte count not in valid range"); + return SCE_ERROR_ATRAC_BAD_SECOND_RESET_SIZE; } if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { @@ -1146,7 +1164,9 @@ u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrit } } else { if (bufferInfo.first.filePos > track_.fileSize) { - return hleDelayResult(hleLogError(Log::ME, SCE_ERROR_ATRAC_API_FAIL, "invalid file position"), "reset play pos", 200); + *delay = true; + // The decoder failed during skip-frame operation. + return SCE_ERROR_ATRAC_API_FAIL; } // Move the offset to the specified position. @@ -1171,7 +1191,7 @@ u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrit } WriteContextToPSPMem(); - return hleNoLog(0); + return 0; } void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo) { diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 99d3eed7c9..f840de5183 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -220,7 +220,7 @@ public: void CreateDecoder(); - virtual int CurrentSample() const = 0; + virtual int GetNextDecodePosition(int *pos) const = 0; virtual int RemainingFrames() const = 0; virtual u32 SecondBufferSize() const = 0; virtual int Bitrate() const = 0; @@ -236,7 +236,7 @@ public: virtual int AddStreamData(u32 bytesToAdd) = 0; virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 0; virtual void SetLoopNum(int loopNum); - virtual u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) = 0; + virtual int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) = 0; virtual int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) = 0; virtual int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) = 0; @@ -282,9 +282,7 @@ public: int Analyze(u32 addr, u32 size) override; int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override; - int CurrentSample() const override { - return currentSample_; - } + int GetNextDecodePosition(int *pos) const override; int RemainingFrames() const override; u32 SecondBufferSize() const override { return second_.size; @@ -315,7 +313,7 @@ public: // Notify the player that the user has written some new data. int AddStreamData(u32 bytesToAdd) override; u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override; - u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override; + int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) override; int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override; int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override; u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override; diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 76ee437225..acb3f23b4e 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -110,7 +110,8 @@ u32 Atrac2::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) { return 0; } -u32 Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) { +int Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) { + *delay = false; return 0; } diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index fd24006390..b098e51403 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -14,7 +14,7 @@ public: int Analyze(u32 addr, u32 size) override; int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override; - int CurrentSample() const override { return currentSample_; } + int GetNextDecodePosition(int *pos) const { return 0; } int RemainingFrames() const override; int LoopStatus() const override { return 0; } int Bitrate() const override { return 0; } @@ -24,7 +24,7 @@ public: void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override; int AddStreamData(u32 bytesToAdd) override; u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) override; - u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) override; + int ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf, bool *delay) override; int GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) override; int SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override; u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index e54e37524e..bfdc0c02b4 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -406,17 +406,18 @@ static u32 sceAtracGetNextDecodePosition(int atracID, u32 outposAddr) { return hleLogError(Log::ME, err); } - if (Memory::IsValidAddress(outposAddr)) { - if (atrac->CurrentSample() >= atrac->GetTrack().endSample) { - Memory::WriteUnchecked_U32(0, outposAddr); - return hleLogDebug(Log::ME, SCE_ERROR_ATRAC_ALL_DATA_DECODED, "all data decoded - beyond endSample"); - } else { - Memory::WriteUnchecked_U32(atrac->CurrentSample(), outposAddr); - return hleLogDebug(Log::ME, 0); - } - } else { + int pos = 0; + int ret = atrac->GetNextDecodePosition(&pos); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + + if (!Memory::IsValidAddress(outposAddr)) { return hleLogError(Log::ME, 0, "invalid address"); } + + Memory::WriteUnchecked_U32(pos, outposAddr); + return hleLogDebug(Log::ME, 0); } static u32 sceAtracGetNextSample(int atracID, u32 outNAddr) { @@ -547,20 +548,9 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi return hleLogError(Log::ME, err); } - if (atrac->BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && atrac->SecondBufferSize() == 0) { - return hleReportError(Log::ME, SCE_ERROR_ATRAC_SECOND_BUFFER_NEEDED, "no second buffer"); - } else if ((u32)sample + atrac->GetTrack().firstSampleOffset > (u32)atrac->GetTrack().endSample + atrac->GetTrack().firstSampleOffset) { - // NOTE: Above we have to add firstSampleOffset to both sides - we seem to rely on wraparound. - return hleLogWarning(Log::ME, SCE_ERROR_ATRAC_BAD_SAMPLE, "invalid sample position"); - } - - u32 res = atrac->ResetPlayPosition(sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); - if (res != 0) { - // Already logged. - return res; - } - - return hleDelayResult(0, "reset play pos", 3000); + bool delay = false; + int res = atrac->ResetPlayPosition(sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf, &delay); + return hleDelayResult(hleLogDebugOrError(Log::ME, res), "reset play pos", 3000 + delay ? 200 : 0); } static int _AtracSetData(int atracID, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) { diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index bc466c5772..4b6806d046 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -999,7 +999,9 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) { ImGui::TableNextColumn(); ImGui::Text("%d", ctx->GetOutputChannels()); ImGui::TableNextColumn(); - ImGui::Text("%d", ctx->CurrentSample()); + int pos; + ctx->GetNextDecodePosition(&pos); + ImGui::Text("%d", pos); ImGui::TableNextColumn(); ImGui::Text("%d", ctx->RemainingFrames()); } @@ -1014,9 +1016,11 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) { char header[32]; snprintf(header, sizeof(header), "Atrac context %d", cfg.selectedAtracCtx); if (ctx && ImGui::CollapsingHeader(header, ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::ProgressBar((float)ctx->CurrentSample() / (float)ctx->GetTrack().endSample, ImVec2(200.0f, 0.0f)); + int pos; + ctx->GetNextDecodePosition(&pos); + ImGui::ProgressBar((float)pos / (float)ctx->GetTrack().endSample, ImVec2(200.0f, 0.0f)); ImGui::Text("Status: %s", AtracStatusToString(ctx->BufferState())); - ImGui::Text("cur/end sample: %d/%d", ctx->CurrentSample(), ctx->GetTrack().endSample); + ImGui::Text("cur/end sample: %d/%d", pos, ctx->GetTrack().endSample); ImGui::Text("ctx addr: "); ImGui::SameLine(); ImClickableValue("addr", ctx->Decoder()->GetCtxPtr(), control, ImCmd::SHOW_IN_MEMORY_VIEWER); ImGui::Text("loop: %d", ctx->LoopNum()); }