Merge pull request #20118 from hrydgard/even-more-refactor

Atrac: Prepare for the new way of context management
This commit is contained in:
Henrik Rydgård 2025-03-16 20:01:24 +01:00 committed by GitHub
commit 8caec3c34d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 162 additions and 194 deletions

View file

@ -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

View file

@ -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)
@ -167,29 +171,17 @@ 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_;
}
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;
@ -241,37 +233,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 +653,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 +1178,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 +1189,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;
@ -1230,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();
}

View file

@ -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();
};
@ -184,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 {
@ -194,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<SceAtracContext> context_{};
@ -216,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;
@ -223,25 +219,19 @@ 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;
virtual void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) = 0;
virtual int AddStreamData(u32 bytesToAdd) = 0;
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;
@ -257,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);
@ -273,15 +266,12 @@ public:
u8 *BufferStart();
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;
void SetID(int id) override {
atracID_ = id;
void SetIDAndAddr(int atracID, u32 contextAddr) override {
atracID_ = atracID;
}
int GetID() const override {
return atracID_;
@ -326,18 +316,19 @@ 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();
void NotifyGetContextAddress() override;
void UpdateContextFromPSPMem() override;
void WriteContextToPSPMem();
private:
void UpdateBufferState();

View file

@ -39,17 +39,15 @@ Atrac2::Atrac2(int codecType) {
track_.codecType = codecType;
}
void Atrac2::SetIDAndAddr(int atracID, u32 contextAddr) {
// Note: We don't allocate a context, we use memory directly from the loaded atrac binary (even if it's otherwise unused).
context_ = PSPPointer<SceAtracContext>::Create(contextAddr);
}
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::WriteContextToPSPMem() {
}
int Atrac2::Analyze(const Track &track, u32 addr, u32 size, u32 filesize) {
return 0;
}
int Atrac2::RemainingFrames() const {
return 0;
}
@ -83,7 +81,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 +103,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) {

View file

@ -9,11 +9,8 @@ class Atrac2 : public AtracBase {
public:
Atrac2(int codecType);
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 {}
void SetIDAndAddr(int atracID, u32 contextAddr) override;
int GetID() const override { return 0; }
int GetNextDecodePosition(int *pos) const { return 0; }
@ -31,17 +28,21 @@ 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;
// These will not be used by the new implementation.
void UpdateContextFromPSPMem() override {}
void NotifyGetContextAddress() override {}
private:
int currentSample_ = 0;
};

View file

@ -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;
@ -581,14 +597,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 +632,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 +656,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 +683,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);
@ -711,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");
}
@ -719,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) {
@ -795,11 +802,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 +822,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 +843,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 +872,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 +895,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);
@ -928,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);
}
@ -975,6 +952,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 +970,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 +1014,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);

View file

@ -89,7 +89,7 @@ struct SceAtracContext {
SceAtracIdInfo info;
};
const int PSP_NUM_ATRAC_IDS = 6;
const int PSP_MAX_ATRAC_IDS = 6;
class AtracBase;

View file

@ -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.