From 09be5935ab58e2d44aa740387b16637f8a314532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Apr 2024 10:26:30 +0200 Subject: [PATCH 1/5] Add accessor for bufferState_, cleanup --- Core/HLE/sceAtrac.cpp | 47 +++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 9aae6db15b..c93332735a 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -158,14 +158,6 @@ struct AtracLoopInfo { int playCount; }; -#ifndef USE_FFMPEG -struct AVPacket { - uint8_t *data; - int size; - int64_t pos; -}; -#endif - struct Atrac { Atrac() { memset(&first_, 0, sizeof(first_)); @@ -414,13 +406,16 @@ struct Atrac { bool ignoreDataBuf_ = false; u32 codecType_ = 0; - AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; InputBuffer first_; InputBuffer second_; PSPPointer context_; + AtracStatus BufferState() const { + return bufferState_; + } + void ForceSeekToSample(int sample) { if (decoder_) { decoder_->FlushBuffers(); @@ -493,6 +488,19 @@ struct Atrac { } } + void UpdateFromPSPRam() { + if (context_.IsValid()) { + // Read in any changes from the game to the context. + // TODO: Might be better to just always track in RAM. + bufferState_ = context_->info.state; + // This value is actually abused by games to store the SAS voice number. + loopNum_ = context_->info.loopNum; + } + } + + // To be moved into private. + AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; + private: void AnalyzeReset(); }; @@ -576,13 +584,8 @@ static Atrac *getAtrac(int atracID) { return nullptr; } Atrac *atrac = atracContexts[atracID]; - - if (atrac && atrac->context_.IsValid()) { - // Read in any changes from the game to the context. - // TODO: Might be better to just always track in RAM. - atrac->bufferState_ = atrac->context_->info.state; - // This value is actually abused by games to store the SAS voice number. - atrac->loopNum_ = atrac->context_->info.loopNum; + if (atrac) { + atrac->UpdateFromPSPRam(); } return atrac; } @@ -642,13 +645,13 @@ int Atrac::Analyze(u32 addr, u32 size) { return hleReportError(ME, ATRAC_ERROR_SIZE_TOO_SMALL, "buffer too small"); } + // TODO: Check the range (addr, size) instead. if (!Memory::IsValidAddress(first_.addr)) { return hleReportWarning(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "invalid buffer address"); } // TODO: Validate stuff. - - if (Memory::Read_U32(first_.addr) != RIFF_CHUNK_MAGIC) { + if (Memory::ReadUnchecked_U32(first_.addr) != RIFF_CHUNK_MAGIC) { return hleReportError(ME, ATRAC_ERROR_UNKNOWN_FORMAT, "invalid RIFF header"); } @@ -928,7 +931,7 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { static u32 AtracValidateData(const Atrac *atrac) { if (!atrac) { return hleLogError(ME, ATRAC_ERROR_BAD_ATRACID, "bad atrac ID"); - } else if (atrac->bufferState_ == ATRAC_STATUS_NO_DATA) { + } else if (atrac->BufferState() == ATRAC_STATUS_NO_DATA) { return hleLogError(ME, ATRAC_ERROR_NO_DATA, "no data"); } else { return 0; @@ -938,11 +941,11 @@ static u32 AtracValidateData(const Atrac *atrac) { static u32 AtracValidateManaged(const Atrac *atrac) { if (!atrac) { return hleLogError(ME, ATRAC_ERROR_BAD_ATRACID, "bad atrac ID"); - } else if (atrac->bufferState_ == ATRAC_STATUS_NO_DATA) { + } else if (atrac->BufferState() == ATRAC_STATUS_NO_DATA) { return hleLogError(ME, ATRAC_ERROR_NO_DATA, "no data"); - } else if (atrac->bufferState_ == ATRAC_STATUS_LOW_LEVEL) { + } else if (atrac->BufferState() == ATRAC_STATUS_LOW_LEVEL) { return hleLogError(ME, ATRAC_ERROR_IS_LOW_LEVEL, "low level stream, can't use"); - } else if (atrac->bufferState_ == ATRAC_STATUS_FOR_SCESAS) { + } else if (atrac->BufferState() == ATRAC_STATUS_FOR_SCESAS) { return hleLogError(ME, ATRAC_ERROR_IS_FOR_SCESAS, "SAS stream, can't use"); } else { return 0; From eef667c5ac6bc6a3966d75923c37c65bf7d6668f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Apr 2024 10:38:31 +0200 Subject: [PATCH 2/5] Separate the external interface used by sceSas --- Core/HLE/sceAtrac.cpp | 147 +++++++++++++++++++++--------------------- Core/HLE/sceAtrac.h | 11 ++-- Core/HW/SasAudio.cpp | 6 +- 3 files changed, 81 insertions(+), 83 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index c93332735a..8ffe3976e8 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -147,7 +147,6 @@ struct InputBuffer { struct Atrac; int __AtracSetContext(Atrac *atrac); -static void _AtracWriteContextToPSPMem(Atrac *atrac); struct AtracLoopInfo { int cuePointID; @@ -488,7 +487,7 @@ struct Atrac { } } - void UpdateFromPSPRam() { + void UpdateFromPSPMem() { if (context_.IsValid()) { // Read in any changes from the game to the context. // TODO: Might be better to just always track in RAM. @@ -498,6 +497,8 @@ struct Atrac { } } + void WriteContextToPSPMem(); + // To be moved into private. AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; @@ -585,7 +586,7 @@ static Atrac *getAtrac(int atracID) { } Atrac *atrac = atracContexts[atracID]; if (atrac) { - atrac->UpdateFromPSPRam(); + atrac->UpdateFromPSPMem(); } return atrac; } @@ -908,10 +909,7 @@ static u32 sceAtracGetAtracID(int codecType) { return hleLogSuccessInfoI(ME, atracID); } -u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { - Atrac *atrac = getAtrac(atracID); - if (!atrac) - return 0; +static u32 _AtracAddStreamData(Atrac *atrac, u32 bufPtr, u32 bytesToAdd) { int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset - atrac->FirstOffsetExtra()); Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset + atrac->FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData"); atrac->first_.size += bytesToAdd; @@ -921,10 +919,8 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; } atrac->first_.fileoffset += addbytes; - if (atrac->context_.IsValid()) { - // refresh context_ - _AtracWriteContextToPSPMem(atrac); - } + // refresh context_ + atrac->WriteContextToPSPMem(); return 0; } @@ -1043,9 +1039,7 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { atrac->first_.size = atrac->first_.filesize; if (atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; - if (atrac->context_.IsValid()) { - _AtracWriteContextToPSPMem(atrac); - } + atrac->WriteContextToPSPMem(); } atrac->first_.offset += bytesToAdd; @@ -1059,15 +1053,7 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { return hleLogSuccessI(ME, 0); } -u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) { - Atrac *atrac = getAtrac(atracID); - - if (atrac == NULL) { - return ATRAC_ERROR_BAD_ATRACID; - } else if (!atrac->dataBuf_) { - return ATRAC_ERROR_NO_DATA; - } - +static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) { int loopNum = atrac->loopNum_; if (atrac->bufferState_ == ATRAC_STATUS_FOR_SCESAS) { // TODO: Might need more testing. @@ -1078,10 +1064,8 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 if (atrac->currentSample_ >= atrac->endSample_ && loopNum == 0) { *SamplesNum = 0; *finish = 1; - if (atrac->context_.IsValid()) { - // refresh context_ - _AtracWriteContextToPSPMem(atrac); - } + // refresh context_ + atrac->WriteContextToPSPMem(); return ATRAC_ERROR_ALL_DATA_DECODED; } @@ -1198,20 +1182,24 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 *finish = finishFlag; *remains = atrac->RemainingFrames(); - if (atrac->context_.IsValid()) { - // refresh context_ - _AtracWriteContextToPSPMem(atrac); - } + // refresh context_ + atrac->WriteContextToPSPMem(); return 0; } +// Note that outAddr being null is completely valid here, used to skip data. static u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishFlagAddr, u32 remainAddr) { - // Note that outAddr being null is completely valid here, used to skip data. + Atrac *atrac = getAtrac(atracID); + if (atrac == NULL) { + return ATRAC_ERROR_BAD_ATRACID; + } else if (!atrac->dataBuf_) { // TODO: Should check bufferState instead? + return ATRAC_ERROR_NO_DATA; + } u32 numSamples = 0; u32 finish = 0; int remains = 0; - int ret = _AtracDecodeData(atracID, Memory::GetPointerWrite(outAddr), outAddr, &numSamples, &finish, &remains); + int ret = _AtracDecodeData(atrac, Memory::GetPointerWrite(outAddr), outAddr, &numSamples, &finish, &remains); if (ret != (int)ATRAC_ERROR_BAD_ATRACID && ret != (int)ATRAC_ERROR_NO_DATA) { if (Memory::IsValidAddress(numSamplesAddr)) Memory::WriteUnchecked_U32(numSamples, numSamplesAddr); @@ -1637,9 +1625,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi atrac->SeekToSample(sample); } - if (atrac->context_.IsValid()) { - _AtracWriteContextToPSPMem(atrac); - } + atrac->WriteContextToPSPMem(); return hleDelayResult(hleLogSuccessInfoI(ME, 0), "reset play pos", 3000); } @@ -1872,9 +1858,7 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { atrac->loopStartSample_ = atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); atrac->loopEndSample_ = atrac->endSample_ + atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); } - if (atrac->context_.IsValid()) { - _AtracWriteContextToPSPMem(atrac); - } + atrac->WriteContextToPSPMem(); return hleLogSuccessI(ME, 0); } @@ -2067,46 +2051,43 @@ static int sceAtracSetAA3DataAndGetID(u32 buffer, u32 bufferSize, u32 fileSize, return _AtracSetData(atracID, buffer, bufferSize, bufferSize, true); } -// Used by SasAudio's AT3 integration. -int _AtracGetIDByContext(u32 contextAddr) { - int atracID = (int)Memory::Read_U32(contextAddr + 0xfc); - return atracID; -} - -void _AtracWriteContextToPSPMem(Atrac *atrac) { +void Atrac::WriteContextToPSPMem() { + if (!context_.IsValid()) { + return; + } // context points into PSP memory. - SceAtracContext *context = atrac->context_; - context->info.buffer = atrac->first_.addr; - context->info.bufferByte = atrac->bufferMaxSize_; - context->info.secondBuffer = atrac->second_.addr; - context->info.secondBufferByte = atrac->second_.size; - context->info.codec = atrac->codecType_; - context->info.loopNum = atrac->loopNum_; - context->info.loopStart = atrac->loopStartSample_ > 0 ? atrac->loopStartSample_ : 0; - context->info.loopEnd = atrac->loopEndSample_ > 0 ? atrac->loopEndSample_ : 0; + SceAtracContext *context = context_; + context->info.buffer = first_.addr; + context->info.bufferByte = bufferMaxSize_; + context->info.secondBuffer = second_.addr; + context->info.secondBufferByte = second_.size; + context->info.codec = codecType_; + context->info.loopNum = loopNum_; + context->info.loopStart = loopStartSample_ > 0 ? loopStartSample_ : 0; + context->info.loopEnd = loopEndSample_ > 0 ? loopEndSample_ : 0; // Note that we read in the state when loading the atrac object, so it's safe // to update it back here all the time. Some games, like Sol Trigger, change it. // TODO: Should we just keep this in PSP ram then, or something? - context->info.state = atrac->bufferState_; - if (atrac->firstSampleOffset_ != 0) { - context->info.samplesPerChan = atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); + context->info.state = bufferState_; + if (firstSampleOffset_ != 0) { + context->info.samplesPerChan = firstSampleOffset_ + FirstOffsetExtra(); } else { - context->info.samplesPerChan = (atrac->codecType_ == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); + context->info.samplesPerChan = (codecType_ == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); } - context->info.sampleSize = atrac->bytesPerFrame_; - context->info.numChan = atrac->channels_; - context->info.dataOff = atrac->dataOff_; - context->info.endSample = atrac->endSample_ + atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); - context->info.dataEnd = atrac->first_.filesize; - context->info.curOff = atrac->first_.fileoffset; - context->info.decodePos = atrac->DecodePosBySample(atrac->currentSample_); - context->info.streamDataByte = atrac->first_.size - atrac->dataOff_; + context->info.sampleSize = bytesPerFrame_; + context->info.numChan = channels_; + context->info.dataOff = dataOff_; + context->info.endSample = endSample_ + firstSampleOffset_ + FirstOffsetExtra(); + context->info.dataEnd = first_.filesize; + context->info.curOff = first_.fileoffset; + context->info.decodePos = DecodePosBySample(currentSample_); + context->info.streamDataByte = first_.size - dataOff_; u8 *buf = (u8 *)context; - *(u32_le *)(buf + 0xfc) = atrac->atracID_; + *(u32_le *)(buf + 0xfc) = atracID_; - NotifyMemInfo(MemBlockFlags::WRITE, atrac->context_.ptr, sizeof(SceAtracContext), "AtracContext"); + NotifyMemInfo(MemBlockFlags::WRITE, context_.ptr, sizeof(SceAtracContext), "AtracContext"); } static u32 _sceAtracGetContextAddress(int atracID) { @@ -2126,8 +2107,7 @@ static u32 _sceAtracGetContextAddress(int atracID) { } else WARN_LOG(ME, "%08x=_sceAtracGetContextAddress(%i)", atrac->context_.ptr, atracID); - if (atrac->context_.IsValid()) - _AtracWriteContextToPSPMem(atrac); + atrac->WriteContextToPSPMem(); return atrac->context_.ptr; } @@ -2207,9 +2187,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { atrac->currentSample_ = 0; int ret = __AtracSetContext(atrac); - if (atrac->context_.IsValid()) { - _AtracWriteContextToPSPMem(atrac); - } + atrac->WriteContextToPSPMem(); if (ret < 0) { // Already logged. @@ -2268,6 +2246,27 @@ static int sceAtracSetAA3HalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buf return _AtracSetData(atracID, buffer, readSize, bufferSize, true); } +// External interface used by sceSas' AT3 integration. + +u32 AtracSasAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { + Atrac *atrac = getAtrac(atracID); + if (!atrac) + return 0; + return _AtracAddStreamData(atrac, bufPtr, bytesToAdd); +} + +u32 AtracSasDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains) { + Atrac *atrac = getAtrac(atracID); + if (!atrac) + return 0; + return _AtracDecodeData(atrac, outbuf, outbufPtr, SamplesNum, finish, remains); +} + +int AtracSasGetIDByContext(u32 contextAddr) { + int atracID = (int)Memory::Read_U32(contextAddr + 0xfc); + return atracID; +} + const HLEFunction sceAtrac3plus[] = { {0X7DB31251, &WrapU_IU, "sceAtracAddStreamData", 'x', "ix" }, {0X6A8C3CD5, &WrapU_IUUUU, "sceAtracDecodeData", 'x', "ixppp"}, diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index 344f8c26f4..f29c59f798 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -25,6 +25,7 @@ void Register_sceAtrac3plus(); void __AtracInit(); void __AtracDoState(PointerWrap &p); void __AtracShutdown(); +void __AtracLoadModule(int version, u32 crc); enum AtracStatus : u8 { ATRAC_STATUS_NO_DATA = 1, @@ -84,9 +85,7 @@ struct SceAtracContext { SceAtracIdInfo info; }; -// provide some decoder interface - -u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd); -u32 _AtracDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains); -int _AtracGetIDByContext(u32 contextAddr); -void __AtracLoadModule(int version, u32 crc); +// External interface used by sceSas. +u32 AtracSasAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd); +u32 AtracSasDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains); +int AtracSasGetIDByContext(u32 contextAddr); diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 39ab2564c8..bfdb41834d 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -192,7 +192,7 @@ void VagDecoder::DoState(PointerWrap &p) { int SasAtrac3::setContext(u32 context) { contextAddr_ = context; - atracID_ = _AtracGetIDByContext(context); + atracID_ = AtracSasGetIDByContext(context); if (!sampleQueue_) sampleQueue_ = new BufferQueue(); sampleQueue_->clear(); @@ -211,7 +211,7 @@ void SasAtrac3::getNextSamples(s16 *outbuf, int wantedSamples) { u32 numSamples = 0; int remains = 0; static s16 buf[0x800]; - _AtracDecodeData(atracID_, (u8*)buf, 0, &numSamples, &finish, &remains); + AtracSasDecodeData(atracID_, (u8*)buf, 0, &numSamples, &finish, &remains); if (numSamples > 0) sampleQueue_->push((u8*)buf, numSamples * sizeof(s16)); else @@ -223,7 +223,7 @@ void SasAtrac3::getNextSamples(s16 *outbuf, int wantedSamples) { int SasAtrac3::addStreamData(u32 bufPtr, u32 addbytes) { if (atracID_ > 0) { - _AtracAddStreamData(atracID_, bufPtr, addbytes); + AtracSasAddStreamData(atracID_, bufPtr, addbytes); } return 0; } From 7d3fc65478d7312c259738a916a2e6733716f48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Apr 2024 10:48:01 +0200 Subject: [PATCH 3/5] Make Decode and GetResetBufferInfo member functions of Atrac. --- Core/HLE/sceAtrac.cpp | 136 ++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 8ffe3976e8..aa159767da 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -157,6 +157,8 @@ struct AtracLoopInfo { int playCount; }; +struct AtracResetBufferInfo; + struct Atrac { Atrac() { memset(&first_, 0, sizeof(first_)); @@ -498,6 +500,8 @@ struct Atrac { } void WriteContextToPSPMem(); + u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains); + void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample); // To be moved into private. AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; @@ -1053,19 +1057,19 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { return hleLogSuccessI(ME, 0); } -static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) { - int loopNum = atrac->loopNum_; - if (atrac->bufferState_ == ATRAC_STATUS_FOR_SCESAS) { +u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) { + int loopNum = loopNum_; + if (bufferState_ == ATRAC_STATUS_FOR_SCESAS) { // TODO: Might need more testing. loopNum = 0; } // We already passed the end - return an error (many games check for this.) - if (atrac->currentSample_ >= atrac->endSample_ && loopNum == 0) { + if (currentSample_ >= endSample_ && loopNum == 0) { *SamplesNum = 0; *finish = 1; // refresh context_ - atrac->WriteContextToPSPMem(); + WriteContextToPSPMem(); return ATRAC_ERROR_ALL_DATA_DECODED; } @@ -1073,32 +1077,33 @@ static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *Sample u32 numSamples = 0; // It seems like the PSP aligns the sample position to 0x800...? - int offsetSamples = atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); + int offsetSamples = firstSampleOffset_ + FirstOffsetExtra(); int skipSamples = 0; - u32 maxSamples = atrac->endSample_ + 1 - atrac->currentSample_; - u32 unalignedSamples = (offsetSamples + atrac->currentSample_) % atrac->SamplesPerFrame(); + u32 maxSamples = endSample_ + 1 - currentSample_; + u32 unalignedSamples = (offsetSamples + currentSample_) % SamplesPerFrame(); if (unalignedSamples != 0) { // We're off alignment, possibly due to a loop. Force it back on. - maxSamples = atrac->SamplesPerFrame() - unalignedSamples; + maxSamples = SamplesPerFrame() - unalignedSamples; skipSamples = unalignedSamples; } - if (skipSamples != 0 && atrac->bufferHeaderSize_ == 0) { + if (skipSamples != 0 && 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(); + ConsumeFrame(); } - if (!atrac->failedDecode_ && (atrac->codecType_ == PSP_MODE_AT_3 || atrac->codecType_ == PSP_MODE_AT_3_PLUS)) { - atrac->SeekToSample(atrac->currentSample_); + // TODO: We don't support any other codec type, check seems unnecessary? + if (!failedDecode_ && (codecType_ == PSP_MODE_AT_3 || codecType_ == PSP_MODE_AT_3_PLUS)) { + SeekToSample(currentSample_); AtracDecodeResult res = ATDECODE_FEEDME; - u32 off = atrac->FileOffsetBySample(atrac->currentSample_ - skipSamples); - if (off < atrac->first_.size) { - uint8_t *indata = atrac->BufferStart() + off; + u32 off = FileOffsetBySample(currentSample_ - skipSamples); + if (off < first_.size) { + uint8_t *indata = BufferStart() + off; int bytesConsumed = 0; int outBytes = 0; - if (!atrac->decoder_->Decode(indata, atrac->bytesPerFrame_, &bytesConsumed, + if (!decoder_->Decode(indata, bytesPerFrame_, &bytesConsumed, outbuf, &outBytes)) { // Decode failed. *SamplesNum = 0; @@ -1108,7 +1113,7 @@ static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *Sample res = ATDECODE_GOTFRAME; numSamples = outBytes / 4; - uint32_t packetAddr = atrac->CurBufferAddress(-skipSamples); + uint32_t packetAddr = CurBufferAddress(-skipSamples); // got a frame int skipped = std::min((u32)skipSamples, numSamples); skipSamples -= skipped; @@ -1123,8 +1128,8 @@ static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *Sample if (packetAddr != 0 && MemBlockInfoDetailed()) { char tagData[128]; - size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "AtracDecode/", packetAddr, atrac->bytesPerFrame_); - NotifyMemInfo(MemBlockFlags::READ, packetAddr, atrac->bytesPerFrame_, tagData, tagSize); + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "AtracDecode/", packetAddr, bytesPerFrame_); + NotifyMemInfo(MemBlockFlags::READ, packetAddr, bytesPerFrame_, tagData, tagSize); NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tagData, tagSize); } else { NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); @@ -1132,12 +1137,12 @@ static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *Sample // We only want one frame per call, let's continue the next time. } - if (res != ATDECODE_GOTFRAME && atrac->currentSample_ < atrac->endSample_) { + if (res != ATDECODE_GOTFRAME && currentSample_ < endSample_) { // Never got a frame. We may have dropped a GHA frame or otherwise have a bug. // For now, let's try to provide an extra "frame" if possible so games don't infinite loop. - if (atrac->FileOffsetBySample(atrac->currentSample_) < atrac->first_.filesize) { - numSamples = std::min(maxSamples, atrac->SamplesPerFrame()); - u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); + if (FileOffsetBySample(currentSample_) < first_.filesize) { + numSamples = std::min(maxSamples, SamplesPerFrame()); + u32 outBytes = numSamples * outputChannels_ * sizeof(s16); if (outbuf != nullptr) { memset(outbuf, 0, outBytes); NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); @@ -1148,28 +1153,28 @@ static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *Sample *SamplesNum = numSamples; // update current sample and decodePos - atrac->currentSample_ += numSamples; - atrac->decodePos_ = atrac->DecodePosBySample(atrac->currentSample_); + currentSample_ += numSamples; + decodePos_ = DecodePosBySample(currentSample_); - atrac->ConsumeFrame(); + ConsumeFrame(); int finishFlag = 0; // TODO: Verify. - bool hitEnd = atrac->currentSample_ >= atrac->endSample_ || (numSamples == 0 && atrac->first_.size >= atrac->first_.filesize); - int loopEndAdjusted = atrac->loopEndSample_ - atrac->FirstOffsetExtra() - atrac->firstSampleOffset_; - if ((hitEnd || atrac->currentSample_ > loopEndAdjusted) && loopNum != 0) { - atrac->SeekToSample(atrac->loopStartSample_ - atrac->FirstOffsetExtra() - atrac->firstSampleOffset_); - if (atrac->bufferState_ != ATRAC_STATUS_FOR_SCESAS) { - if (atrac->loopNum_ > 0) - atrac->loopNum_--; + bool hitEnd = currentSample_ >= endSample_ || (numSamples == 0 && first_.size >= first_.filesize); + int loopEndAdjusted = loopEndSample_ - FirstOffsetExtra() - firstSampleOffset_; + if ((hitEnd || currentSample_ > loopEndAdjusted) && loopNum != 0) { + SeekToSample(loopStartSample_ - FirstOffsetExtra() - firstSampleOffset_); + if (bufferState_ != ATRAC_STATUS_FOR_SCESAS) { + if (loopNum_ > 0) + loopNum_--; } - if ((atrac->bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { + if ((bufferState_ & ATRAC_STATUS_STREAMED_MASK) == ATRAC_STATUS_STREAMED_MASK) { // Whatever bytes we have left were added from the loop. - u32 loopOffset = atrac->FileOffsetBySample(atrac->loopStartSample_ - atrac->FirstOffsetExtra() - atrac->firstSampleOffset_ - atrac->SamplesPerFrame() * 2); + u32 loopOffset = FileOffsetBySample(loopStartSample_ - FirstOffsetExtra() - firstSampleOffset_ - SamplesPerFrame() * 2); // TODO: Hmm, need to manage the buffer better. But don't move fileoffset if we already have valid data. - if (loopOffset > atrac->first_.fileoffset || loopOffset + atrac->bufferValidBytes_ < atrac->first_.fileoffset) { + if (loopOffset > first_.fileoffset || loopOffset + bufferValidBytes_ < first_.fileoffset) { // Skip the initial frame at the start. - atrac->first_.fileoffset = atrac->FileOffsetBySample(atrac->loopStartSample_ - atrac->FirstOffsetExtra() - atrac->firstSampleOffset_ - atrac->SamplesPerFrame() * 2); + first_.fileoffset = FileOffsetBySample(loopStartSample_ - FirstOffsetExtra() - firstSampleOffset_ - SamplesPerFrame() * 2); } } } else if (hitEnd) { @@ -1177,13 +1182,13 @@ static u32 _AtracDecodeData(Atrac *atrac, u8 *outbuf, u32 outbufPtr, u32 *Sample // Still move forward, so we know that we've read everything. // This seems to be reflected in the context as well. - atrac->currentSample_ += atrac->SamplesPerFrame() - numSamples; + currentSample_ += SamplesPerFrame() - numSamples; } *finish = finishFlag; - *remains = atrac->RemainingFrames(); + *remains = RemainingFrames(); // refresh context_ - atrac->WriteContextToPSPMem(); + WriteContextToPSPMem(); return 0; } @@ -1199,7 +1204,7 @@ static u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 u32 numSamples = 0; u32 finish = 0; int remains = 0; - int ret = _AtracDecodeData(atrac, Memory::GetPointerWrite(outAddr), outAddr, &numSamples, &finish, &remains); + int ret = atrac->DecodeData(Memory::GetPointerWrite(outAddr), outAddr, &numSamples, &finish, &remains); if (ret != (int)ATRAC_ERROR_BAD_ATRACID && ret != (int)ATRAC_ERROR_NO_DATA) { if (Memory::IsValidAddress(numSamplesAddr)) Memory::WriteUnchecked_U32(numSamples, numSamplesAddr); @@ -1225,47 +1230,47 @@ static u32 sceAtracEndEntry() { return 0; } -static void AtracGetResetBufferInfo(Atrac *atrac, AtracResetBufferInfo *bufferInfo, int sample) { - if (atrac->bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { - bufferInfo->first.writePosPtr = atrac->first_.addr; +void Atrac::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) { + if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { + bufferInfo->first.writePosPtr = first_.addr; // Everything is loaded, so nothing needs to be read. bufferInfo->first.writableBytes = 0; bufferInfo->first.minWriteBytes = 0; bufferInfo->first.filePos = 0; - } else if (atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) { + } else if (bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) { // Here the message is: you need to read at least this many bytes to get to that position. // This is because we're filling the buffer start to finish, not streaming. - bufferInfo->first.writePosPtr = atrac->first_.addr + atrac->first_.size; - bufferInfo->first.writableBytes = atrac->first_.filesize - atrac->first_.size; - int minWriteBytes = atrac->FileOffsetBySample(sample) - atrac->first_.size; + bufferInfo->first.writePosPtr = first_.addr + first_.size; + bufferInfo->first.writableBytes = first_.filesize - first_.size; + int minWriteBytes = FileOffsetBySample(sample) - first_.size; if (minWriteBytes > 0) { bufferInfo->first.minWriteBytes = minWriteBytes; } else { bufferInfo->first.minWriteBytes = 0; } - bufferInfo->first.filePos = atrac->first_.size; + bufferInfo->first.filePos = first_.size; } else { // This is without the sample offset. The file offset also includes the previous batch of samples? - int sampleFileOffset = atrac->FileOffsetBySample(sample - atrac->firstSampleOffset_ - atrac->SamplesPerFrame()); + int sampleFileOffset = FileOffsetBySample(sample - firstSampleOffset_ - SamplesPerFrame()); // Update the writable bytes. When streaming, this is just the number of bytes until the end. - const u32 bufSizeAligned = (atrac->bufferMaxSize_ / atrac->bytesPerFrame_) * atrac->bytesPerFrame_; - const int needsMoreFrames = atrac->FirstOffsetExtra(); + const u32 bufSizeAligned = (bufferMaxSize_ / bytesPerFrame_) * bytesPerFrame_; + const int needsMoreFrames = FirstOffsetExtra(); - bufferInfo->first.writePosPtr = atrac->first_.addr; - bufferInfo->first.writableBytes = std::min(atrac->first_.filesize - sampleFileOffset, bufSizeAligned); - if (((sample + atrac->firstSampleOffset_) % (int)atrac->SamplesPerFrame()) >= (int)atrac->SamplesPerFrame() - needsMoreFrames) { + bufferInfo->first.writePosPtr = first_.addr; + bufferInfo->first.writableBytes = std::min(first_.filesize - sampleFileOffset, bufSizeAligned); + if (((sample + firstSampleOffset_) % (int)SamplesPerFrame()) >= (int)SamplesPerFrame() - needsMoreFrames) { // Not clear why, but it seems it wants a bit extra in case the sample is late? - bufferInfo->first.minWriteBytes = atrac->bytesPerFrame_ * 3; + bufferInfo->first.minWriteBytes = bytesPerFrame_ * 3; } else { - bufferInfo->first.minWriteBytes = atrac->bytesPerFrame_ * 2; + bufferInfo->first.minWriteBytes = bytesPerFrame_ * 2; } - if ((u32)sample < (u32)atrac->firstSampleOffset_ && sampleFileOffset != atrac->dataOff_) { - sampleFileOffset -= atrac->bytesPerFrame_; + if ((u32)sample < (u32)firstSampleOffset_ && sampleFileOffset != dataOff_) { + sampleFileOffset -= bytesPerFrame_; } bufferInfo->first.filePos = sampleFileOffset; - if (atrac->second_.size != 0) { + if (second_.size != 0) { // TODO: We have a second buffer. Within it, minWriteBytes should be zero. // The filePos should be after the end of the second buffer (or zero.) // We actually need to ensure we READ from the second buffer before implementing that. @@ -1273,7 +1278,7 @@ static void AtracGetResetBufferInfo(Atrac *atrac, AtracResetBufferInfo *bufferIn } // It seems like this is always the same as the first buffer's pos, weirdly. - bufferInfo->second.writePosPtr = atrac->first_.addr; + bufferInfo->second.writePosPtr = first_.addr; // Reset never needs a second buffer write, since the loop is in a fixed place. bufferInfo->second.writableBytes = 0; bufferInfo->second.minWriteBytes = 0; @@ -1299,7 +1304,7 @@ static u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 buffer } else if ((u32)sample + atrac->firstSampleOffset_ > (u32)atrac->endSample_ + atrac->firstSampleOffset_) { return hleLogWarning(ME, ATRAC_ERROR_BAD_SAMPLE, "invalid sample position"); } else { - AtracGetResetBufferInfo(atrac, bufferInfo, sample); + atrac->GetResetBufferInfo(bufferInfo, sample); return hleLogSuccessInfoI(ME, 0); } } @@ -1572,7 +1577,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi } // Reuse the same calculation as before. AtracResetBufferInfo bufferInfo; - AtracGetResetBufferInfo(atrac, &bufferInfo, sample); + atrac->GetResetBufferInfo(&bufferInfo, sample); if ((u32)bytesWrittenFirstBuf < bufferInfo.first.minWriteBytes || (u32)bytesWrittenFirstBuf > bufferInfo.first.writableBytes) { return hleLogError(ME, ATRAC_ERROR_BAD_FIRST_RESET_SIZE, "first byte count not in valid range"); @@ -2212,7 +2217,6 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo return hleReportError(ME, 0, "invalid pointers"); } - int numSamples = (atrac->codecType_ == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); int bytesConsumed = 0; int bytesWritten = 0; atrac->decoder_->Decode(srcp, atrac->bytesPerFrame_, &bytesConsumed, outp, &bytesWritten); @@ -2259,7 +2263,7 @@ u32 AtracSasDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, Atrac *atrac = getAtrac(atracID); if (!atrac) return 0; - return _AtracDecodeData(atrac, outbuf, outbufPtr, SamplesNum, finish, remains); + return atrac->DecodeData(outbuf, outbufPtr, SamplesNum, finish, remains); } int AtracSasGetIDByContext(u32 contextAddr) { From eeaa3c8445a8b1713de2365a61864213c6c585a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Apr 2024 10:55:17 +0200 Subject: [PATCH 4/5] Make more functions member functions of Atrac --- Core/HLE/sceAtrac.cpp | 109 +++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index aa159767da..5196faf4bc 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -146,7 +146,6 @@ struct InputBuffer { }; struct Atrac; -int __AtracSetContext(Atrac *atrac); struct AtracLoopInfo { int cuePointID; @@ -305,7 +304,7 @@ struct Atrac { // Make sure to do this late; it depends on things like bytesPerFrame_. if (p.mode == p.MODE_READ && bufferState_ != ATRAC_STATUS_NO_DATA) { - __AtracSetContext(this); + SetContext(); } if (s >= 2 && s < 9) { @@ -489,19 +488,14 @@ struct Atrac { } } - void UpdateFromPSPMem() { - if (context_.IsValid()) { - // Read in any changes from the game to the context. - // TODO: Might be better to just always track in RAM. - bufferState_ = context_->info.state; - // This value is actually abused by games to store the SAS voice number. - loopNum_ = context_->info.loopNum; - } - } + void UpdateContextFromPSPMem(); void WriteContextToPSPMem(); u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains); void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample); + void SetLoopNum(int loopNum); + u32 AddStreamData(u32 bufPtr, u32 bytesToAdd); + int SetContext(); // To be moved into private. AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; @@ -510,6 +504,17 @@ private: void AnalyzeReset(); }; +void Atrac::SetLoopNum(int loopNum) { + // Spammed in MHU + loopNum_ = loopNum; + if (loopNum != 0 && loopinfo_.size() == 0) { + // Just loop the whole audio + loopStartSample_ = firstSampleOffset_ + FirstOffsetExtra(); + loopEndSample_ = endSample_ + firstSampleOffset_ + FirstOffsetExtra(); + } + WriteContextToPSPMem(); +} + struct AtracSingleResetBufferInfo { u32_le writePosPtr; u32_le writableBytes; @@ -590,7 +595,7 @@ static Atrac *getAtrac(int atracID) { } Atrac *atrac = atracContexts[atracID]; if (atrac) { - atrac->UpdateFromPSPMem(); + atrac->UpdateContextFromPSPMem(); } return atrac; } @@ -631,15 +636,15 @@ void Atrac::AnalyzeReset() { channels_ = 2; } -struct RIFFFmtChunk { - u16_le fmtTag; - u16_le channels; - u32_le samplerate; - u32_le avgBytesPerSec; - u16_le blockAlign; -}; - int Atrac::Analyze(u32 addr, u32 size) { + struct RIFFFmtChunk { + u16_le fmtTag; + u16_le channels; + u32_le samplerate; + u32_le avgBytesPerSec; + u16_le blockAlign; + }; + first_.addr = addr; first_.size = size; @@ -913,18 +918,18 @@ static u32 sceAtracGetAtracID(int codecType) { return hleLogSuccessInfoI(ME, atracID); } -static u32 _AtracAddStreamData(Atrac *atrac, u32 bufPtr, u32 bytesToAdd) { - int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset - atrac->FirstOffsetExtra()); - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset + atrac->FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData"); - atrac->first_.size += bytesToAdd; - if (atrac->first_.size >= atrac->first_.filesize) { - atrac->first_.size = atrac->first_.filesize; - if (atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) - atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; +u32 Atrac::AddStreamData(u32 bufPtr, u32 bytesToAdd) { + int addbytes = std::min(bytesToAdd, first_.filesize - first_.fileoffset - FirstOffsetExtra()); + Memory::Memcpy(dataBuf_ + first_.fileoffset + FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData"); + first_.size += bytesToAdd; + if (first_.size >= first_.filesize) { + first_.size = first_.filesize; + if (bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) + bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; } - atrac->first_.fileoffset += addbytes; + first_.fileoffset += addbytes; // refresh context_ - atrac->WriteContextToPSPMem(); + WriteContextToPSPMem(); return 0; } @@ -1646,21 +1651,21 @@ void InitAT3ExtraData(Atrac *atrac, uint8_t *extraData) { extraData[10] = 1; } -int __AtracSetContext(Atrac *atrac) { - if (atrac->decoder_) { - delete atrac->decoder_; +int Atrac::SetContext() { + if (decoder_) { + delete decoder_; } // First, init the standalone decoder. Only used for low-level-decode initially, but simple. - if (atrac->codecType_ == PSP_MODE_AT_3) { + if (codecType_ == PSP_MODE_AT_3) { uint8_t extraData[14]{}; - InitAT3ExtraData(atrac, extraData); - atrac->decoder_ = CreateAtrac3Audio(atrac->channels_, atrac->bytesPerFrame_, extraData, sizeof(extraData)); + InitAT3ExtraData(this, extraData); + decoder_ = CreateAtrac3Audio(channels_, bytesPerFrame_, extraData, sizeof(extraData)); } else { - atrac->decoder_ = CreateAtrac3PlusAudio(atrac->channels_, atrac->bytesPerFrame_); + decoder_ = CreateAtrac3PlusAudio(channels_, bytesPerFrame_); } // reinit decodePos, because ffmpeg had changed it. - atrac->decodePos_ = 0; + decodePos_ = 0; return 0; } @@ -1710,7 +1715,7 @@ static int _AtracSetData(Atrac *atrac, u32 buffer, u32 readSize, u32 bufferSize, u32 copybytes = std::min(bufferSize, atrac->first_.filesize); Memory::Memcpy(atrac->dataBuf_, buffer, copybytes, "AtracSetData"); } - int ret = __AtracSetContext(atrac); + int ret = atrac->SetContext(); if (ret < 0) { // Already logged. return ret; @@ -1856,14 +1861,8 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { if (atrac->loopinfo_.size() == 0) { return hleLogError(ME, ATRAC_ERROR_NO_LOOP_INFORMATION, "no loop information"); } - // Spammed in MHU - atrac->loopNum_ = loopNum; - if (loopNum != 0 && atrac->loopinfo_.size() == 0) { - // Just loop the whole audio - atrac->loopStartSample_ = atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); - atrac->loopEndSample_ = atrac->endSample_ + atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); - } - atrac->WriteContextToPSPMem(); + + atrac->SetLoopNum(loopNum); return hleLogSuccessI(ME, 0); } @@ -2056,6 +2055,18 @@ static int sceAtracSetAA3DataAndGetID(u32 buffer, u32 bufferSize, u32 fileSize, return _AtracSetData(atracID, buffer, bufferSize, bufferSize, true); } +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. + bufferState_ = context_->info.state; + // This value is actually abused by games to store the SAS voice number. + loopNum_ = context_->info.loopNum; +} + void Atrac::WriteContextToPSPMem() { if (!context_.IsValid()) { return; @@ -2190,7 +2201,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { atrac->first_.filesize = atrac->bytesPerFrame_; atrac->bufferState_ = ATRAC_STATUS_LOW_LEVEL; atrac->currentSample_ = 0; - int ret = __AtracSetContext(atrac); + int ret = atrac->SetContext(); atrac->WriteContextToPSPMem(); @@ -2256,7 +2267,7 @@ u32 AtracSasAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { Atrac *atrac = getAtrac(atracID); if (!atrac) return 0; - return _AtracAddStreamData(atrac, bufPtr, bytesToAdd); + return atrac->AddStreamData(bufPtr, bytesToAdd); } u32 AtracSasDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains) { From 35578f0a2e22b9918894dac888ec66aad2223739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Apr 2024 11:25:19 +0200 Subject: [PATCH 5/5] More member functions --- Core/HLE/sceAtrac.cpp | 332 ++++++++++++++++++++++-------------------- 1 file changed, 173 insertions(+), 159 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 5196faf4bc..d84948cec8 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -181,9 +181,6 @@ struct Atrac { if (context_.IsValid()) kernelMemory.Free(context_.ptr); - - // Clean slate time. - failedDecode_ = false; } void SetBufferState() { @@ -304,7 +301,7 @@ struct Atrac { // Make sure to do this late; it depends on things like bytesPerFrame_. if (p.mode == p.MODE_READ && bufferState_ != ATRAC_STATUS_NO_DATA) { - SetContext(); + CreateDecoder(); } if (s >= 2 && s < 9) { @@ -401,7 +398,6 @@ struct Atrac { int loopEndSample_ = -1; int loopNum_ = 0; - bool failedDecode_ = false; // Indicates that the dataBuf_ array should not be used. bool ignoreDataBuf_ = false; @@ -494,14 +490,19 @@ struct Atrac { u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains); void GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample); void SetLoopNum(int loopNum); - u32 AddStreamData(u32 bufPtr, u32 bytesToAdd); - int SetContext(); + int AddStreamData(u32 bytesToAdd); + u32 AddStreamDataSas(u32 bufPtr, u32 bytesToAdd); + void CreateDecoder(); + u32 ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf); + int SetData(u32 buffer, u32 readSize, u32 bufferSize, int successCode = 0); + u32 GetNextSamples(); - // To be moved into private. - AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; + void InitLowLevel(u32 paramsAddr, bool jointStereo); private: void AnalyzeReset(); + + AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA; }; void Atrac::SetLoopNum(int loopNum) { @@ -918,7 +919,7 @@ static u32 sceAtracGetAtracID(int codecType) { return hleLogSuccessInfoI(ME, atracID); } -u32 Atrac::AddStreamData(u32 bufPtr, u32 bytesToAdd) { +u32 Atrac::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) { int addbytes = std::min(bytesToAdd, first_.filesize - first_.fileoffset - FirstOffsetExtra()); Memory::Memcpy(dataBuf_ + first_.fileoffset + FirstOffsetExtra(), bufPtr, addbytes, "AtracAddStreamData"); first_.size += bytesToAdd; @@ -1022,44 +1023,51 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { return err; } - if (atrac->bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { + if (atrac->BufferState() == ATRAC_STATUS_ALL_DATA_LOADED) { // Let's avoid spurious warnings. Some games call this with 0 which is pretty harmless. if (bytesToAdd == 0) return hleLogDebug(ME, ATRAC_ERROR_ALL_DATA_LOADED, "stream entirely loaded"); return hleLogWarning(ME, ATRAC_ERROR_ALL_DATA_LOADED, "stream entirely loaded"); } - u32 readOffset; - atrac->CalculateStreamInfo(&readOffset); + int ret = atrac->AddStreamData(bytesToAdd); + if (ret < 0) { + return ret; + } + return hleLogSuccessI(ME, 0); +} - if (bytesToAdd > atrac->first_.writableBytes) +int Atrac::AddStreamData(u32 bytesToAdd) { + u32 readOffset; + CalculateStreamInfo(&readOffset); + if (bytesToAdd > first_.writableBytes) return hleLogWarning(ME, ATRAC_ERROR_ADD_DATA_IS_TOO_BIG, "too many bytes"); if (bytesToAdd > 0) { - atrac->first_.fileoffset = readOffset; - int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset); - if (!atrac->ignoreDataBuf_) { - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, atrac->first_.addr + atrac->first_.offset, addbytes, "AtracAddStreamData"); + first_.fileoffset = readOffset; + int addbytes = std::min(bytesToAdd, first_.filesize - first_.fileoffset); + if (!ignoreDataBuf_) { + Memory::Memcpy(dataBuf_ + first_.fileoffset, first_.addr + first_.offset, addbytes, "AtracAddStreamData"); } - atrac->first_.fileoffset += addbytes; + first_.fileoffset += addbytes; } - atrac->first_.size += bytesToAdd; - if (atrac->first_.size >= atrac->first_.filesize) { - atrac->first_.size = atrac->first_.filesize; - if (atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) - atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; - atrac->WriteContextToPSPMem(); + first_.size += bytesToAdd; + if (first_.size >= first_.filesize) { + first_.size = first_.filesize; + if (bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) + bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; + WriteContextToPSPMem(); } - atrac->first_.offset += bytesToAdd; - atrac->bufferValidBytes_ += bytesToAdd; + first_.offset += bytesToAdd; + bufferValidBytes_ += bytesToAdd; - if (PSP_CoreParameter().compat.flags().AtracLoopHack && atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && atrac->RemainingFrames() > 2) { - atrac->loopNum_++; - atrac->SeekToSample(atrac->loopStartSample_ - atrac->FirstOffsetExtra() - atrac->firstSampleOffset_); + if (PSP_CoreParameter().compat.flags().AtracLoopHack && bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && RemainingFrames() > 2) { + loopNum_++; + SeekToSample(loopStartSample_ - FirstOffsetExtra() - firstSampleOffset_); } - return hleLogSuccessI(ME, 0); + return 0; } u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) { @@ -1099,7 +1107,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i } // TODO: We don't support any other codec type, check seems unnecessary? - if (!failedDecode_ && (codecType_ == PSP_MODE_AT_3 || codecType_ == PSP_MODE_AT_3_PLUS)) { + if ((codecType_ == PSP_MODE_AT_3 || codecType_ == PSP_MODE_AT_3_PLUS)) { SeekToSample(currentSample_); AtracDecodeResult res = ATDECODE_FEEDME; @@ -1304,7 +1312,7 @@ static u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 buffer if (!bufferInfo.IsValid()) { return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "invalid buffer, should crash"); - } else if (atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && atrac->second_.size == 0) { + } else if (atrac->BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && atrac->second_.size == 0) { return hleReportError(ME, ATRAC_ERROR_SECOND_BUFFER_NEEDED, "no second buffer"); } else if ((u32)sample + atrac->firstSampleOffset_ > (u32)atrac->endSample_ + atrac->firstSampleOffset_) { return hleLogWarning(ME, ATRAC_ERROR_BAD_SAMPLE, "invalid sample position"); @@ -1436,28 +1444,34 @@ static u32 sceAtracGetNextSample(int atracID, u32 outNAddr) { return hleLogSuccessI(ME, 0, "0 samples left"); } - // It seems like the PSP aligns the sample position to 0x800...? - u32 skipSamples = atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); - u32 firstSamples = (atrac->SamplesPerFrame() - skipSamples) % atrac->SamplesPerFrame(); - u32 numSamples = atrac->endSample_ + 1 - atrac->currentSample_; - if (atrac->currentSample_ == 0 && firstSamples != 0) { - numSamples = firstSamples; - } - u32 unalignedSamples = (skipSamples + atrac->currentSample_) % atrac->SamplesPerFrame(); - if (unalignedSamples != 0) { - // We're off alignment, possibly due to a loop. Force it back on. - numSamples = atrac->SamplesPerFrame() - unalignedSamples; - } - if (numSamples > atrac->SamplesPerFrame()) - numSamples = atrac->SamplesPerFrame(); - if (atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && (int)numSamples + atrac->currentSample_ > atrac->endSample_) { - atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; - } + u32 numSamples = atrac->GetNextSamples(); + if (Memory::IsValidAddress(outNAddr)) Memory::WriteUnchecked_U32(numSamples, outNAddr); return hleLogSuccessI(ME, 0, "%d samples left", numSamples); } +u32 Atrac::GetNextSamples() { + // It seems like the PSP aligns the sample position to 0x800...? + u32 skipSamples = firstSampleOffset_ + FirstOffsetExtra(); + u32 firstSamples = (SamplesPerFrame() - skipSamples) % SamplesPerFrame(); + u32 numSamples = endSample_ + 1 - currentSample_; + if (currentSample_ == 0 && firstSamples != 0) { + numSamples = firstSamples; + } + u32 unalignedSamples = (skipSamples + currentSample_) % SamplesPerFrame(); + if (unalignedSamples != 0) { + // We're off alignment, possibly due to a loop. Force it back on. + numSamples = SamplesPerFrame() - unalignedSamples; + } + if (numSamples > SamplesPerFrame()) + numSamples = SamplesPerFrame(); + if (bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END && (int)numSamples + currentSample_ > endSample_) { + bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; + } + return numSamples; +} + // Obtains the number of frames remaining in the buffer which can be decoded. // When no more data would be needed, this returns a negative number. static u32 sceAtracGetRemainFrame(int atracID, u32 remainAddr) { @@ -1495,7 +1509,7 @@ static u32 sceAtracGetSecondBufferInfo(int atracID, u32 fileOffsetAddr, u32 desi return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "invalid addresses"); } - if (atrac->bufferState_ != ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) { + if (atrac->BufferState() != ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) { // Writes zeroes in this error case. *fileOffset = 0; *desiredSize = 0; @@ -1575,14 +1589,25 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi return err; } - if (atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && atrac->second_.size == 0) { + if (atrac->BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && atrac->second_.size == 0) { return hleReportError(ME, ATRAC_ERROR_SECOND_BUFFER_NEEDED, "no second buffer"); } else if ((u32)sample + atrac->firstSampleOffset_ > (u32)atrac->endSample_ + atrac->firstSampleOffset_) { return hleLogWarning(ME, ATRAC_ERROR_BAD_SAMPLE, "invalid sample position"); } + + u32 res = atrac->ResetPlayPosition(sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); + if (res != 0) { + // Already logged. + return res; + } + + return hleDelayResult(hleLogSuccessInfoI(ME, 0), "reset play pos", 3000); +} + +u32 Atrac::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) { // Reuse the same calculation as before. AtracResetBufferInfo bufferInfo; - atrac->GetResetBufferInfo(&bufferInfo, sample); + GetResetBufferInfo(&bufferInfo, sample); if ((u32)bytesWrittenFirstBuf < bufferInfo.first.minWriteBytes || (u32)bytesWrittenFirstBuf > bufferInfo.first.writableBytes) { return hleLogError(ME, ATRAC_ERROR_BAD_FIRST_RESET_SIZE, "first byte count not in valid range"); @@ -1591,135 +1616,124 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi return hleLogError(ME, ATRAC_ERROR_BAD_SECOND_RESET_SIZE, "second byte count not in valid range"); } - if (atrac->bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { + if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED) { // Always adds zero bytes. - } else if (atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) { + } else if (bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) { // Okay, it's a valid number of bytes. Let's set them up. if (bytesWrittenFirstBuf != 0) { - if (!atrac->ignoreDataBuf_) { - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.size, atrac->first_.addr + atrac->first_.size, bytesWrittenFirstBuf, "AtracResetPlayPosition"); + if (!ignoreDataBuf_) { + Memory::Memcpy(dataBuf_ + first_.size, first_.addr + first_.size, bytesWrittenFirstBuf, "AtracResetPlayPosition"); } - atrac->first_.fileoffset += bytesWrittenFirstBuf; - atrac->first_.size += bytesWrittenFirstBuf; - atrac->first_.offset += bytesWrittenFirstBuf; + first_.fileoffset += bytesWrittenFirstBuf; + first_.size += bytesWrittenFirstBuf; + first_.offset += bytesWrittenFirstBuf; } // Did we transition to a full buffer? - if (atrac->first_.size >= atrac->first_.filesize) { - atrac->first_.size = atrac->first_.filesize; - atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; + if (first_.size >= first_.filesize) { + first_.size = first_.filesize; + bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; } } else { - if (bufferInfo.first.filePos > atrac->first_.filesize) { + if (bufferInfo.first.filePos > first_.filesize) { return hleDelayResult(hleLogError(ME, ATRAC_ERROR_API_FAIL, "invalid file position"), "reset play pos", 200); } // Move the offset to the specified position. - atrac->first_.fileoffset = bufferInfo.first.filePos; + first_.fileoffset = bufferInfo.first.filePos; if (bytesWrittenFirstBuf != 0) { - if (!atrac->ignoreDataBuf_) { - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, atrac->first_.addr, bytesWrittenFirstBuf, "AtracResetPlayPosition"); + if (!ignoreDataBuf_) { + Memory::Memcpy(dataBuf_ + first_.fileoffset, first_.addr, bytesWrittenFirstBuf, "AtracResetPlayPosition"); } - atrac->first_.fileoffset += bytesWrittenFirstBuf; + first_.fileoffset += bytesWrittenFirstBuf; } - atrac->first_.size = atrac->first_.fileoffset; - atrac->first_.offset = bytesWrittenFirstBuf; + first_.size = first_.fileoffset; + first_.offset = bytesWrittenFirstBuf; - atrac->bufferHeaderSize_ = 0; - atrac->bufferPos_ = atrac->bytesPerFrame_; - atrac->bufferValidBytes_ = bytesWrittenFirstBuf - atrac->bufferPos_; + bufferHeaderSize_ = 0; + bufferPos_ = bytesPerFrame_; + bufferValidBytes_ = bytesWrittenFirstBuf - bufferPos_; } - if (atrac->codecType_ == PSP_MODE_AT_3 || atrac->codecType_ == PSP_MODE_AT_3_PLUS) { - atrac->SeekToSample(sample); + if (codecType_ == PSP_MODE_AT_3 || codecType_ == PSP_MODE_AT_3_PLUS) { + SeekToSample(sample); } - atrac->WriteContextToPSPMem(); - return hleDelayResult(hleLogSuccessInfoI(ME, 0), "reset play pos", 3000); + WriteContextToPSPMem(); + return 0; } -// extraData should be 14 zeroed bytes. -void InitAT3ExtraData(Atrac *atrac, uint8_t *extraData) { - // We don't pull this from the RIFF so that we can support OMA also. - - // The only thing that changes are the jointStereo_ values. - extraData[0] = 1; - extraData[3] = atrac->channels_ << 3; - extraData[6] = atrac->jointStereo_; - extraData[8] = atrac->jointStereo_; - extraData[10] = 1; -} - -int Atrac::SetContext() { +void Atrac::CreateDecoder() { if (decoder_) { delete decoder_; } // First, init the standalone decoder. Only used for low-level-decode initially, but simple. if (codecType_ == PSP_MODE_AT_3) { + // We don't pull this from the RIFF so that we can support OMA also. uint8_t extraData[14]{}; - InitAT3ExtraData(this, extraData); + // The only thing that changes are the jointStereo_ values. + extraData[0] = 1; + extraData[3] = channels_ << 3; + extraData[6] = jointStereo_; + extraData[8] = jointStereo_; + extraData[10] = 1; decoder_ = CreateAtrac3Audio(channels_, bytesPerFrame_, extraData, sizeof(extraData)); } else { decoder_ = CreateAtrac3PlusAudio(channels_, bytesPerFrame_); } // reinit decodePos, because ffmpeg had changed it. decodePos_ = 0; - return 0; } -static int _AtracSetData(Atrac *atrac, u32 buffer, u32 readSize, u32 bufferSize, int successCode = 0) { - atrac->first_.addr = buffer; - atrac->first_.size = readSize; +int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int successCode) { + first_.addr = buffer; + first_.size = readSize; - if (atrac->first_.size > atrac->first_.filesize) - atrac->first_.size = atrac->first_.filesize; - atrac->first_.fileoffset = atrac->first_.size; + if (first_.size > first_.filesize) + first_.size = first_.filesize; + first_.fileoffset = first_.size; // got the size of temp buf, and calculate offset - atrac->bufferMaxSize_ = bufferSize; - atrac->first_.offset = atrac->first_.size; + bufferMaxSize_ = bufferSize; + first_.offset = first_.size; // some games may reuse an atracID for playing sound - atrac->ResetData(); - atrac->SetBufferState(); + ResetData(); + SetBufferState(); - if (atrac->codecType_ != PSP_MODE_AT_3 && atrac->codecType_ != PSP_MODE_AT_3_PLUS) { + if (codecType_ != PSP_MODE_AT_3 && codecType_ != PSP_MODE_AT_3_PLUS) { // Shouldn't have gotten here, Analyze() checks this. - atrac->bufferState_ = ATRAC_STATUS_NO_DATA; + bufferState_ = ATRAC_STATUS_NO_DATA; return hleReportError(ME, ATRAC_ERROR_UNKNOWN_FORMAT, "unexpected codec type in set data"); } - if (atrac->bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED || atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) { + if (bufferState_ == ATRAC_STATUS_ALL_DATA_LOADED || bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) { // This says, don't use the dataBuf_ array, use the PSP RAM. // This way, games can load data async into the buffer, and it still works. // TODO: Support this always, even for streaming. - atrac->ignoreDataBuf_ = true; + ignoreDataBuf_ = true; } - if (atrac->bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP || atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END || atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) { - atrac->bufferHeaderSize_ = atrac->dataOff_; - atrac->bufferPos_ = atrac->dataOff_ + atrac->bytesPerFrame_; - atrac->bufferValidBytes_ = atrac->first_.size - atrac->bufferPos_; + if (bufferState_ == ATRAC_STATUS_STREAMED_WITHOUT_LOOP || bufferState_ == ATRAC_STATUS_STREAMED_LOOP_FROM_END || bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) { + bufferHeaderSize_ = dataOff_; + bufferPos_ = dataOff_ + bytesPerFrame_; + bufferValidBytes_ = first_.size - bufferPos_; } - const char *codecName = atrac->codecType_ == PSP_MODE_AT_3 ? "atrac3" : "atrac3+"; - const char *channelName = atrac->channels_ == 1 ? "mono" : "stereo"; + const char *codecName = codecType_ == PSP_MODE_AT_3 ? "atrac3" : "atrac3+"; + const char *channelName = channels_ == 1 ? "mono" : "stereo"; // Over-allocate databuf to prevent going off the end if the bitstream is bad or if there are // bugs in the decoder. This happens, see issue #15788. Arbitrary, but let's make it a whole page on the popular // architecture that has the largest pages (M1). - atrac->dataBuf_ = new u8[atrac->first_.filesize + overAllocBytes]; - memset(atrac->dataBuf_, 0, atrac->first_.filesize + overAllocBytes); - if (!atrac->ignoreDataBuf_) { - u32 copybytes = std::min(bufferSize, atrac->first_.filesize); - Memory::Memcpy(atrac->dataBuf_, buffer, copybytes, "AtracSetData"); - } - int ret = atrac->SetContext(); - if (ret < 0) { - // Already logged. - return ret; + dataBuf_ = new u8[first_.filesize + overAllocBytes]; + memset(dataBuf_, 0, first_.filesize + overAllocBytes); + if (!ignoreDataBuf_) { + u32 copybytes = std::min(bufferSize, first_.filesize); + Memory::Memcpy(dataBuf_, buffer, copybytes, "AtracSetData"); } + CreateDecoder(); return hleLogSuccessInfoI(ME, successCode, "%s %s audio", codecName, channelName); } @@ -1728,7 +1742,7 @@ static int _AtracSetData(int atracID, u32 buffer, u32 readSize, u32 bufferSize, // Don't use AtracValidateManaged here. if (!atrac) return hleLogError(ME, ATRAC_ERROR_BAD_ATRACID, "invalid atrac ID"); - int ret = _AtracSetData(atrac, buffer, readSize, bufferSize, needReturnAtracID ? atracID : 0); + int ret = atrac->SetData(buffer, readSize, bufferSize, needReturnAtracID ? atracID : 0); // not sure the real delay time return hleDelayResult(ret, "atrac set data", 100); } @@ -1769,7 +1783,7 @@ static u32 sceAtracSetSecondBuffer(int atracID, u32 secondBuffer, u32 secondBuff if (secondBufferSize < desiredSize && secondBufferSize < (u32)atrac->bytesPerFrame_ * 3) { return hleReportError(ME, ATRAC_ERROR_SIZE_TOO_SMALL, "too small"); } - if (atrac->bufferState_ != ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) { + if (atrac->BufferState() != ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) { return hleReportError(ME, ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED, "not needed"); } @@ -1935,7 +1949,7 @@ static int sceAtracIsSecondBufferNeeded(int atracID) { } // Note that this returns true whether the buffer is already set or not. - int needed = atrac->bufferState_ == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER ? 1 : 0; + int needed = atrac->BufferState() == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER ? 1 : 0; return hleLogSuccessI(ME, needed); } @@ -1957,7 +1971,7 @@ static int sceAtracSetMOutHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u if (atrac->channels_ != 1) { // It seems it still sets the data. atrac->outputChannels_ = 2; - _AtracSetData(atrac, buffer, readSize, bufferSize); + atrac->SetData(buffer, readSize, bufferSize); return hleReportError(ME, ATRAC_ERROR_NOT_MONO, "not mono data"); } else { atrac->outputChannels_ = 1; @@ -1981,7 +1995,7 @@ static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) { if (atrac->channels_ != 1) { // It seems it still sets the data. atrac->outputChannels_ = 2; - _AtracSetData(atrac, buffer, bufferSize, bufferSize); + atrac->SetData(buffer, bufferSize, bufferSize); return hleReportError(ME, ATRAC_ERROR_NOT_MONO, "not mono data"); } else { atrac->outputChannels_ = 1; @@ -2163,26 +2177,13 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { return hleReportError(ME, 0, "invalid pointers"); } - atrac->channels_ = Memory::Read_U32(paramsAddr); - atrac->outputChannels_ = Memory::Read_U32(paramsAddr + 4); - atrac->bufferMaxSize_ = Memory::Read_U32(paramsAddr + 8); - atrac->bytesPerFrame_ = atrac->bufferMaxSize_; - atrac->first_.writableBytes = atrac->bytesPerFrame_; - atrac->ResetData(); - - const char *codecName = atrac->codecType_ == PSP_MODE_AT_3 ? "atrac3" : "atrac3+"; - const char *channelName = atrac->channels_ == 1 ? "mono" : "stereo"; - + bool jointStereo = false; if (atrac->codecType_ == PSP_MODE_AT_3) { - atrac->bitrate_ = (atrac->bytesPerFrame_ * 352800) / 1000; - atrac->bitrate_ = (atrac->bitrate_ + 511) >> 10; - atrac->jointStereo_ = false; - // See if we can match the actual jointStereo value. bool found = false; for (size_t i = 0; i < ARRAY_SIZE(at3HeaderMap); ++i) { if (at3HeaderMap[i].Matches(atrac)) { - atrac->jointStereo_ = at3HeaderMap[i].jointStereo; + jointStereo = at3HeaderMap[i].jointStereo; found = true; } } @@ -2190,26 +2191,40 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { ERROR_LOG_REPORT(ME, "AT3 header map lacks entry for bpf: %i channels: %i", atrac->bytesPerFrame_, atrac->channels_); // TODO: Should we return an error code for these values? } - } else if (atrac->codecType_ == PSP_MODE_AT_3_PLUS) { - atrac->bitrate_ = (atrac->bytesPerFrame_ * 352800) / 1000; - atrac->bitrate_ = ((atrac->bitrate_ >> 11) + 8) & 0xFFFFFFF0; - atrac->jointStereo_ = false; } - atrac->dataOff_ = 0; - atrac->first_.size = 0; - atrac->first_.filesize = atrac->bytesPerFrame_; - atrac->bufferState_ = ATRAC_STATUS_LOW_LEVEL; - atrac->currentSample_ = 0; - int ret = atrac->SetContext(); + atrac->InitLowLevel(paramsAddr, jointStereo); - atrac->WriteContextToPSPMem(); + const char *codecName = atrac->codecType_ == PSP_MODE_AT_3 ? "atrac3" : "atrac3+"; + const char *channelName = atrac->channels_ == 1 ? "mono" : "stereo"; + return hleLogSuccessInfoI(ME, 0, "%s %s audio", codecName, channelName); +} - if (ret < 0) { - // Already logged. - return ret; +void Atrac::InitLowLevel(u32 paramsAddr, bool jointStereo) { + channels_ = Memory::Read_U32(paramsAddr); + outputChannels_ = Memory::Read_U32(paramsAddr + 4); + bufferMaxSize_ = Memory::Read_U32(paramsAddr + 8); + bytesPerFrame_ = bufferMaxSize_; + first_.writableBytes = bytesPerFrame_; + ResetData(); + + if (codecType_ == PSP_MODE_AT_3) { + bitrate_ = (bytesPerFrame_ * 352800) / 1000; + bitrate_ = (bitrate_ + 511) >> 10; + jointStereo_ = false; + } else if (codecType_ == PSP_MODE_AT_3_PLUS) { + bitrate_ = (bytesPerFrame_ * 352800) / 1000; + bitrate_ = ((bitrate_ >> 11) + 8) & 0xFFFFFFF0; + jointStereo_ = false; } - return hleLogSuccessInfoI(ME, ret, "%s %s audio", codecName, channelName); + + dataOff_ = 0; + first_.size = 0; + first_.filesize = bytesPerFrame_; + bufferState_ = ATRAC_STATUS_LOW_LEVEL; + currentSample_ = 0; + CreateDecoder(); + WriteContextToPSPMem(); } static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedAddr, u32 samplesAddr, u32 sampleBytesAddr) { @@ -2235,7 +2250,6 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo *outWritten = bytesWritten; NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, bytesWritten, "AtracLowLevelDecode"); - return hleLogDebug(ME, hleDelayResult(0, "low level atrac decode data", atracDecodeDelay)); } @@ -2267,7 +2281,7 @@ u32 AtracSasAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { Atrac *atrac = getAtrac(atracID); if (!atrac) return 0; - return atrac->AddStreamData(bufPtr, bytesToAdd); + return atrac->AddStreamDataSas(bufPtr, bytesToAdd); } u32 AtracSasDecodeData(int atracID, u8* outbuf, u32 outbufPtr, u32 *SamplesNum, u32* finish, int *remains) {