diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index d9252c0aef..e0bc7923e6 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -241,8 +241,7 @@ void Track::DebugLog() { DEBUG_LOG(Log::ME, "loopStartSample: %d loopEndSample: %d", loopStartSample, loopEndSample); } -int Atrac::Analyze(u32 addr, u32 size) { - track_ = {}; +int Atrac::Analyze(const Track &track, u32 addr, u32 size, u32 fileSize) { first_ = {}; first_.addr = addr; first_.size = size; @@ -259,16 +258,18 @@ int Atrac::Analyze(u32 addr, u32 size) { return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS; } + bool aa3 = fileSize != 0; + // TODO: Validate stuff. - if (Memory::ReadUnchecked_U32(addr) != RIFF_CHUNK_MAGIC) { + if (!aa3 && Memory::ReadUnchecked_U32(addr) != RIFF_CHUNK_MAGIC) { ERROR_LOG(Log::ME, "Couldn't find RIFF header"); return SCE_ERROR_ATRAC_UNKNOWN_FORMAT; } - int retval = AnalyzeAtracTrack(addr, size, &track_); - first_._filesize_dontuse = track_.fileSize; + track_ = track; + first_._filesize_dontuse = aa3 ? fileSize : track_.fileSize; track_.DebugLog(); - return retval; + return 0; } int AnalyzeAtracTrack(u32 addr, u32 size, Track *track) { @@ -537,16 +538,6 @@ int AnalyzeAA3Track(u32 addr, u32 size, u32 fileSize, Track *track) { return 0; } -int Atrac::AnalyzeAA3(u32 addr, u32 size, u32 fileSize) { - first_.addr = addr; - first_.size = size; - first_._filesize_dontuse = fileSize; - - AnalyzeReset(); - - return AnalyzeAA3Track(addr, size, fileSize, &track_); -} - int Atrac::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const { *endSample = track_.endSample; *loopStartSample = track_.loopStartSample == -1 ? -1 : track_.loopStartSample - track_.FirstSampleOffsetFull(); @@ -756,6 +747,11 @@ int Atrac::SetData(u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) } CreateDecoder(); INFO_LOG(Log::ME, "Atrac::SetData (buffer=%08x, readSize=%d, bufferSize=%d): %s %s (%d channels) audio", buffer, readSize, bufferSize, codecName, channelName, track_.channels); + + if (track_.channels == 2 && outputChannels == 1) { + // We still do all the tasks, we just return this error. + return SCE_ERROR_ATRAC_NOT_MONO; + } return 0; } diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index e32ee428e0..652a2ffa7c 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -194,8 +194,8 @@ public: outputChannels_ = channels; } - // Refactor? - int atracID_ = -1; + virtual void SetID(int id) = 0; + virtual int GetID() const = 0; PSPPointer context_{}; @@ -223,8 +223,8 @@ public: virtual int BytesPerFrame() const = 0; virtual int SamplesPerFrame() const = 0; - virtual int Analyze(u32 addr, u32 size) = 0; - virtual int AnalyzeAA3(u32 addr, u32 size, u32 filesize) = 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; @@ -275,11 +275,18 @@ public: void DoState(PointerWrap &p) override; void WriteContextToPSPMem() override; - int Analyze(u32 addr, u32 size) override; - int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override; + int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) override; int GetNextDecodePosition(int *pos) const override; int RemainingFrames() const override; + + void SetID(int id) override { + atracID_ = id; + } + int GetID() const override { + return atracID_; + } + u32 SecondBufferSize() const override { return second_.size; } @@ -361,4 +368,7 @@ private: u32 bufferPos_ = 0; u32 bufferValidBytes_ = 0; u32 bufferHeaderSize_ = 0; + + // Refactor? + int atracID_ = -1; }; diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index acb3f23b4e..24e1223ed5 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -44,50 +44,10 @@ void Atrac2::DoState(PointerWrap &p) { } void Atrac2::WriteContextToPSPMem() { - if (!context_.IsValid()) { - return; - } - // context points into PSP memory. - SceAtracContext *context = context_; - context->info.buffer = 0; // bufferAddr_; // first_.addr; - context->info.bufferByte = 0; // bufferMaxSize_; - context->info.secondBuffer = 0; // TODO - context->info.secondBufferByte = 0; // TODO - context->info.codec = track_.codecType; - context->info.loopNum = loopNum_; - context->info.loopStart = track_.loopStartSample > 0 ? track_.loopStartSample : 0; - context->info.loopEnd = track_.loopEndSample > 0 ? track_.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 = bufferState_; - if (track_.firstSampleOffset != 0) { - context->info.samplesPerChan = track_.FirstSampleOffsetFull(); - } else { - context->info.samplesPerChan = (track_.codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); - } - context->info.sampleSize = track_.bytesPerFrame; - context->info.numChan = track_.channels; - context->info.dataOff = track_.dataByteOffset; - context->info.endSample = track_.endSample + track_.FirstSampleOffsetFull(); - context->info.dataEnd = track_.fileSize; - context->info.curOff = 0; // first_.fileoffset; - context->info.decodePos = track_.DecodePosBySample(currentSample_); - context->info.streamDataByte = 0; // first_.size - track_.dataOff; - - u8 *buf = (u8 *)context; - *(u32_le *)(buf + 0xfc) = atracID_; - - NotifyMemInfo(MemBlockFlags::WRITE, context_.ptr, sizeof(SceAtracContext), "AtracContext"); } -int Atrac2::Analyze(u32 addr, u32 size) { - return AnalyzeAtracTrack(addr, size, &track_); -} - -int Atrac2::AnalyzeAA3(u32 addr, u32 size, u32 filesize) { - return AnalyzeAA3Track(addr, size, filesize, &track_); +int Atrac2::Analyze(const Track &track, u32 addr, u32 size, u32 filesize) { + return 0; } int Atrac2::RemainingFrames() const { diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index adc408b54b..41b2ec85f5 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -11,8 +11,10 @@ public: void DoState(PointerWrap &p) override; void WriteContextToPSPMem() override; - int Analyze(u32 addr, u32 size) override; - int AnalyzeAA3(u32 addr, u32 size, u32 filesize) override; + int Analyze(const Track &track, u32 addr, u32 size, u32 filesize) override; + + void SetID(int id) override {} + int GetID() const override { return 0; } int GetNextDecodePosition(int *pos) const { return 0; } int RemainingFrames() const override; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 18570c00c1..644a068be0 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -180,11 +180,11 @@ static AtracBase *getAtrac(int atracID) { return atrac; } -static int createAtrac(AtracBase *atrac) { +static int RegisterAtrac(AtracBase *atrac) { for (int i = 0; i < (int)ARRAY_SIZE(atracContexts); ++i) { if (atracContextTypes[i] == atrac->CodecType() && atracContexts[i] == 0) { atracContexts[i] = atrac; - atrac->atracID_ = i; + atrac->SetID(i); return i; } } @@ -210,7 +210,7 @@ static u32 sceAtracGetAtracID(int codecType) { } AtracBase *atrac = allocAtrac(codecType); - int atracID = createAtrac(atrac); + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); @@ -571,12 +571,22 @@ static u32 sceAtracSetHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u32 b return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large"); } - int ret = atrac->Analyze(buffer, readSize); + Track track; + int ret = AnalyzeAtracTrack(buffer, readSize, &track); if (ret < 0) { return hleLogError(Log::ME, ret); } + if (track.codecType != atracContextTypes[atracID]) { + // TODO: Should this not change the buffer size? + return hleLogError(Log::ME, SCE_ERROR_ATRAC_WRONG_CODECTYPE, "atracID uses different codec type than data"); + } + ret = atrac->Analyze(track, buffer, readSize, 0); + if (ret < 0) { + 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); } @@ -596,16 +606,20 @@ static u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize) { return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_ATRACID, "bad atrac ID"); } - int ret = atrac->Analyze(buffer, bufferSize); + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); if (ret < 0) { return hleLogError(Log::ME, ret); } - - if (atrac->CodecType() != atracContextTypes[atracID]) { + if (track.codecType != atracContextTypes[atracID]) { // TODO: Should this not change the buffer size? return hleReportError(Log::ME, SCE_ERROR_ATRAC_WRONG_CODECTYPE, "atracID uses different codec type than data"); } + ret = atrac->Analyze(track, buffer, bufferSize, 0); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data", 100); } @@ -618,39 +632,63 @@ static int sceAtracSetDataAndGetID(u32 buffer, int bufferSize) { bufferSize = 0x10000000; } + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + AtracBase *atrac = allocAtrac(); - int ret = atrac->Analyze(buffer, bufferSize); + ret = atrac->Analyze(track, buffer, bufferSize, 0); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); } - int atracID = createAtrac(atrac); + ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); + if (ret < 0) { + delete atrac; + return hleLogError(Log::ME, ret); + } + + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100); + return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); } static int sceAtracSetHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 bufferSize) { if (readSize > bufferSize) { return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large"); } + + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + AtracBase *atrac = allocAtrac(); - int ret = atrac->Analyze(buffer, readSize); + ret = atrac->Analyze(track, buffer, readSize, 0); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); } - int atracID = createAtrac(atrac); + ret = atrac->SetData(buffer, readSize, bufferSize, 2); + if (ret < 0) { + delete atrac; + return hleLogError(Log::ME, ret); + } + + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } - ret = atrac->SetData(buffer, readSize, bufferSize, 2); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100); + + return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); } static u32 sceAtracStartEntry() { @@ -664,7 +702,6 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { if (err != 0) { return hleLogError(Log::ME, err); } - int ret = atrac->SetLoopNum(loopNum); if (ret == SCE_ERROR_ATRAC_NO_LOOP_INFORMATION && loopNum == -1) { // Not really an issue @@ -752,21 +789,23 @@ static int sceAtracSetMOutHalfwayBuffer(int atracID, u32 buffer, u32 readSize, u return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large"); } - int ret = atrac->Analyze(buffer, readSize); + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); if (ret < 0) { return hleLogError(Log::ME, ret); } - if (atrac->Channels() != 1) { - // It seems it still sets the data. - atrac->SetData(buffer, readSize, bufferSize, 2); - return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); - } else { - ret = atrac->SetData(buffer, readSize, bufferSize, 1); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); + + ret = atrac->Analyze(track, buffer, readSize, 0); + if (ret < 0) { + return hleLogError(Log::ME, ret); } + ret = atrac->SetData(buffer, readSize, bufferSize, 1); + return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); } // Note: This doesn't seem to be part of any available libatrac3plus library. +// So we should probably remove it? +// HalfwayBuffer can fully replace it though, of course (just set readSize == bufferSize). static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) { AtracBase *atrac = getAtrac(atracID); // Don't use AtracValidate* here. @@ -774,81 +813,113 @@ static u32 sceAtracSetMOutData(int atracID, u32 buffer, u32 bufferSize) { return hleLogError(Log::ME, SCE_ERROR_ATRAC_BAD_ATRACID, "bad atrac ID"); } - int ret = atrac->Analyze(buffer, bufferSize); + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); if (ret < 0) { return hleLogError(Log::ME, ret); } - if (atrac->Channels() != 1) { - // It seems it still sets the data. - atrac->SetData(buffer, bufferSize, bufferSize, 2); - return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); - } else { - ret = atrac->SetData(buffer, bufferSize, bufferSize, 1); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); + + ret = atrac->Analyze(track, buffer, bufferSize, 0); + if (ret < 0) { + return hleLogError(Log::ME, ret); } + ret = atrac->SetData(buffer, bufferSize, bufferSize, 1); + return hleDelayResult(hleLogDebugOrError(Log::ME, ret), "atrac set data mono", 100); } // Note: This doesn't seem to be part of any available libatrac3plus library. +// See note in above function. static int sceAtracSetMOutDataAndGetID(u32 buffer, u32 bufferSize) { + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + if (track.channels != 1) { + return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); + } + AtracBase *atrac = allocAtrac(); - int ret = atrac->Analyze(buffer, bufferSize); + ret = atrac->Analyze(track, buffer, bufferSize, 0); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); } - if (atrac->Channels() != 1) { + ret = atrac->SetData(buffer, bufferSize, bufferSize, 1); + if (ret < 0) { delete atrac; - return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); + return hleLogError(Log::ME, ret); } - int atracID = createAtrac(atrac); + + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } - - ret = atrac->SetData(buffer, bufferSize, bufferSize, 1); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100); + return hleDelayResult(hleLogDebugOrError(Log::ME, atracID), "atrac set data", 100); } static int sceAtracSetMOutHalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 bufferSize) { if (readSize > bufferSize) { return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large"); } + + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + if (track.channels != 1) { + return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); + } + AtracBase *atrac = allocAtrac(); - int ret = atrac->Analyze(buffer, readSize); + ret = atrac->Analyze(track, buffer, readSize, 0); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); } - if (atrac->Channels() != 1) { + ret = atrac->SetData(buffer, readSize, bufferSize, 1); + if (ret < 0) { delete atrac; - return hleReportError(Log::ME, SCE_ERROR_ATRAC_NOT_MONO, "not mono data"); + return hleLogError(Log::ME, ret); } - int atracID = createAtrac(atrac); + + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } - ret = atrac->SetData(buffer, readSize, bufferSize, 1); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100); + return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); } static int sceAtracSetAA3DataAndGetID(u32 buffer, u32 bufferSize, u32 fileSize, u32 metadataSizeAddr) { + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + AtracBase *atrac = allocAtrac(); - int ret = atrac->AnalyzeAA3(buffer, bufferSize, fileSize); + ret = atrac->Analyze(track, buffer, bufferSize, fileSize); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); } - int atracID = createAtrac(atrac); + ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); + if (ret < 0) { + delete atrac; + return hleLogError(Log::ME, ret); + } + + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } - ret = atrac->SetData(buffer, bufferSize, bufferSize, 2); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100); + return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set aa3 data", 100); } static u32 _sceAtracGetContextAddress(int atracID) { @@ -957,20 +1028,30 @@ static int sceAtracSetAA3HalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buf return hleLogError(Log::ME, SCE_ERROR_ATRAC_INCORRECT_READ_SIZE, "read size too large"); } + Track track; + int ret = AnalyzeAtracTrack(buffer, bufferSize, &track); + if (ret < 0) { + return hleLogError(Log::ME, ret); + } + AtracBase *atrac = allocAtrac(); - int ret = atrac->AnalyzeAA3(buffer, readSize, fileSize); + ret = atrac->Analyze(track, buffer, readSize, fileSize); if (ret < 0) { delete atrac; return hleLogError(Log::ME, ret); } - int atracID = createAtrac(atrac); + ret = atrac->SetData(buffer, readSize, bufferSize, 2); + if (ret < 0) { + delete atrac; + return hleLogError(Log::ME, ret); + } + + int atracID = RegisterAtrac(atrac); if (atracID < 0) { delete atrac; return hleLogError(Log::ME, atracID, "no free ID"); } - - ret = atrac->SetData(buffer, readSize, bufferSize, 2); - return hleDelayResult(hleLogDebugOrError(Log::ME, ret == 0 ? atracID : ret), "atrac set data", 100); + return hleDelayResult(hleLogDebug(Log::ME, atracID), "atrac set data", 100); } // External interface used by sceSas' AT3 integration.