From 63c997b9735b2dfa1825fa2bd3883893f01748cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 16 Mar 2025 22:46:44 +0100 Subject: [PATCH] Fix an ordering issue in Atrac context creation --- Common/Serialize/SerializeFuncs.h | 7 +- Core/HLE/AtracCtx.h | 6 +- Core/HLE/AtracCtx2.cpp | 8 +- Core/HLE/AtracCtx2.h | 3 +- Core/HLE/sceAtrac.cpp | 131 +++++++++++++----------------- 5 files changed, 64 insertions(+), 91 deletions(-) diff --git a/Common/Serialize/SerializeFuncs.h b/Common/Serialize/SerializeFuncs.h index 88712d1c9b..ef99b6db89 100644 --- a/Common/Serialize/SerializeFuncs.h +++ b/Common/Serialize/SerializeFuncs.h @@ -70,17 +70,16 @@ void DoClass(PointerWrap &p, T *&x) { x->DoState(p); } -template -void DoSubClass(PointerWrap &p, T *&x) { +template +void DoSubClass(PointerWrap &p, T *&x, Args... args) { if (p.mode == PointerWrap::MODE_READ) { if (x != nullptr) delete x; - x = new S(); + x = new S(args...); } x->DoState(p); } - template void DoArray(PointerWrap &p, T *x, int count) { DoHelper_::DoArray(p, x, count); diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index dc5a12e086..e36e4c85bd 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -188,7 +188,6 @@ public: outputChannels_ = channels; } - virtual void SetIDAndAddr(int atracID, u32 contextAddr) = 0; virtual int GetID() const = 0; PSPPointer context_{}; @@ -247,7 +246,7 @@ protected: class Atrac : public AtracBase { public: - Atrac(int codecType = 0) { + Atrac(int atracID, int codecType = 0) : atracID_(atracID) { if (codecType) { track_.codecType = codecType; } @@ -270,9 +269,6 @@ public: int GetNextDecodePosition(int *pos) const override; int RemainingFrames() const override; - void SetIDAndAddr(int atracID, u32 contextAddr) override { - atracID_ = atracID; - } int GetID() const override { return atracID_; } diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 331fd9d311..8b4be5cb4a 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -35,13 +35,11 @@ // * Half Minute Hero (bufsize 65536) // * Flatout (tricky! needs investigation) -Atrac2::Atrac2(int codecType) { - track_.codecType = codecType; -} -void Atrac2::SetIDAndAddr(int atracID, u32 contextAddr) { - // Note: We don't allocate a context, we use memory directly from the loaded atrac binary (even if it's otherwise unused). +Atrac2::Atrac2(int atracID, u32 contextAddr, int codecType) { context_ = PSPPointer::Create(contextAddr); + track_.codecType = codecType; + context_->info.codec = codecType; } void Atrac2::DoState(PointerWrap &p) { diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index ed0e6f932f..65a743650a 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -7,10 +7,9 @@ class Atrac2 : public AtracBase { public: - Atrac2(int codecType); + Atrac2(int atracID, u32 contextAddr, int codecType); void DoState(PointerWrap &p) override; - void SetIDAndAddr(int atracID, u32 contextAddr) override; int GetID() const override { return 0; } int GetNextDecodePosition(int *pos) const { return 0; } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 419502c49e..d136338664 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -153,7 +153,7 @@ void __AtracDoState(PointerWrap &p) { bool valid = atracContexts[i] != nullptr; Do(p, valid); if (valid) { - DoSubClass(p, atracContexts[i]); + DoSubClass(p, atracContexts[i], i); } else { delete atracContexts[i]; atracContexts[i] = nullptr; @@ -170,17 +170,6 @@ void __AtracDoState(PointerWrap &p) { } } -static AtracBase *allocAtrac(int codecType = 0) { - if (g_Config.bUseExperimentalAtrac) { - // Note: This assert isn't really valid until we savestate the new contexts. - _dbg_assert_(g_atracBSS != 0); - return new Atrac2(codecType); - } else { - Atrac *atrac = new Atrac(codecType); - return atrac; - } -} - static AtracBase *getAtrac(int atracID) { if (atracID < 0 || atracID >= PSP_MAX_ATRAC_IDS) { return nullptr; @@ -192,22 +181,23 @@ static AtracBase *getAtrac(int atracID) { return atrac; } -static int RegisterAtrac(AtracBase *atrac) { +static int AllocAndRegisterAtrac(int codecType) { for (int i = 0; i < g_atracMaxContexts; ++i) { - if (atracContextTypes[i] == atrac->CodecType() && atracContexts[i] == 0) { - atracContexts[i] = atrac; + if (atracContextTypes[i] == codecType && atracContexts[i] == 0) { if (g_Config.bUseExperimentalAtrac) { // Note: This assert isn't really valid until we savestate the new contexts. _dbg_assert_(g_atracBSS != 0); + atracContexts[i] = new Atrac2(i, GetAtracContextAddress(i), codecType); + } else { + atracContexts[i] = new Atrac(i, codecType); } - atrac->SetIDAndAddr(i, GetAtracContextAddress(i)); return i; } } return SCE_ERROR_ATRAC_NO_ATRACID; } -static int deleteAtrac(int atracID) { +static int UnregisterAndDeleteAtrac(int atracID) { if (atracID >= 0 && atracID < PSP_MAX_ATRAC_IDS) { if (atracContexts[atracID] != nullptr) { delete atracContexts[atracID]; @@ -225,10 +215,8 @@ static u32 sceAtracGetAtracID(int codecType) { return hleReportError(Log::ME, SCE_ERROR_ATRAC_INVALID_CODECTYPE, "invalid codecType"); } - AtracBase *atrac = allocAtrac(codecType); - int atracID = RegisterAtrac(atrac); + int atracID = AllocAndRegisterAtrac(codecType); if (atracID < 0) { - delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } @@ -543,7 +531,7 @@ static u32 sceAtracGetStreamDataInfo(int atracID, u32 writePtrAddr, u32 writable } static u32 sceAtracReleaseAtracID(int atracID) { - int result = deleteAtrac(atracID); + int result = UnregisterAndDeleteAtrac(atracID); if (result < 0) { if (atracID >= 0) { return hleLogError(Log::ME, result, "did not exist"); @@ -655,17 +643,15 @@ static int sceAtracSetDataAndGetID(u32 buffer, int bufferSize) { return hleLogError(Log::ME, ret); } - AtracBase *atrac = allocAtrac(); - ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 2); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); + int atracID = AllocAndRegisterAtrac(track.codecType); + if (atracID < 0) { + return hleLogError(Log::ME, atracID, "no free ID"); } - int atracID = RegisterAtrac(atrac); - if (atracID < 0) { - delete atrac; - return hleLogError(Log::ME, atracID, "no free ID"); + ret = atracContexts[atracID]->SetData(track, buffer, bufferSize, bufferSize, 2); + if (ret < 0) { + UnregisterAndDeleteAtrac(atracID); + return hleLogError(Log::ME, ret); } return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); @@ -682,17 +668,15 @@ static int sceAtracSetHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buffer return hleLogError(Log::ME, ret); } - AtracBase *atrac = allocAtrac(); - ret = atrac->SetData(track, buffer, readSize, bufferSize, 2); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); + int atracID = AllocAndRegisterAtrac(track.codecType); + if (atracID < 0) { + return hleLogError(Log::ME, atracID, "no free ID"); } - int atracID = RegisterAtrac(atrac); - if (atracID < 0) { - delete atrac; - return hleLogError(Log::ME, atracID, "no free ID"); + ret = atracContexts[atracID]->SetData(track, buffer, readSize, bufferSize, 2); + if (ret < 0) { + UnregisterAndDeleteAtrac(atracID); + return hleLogError(Log::ME, ret); } return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); @@ -803,6 +787,10 @@ static int sceAtracSetMOutHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u } ret = atrac->SetData(track, buffer, readSize, bufferSize, 1); + if (ret < 0 && ret != SCE_ERROR_ATRAC_NOT_MONO) { + // Must not delay. + return hleLogError(Log::ME, ret); + } return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); } @@ -823,10 +811,11 @@ static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) { } ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 1); - if (ret < 0) { + if (ret < 0 && ret != SCE_ERROR_ATRAC_NOT_MONO) { // Must not delay. return hleLogError(Log::ME, ret); } + // It's OK if this fails, at least with NO_MONO... return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); } @@ -842,17 +831,15 @@ static int sceAtracSetMOutDataAndGetID(u32 buffer, u32 bufferSize) { return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); } - AtracBase *atrac = allocAtrac(); - ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 1); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); + int atracID = AllocAndRegisterAtrac(track.codecType); + if (atracID < 0) { + return hleLogError(Log::ME, atracID, "no free ID"); } - int atracID = RegisterAtrac(atrac); - if (atracID < 0) { - delete atrac; - return hleLogError(Log::ME, atracID, "no free ID"); + ret = atracContexts[atracID]->SetData(track, buffer, bufferSize, bufferSize, 1); + if (ret < 0 && ret != SCE_ERROR_ATRAC_NOT_MONO) { + UnregisterAndDeleteAtrac(atracID); + return hleLogError(Log::ME, ret); } return hleDelayResult(hleLogDebugOrError(Log::ME, atracID), "atrac set data", 100); } @@ -871,19 +858,16 @@ static int sceAtracSetMOutHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 bu return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); } - AtracBase *atrac = allocAtrac(); - ret = atrac->SetData(track, buffer, readSize, bufferSize, 1); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - - int atracID = RegisterAtrac(atrac); + int atracID = AllocAndRegisterAtrac(track.codecType); if (atracID < 0) { - delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } + ret = atracContexts[atracID]->SetData(track, buffer, readSize, bufferSize, 1); + if (ret < 0 && ret != SCE_ERROR_ATRAC_NOT_MONO) { + UnregisterAndDeleteAtrac(atracID); + return hleLogError(Log::ME, ret); + } return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); } @@ -894,17 +878,15 @@ static int sceAtracSetAA3DataAndGetID(u32 buffer, u32 bufferSize, u32 fileSize, return hleLogError(Log::ME, ret); } - AtracBase *atrac = allocAtrac(); - ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 2); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); + int atracID = AllocAndRegisterAtrac(track.codecType); + if (atracID < 0) { + return hleLogError(Log::ME, atracID, "no free ID"); } - int atracID = RegisterAtrac(atrac); - if (atracID < 0) { - delete atrac; - return hleLogError(Log::ME, atracID, "no free ID"); + ret = atracContexts[atracID]->SetData(track, buffer, bufferSize, bufferSize, 2); + if (ret < 0) { + UnregisterAndDeleteAtrac(atracID); + return hleLogError(Log::ME, ret); } return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set aa3 data", 100); @@ -1013,18 +995,17 @@ static int sceAtracSetAA3HalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buf return hleLogError(Log::ME, ret); } - AtracBase *atrac = allocAtrac(); - ret = atrac->SetData(track, buffer, readSize, bufferSize, 2); + int atracID = AllocAndRegisterAtrac(track.codecType); + if (atracID < 0) { + return hleLogError(Log::ME, atracID, "no free ID"); + } + + ret = atracContexts[atracID]->SetData(track, buffer, readSize, bufferSize, 2); if (ret < 0) { - delete atrac; + UnregisterAndDeleteAtrac(atracID); return hleLogError(Log::ME, ret); } - int atracID = RegisterAtrac(atrac); - if (atracID < 0) { - delete atrac; - return hleLogError(Log::ME, atracID, "no free ID"); - } return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); }