From 4fbdb58bebd306f46686aaa08fba5d9921d6f4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 16 Mar 2025 18:04:39 +0100 Subject: [PATCH 1/3] Merge the "Analyze" function into SetData --- Core/HLE/AtracCtx.cpp | 76 +++++++++++++++++------------------------- Core/HLE/AtracCtx.h | 29 ++++------------ Core/HLE/AtracCtx2.cpp | 26 ++------------- Core/HLE/AtracCtx2.h | 6 ++-- Core/HLE/sceAtrac.cpp | 69 +++++++++++--------------------------- 5 files changed, 60 insertions(+), 146 deletions(-) diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index e0bc7923e6..42c86281d2 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -167,16 +167,6 @@ void Atrac::ResetData() { kernelMemory.Free(context_.ptr); } -void Atrac::AnalyzeReset() { - // Reset some values. - track_.AnalyzeReset(); - - currentSample_ = 0; - loopNum_ = 0; - decodePos_ = 0; - bufferPos_ = 0; -} - u8 *Atrac::BufferStart() { return ignoreDataBuf_ ? Memory::GetPointerWrite(first_.addr) : dataBuf_; } @@ -241,37 +231,6 @@ void Track::DebugLog() { DEBUG_LOG(Log::ME, "loopStartSample: %d loopEndSample: %d", loopStartSample, loopEndSample); } -int Atrac::Analyze(const Track &track, u32 addr, u32 size, u32 fileSize) { - first_ = {}; - first_.addr = addr; - first_.size = size; - - AnalyzeReset(); - - // 72 is about the size of the minimum required data to even be valid. - if (size < 72) { - return SCE_ERROR_ATRAC_SIZE_TOO_SMALL; - } - - // TODO: Check the range (addr, size) instead. - if (!Memory::IsValidAddress(addr)) { - return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS; - } - - bool aa3 = fileSize != 0; - - // TODO: Validate stuff. - if (!aa3 && Memory::ReadUnchecked_U32(addr) != RIFF_CHUNK_MAGIC) { - ERROR_LOG(Log::ME, "Couldn't find RIFF header"); - return SCE_ERROR_ATRAC_UNKNOWN_FORMAT; - } - - track_ = track; - first_._filesize_dontuse = aa3 ? fileSize : track_.fileSize; - track_.DebugLog(); - return 0; -} - int AnalyzeAtracTrack(u32 addr, u32 size, Track *track) { struct RIFFFmtChunk { u16_le fmtTag; @@ -692,9 +651,31 @@ int Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) { return 0; } -int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) { +int Atrac::SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) { + // 72 is about the size of the minimum required data to even be valid. + if (readSize < 72) { + return SCE_ERROR_ATRAC_SIZE_TOO_SMALL; + } + + // TODO: Check the range (addr, size) instead. + if (!Memory::IsValidAddress(buffer)) { + return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS; + } + + first_ = {}; + first_.addr = buffer; + first_.size = readSize; + + currentSample_ = 0; + loopNum_ = 0; + decodePos_ = 0; + bufferPos_ = 0; outputChannels_ = outputChannels; + track_ = track; + first_._filesize_dontuse = track_.fileSize; + track_.DebugLog(); + if (outputChannels != track_.channels) { WARN_LOG(Log::ME, "Atrac::SetData: outputChannels %d doesn't match track_.channels %d", outputChannels, track_.channels); } @@ -1195,7 +1176,10 @@ int Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrit return 0; } -void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo) { +void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) { + track_ = Track(); + track_.codecType = codecType; + track_.endSample = 0; track_.channels = Memory::Read_U32(paramsAddr); outputChannels_ = Memory::Read_U32(paramsAddr + 4); bufferMaxSize_ = Memory::Read_U32(paramsAddr + 8); @@ -1203,14 +1187,16 @@ void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo) { first_.writableBytes = track_.bytesPerFrame; ResetData(); - if (track_.codecType == PSP_MODE_AT_3) { + if (codecType == PSP_MODE_AT_3) { track_.bitrate = (track_.bytesPerFrame * 352800) / 1000; track_.bitrate = (track_.bitrate + 511) >> 10; track_.jointStereo = false; - } else if (track_.codecType == PSP_MODE_AT_3_PLUS) { + } else if (codecType == PSP_MODE_AT_3_PLUS) { track_.bitrate = (track_.bytesPerFrame * 352800) / 1000; track_.bitrate = ((track_.bitrate >> 11) + 8) & 0xFFFFFFF0; track_.jointStereo = false; + } else { + _dbg_assert_msg_(false, "bad codec type %08x", codecType); } track_.dataByteOffset = 0; diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 652a2ffa7c..b268422a51 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -96,7 +96,7 @@ struct Track { int jointStereo = 0; // Number of audio channels in the track. - u16 channels = 0; + u16 channels = 2; // The size of an encoded frame in bytes. u16 bytesPerFrame = 0; @@ -113,7 +113,7 @@ struct Track { // Last sample number. Inclusive. Though, we made it so that in Analyze, it's exclusive in the file. // Does not take firstSampleOffset into account. - int endSample = 0; + int endSample = -1; // NOTE: The below CAN be written. // Loop configuration. The PSP only supports one loop but we store them all. @@ -163,15 +163,6 @@ struct Track { return (u32)(dataByteOffset + bytesPerFrame + frameOffset * bytesPerFrame); } - void AnalyzeReset() { - endSample = -1; - loopinfo.clear(); - loopStartSample = -1; - loopEndSample = -1; - channels = 2; - // TODO: Could probably reset more. - } - void DebugLog(); }; @@ -223,9 +214,6 @@ public: virtual int BytesPerFrame() const = 0; virtual int SamplesPerFrame() const = 0; - // Set filesize to 0 for autodetect, unless you are using aa3. - virtual int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) = 0; - void UpdateContextFromPSPMem(); virtual void WriteContextToPSPMem() = 0; @@ -234,14 +222,14 @@ public: virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 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; + virtual int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) = 0; virtual int GetSecondBufferInfo(u32 *fileOffset, u32 *desiredSize); virtual u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) = 0; virtual u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) = 0; virtual int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) = 0; virtual u32 GetNextSamples() = 0; - virtual void InitLowLevel(u32 paramsAddr, bool jointStereo) = 0; + virtual void InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) = 0; virtual int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const = 0; @@ -275,8 +263,6 @@ public: void DoState(PointerWrap &p) override; void WriteContextToPSPMem() override; - int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) override; - int GetNextDecodePosition(int *pos) const override; int RemainingFrames() const override; @@ -326,19 +312,16 @@ public: u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) 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; + int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override; u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override; u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override; int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) override; // Returns how many samples the next DecodeData will write. u32 GetNextSamples() override; - void InitLowLevel(u32 paramsAddr, bool jointStereo) override; + void InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) override; int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const override; -protected: - void AnalyzeReset(); - private: void UpdateBufferState(); void ResetData(); diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 24e1223ed5..dd7704fb5e 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -46,10 +46,6 @@ void Atrac2::DoState(PointerWrap &p) { void Atrac2::WriteContextToPSPMem() { } -int Atrac2::Analyze(const Track &track, u32 addr, u32 size, u32 filesize) { - return 0; -} - int Atrac2::RemainingFrames() const { return 0; } @@ -83,7 +79,7 @@ int Atrac2::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSam return 0; } -int Atrac2::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) { +int Atrac2::SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) { if (readSize == bufferSize) { bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; } else { @@ -105,25 +101,7 @@ u32 Atrac2::GetNextSamples() { return 0; } -void Atrac2::InitLowLevel(u32 paramsAddr, bool jointStereo) { - track_.AnalyzeReset(); - track_.channels = Memory::Read_U32(paramsAddr); - outputChannels_ = Memory::Read_U32(paramsAddr + 4); - track_.bytesPerFrame = Memory::Read_U32(paramsAddr + 8); - if (track_.codecType == PSP_MODE_AT_3) { - track_.bitrate = (track_.bytesPerFrame * 352800) / 1000; - track_.bitrate = (track_.bitrate + 511) >> 10; - track_.jointStereo = false; - } else if (track_.codecType == PSP_MODE_AT_3_PLUS) { - track_.bitrate = (track_.bytesPerFrame * 352800) / 1000; - track_.bitrate = ((track_.bitrate >> 11) + 8) & 0xFFFFFFF0; - track_.jointStereo = false; - } - track_.dataByteOffset = 0; - bufferState_ = ATRAC_STATUS_LOW_LEVEL; - currentSample_ = 0; - CreateDecoder(); - WriteContextToPSPMem(); +void Atrac2::InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) { } int Atrac2::DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) { diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index 41b2ec85f5..be1d5d48e0 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -11,8 +11,6 @@ public: void DoState(PointerWrap &p) override; void WriteContextToPSPMem() override; - int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) override; - void SetID(int id) override {} int GetID() const override { return 0; } @@ -31,14 +29,14 @@ public: u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) 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; + int SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) override; u32 SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) override; u32 SecondBufferSize() const override; u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override; int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) override; u32 GetNextSamples() override; - void InitLowLevel(u32 paramsAddr, bool jointStereo) override; + void InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) override; int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const override; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 644a068be0..85581e2c4d 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -581,14 +581,14 @@ static u32 sceAtracSetHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u32 b return hleLogError(Log::ME, SCE_ERROR_ATRAC_WRONG_CODECTYPE, "atracID uses different codec type than data"); } - ret = atrac->Analyze(track, buffer, readSize, 0); + ret = atrac->SetData(track, buffer, readSize, bufferSize, 2); if (ret < 0) { + // Must not delay. return hleLogError(Log::ME, ret); } - ret = atrac->SetData(buffer, readSize, bufferSize, 2); // not sure the real delay time - return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data", 100); + return hleDelayResult(hleLogDebug(Log::ME, ret), "atrac set data", 100); } static u32 sceAtracSetSecondBuffer(int atracID, u32 secondBuffer, u32 secondBufferSize) { @@ -616,12 +616,13 @@ static u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize) { return hleReportError(Log::ME, SCE_ERROR_ATRAC_WRONG_CODECTYPE, "atracID uses different codec type than data"); } - ret = atrac->Analyze(track, buffer, bufferSize, 0); + ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 2); if (ret < 0) { + // Must not delay. return hleLogError(Log::ME, ret); } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data", 100); + + return hleDelayResult(hleLogDebug(Log::ME, ret), "atrac set data", 100); } static int sceAtracSetDataAndGetID(u32 buffer, int bufferSize) { @@ -639,12 +640,7 @@ static int sceAtracSetDataAndGetID(u32 buffer, int bufferSize) { } AtracBase *atrac = allocAtrac(); - ret = atrac->Analyze(track, buffer, bufferSize, 0); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); + ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 2); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); @@ -671,12 +667,7 @@ static int sceAtracSetHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buffer } AtracBase *atrac = allocAtrac(); - ret = atrac->Analyze(track, buffer, readSize, 0); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, readSize, bufferSize, 2); + ret = atrac->SetData(track, buffer, readSize, bufferSize, 2); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); @@ -795,11 +786,7 @@ static int sceAtracSetMOutHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u return hleLogError(Log::ME, ret); } - ret = atrac->Analyze(track, buffer, readSize, 0); - if (ret < 0) { - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, readSize, bufferSize, 1); + ret = atrac->SetData(track, buffer, readSize, bufferSize, 1); return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); } @@ -819,11 +806,11 @@ static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) { return hleLogError(Log::ME, ret); } - ret = atrac->Analyze(track, buffer, bufferSize, 0); + ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 1); if (ret < 0) { + // Must not delay. return hleLogError(Log::ME, ret); } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 1); return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); } @@ -840,12 +827,7 @@ static int sceAtracSetMOutDataAndGetID(u32 buffer, u32 bufferSize) { } AtracBase *atrac = allocAtrac(); - ret = atrac->Analyze(track, buffer, bufferSize, 0); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 1); + ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 1); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); @@ -874,12 +856,7 @@ static int sceAtracSetMOutHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 bu } AtracBase *atrac = allocAtrac(); - ret = atrac->Analyze(track, buffer, readSize, 0); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, readSize, bufferSize, 1); + ret = atrac->SetData(track, buffer, readSize, bufferSize, 1); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); @@ -902,12 +879,7 @@ static int sceAtracSetAA3DataAndGetID(u32 buffer, u32 bufferSize, u32 fileSize, } AtracBase *atrac = allocAtrac(); - ret = atrac->Analyze(track, buffer, bufferSize, fileSize); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); + ret = atrac->SetData(track, buffer, bufferSize, bufferSize, 2); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); @@ -975,6 +947,8 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { return hleReportError(Log::ME, 0, "invalid pointers"); } + int codecType = atracContextTypes[atracID]; + bool jointStereo = false; if (atrac->CodecType() == PSP_MODE_AT_3) { // See if we can match the actual jointStereo value. @@ -991,7 +965,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { } } - atrac->InitLowLevel(paramsAddr, jointStereo); + atrac->InitLowLevel(paramsAddr, jointStereo, codecType); const char *codecName = atrac->CodecType() == PSP_MODE_AT_3 ? "atrac3" : "atrac3+"; const char *channelName = atrac->Channels() == 1 ? "mono" : "stereo"; @@ -1035,12 +1009,7 @@ static int sceAtracSetAA3HalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buf } AtracBase *atrac = allocAtrac(); - ret = atrac->Analyze(track, buffer, readSize, fileSize); - if (ret < 0) { - delete atrac; - return hleLogError(Log::ME, ret); - } - ret = atrac->SetData(buffer, readSize, bufferSize, 2); + ret = atrac->SetData(track, buffer, readSize, bufferSize, 2); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); From b7782d98f3d335e2c27f9257880c9f9b0b0e8d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 16 Mar 2025 19:08:20 +0100 Subject: [PATCH 2/3] Prepare for Atrac context data to work the new way. Not actually active yet. Also restrict old versions to 4 contexts. --- Core/HLE/AtracCtx.cpp | 25 ++++++++++++--- Core/HLE/AtracCtx.h | 26 +++++++++------ Core/HLE/AtracCtx2.cpp | 8 +++-- Core/HLE/AtracCtx2.h | 7 +++-- Core/HLE/sceAtrac.cpp | 61 +++++++++++++++++++----------------- Core/HLE/sceAtrac.h | 2 +- UI/ImDebugger/ImDebugger.cpp | 4 +-- 7 files changed, 84 insertions(+), 49 deletions(-) diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index 42c86281d2..761117fa40 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -39,6 +39,10 @@ const int DATA_CHUNK_MAGIC = 0x61746164; const int SMPL_CHUNK_MAGIC = 0x6C706D73; const int FACT_CHUNK_MAGIC = 0x74636166; +Atrac::~Atrac() { + ResetData(); +} + void Atrac::DoState(PointerWrap &p) { auto s = p.Section("Atrac", 1, 9); if (!s) @@ -171,15 +175,13 @@ u8 *Atrac::BufferStart() { return ignoreDataBuf_ ? Memory::GetPointerWrite(first_.addr) : dataBuf_; } -void AtracBase::UpdateContextFromPSPMem() { +void Atrac::UpdateContextFromPSPMem() { if (!context_.IsValid()) { return; } // Read in any changes from the game to the context. - // TODO: Might be better to just always track in RAM. - // TODO: It's possible that there are more changes we should read. Who knows, - // problem games like FlatOut might poke stuff into the context? + // TODO: Might be better to just always track in RAM. Actually, Atrac2 will do that. bufferState_ = context_->info.state; // This value is actually abused by games to store the SAS voice number. loopNum_ = context_->info.loopNum; @@ -1216,3 +1218,18 @@ int Atrac::DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, i // TODO: Possibly return a decode error on bad data. return 0; } + +void Atrac::NotifyGetContextAddress() { + if (!context_.IsValid()) { + // allocate a new context_ + u32 contextSize = sizeof(SceAtracContext); + // Note that Alloc can increase contextSize to the "grain" size. + context_ = kernelMemory.Alloc(contextSize, false, StringFromFormat("AtracCtx/%d", atracID_).c_str()); + if (context_.IsValid()) + Memory::Memset(context_.ptr, 0, contextSize, "AtracContextClear"); + WARN_LOG(Log::ME, "%08x=_sceAtracGetContextAddress(%i): allocated new context", context_.ptr, atracID_); + } else { + WARN_LOG(Log::ME, "%08x=_sceAtracGetContextAddress(%i)", context_.ptr, atracID_); + } + WriteContextToPSPMem(); +} diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index b268422a51..dc5a12e086 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -175,6 +175,9 @@ public: virtual void DoState(PointerWrap &p) = 0; + // TODO: Find a way to get rid of this from the base class. + virtual void UpdateContextFromPSPMem() = 0; + virtual int Channels() const = 0; int GetOutputChannels() const { @@ -185,7 +188,7 @@ public: outputChannels_ = channels; } - virtual void SetID(int id) = 0; + virtual void SetIDAndAddr(int atracID, u32 contextAddr) = 0; virtual int GetID() const = 0; PSPPointer context_{}; @@ -207,6 +210,8 @@ public: void CreateDecoder(); + virtual void NotifyGetContextAddress() = 0; + virtual int GetNextDecodePosition(int *pos) const = 0; virtual int RemainingFrames() const = 0; virtual u32 SecondBufferSize() const = 0; @@ -214,9 +219,6 @@ public: virtual int BytesPerFrame() const = 0; virtual int SamplesPerFrame() const = 0; - void UpdateContextFromPSPMem(); - virtual void WriteContextToPSPMem() = 0; - virtual void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) = 0; virtual int AddStreamData(u32 bytesToAdd) = 0; virtual u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) = 0; @@ -245,9 +247,12 @@ protected: class Atrac : public AtracBase { public: - ~Atrac() { - ResetData(); + Atrac(int codecType = 0) { + if (codecType) { + track_.codecType = codecType; + } } + ~Atrac(); uint32_t CurBufferAddress(int adjust = 0) const { u32 off = track_.FileOffsetBySample(currentSample_ + adjust); @@ -261,13 +266,12 @@ public: u8 *BufferStart(); void DoState(PointerWrap &p) override; - void WriteContextToPSPMem() override; int GetNextDecodePosition(int *pos) const override; int RemainingFrames() const override; - void SetID(int id) override { - atracID_ = id; + void SetIDAndAddr(int atracID, u32 contextAddr) override { + atracID_ = atracID; } int GetID() const override { return atracID_; @@ -322,6 +326,10 @@ public: int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const override; + void NotifyGetContextAddress() override; + void UpdateContextFromPSPMem() override; + void WriteContextToPSPMem(); + private: void UpdateBufferState(); void ResetData(); diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index dd7704fb5e..331fd9d311 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -39,11 +39,13 @@ Atrac2::Atrac2(int codecType) { track_.codecType = codecType; } -void Atrac2::DoState(PointerWrap &p) { - _assert_msg_(false, "Savestates not yet support with new Atrac implementation.\n\nTurn it off in Developer settings.\n\n"); +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). + context_ = PSPPointer::Create(contextAddr); } -void Atrac2::WriteContextToPSPMem() { +void Atrac2::DoState(PointerWrap &p) { + _assert_msg_(false, "Savestates not yet support with new Atrac implementation.\n\nTurn it off in Developer settings.\n\n"); } int Atrac2::RemainingFrames() const { diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index be1d5d48e0..ed0e6f932f 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -9,9 +9,8 @@ class Atrac2 : public AtracBase { public: Atrac2(int codecType); void DoState(PointerWrap &p) override; - void WriteContextToPSPMem() override; - void SetID(int id) override {} + void SetIDAndAddr(int atracID, u32 contextAddr) override; int GetID() const override { return 0; } int GetNextDecodePosition(int *pos) const { return 0; } @@ -40,6 +39,10 @@ public: int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const override; + // These will not be used by the new implementation. + void UpdateContextFromPSPMem() override {} + void NotifyGetContextAddress() override {} + private: int currentSample_ = 0; }; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 85581e2c4d..419502c49e 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -79,10 +79,12 @@ static const int atracDecodeDelay = 2300; static bool atracInited = true; -static AtracBase *atracContexts[PSP_NUM_ATRAC_IDS]; -static u32 atracContextTypes[PSP_NUM_ATRAC_IDS]; +static AtracBase *atracContexts[PSP_MAX_ATRAC_IDS]; +static u32 atracContextTypes[PSP_MAX_ATRAC_IDS]; static int atracLibVersion = 0; static u32 atracLibCrc = 0; +static int g_atracMaxContexts = 6; +static int g_atracBSS = 0; // For debugger only. const AtracBase *__AtracGetCtx(int i, u32 *type) { @@ -97,6 +99,8 @@ void __AtracInit() { atracLibVersion = 0; atracLibCrc = 0; + g_atracMaxContexts = 6; + g_atracBSS = 0; atracInited = true; // TODO: This should probably only happen in __AtracNotifyLoadModule. @@ -122,12 +126,21 @@ void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) { atracLibVersion = version; atracLibCrc = crc; INFO_LOG(Log::ME, "Atrac module loaded: atracLibVersion 0x%0x, atracLibcrc %x, bss: %x (%x bytes)", atracLibVersion, atracLibCrc, bssAddr, bssSize); - // Later, save bssAddr/bssSize and use them to return context addresses. + g_atracBSS = bssAddr; + g_atracMaxContexts = atracLibVersion <= 0x101 ? 4 : 6; // Need to figure out where the cutoff is. + _dbg_assert_(bssSize >= g_atracMaxContexts * sizeof(SceAtracContext)); } void __AtracNotifyUnloadModule() { atracLibVersion = 0; atracLibCrc = 0; + INFO_LOG(Log::ME, "Atrac module unloaded."); + g_atracBSS = 0; + g_atracMaxContexts = 6; // TODO: We should make this zero here. +} + +static u32 GetAtracContextAddress(int atracID) { + return g_atracBSS + atracID * sizeof(SceAtracContext); } void __AtracDoState(PointerWrap &p) { @@ -136,7 +149,7 @@ void __AtracDoState(PointerWrap &p) { return; Do(p, atracInited); - for (int i = 0; i < PSP_NUM_ATRAC_IDS; ++i) { + for (int i = 0; i < PSP_MAX_ATRAC_IDS; ++i) { bool valid = atracContexts[i] != nullptr; Do(p, valid); if (valid) { @@ -146,7 +159,7 @@ void __AtracDoState(PointerWrap &p) { atracContexts[i] = nullptr; } } - DoArray(p, atracContextTypes, PSP_NUM_ATRAC_IDS); + DoArray(p, atracContextTypes, PSP_MAX_ATRAC_IDS); if (s < 2) { atracLibVersion = 0; atracLibCrc = 0; @@ -159,18 +172,17 @@ 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(); - if (codecType) { - atrac->GetTrackMut().codecType = codecType; - } + Atrac *atrac = new Atrac(codecType); return atrac; } } static AtracBase *getAtrac(int atracID) { - if (atracID < 0 || atracID >= PSP_NUM_ATRAC_IDS) { + if (atracID < 0 || atracID >= PSP_MAX_ATRAC_IDS) { return nullptr; } AtracBase *atrac = atracContexts[atracID]; @@ -181,10 +193,14 @@ static AtracBase *getAtrac(int atracID) { } static int RegisterAtrac(AtracBase *atrac) { - for (int i = 0; i < (int)ARRAY_SIZE(atracContexts); ++i) { + for (int i = 0; i < g_atracMaxContexts; ++i) { if (atracContextTypes[i] == atrac->CodecType() && atracContexts[i] == 0) { atracContexts[i] = atrac; - atrac->SetID(i); + if (g_Config.bUseExperimentalAtrac) { + // Note: This assert isn't really valid until we savestate the new contexts. + _dbg_assert_(g_atracBSS != 0); + } + atrac->SetIDAndAddr(i, GetAtracContextAddress(i)); return i; } } @@ -192,7 +208,7 @@ static int RegisterAtrac(AtracBase *atrac) { } static int deleteAtrac(int atracID) { - if (atracID >= 0 && atracID < PSP_NUM_ATRAC_IDS) { + if (atracID >= 0 && atracID < PSP_MAX_ATRAC_IDS) { if (atracContexts[atracID] != nullptr) { delete atracContexts[atracID]; atracContexts[atracID] = nullptr; @@ -702,7 +718,7 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { } static int sceAtracReinit(int at3Count, int at3plusCount) { - for (int i = 0; i < PSP_NUM_ATRAC_IDS; ++i) { + for (int i = 0; i < PSP_MAX_ATRAC_IDS; ++i) { if (atracContexts[i] != nullptr) { return hleReportError(Log::ME, SCE_KERNEL_ERROR_BUSY, "cannot reinit while IDs in use"); } @@ -710,7 +726,7 @@ static int sceAtracReinit(int at3Count, int at3plusCount) { memset(atracContextTypes, 0, sizeof(atracContextTypes)); int next = 0; - int space = PSP_NUM_ATRAC_IDS; + int space = g_atracMaxContexts; // This seems to deinit things. Mostly, it cause a reschedule on next deinit (but -1, -1 does not.) if (at3Count == 0 && at3plusCount == 0) { @@ -900,19 +916,8 @@ static u32 _sceAtracGetContextAddress(int atracID) { return hleLogError(Log::ME, 0, "bad atrac id"); } - if (!atrac->context_.IsValid()) { - // allocate a new context_ - u32 contextSize = sizeof(SceAtracContext); - // Note that Alloc can increase contextSize to the "grain" size. - atrac->context_ = kernelMemory.Alloc(contextSize, false, StringFromFormat("AtracCtx/%d", atracID).c_str()); - if (atrac->context_.IsValid()) - Memory::Memset(atrac->context_.ptr, 0, contextSize, "AtracContextClear"); - WARN_LOG(Log::ME, "%08x=_sceAtracGetContextAddress(%i): allocated new context", atrac->context_.ptr, atracID); - } else { - WARN_LOG(Log::ME, "%08x=_sceAtracGetContextAddress(%i)", atrac->context_.ptr, atracID); - } - - atrac->WriteContextToPSPMem(); + // Only the old context needs this. The new one will always have a context pointer. + atrac->NotifyGetContextAddress(); return hleLogDebug(Log::ME, atrac->context_.ptr); } diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index ad776f25e3..5fff1a062e 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -89,7 +89,7 @@ struct SceAtracContext { SceAtracIdInfo info; }; -const int PSP_NUM_ATRAC_IDS = 6; +const int PSP_MAX_ATRAC_IDS = 6; class AtracBase; diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 7de3997c17..2e81cc4e82 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -968,7 +968,7 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) { ImGui::TableHeadersRow(); - for (int i = 0; i < PSP_NUM_ATRAC_IDS; i++) { + for (int i = 0; i < PSP_MAX_ATRAC_IDS; i++) { u32 type = 0; const AtracBase *ctx = __AtracGetCtx(i, &type); if (!ctx) { @@ -1009,7 +1009,7 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) { ImGui::EndTable(); } - if (cfg.selectedAtracCtx >= 0 && cfg.selectedAtracCtx < PSP_NUM_ATRAC_IDS) { + if (cfg.selectedAtracCtx >= 0 && cfg.selectedAtracCtx < PSP_MAX_ATRAC_IDS) { u32 type = 0; const AtracBase *ctx = __AtracGetCtx(cfg.selectedAtracCtx, &type); // Show details about the selected atrac context here. From bc283ac60e1cbdcf0c4e5c7f46e34b08b14fbe78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 13 Mar 2025 15:56:18 +0100 Subject: [PATCH 3/3] Add new assert/log facility _dbg_assert_or_log_. Asserts in debug builds, logs in release builds. --- Common/Log.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Common/Log.h b/Common/Log.h index c10a342f2f..2b2bdc02b2 100644 --- a/Common/Log.h +++ b/Common/Log.h @@ -141,16 +141,35 @@ void SetCleanExitOnAssert(); if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \ } +#define _dbg_assert_or_log_(_a_) \ + if (!(_a_)) {\ + if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \ + } + #define _dbg_assert_msg_(_a_, ...) \ if (!(_a_)) { \ if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \ } +#define _dbg_assert_msg_or_log_(_a_, log, ...) \ + if (!(_a_)) { \ + if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \ + } + #else // not debug #ifndef _dbg_assert_ #define _dbg_assert_(_a_) {} +#define _dbg_assert_or_log_(_a_) \ + if (!(_a_)) { \ + ERROR_LOG(Log::System, "Assert! " ## #_a_); \ + } #define _dbg_assert_msg_(_a_, _desc_, ...) {} +#define _dbg_assert_msg_or_log_(_a_, log, ...) \ + if (!(_a_)) { \ + ERROR_LOG(log, __VA_ARGS__); \ + } + #endif // dbg_assert #endif // MAX_LOGLEVEL DEBUG