diff --git a/rpcs3/Emu/Cell/Modules/cellAdec.cpp b/rpcs3/Emu/Cell/Modules/cellAdec.cpp index a026105698..031337a5b2 100644 --- a/rpcs3/Emu/Cell/Modules/cellAdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAdec.cpp @@ -910,7 +910,7 @@ error_code cellAdecDecodeAu(u32 handle, vm::ptr auInfo) AdecTask task(adecDecodeAu); task.au.auInfo_addr = auInfo.addr(); - task.au.addr = auInfo->startAddr; + task.au.addr = auInfo->startAddr.addr(); task.au.size = auInfo->size; task.au.pts = (u64{auInfo->pts.upper} << 32) | u64{auInfo->pts.lower}; task.au.userdata = auInfo->userData; @@ -1072,7 +1072,7 @@ error_code cellAdecGetPcmItem(u32 handle, vm::pptr pcmItem) pcm->auInfo.pts.lower = static_cast(af.pts); pcm->auInfo.pts.upper = static_cast(af.pts >> 32); pcm->auInfo.size = af.auSize; - pcm->auInfo.startAddr = af.auAddr; + pcm->auInfo.startAddr.set(af.auAddr); pcm->auInfo.userData = af.userdata; if (adecIsAtracX(adec->type)) diff --git a/rpcs3/Emu/Cell/Modules/cellAdec.h b/rpcs3/Emu/Cell/Modules/cellAdec.h index 6167635188..c11a432106 100644 --- a/rpcs3/Emu/Cell/Modules/cellAdec.h +++ b/rpcs3/Emu/Cell/Modules/cellAdec.h @@ -250,38 +250,38 @@ enum CellAdecError : u32 // Audio Codec Type enum AudioCodecType : s32 { - CELL_ADEC_TYPE_RESERVED1, + CELL_ADEC_TYPE_INVALID1, CELL_ADEC_TYPE_LPCM_PAMF, CELL_ADEC_TYPE_AC3, CELL_ADEC_TYPE_ATRACX, CELL_ADEC_TYPE_MP3, CELL_ADEC_TYPE_ATRAC3, CELL_ADEC_TYPE_MPEG_L2, - CELL_ADEC_TYPE_RESERVED5, - CELL_ADEC_TYPE_RESERVED6, - CELL_ADEC_TYPE_RESERVED7, - CELL_ADEC_TYPE_RESERVED8, + CELL_ADEC_TYPE_M2AAC, + CELL_ADEC_TYPE_EAC3, + CELL_ADEC_TYPE_TRUEHD, + CELL_ADEC_TYPE_DTS, // Removed in firmware 4.00, integrated into DTSHD CELL_ADEC_TYPE_CELP, - CELL_ADEC_TYPE_RESERVED10, + CELL_ADEC_TYPE_LPCM_BLURAY, CELL_ADEC_TYPE_ATRACX_2CH, CELL_ADEC_TYPE_ATRACX_6CH, CELL_ADEC_TYPE_ATRACX_8CH, CELL_ADEC_TYPE_M4AAC, - CELL_ADEC_TYPE_RESERVED12, - CELL_ADEC_TYPE_RESERVED13, - CELL_ADEC_TYPE_RESERVED14, - CELL_ADEC_TYPE_RESERVED15, - CELL_ADEC_TYPE_RESERVED16, - CELL_ADEC_TYPE_RESERVED17, - CELL_ADEC_TYPE_RESERVED18, - CELL_ADEC_TYPE_RESERVED19, + CELL_ADEC_TYPE_LPCM_DVD, + CELL_ADEC_TYPE_WMA, + CELL_ADEC_TYPE_DTSLBR, + CELL_ADEC_TYPE_M4AAC_2CH, + CELL_ADEC_TYPE_DTSHD, + CELL_ADEC_TYPE_MPEG_L1, + CELL_ADEC_TYPE_MP3S, + CELL_ADEC_TYPE_M4AAC_2CH_MOD, CELL_ADEC_TYPE_CELP8, - CELL_ADEC_TYPE_RESERVED20, - CELL_ADEC_TYPE_RESERVED21, - CELL_ADEC_TYPE_RESERVED22, - CELL_ADEC_TYPE_RESERVED23, - CELL_ADEC_TYPE_RESERVED24, - CELL_ADEC_TYPE_RESERVED25, + CELL_ADEC_TYPE_INVALID2, + CELL_ADEC_TYPE_INVALID3, + CELL_ADEC_TYPE_RESERVED22, // Either WMA Pro or WMA Lossless, was never released + CELL_ADEC_TYPE_RESERVED23, // Either WMA Pro or WMA Lossless, was never released + CELL_ADEC_TYPE_DTSHDCORE, // Removed in firmware 4.00, integrated into DTSHD + CELL_ADEC_TYPE_ATRAC3MULTI, }; inline bool adecIsAtracX(s32 type) @@ -313,10 +313,12 @@ enum CellAdecChannel : s32 // Sampling Rate enum CellAdecSampleRate : s32 { - CELL_ADEC_FS_RESERVED1 = 0, - CELL_ADEC_FS_48kHz = 1, - CELL_ADEC_FS_16kHz = 2, - CELL_ADEC_FS_8kHz = 5, + CELL_ADEC_FS_RESERVED1, + CELL_ADEC_FS_48kHz, + CELL_ADEC_FS_16kHz, + CELL_ADEC_FS_96kHz, + CELL_ADEC_FS_192kHz, + CELL_ADEC_FS_8kHz, }; enum CellAdecBitLength : s32 @@ -359,6 +361,13 @@ struct CellAdecResourceEx be_t maxContention; }; +struct CellAdecResourceSpurs +{ + be_t spurs_addr; // CellSpurs* + u8 priority[8]; + be_t maxContention; +}; + // Callback Messages enum CellAdecMsgType : s32 { @@ -370,16 +379,20 @@ enum CellAdecMsgType : s32 using CellAdecCbMsg = s32(u32 handle, CellAdecMsgType msgType, s32 msgData, u32 cbArg); -struct CellAdecCb +// Used for internal callbacks as well +template +struct AdecCb { - vm::bptr cbFunc; - be_t cbArg; + vm::bptr cbFunc; + vm::bptr cbArg; }; +typedef AdecCb CellAdecCb; + // AU Info struct CellAdecAuInfo { - be_t startAddr; + vm::bcptr startAddr; be_t size; CellCodecTimeStamp pts; be_t userData; @@ -401,6 +414,125 @@ struct CellAdecPcmItem CellAdecAuInfo auInfo; }; +// Controls how much is added to the presentation time stamp of the previous frame if the game didn't set a pts itself in CellAdecAuInfo when calling cellAdecDecodeAu() +enum AdecCorrectPtsValueType : s8 +{ + ADEC_CORRECT_PTS_VALUE_TYPE_UNSPECIFIED = -1, + + // Adds a fixed amount + ADEC_CORRECT_PTS_VALUE_TYPE_LPCM = 0, + // 1 + ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_48000Hz = 2, + ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_44100Hz = 3, + ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_32000Hz = 4, + // 5: Dolby Digital + // 6: ATRAC3 + // 7: MP3 + // 8: MP3 + // 9: MP3 + // 39: ATRAC3 multi-track + + // Calls a decoder function (_SceAdecCorrectPtsValue_codec()) + // 17: Dolby Digital Plus + // 18 + // 19 + // 20 + // 21: DTS HD + // 22 + // 23 + // 24: CELP + // 25: MPEG-2 AAC + // 26: MPEG-2 BC + // 27: Dolby TrueHD + // 28: DTS + // 29: MPEG-4 AAC + // 30: Windows Media Audio + // 31: DTS Express + // 32: MP1 + // 33: MP3 Surround + // 34: CELP8 + // 35: Windows Media Audio Professional + // 36: Windows Media Audio Lossless + // 37: DTS HD Core + // 38: DTS HD Core +}; + +// Internal callbacks +using AdecNotifyAuDone = error_code(s32 pcmHandle, vm::ptr cbArg); +using AdecNotifyPcmOut = error_code(s32 pcmHandle, vm::ptr pcmAddr, u32 pcmSize, vm::ptr cbArg, vm::cpptr bsiInfo, AdecCorrectPtsValueType correctPtsValueType, s32 errorCode); +using AdecNotifyError = error_code(s32 errorCode, vm::ptr cbArg); +using AdecNotifySeqDone = error_code(vm::ptr cbArg); + +// Decoder functions +using CellAdecCoreOpGetMemSize = error_code(vm::ptr attr); +using CellAdecCoreOpOpen = error_code(vm::ptr coreHandle, vm::ptr cbFuncAuDone, vm::ptr cbArgAuDone, vm::ptr cbFuncPcmOut, vm::ptr cbArgPcmOut, + vm::ptr cbFuncError, vm::ptr cbArgError, vm::ptr cbFuncSeqDone, vm::ptr cbArgSeqDone, vm::cptr res); +using CellAdecCoreOpClose = error_code(vm::ptr coreHandle); +using CellAdecCoreOpStartSeq = error_code(vm::ptr coreHandle, vm::cptr param); +using CellAdecCoreOpEndSeq = error_code(vm::ptr coreHandle); +using CellAdecCoreOpDecodeAu = error_code(vm::ptr coreHandle, s32 pcmHandle, vm::cptr auInfo); +using CellAdecCoreOpGetVersion = void(vm::ptr> version); +using CellAdecCoreOpRealign = error_code(vm::ptr coreHandle, vm::ptr outBuffer, vm::cptr pcmStartAddr); +using CellAdecCoreOpReleasePcm = error_code(vm::ptr coreHandle, s32 pcmHandle, vm::cptr outBuffer); +using CellAdecCoreOpGetPcmHandleNum = s32(); +using CellAdecCoreOpGetBsiInfoSize = u32(); +using CellAdecCoreOpOpenExt = error_code(vm::ptr coreHandle, vm::ptr cbFuncAuDone, vm::ptr cbArgAuDone, vm::ptr cbFuncPcmOut, vm::ptr cbArgPcmOut, + vm::ptr cbFuncError, vm::ptr cbArgError, vm::ptr cbFuncSeqDone, vm::ptr cbArgSeqDone, vm::cptr res, vm::cptr spursRes); + +// Decoders export a pointer to this struct +struct CellAdecCoreOps +{ + vm::bptr getMemSize; + vm::bptr open; + vm::bptr close; + vm::bptr startSeq; + vm::bptr endSeq; + vm::bptr decodeAu; + vm::bptr getVersion; + vm::bptr realign; + vm::bptr releasePcm; + vm::bptr getPcmHandleNum; + vm::bptr getBsiInfoSize; + vm::bptr openExt; +}; + +// Used by several decoders as command queue +template +struct AdecCmdQueue +{ + T elements[4]; + + be_t front = 0; + be_t back = 0; + be_t size = 0; + + template + void pop(T& cmd) + { + // LLE returns uninitialized stack memory if the queue is empty + cmd = elements[front]; + + if constexpr (!is_peek) + { + elements[front].pcm_handle = 0xff; + front = (front + 1) & 3; + size--; + } + } + + void emplace(auto&&... args) + { + new (&elements[back]) T(std::forward(args)...); + + back = (back + 1) & 3; + size++; + } + + void peek(T& cmd) const { return pop(cmd); } + bool empty() const { return size == 0; } + bool full() const { return size >= 4; } +}; + struct CellAdecParamLpcm { be_t channelNumber;