cellDmuxPamf implementation part 2: PPU thread

This commit is contained in:
capriots 2025-07-10 19:39:49 +02:00 committed by Elad
parent 5559243b48
commit 6a6425d2ee
5 changed files with 2040 additions and 209 deletions

View file

@ -169,18 +169,18 @@ public:
static const u32 id_count = 1023; static const u32 id_count = 1023;
SAVESTATE_INIT_POS(34); SAVESTATE_INIT_POS(34);
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec); ElementaryStream(Demuxer* dmux, vm::ptr<void> addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, vm::ptr<void> cbArg, u32 spec);
Demuxer* dmux; Demuxer* dmux;
const u32 id = idm::last_id(); const u32 id = idm::last_id();
const u32 memAddr; const vm::ptr<void> memAddr;
const u32 memSize; const u32 memSize;
const u32 fidMajor; const u32 fidMajor;
const u32 fidMinor; const u32 fidMinor;
const u32 sup1; const u32 sup1;
const u32 sup2; const u32 sup2;
const vm::ptr<CellDmuxCbEsMsg> cbFunc; const vm::ptr<CellDmuxCbEsMsg> cbFunc;
const u32 cbArg; const vm::ptr<void> cbArg;
const u32 spec; //addr const u32 spec; //addr
std::vector<u8> raw_data; // demultiplexed data stream (managed by demuxer thread) std::vector<u8> raw_data; // demultiplexed data stream (managed by demuxer thread)
@ -208,13 +208,13 @@ public:
const u32 memAddr; const u32 memAddr;
const u32 memSize; const u32 memSize;
const vm::ptr<CellDmuxCbMsg> cbFunc; const vm::ptr<CellDmuxCbMsg> cbFunc;
const u32 cbArg; const vm::ptr<void> cbArg;
volatile bool is_finished = false; volatile bool is_finished = false;
volatile bool is_closed = false; volatile bool is_closed = false;
atomic_t<bool> is_running = false; atomic_t<bool> is_running = false;
atomic_t<bool> is_working = false; atomic_t<bool> is_working = false;
Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, u32 arg) Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, vm::ptr<void> arg)
: ppu_thread({}, "", 0) : ppu_thread({}, "", 0)
, memAddr(addr) , memAddr(addr)
, memSize(size) , memSize(size)
@ -755,11 +755,11 @@ PesHeader::PesHeader(DemuxerStream& stream)
is_ok = true; is_ok = true;
} }
ElementaryStream::ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec) ElementaryStream::ElementaryStream(Demuxer* dmux, vm::ptr<void> addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, vm::ptr<void> cbArg, u32 spec)
: put(utils::align(addr, 128)) : put(utils::align(addr.addr(), 128))
, dmux(dmux) , dmux(dmux)
, memAddr(utils::align(addr, 128)) , memAddr(vm::ptr<void>::make(utils::align(addr.addr(), 128)))
, memSize(size - (addr - memAddr)) , memSize(size - (addr.addr() - memAddr.addr()))
, fidMajor(fidMajor) , fidMajor(fidMajor)
, fidMinor(fidMinor) , fidMinor(fidMinor)
, sup1(sup1) , sup1(sup1)
@ -788,9 +788,9 @@ bool ElementaryStream::is_full(u32 space)
{ {
return first - put < space + 128; return first - put < space + 128;
} }
else if (put + space + 128 > memAddr + memSize) else if (put + space + 128 > memAddr.addr() + memSize)
{ {
return first - memAddr < space + 128; return first - memAddr.addr() < space + 128;
} }
else else
{ {
@ -816,35 +816,35 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
ensure(!is_full(size)); ensure(!is_full(size));
if (put + size + 128 > memAddr + memSize) if (put + size + 128 > memAddr.addr() + memSize)
{ {
put = memAddr; put = memAddr.addr();
} }
std::memcpy(vm::base(put + 128), raw_data.data(), size); std::memcpy(vm::base(put + 128), raw_data.data(), size);
raw_data.erase(raw_data.begin(), raw_data.begin() + size); raw_data.erase(raw_data.begin(), raw_data.begin() + size);
auto info = vm::ptr<CellDmuxAuInfoEx>::make(put); auto info = vm::ptr<CellDmuxAuInfoEx>::make(put);
info->auAddr = put + 128; info->auAddr.set(put + 128);
info->auSize = size; info->auSize = size;
info->dts.lower = static_cast<u32>(dts); info->dts.lower = static_cast<u32>(dts);
info->dts.upper = static_cast<u32>(dts >> 32); info->dts.upper = static_cast<u32>(dts >> 32);
info->pts.lower = static_cast<u32>(pts); info->pts.lower = static_cast<u32>(pts);
info->pts.upper = static_cast<u32>(pts >> 32); info->pts.upper = static_cast<u32>(pts >> 32);
info->isRap = rap; info->isRap = rap;
info->reserved = 0; info->auMaxSize = 0;
info->userData = userdata; info->userData = userdata;
auto spec = vm::ptr<u32>::make(put + u32{sizeof(CellDmuxAuInfoEx)}); auto spec = vm::ptr<u32>::make(put + u32{sizeof(CellDmuxAuInfoEx)});
*spec = specific; *spec = specific;
auto inf = vm::ptr<CellDmuxAuInfo>::make(put + 64); auto inf = vm::ptr<CellDmuxAuInfo>::make(put + 64);
inf->auAddr = put + 128; inf->auAddr.set(put + 128);
inf->auSize = size; inf->auSize = size;
inf->dtsLower = static_cast<u32>(dts); inf->dts.lower = static_cast<u32>(dts);
inf->dtsUpper = static_cast<u32>(dts >> 32); inf->dts.upper = static_cast<u32>(dts >> 32);
inf->ptsLower = static_cast<u32>(pts); inf->pts.lower = static_cast<u32>(pts);
inf->ptsUpper = static_cast<u32>(pts >> 32); inf->pts.upper = static_cast<u32>(pts >> 32);
inf->auMaxSize = 0; // ????? inf->auMaxSize = 0; // ?????
inf->userData = userdata; inf->userData = userdata;
@ -927,7 +927,7 @@ bool ElementaryStream::peek(u32& out_data, bool no_ex, u32& out_spec, bool updat
void ElementaryStream::reset() void ElementaryStream::reset()
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
put = memAddr; put = memAddr.addr();
entries.clear(); entries.clear();
put_count = 0; put_count = 0;
got_count = 0; got_count = 0;

View file

@ -33,118 +33,6 @@ enum CellDmuxEsMsgType : s32
CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE = 1, CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE = 1,
}; };
enum CellDmuxPamfM2vLevel : s32
{
CELL_DMUX_PAMF_M2V_MP_LL = 0,
CELL_DMUX_PAMF_M2V_MP_ML,
CELL_DMUX_PAMF_M2V_MP_H14,
CELL_DMUX_PAMF_M2V_MP_HL,
};
enum CellDmuxPamfAvcLevel : s32
{
CELL_DMUX_PAMF_AVC_LEVEL_2P1 = 21,
CELL_DMUX_PAMF_AVC_LEVEL_3P0 = 30,
CELL_DMUX_PAMF_AVC_LEVEL_3P1 = 31,
CELL_DMUX_PAMF_AVC_LEVEL_3P2 = 32,
CELL_DMUX_PAMF_AVC_LEVEL_4P1 = 41,
CELL_DMUX_PAMF_AVC_LEVEL_4P2 = 42,
};
struct CellDmuxPamfAuSpecificInfoM2v
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAvc
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoLpcm
{
u8 channelAssignmentInfo;
u8 samplingFreqInfo;
u8 bitsPerSample;
};
struct CellDmuxPamfAuSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoUserData
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoM2v
{
be_t<u32> profileLevel;
};
struct CellDmuxPamfEsSpecificInfoAvc
{
be_t<u32> level;
};
struct CellDmuxPamfEsSpecificInfoLpcm
{
be_t<u32> samplingFreq;
be_t<u32> numOfChannels;
be_t<u32> bitsPerSample;
};
struct CellDmuxPamfEsSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoUserData
{
be_t<u32> reserved1;
};
enum CellDmuxPamfSamplingFrequency : s32
{
CELL_DMUX_PAMF_FS_48K = 48000,
};
enum CellDmuxPamfBitsPerSample : s32
{
CELL_DMUX_PAMF_BITS_PER_SAMPLE_16 = 16,
CELL_DMUX_PAMF_BITS_PER_SAMPLE_24 = 24,
};
enum CellDmuxPamfLpcmChannelAssignmentInfo : s32
{
CELL_DMUX_PAMF_LPCM_CH_M1 = 1,
CELL_DMUX_PAMF_LPCM_CH_LR = 3,
CELL_DMUX_PAMF_LPCM_CH_LRCLSRSLFE = 9,
CELL_DMUX_PAMF_LPCM_CH_LRCLSCS1CS2RSLFE = 11,
};
enum CellDmuxPamfLpcmFs : s32
{
CELL_DMUX_PAMF_LPCM_FS_48K = 1,
};
enum CellDmuxPamfLpcmBitsPerSamples : s32
{
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_16 = 1,
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_24 = 3,
};
struct CellDmuxMsg struct CellDmuxMsg
{ {
be_t<s32> msgType; // CellDmuxMsgType be_t<s32> msgType; // CellDmuxMsgType
@ -163,12 +51,6 @@ struct CellDmuxType
be_t<u32> reserved[2]; be_t<u32> reserved[2];
}; };
struct CellDmuxPamfSpecificInfo
{
be_t<u32> thisSize;
b8 programEndCodeCb;
};
struct CellDmuxType2 struct CellDmuxType2
{ {
be_t<s32> streamType; // CellDmuxStreamType be_t<s32> streamType; // CellDmuxStreamType
@ -177,7 +59,7 @@ struct CellDmuxType2
struct CellDmuxResource struct CellDmuxResource
{ {
be_t<u32> memAddr; vm::bptr<void> memAddr;
be_t<u32> memSize; be_t<u32> memSize;
be_t<u32> ppuThreadPriority; be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize; be_t<u32> ppuThreadStackSize;
@ -187,7 +69,7 @@ struct CellDmuxResource
struct CellDmuxResourceEx struct CellDmuxResourceEx
{ {
be_t<u32> memAddr; vm::bptr<void> memAddr;
be_t<u32> memSize; be_t<u32> memSize;
be_t<u32> ppuThreadPriority; be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize; be_t<u32> ppuThreadStackSize;
@ -227,16 +109,16 @@ struct CellDmuxResource2
be_t<u32> shit[4]; be_t<u32> shit[4];
}; };
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::ptr<CellDmuxMsg> demuxerMsg, u32 cbArg); using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::ptr<CellDmuxEsMsg> esMsg, u32 cbArg); using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
// Used for internal callbacks as well // Used for internal callbacks as well
template <typename F> template <typename F>
struct DmuxCb struct DmuxCb
{ {
vm::bptr<F> cbFunc; vm::bptr<F> cbFunc;
be_t<u32> cbArg; vm::bptr<void> cbArg;
}; };
using CellDmuxCb = DmuxCb<CellDmuxCbMsg>; using CellDmuxCb = DmuxCb<CellDmuxCbMsg>;
@ -250,42 +132,50 @@ struct CellDmuxAttr
be_t<u32> demuxerVerLower; be_t<u32> demuxerVerLower;
}; };
struct CellDmuxPamfAttr
{
be_t<u32> maxEnabledEsNum;
be_t<u32> version;
be_t<u32> memSize;
};
struct CellDmuxEsAttr struct CellDmuxEsAttr
{ {
be_t<u32> memSize; be_t<u32> memSize;
}; };
struct CellDmuxPamfEsAttr
{
be_t<u32> auQueueMaxSize;
be_t<u32> memSize;
be_t<u32> specificInfoSize;
};
struct CellDmuxEsResource struct CellDmuxEsResource
{ {
be_t<u32> memAddr; vm::bptr<void> memAddr;
be_t<u32> memSize; be_t<u32> memSize;
}; };
struct CellDmuxAuInfo struct CellDmuxAuInfo
{ {
be_t<u32> auAddr; vm::bptr<void> auAddr;
be_t<u32> auSize; be_t<u32> auSize;
be_t<u32> auMaxSize; be_t<u32> auMaxSize;
be_t<u64> userData;
be_t<u32> ptsUpper;
be_t<u32> ptsLower;
be_t<u32> dtsUpper;
be_t<u32> dtsLower;
};
struct CellDmuxAuInfoEx
{
be_t<u32> auAddr;
be_t<u32> auSize;
be_t<u32> reserved;
b8 isRap; b8 isRap;
be_t<u64> userData; be_t<u64> userData;
CellCodecTimeStamp pts; CellCodecTimeStamp pts;
CellCodecTimeStamp dts; CellCodecTimeStamp dts;
}; };
struct CellDmuxPamfAttr; using CellDmuxAuInfoEx = CellDmuxAuInfo;
struct CellDmuxPamfEsAttr;
struct DmuxAuInfo
{
CellDmuxAuInfo info;
vm::bptr<void> specific_info;
be_t<u32> specific_info_size;
};
using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>); using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>);
using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>); using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>);

File diff suppressed because it is too large Load diff

View file

@ -661,16 +661,376 @@ using dmux_pamf_spu_thread = named_thread<dmux_pamf_spu_context>;
// PPU thread // PPU thread
struct CellDmuxPamfAttr // For some reason, cellDmuxPamf doesn't use regular error code values and also has a second set of error codes that's only used internally
enum CellDmuxPamfError
{ {
be_t<u32> maxEnabledEsNum; CELL_DMUX_PAMF_ERROR_BUSY = 1,
be_t<u32> version; CELL_DMUX_PAMF_ERROR_ARG = 2,
CELL_DMUX_PAMF_ERROR_UNKNOWN_STREAM = 3,
CELL_DMUX_PAMF_ERROR_NO_MEMORY = 5,
CELL_DMUX_PAMF_ERROR_FATAL = 6,
};
enum CellDmuxPamfM2vLevel
{
CELL_DMUX_PAMF_M2V_MP_LL = 0,
CELL_DMUX_PAMF_M2V_MP_ML,
CELL_DMUX_PAMF_M2V_MP_H14,
CELL_DMUX_PAMF_M2V_MP_HL,
};
enum CellDmuxPamfAvcLevel
{
CELL_DMUX_PAMF_AVC_LEVEL_2P1 = 21,
CELL_DMUX_PAMF_AVC_LEVEL_3P0 = 30,
CELL_DMUX_PAMF_AVC_LEVEL_3P1 = 31,
CELL_DMUX_PAMF_AVC_LEVEL_3P2 = 32,
CELL_DMUX_PAMF_AVC_LEVEL_4P1 = 41,
CELL_DMUX_PAMF_AVC_LEVEL_4P2 = 42,
};
struct CellDmuxPamfAuSpecificInfoM2v
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAvc
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoLpcm
{
u8 channelAssignmentInfo;
u8 samplingFreqInfo;
u8 bitsPerSample;
};
struct CellDmuxPamfAuSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoUserData
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoM2v
{
be_t<u32> profileLevel;
};
struct CellDmuxPamfEsSpecificInfoAvc
{
be_t<u32> level;
};
struct CellDmuxPamfEsSpecificInfoLpcm
{
be_t<u32> samplingFreq;
be_t<u32> numOfChannels;
be_t<u32> bitsPerSample;
};
struct CellDmuxPamfEsSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoUserData
{
be_t<u32> reserved1;
};
enum CellDmuxPamfSamplingFrequency
{
CELL_DMUX_PAMF_FS_48K = 48000,
};
enum CellDmuxPamfBitsPerSample
{
CELL_DMUX_PAMF_BITS_PER_SAMPLE_16 = 16,
CELL_DMUX_PAMF_BITS_PER_SAMPLE_24 = 24,
};
enum CellDmuxPamfLpcmChannelAssignmentInfo
{
CELL_DMUX_PAMF_LPCM_CH_M1 = 1,
CELL_DMUX_PAMF_LPCM_CH_LR = 3,
CELL_DMUX_PAMF_LPCM_CH_LRCLSRSLFE = 9,
CELL_DMUX_PAMF_LPCM_CH_LRCLSCS1CS2RSLFE = 11,
};
enum CellDmuxPamfLpcmFs
{
CELL_DMUX_PAMF_LPCM_FS_48K = 1,
};
enum CellDmuxPamfLpcmBitsPerSamples
{
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_16 = 1,
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_24 = 3,
};
struct CellDmuxPamfSpecificInfo
{
be_t<u32> thisSize;
b8 programEndCodeCb;
};
struct CellDmuxPamfResource
{
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
be_t<u32> numOfSpus;
be_t<u32> spuThreadPriority;
vm::bptr<void> memAddr;
be_t<u32> memSize; be_t<u32> memSize;
}; };
struct CellDmuxPamfEsAttr struct DmuxPamfAuInfo
{ {
be_t<u32> auQueueMaxSize; vm::bptr<void> addr;
be_t<u32> memSize; be_t<u32> size;
be_t<u32> specificInfoSize; CellCodecTimeStamp pts;
CellCodecTimeStamp dts;
be_t<u64> user_data;
vm::bptr<void> specific_info;
be_t<u32> specific_info_size;
b8 is_rap;
}; };
CHECK_SIZE(DmuxPamfAuInfo, 0x30);
constexpr u32 DMUX_PAMF_VERSION = 0x280000;
constexpr s32 DMUX_PAMF_MAX_ENABLED_ES_NUM = 0x40;
// HLE exclusive, for savestates
enum class dmux_pamf_state : u8
{
initial,
waiting_for_au_released,
waiting_for_au_released_error,
waiting_for_event,
starting_demux_done,
starting_demux_done_mutex_lock_error,
starting_demux_done_mutex_unlock_error,
starting_demux_done_checking_stream_reset,
starting_demux_done_checking_stream_reset_error,
setting_au_reset,
setting_au_reset_error,
processing_event,
au_found_waiting_for_spu,
unsetting_au_cancel,
demux_done_notifying,
demux_done_mutex_lock,
demux_done_cond_signal,
resuming_demux_mutex_lock,
resuming_demux_waiting_for_spu,
sending_fatal_err
};
enum class DmuxPamfSequenceState : u32
{
dormant,
resetting,
running
};
struct DmuxPamfElementaryStream;
class DmuxPamfContext
{
// HLE exclusive
// These are local variables in the PPU thread function, they're here for savestates
DmuxPamfEvent event;
u64 au_queue_full_bitset;
b8 stream_reset_started;
b8 stream_reset_in_progress;
u32 hle_spu_thread_id;
dmux_pamf_state savestate;
[[maybe_unused]] u8 spurs[0xf6b]; // CellSpurs, 0x1000 bytes on LLE
[[maybe_unused]] vm::bptr<void> spurs_addr; // CellSpurs*
[[maybe_unused]] b8 use_existing_spurs;
[[maybe_unused]] alignas(0x80) u8 spurs_taskset[0x1900]; // CellSpursTaskset
[[maybe_unused]] be_t<u32> spurs_task_id; // CellSpursTaskId
vm::bptr<void> spurs_context_addr;
[[maybe_unused]] u8 reserved1[0x10];
vm::bptr<DmuxPamfContext> _this;
be_t<u32> this_size;
be_t<u32> version;
DmuxCb<DmuxNotifyDemuxDone> notify_demux_done;
DmuxCb<DmuxNotifyProgEndCode> notify_prog_end_code;
DmuxCb<DmuxNotifyFatalErr> notify_fatal_err;
CellDmuxPamfResource resource;
be_t<u64> thread_id; // sys_ppu_thread_t
be_t<u32> unk; // Unused
be_t<u32> ppu_thread_stack_size;
be_t<u64> au_released_bitset; // Each bit corresponds to an elementary stream, if a bit is set then cellDmuxReleaseAu() was called for that elementary stream
b8 stream_reset_requested;
be_t<DmuxPamfSequenceState> sequence_state;
be_t<s32> max_enabled_es_num;
be_t<s32> enabled_es_num;
vm::bptr<DmuxPamfElementaryStream> elementary_streams[DMUX_PAMF_MAX_ENABLED_ES_NUM];
be_t<u32> mutex; // sys_mutex_t
be_t<u32> cond; // sys_cond_t
vm::bptr<dmux_pamf_hle_spurs_queue<DmuxPamfCommand, 1>> cmd_queue_addr_; // Same as cmd_queue_addr, unused
vm::bptr<DmuxPamfCommand[1]> cmd_queue_buffer_addr_; // Same as cmd_queue_buffer_addr, unused
vm::bptr<dmux_pamf_hle_spurs_queue<DmuxPamfCommand, 1>> cmd_queue_addr; // CellSpursQueue*
vm::bptr<dmux_pamf_hle_spurs_queue<be_t<u32>, 1>> cmd_result_queue_addr; // CellSpursQueue*
vm::bptr<dmux_pamf_hle_spurs_queue<DmuxPamfStreamInfo, 1>> stream_info_queue_addr; // CellSpursQueue*
vm::bptr<dmux_pamf_hle_spurs_queue<DmuxPamfEvent, 4 + 2 * DMUX_PAMF_MAX_ENABLED_ES_NUM>> event_queue_addr; // CellSpursQueue*
vm::bptr<DmuxPamfCommand[1]> cmd_queue_buffer_addr;
vm::bptr<be_t<u32>[1]> cmd_result_queue_buffer_addr;
vm::bptr<DmuxPamfEvent[4 + 2 * DMUX_PAMF_MAX_ENABLED_ES_NUM]> event_queue_buffer_addr;
vm::bptr<DmuxPamfStreamInfo[1]> stream_info_queue_buffer_addr;
vm::bptr<dmux_pamf_hle_spurs_queue<DmuxPamfCommand, 1>> cmd_queue_addr__; // Same as cmd_queue_addr, unused
be_t<u64> user_data;
b8 is_raw_es;
be_t<u32> next_es_id;
char spurs_taskset_name[24];
[[maybe_unused]] u8 reserved2[928]; // Unused
dmux_pamf_hle_spurs_queue<DmuxPamfCommand, 1> cmd_queue; // CellSpursQueue
dmux_pamf_hle_spurs_queue<be_t<u32>, 1> cmd_result_queue; // CellSpursQueue
dmux_pamf_hle_spurs_queue<DmuxPamfStreamInfo, 1> stream_info_queue; // CellSpursQueue
dmux_pamf_hle_spurs_queue<DmuxPamfEvent, 4 + 2 * DMUX_PAMF_MAX_ENABLED_ES_NUM> event_queue; // CellSpursQueue
DmuxPamfCommand cmd_queue_buffer[1];
alignas(0x80) be_t<u32> cmd_result_queue_buffer[1];
DmuxPamfStreamInfo stream_info_queue_buffer[1];
DmuxPamfEvent event_queue_buffer[4 + 2 * DMUX_PAMF_MAX_ENABLED_ES_NUM];
alignas(0x80) u8 spurs_context[0x36400];
template <DmuxPamfCommandType type>
void send_spu_command_and_wait(ppu_thread& ppu, bool waiting_for_spu_state, auto&&... cmd_params);
error_code wait_au_released_or_stream_reset(ppu_thread& ppu, u64 au_queue_full_bitset, b8& stream_reset_started, dmux_pamf_state& savestate);
template <bool reset>
error_code set_au_reset(ppu_thread& ppu);
template <typename F>
static error_code callback(ppu_thread& ppu, DmuxCb<F> cb, auto&&... args);
friend struct DmuxPamfElementaryStream;
public:
void run_spu_thread();
DmuxPamfElementaryStream* find_es(u16 stream_id, u16 private_stream_id);
void exec(ppu_thread& ppu);
static error_code open(ppu_thread& ppu, const CellDmuxPamfResource& res, const DmuxCb<DmuxNotifyDemuxDone>& notify_dmux_done, const DmuxCb<DmuxNotifyProgEndCode>& notify_prog_end_code, const DmuxCb<DmuxNotifyFatalErr>& notify_fatal_err, vm::bptr<DmuxPamfContext>& handle);
error_code create_thread(ppu_thread& ppu);
error_code close(ppu_thread& ppu);
error_code reset_stream(ppu_thread& ppu);
error_code join_thread(ppu_thread& ppu);
template <bool raw_es>
error_code set_stream(ppu_thread& ppu, vm::cptr<u8> stream_address, u32 stream_size, b8 discontinuity, u32 user_data);
template <bool raw_es>
error_code enable_es(ppu_thread& ppu, u16 stream_id, u16 private_stream_id, bool is_avc, vm::cptr<void> es_specific_info, vm::ptr<void> mem_addr, u32 mem_size, const DmuxCb<DmuxEsNotifyAuFound>& notify_au_found,
const DmuxCb<DmuxEsNotifyFlushDone>& notify_flush_done, vm::bptr<DmuxPamfElementaryStream>& es);
error_code reset_stream_and_wait_done(ppu_thread& ppu);
};
static_assert(std::is_standard_layout_v<DmuxPamfContext> && std::is_trivial_v<DmuxPamfContext>);
CHECK_SIZE_ALIGN(DmuxPamfContext, 0x3d880, 0x80);
struct CellDmuxPamfHandle
{
vm::bptr<DmuxPamfContext> demuxer;
DmuxCb<DmuxNotifyDemuxDone> notify_demux_done;
DmuxCb<DmuxNotifyProgEndCode> notify_prog_end_code;
DmuxCb<DmuxNotifyFatalErr> notify_fatal_err;
};
CHECK_SIZE(CellDmuxPamfHandle, 0x1c);
struct DmuxPamfElementaryStream
{
vm::bptr<DmuxPamfElementaryStream> _this;
be_t<u32> this_size;
u8 this_index;
vm::bptr<DmuxPamfContext> demuxer;
DmuxCb<DmuxEsNotifyAuFound> notify_au_found;
DmuxCb<DmuxEsNotifyFlushDone> notify_flush_done;
be_t<u16> stream_id;
be_t<u16> private_stream_id;
b8 is_avc;
vm::bptr<u8> au_queue_buffer;
be_t<u32> unk; // Likely au_queue_buffer_size, unused
be_t<u32> au_max_size;
u8 au_specific_info[0x10];
be_t<u32> au_specific_info_size;
b8 reset_next_au;
be_t<u32> es_id;
u8 reserved[72];
error_code release_au(ppu_thread& ppu, vm::ptr<u8> au_addr, u32 au_size) const;
error_code disable_es(ppu_thread& ppu);
error_code flush_es(ppu_thread& ppu) const;
error_code reset_es(ppu_thread& ppu) const;
};
static_assert(std::is_standard_layout_v<DmuxPamfElementaryStream> && std::is_trivial_v<DmuxPamfElementaryStream>);
CHECK_SIZE_ALIGN(DmuxPamfElementaryStream, 0x98, 4);
struct CellDmuxPamfEsHandle
{
vm::bptr<DmuxPamfElementaryStream> es;
DmuxCb<DmuxEsNotifyAuFound> notify_au_found;
DmuxCb<DmuxEsNotifyFlushDone> notify_flush_done;
};
CHECK_SIZE(CellDmuxPamfEsHandle, 0x14);

View file

@ -64,7 +64,7 @@ extern const std::map<std::string_view, int> g_prx_list
{ "libddpdec.sprx", 0 }, { "libddpdec.sprx", 0 },
{ "libdivxdec.sprx", 0 }, { "libdivxdec.sprx", 0 },
{ "libdmux.sprx", 0 }, { "libdmux.sprx", 0 },
{ "libdmuxpamf.sprx", 0 }, { "libdmuxpamf.sprx", 1 },
{ "libdtslbrdec.sprx", 0 }, { "libdtslbrdec.sprx", 0 },
{ "libfiber.sprx", 0 }, { "libfiber.sprx", 0 },
{ "libfont.sprx", 0 }, { "libfont.sprx", 0 },