mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-03-10 23:45:16 +01:00
Merge 8a529dfb33 into 71f0d5c602
This commit is contained in:
commit
288a9b7e71
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "cellPamf.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Utilities/BitField.h"
|
||||
|
||||
// Error Codes
|
||||
enum CellDmuxError :u32
|
||||
|
|
@ -18,6 +19,10 @@ enum CellDmuxStreamType : s32
|
|||
CELL_DMUX_STREAM_TYPE_UNDEF = 0,
|
||||
CELL_DMUX_STREAM_TYPE_PAMF = 1,
|
||||
CELL_DMUX_STREAM_TYPE_TERMINATOR = 2,
|
||||
|
||||
// Only used in cellSail
|
||||
CELL_DMUX_STREAM_TYPE_MP4 = 0x81,
|
||||
CELL_DMUX_STREAM_TYPE_AVI = 0x82
|
||||
};
|
||||
|
||||
enum CellDmuxMsgType : s32
|
||||
|
|
@ -48,13 +53,14 @@ struct CellDmuxEsMsg
|
|||
struct CellDmuxType
|
||||
{
|
||||
be_t<s32> streamType; // CellDmuxStreamType
|
||||
be_t<u32> reserved[2];
|
||||
be_t<s32> reserved1;
|
||||
be_t<s32> reserved2;
|
||||
};
|
||||
|
||||
struct CellDmuxType2
|
||||
{
|
||||
be_t<s32> streamType; // CellDmuxStreamType
|
||||
be_t<u32> streamSpecificInfo;
|
||||
be_t<s32> streamType;
|
||||
vm::bcptr<void> streamSpecificInfo;
|
||||
};
|
||||
|
||||
struct CellDmuxResource
|
||||
|
|
@ -73,8 +79,8 @@ struct CellDmuxResourceEx
|
|||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
be_t<u32> spurs_addr;
|
||||
u8 priority[8];
|
||||
vm::bptr<void> spurs; // CellSpurs*
|
||||
be_t<u64, 1> priority;
|
||||
be_t<u32> maxContention;
|
||||
};
|
||||
|
||||
|
|
@ -85,33 +91,23 @@ struct CellDmuxResourceSpurs
|
|||
be_t<u32> maxContention;
|
||||
};
|
||||
|
||||
/*
|
||||
struct CellDmuxResource2Ex
|
||||
{
|
||||
b8 isResourceEx; //true
|
||||
CellDmuxResourceEx resourceEx;
|
||||
};
|
||||
|
||||
struct CellDmuxResource2NoEx
|
||||
{
|
||||
b8 isResourceEx; //false
|
||||
CellDmuxResource resource;
|
||||
};
|
||||
*/
|
||||
|
||||
struct CellDmuxResource2
|
||||
{
|
||||
b8 isResourceEx;
|
||||
be_t<u32> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
be_t<u32> shit[4];
|
||||
|
||||
union
|
||||
{
|
||||
CellDmuxResource resource;
|
||||
CellDmuxResourceEx resourceEx;
|
||||
};
|
||||
};
|
||||
|
||||
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
|
||||
struct DmuxContext;
|
||||
struct DmuxEsContext;
|
||||
|
||||
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
|
||||
using CellDmuxCbMsg = u32(vm::ptr<DmuxContext> demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
|
||||
|
||||
using CellDmuxCbEsMsg = u32(vm::ptr<DmuxContext> demuxerHandle, vm::ptr<DmuxEsContext> esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
|
||||
|
||||
// Used for internal callbacks as well
|
||||
template <typename F>
|
||||
|
|
@ -177,6 +173,70 @@ struct DmuxAuInfo
|
|||
be_t<u32> specific_info_size;
|
||||
};
|
||||
|
||||
struct DmuxAuQueueElement
|
||||
{
|
||||
be_t<u32> index;
|
||||
u8 unk; // unused
|
||||
DmuxAuInfo au_info;
|
||||
};
|
||||
|
||||
CHECK_SIZE(DmuxAuQueueElement, 0x38);
|
||||
|
||||
enum DmuxState : u32
|
||||
{
|
||||
DMUX_STOPPED = 1 << 0,
|
||||
DMUX_RUNNING = 1 << 1,
|
||||
};
|
||||
|
||||
struct alignas(0x10) DmuxContext // CellDmuxHandle = DmuxContext*
|
||||
{
|
||||
vm::bptr<DmuxContext> _this;
|
||||
be_t<u32> _this_size;
|
||||
be_t<u32> version;
|
||||
be_t<u32> dmux_state;
|
||||
CellDmuxType dmux_type;
|
||||
CellDmuxCb dmux_cb;
|
||||
b8 stream_is_set;
|
||||
vm::bptr<void> core_handle;
|
||||
be_t<u32> version_; // Same value as 'version'
|
||||
be_t<u64> user_data;
|
||||
be_t<s32> max_enabled_es_num;
|
||||
be_t<s32> enabled_es_num;
|
||||
be_t<u32> _dx_mhd; // sys_mutex_t
|
||||
u8 reserved[0x7c];
|
||||
};
|
||||
|
||||
CHECK_SIZE_ALIGN(DmuxContext, 0xc0, 0x10);
|
||||
|
||||
struct alignas(0x10) DmuxEsContext // CellDmuxEsHandle = DmuxEsContext*
|
||||
{
|
||||
be_t<u32> _dx_mes; // sys_mutex_t
|
||||
be_t<u32> is_enabled;
|
||||
be_t<u32> error_mem_size;
|
||||
be_t<u32> error_count;
|
||||
vm::bptr<void> error_mem_addr;
|
||||
vm::bptr<DmuxEsContext> _this;
|
||||
be_t<u32> _this_size;
|
||||
be_t<s32> _this_index;
|
||||
vm::bptr<DmuxContext> dmux_handle;
|
||||
CellDmuxEsCb es_cb;
|
||||
vm::bptr<void> core_es_handle;
|
||||
bf_t<be_t<u32>, 0, 1> flush_started;
|
||||
|
||||
struct
|
||||
{
|
||||
be_t<s32> max_size;
|
||||
be_t<s32> allocated_size;
|
||||
be_t<s32> size;
|
||||
be_t<s32> front;
|
||||
be_t<s32> back;
|
||||
be_t<s32> allocated_back;
|
||||
}
|
||||
au_queue;
|
||||
};
|
||||
|
||||
CHECK_SIZE_ALIGN(DmuxEsContext, 0x50, 0x10);
|
||||
|
||||
using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>);
|
||||
using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>);
|
||||
using DmuxNotifyProgEndCode = error_code(vm::ptr<void>, vm::ptr<void>);
|
||||
|
|
@ -194,10 +254,10 @@ using CellDmuxCoreOpSetStream = error_code(vm::ptr<void>, vm::cptr<void>, u32, b
|
|||
using CellDmuxCoreOpReleaseAu = error_code(vm::ptr<void>, vm::ptr<void>, u32);
|
||||
using CellDmuxCoreOpQueryEsAttr = error_code(vm::cptr<void>, vm::cptr<void>, vm::ptr<CellDmuxPamfEsAttr>);
|
||||
using CellDmuxCoreOpEnableEs = error_code(vm::ptr<void>, vm::cptr<void>, vm::cptr<CellDmuxEsResource>, vm::cptr<DmuxCb<DmuxEsNotifyAuFound>>, vm::cptr<DmuxCb<DmuxEsNotifyFlushDone>>, vm::cptr<void>, vm::pptr<void>);
|
||||
using CellDmuxCoreOpDisableEs = u32(vm::ptr<void>);
|
||||
using CellDmuxCoreOpFlushEs = u32(vm::ptr<void>);
|
||||
using CellDmuxCoreOpResetEs = u32(vm::ptr<void>);
|
||||
using CellDmuxCoreOpResetStreamAndWaitDone = u32(vm::ptr<void>);
|
||||
using CellDmuxCoreOpDisableEs = error_code(vm::ptr<void>);
|
||||
using CellDmuxCoreOpFlushEs = error_code(vm::ptr<void>);
|
||||
using CellDmuxCoreOpResetEs = error_code(vm::ptr<void>);
|
||||
using CellDmuxCoreOpResetStreamAndWaitDone = error_code(vm::ptr<void>);
|
||||
|
||||
struct CellDmuxCoreOps
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2573,7 +2573,7 @@ template <bool raw_es>
|
|||
error_code _CellDmuxCoreOpEnableEs(ppu_thread& ppu, vm::ptr<CellDmuxPamfHandle> handle, vm::cptr<void> esFilterId, vm::cptr<CellDmuxEsResource> esResource, vm::cptr<DmuxCb<DmuxEsNotifyAuFound>> notifyAuFound,
|
||||
vm::cptr<DmuxCb<DmuxEsNotifyFlushDone>> notifyFlushDone, vm::cptr<void> esSpecificInfo, vm::pptr<CellDmuxPamfEsHandle> esHandle)
|
||||
{
|
||||
cellDmuxPamf.notice("_CellDmuxCoreOpEnableEs<raw_es=%d>(handle=*0x%x, esFilterId=*0x%x, esResource=*0x%x, notifyAuFound=*0x%x, notifyFlushDone=*0x%x, esSpecificInfo=*0x%x, esHandle)",
|
||||
cellDmuxPamf.notice("_CellDmuxCoreOpEnableEs<raw_es=%d>(handle=*0x%x, esFilterId=*0x%x, esResource=*0x%x, notifyAuFound=*0x%x, notifyFlushDone=*0x%x, esSpecificInfo=*0x%x, esHandle=**0x%x)",
|
||||
raw_es, handle, esFilterId, esResource, notifyAuFound, notifyFlushDone, esSpecificInfo, esHandle);
|
||||
|
||||
if (!handle || !esFilterId || !esResource || !esResource->memAddr || esResource->memSize == 0u || !notifyAuFound || !notifyAuFound->cbFunc || !notifyAuFound->cbArg || !notifyFlushDone || !notifyFlushDone->cbFunc || !notifyFlushDone->cbArg)
|
||||
|
|
|
|||
|
|
@ -5,14 +5,6 @@
|
|||
#include <bitset>
|
||||
#include "cellPamf.h"
|
||||
|
||||
const std::function<bool()> SQUEUE_ALWAYS_EXIT = []() { return true; };
|
||||
const std::function<bool()> SQUEUE_NEVER_EXIT = []() { return false; };
|
||||
|
||||
bool squeue_test_exit()
|
||||
{
|
||||
return Emu.IsStopped();
|
||||
}
|
||||
|
||||
LOG_CHANNEL(cellPamf);
|
||||
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -595,345 +595,3 @@ struct CellPamfReader
|
|||
CHECK_SIZE(CellPamfReader, 128);
|
||||
|
||||
error_code cellPamfReaderInitialize(vm::ptr<CellPamfReader> pSelf, vm::cptr<PamfHeader> pAddr, u64 fileSize, u32 attribute);
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
|
||||
extern const std::function<bool()> SQUEUE_NEVER_EXIT;
|
||||
|
||||
bool squeue_test_exit();
|
||||
|
||||
// TODO: eliminate this boolshit
|
||||
template<typename T, u32 sq_size = 256>
|
||||
class squeue_t
|
||||
{
|
||||
struct squeue_sync_var_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 position : 31;
|
||||
u32 pop_lock : 1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 count : 31;
|
||||
u32 push_lock : 1;
|
||||
};
|
||||
};
|
||||
|
||||
atomic_t<squeue_sync_var_t> m_sync;
|
||||
|
||||
mutable std::mutex m_rcv_mutex;
|
||||
mutable std::mutex m_wcv_mutex;
|
||||
mutable std::condition_variable m_rcv;
|
||||
mutable std::condition_variable m_wcv;
|
||||
|
||||
T m_data[sq_size];
|
||||
|
||||
enum squeue_sync_var_result : u32
|
||||
{
|
||||
SQSVR_OK = 0,
|
||||
SQSVR_LOCKED = 1,
|
||||
SQSVR_FAILED = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
squeue_t()
|
||||
: m_sync(squeue_sync_var_t{})
|
||||
{
|
||||
}
|
||||
|
||||
static u32 get_max_size()
|
||||
{
|
||||
return sq_size;
|
||||
}
|
||||
|
||||
bool is_full() const
|
||||
{
|
||||
return m_sync.load().count == sq_size;
|
||||
}
|
||||
|
||||
bool push(const T& data, const std::function<bool()>& test_exit)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
|
||||
if (sync.push_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
if (sync.count == sq_size)
|
||||
{
|
||||
return SQSVR_FAILED;
|
||||
}
|
||||
|
||||
sync.push_lock = 1;
|
||||
pos = sync.position + sync.count;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> wcv_lock(m_wcv_mutex);
|
||||
m_wcv.wait_for(wcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
m_data[pos >= sq_size ? pos - sq_size : pos] = data;
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
ensure(!!sync.push_lock);
|
||||
sync.push_lock = 0;
|
||||
sync.count++;
|
||||
});
|
||||
|
||||
m_rcv.notify_one();
|
||||
m_wcv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool push(const T& data, const volatile bool* do_exit)
|
||||
{
|
||||
return push(data, [do_exit]() { return do_exit && *do_exit; });
|
||||
}
|
||||
|
||||
bool push(const T& data)
|
||||
{
|
||||
return push(data, SQUEUE_NEVER_EXIT);
|
||||
}
|
||||
|
||||
bool try_push(const T& data)
|
||||
{
|
||||
return push(data, SQUEUE_ALWAYS_EXIT);
|
||||
}
|
||||
|
||||
bool pop(T& data, const std::function<bool()>& test_exit)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
|
||||
if (!sync.count)
|
||||
{
|
||||
return SQSVR_FAILED;
|
||||
}
|
||||
if (sync.pop_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
sync.pop_lock = 1;
|
||||
pos = sync.position;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
data = m_data[pos];
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
ensure(!!sync.pop_lock);
|
||||
sync.pop_lock = 0;
|
||||
sync.position++;
|
||||
sync.count--;
|
||||
if (sync.position == sq_size)
|
||||
{
|
||||
sync.position = 0;
|
||||
}
|
||||
});
|
||||
|
||||
m_rcv.notify_one();
|
||||
m_wcv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pop(T& data, const volatile bool* do_exit)
|
||||
{
|
||||
return pop(data, [do_exit]() { return do_exit && *do_exit; });
|
||||
}
|
||||
|
||||
bool pop(T& data)
|
||||
{
|
||||
return pop(data, SQUEUE_NEVER_EXIT);
|
||||
}
|
||||
|
||||
bool try_pop(T& data)
|
||||
{
|
||||
return pop(data, SQUEUE_ALWAYS_EXIT);
|
||||
}
|
||||
|
||||
bool peek(T& data, u32 start_pos, const std::function<bool()>& test_exit)
|
||||
{
|
||||
ensure(start_pos < sq_size);
|
||||
u32 pos = 0;
|
||||
|
||||
while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
|
||||
if (sync.count <= start_pos)
|
||||
{
|
||||
return SQSVR_FAILED;
|
||||
}
|
||||
if (sync.pop_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
sync.pop_lock = 1;
|
||||
pos = sync.position + start_pos;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
data = m_data[pos >= sq_size ? pos - sq_size : pos];
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
ensure(!!sync.pop_lock);
|
||||
sync.pop_lock = 0;
|
||||
});
|
||||
|
||||
m_rcv.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peek(T& data, u32 start_pos, const volatile bool* do_exit)
|
||||
{
|
||||
return peek(data, start_pos, [do_exit]() { return do_exit && *do_exit; });
|
||||
}
|
||||
|
||||
bool peek(T& data, u32 start_pos = 0)
|
||||
{
|
||||
return peek(data, start_pos, SQUEUE_NEVER_EXIT);
|
||||
}
|
||||
|
||||
bool try_peek(T& data, u32 start_pos = 0)
|
||||
{
|
||||
return peek(data, start_pos, SQUEUE_ALWAYS_EXIT);
|
||||
}
|
||||
|
||||
class squeue_data_t
|
||||
{
|
||||
T* const m_data;
|
||||
const u32 m_pos;
|
||||
const u32 m_count;
|
||||
|
||||
squeue_data_t(T* data, u32 pos, u32 count)
|
||||
: m_data(data)
|
||||
, m_pos(pos)
|
||||
, m_count(count)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
T& operator [] (u32 index)
|
||||
{
|
||||
ensure(index < m_count);
|
||||
index += m_pos;
|
||||
index = index < sq_size ? index : index - sq_size;
|
||||
return m_data[index];
|
||||
}
|
||||
};
|
||||
|
||||
void process(void(*proc)(squeue_data_t data))
|
||||
{
|
||||
u32 pos, count;
|
||||
|
||||
while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
|
||||
if (sync.pop_lock || sync.push_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
pos = sync.position;
|
||||
count = sync.count;
|
||||
sync.pop_lock = 1;
|
||||
sync.push_lock = 1;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
proc(squeue_data_t(m_data, pos, count));
|
||||
|
||||
m_sync.atomic_op([](squeue_sync_var_t& sync)
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
ensure(!!sync.pop_lock);
|
||||
ensure(!!sync.push_lock);
|
||||
sync.pop_lock = 0;
|
||||
sync.push_lock = 0;
|
||||
});
|
||||
|
||||
m_wcv.notify_one();
|
||||
m_rcv.notify_one();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32
|
||||
{
|
||||
ensure(sync.count <= sq_size);
|
||||
ensure(sync.position < sq_size);
|
||||
|
||||
if (sync.pop_lock || sync.push_lock)
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
sync.pop_lock = 1;
|
||||
sync.push_lock = 1;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
|
||||
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
m_sync.exchange({});
|
||||
m_wcv.notify_one();
|
||||
m_rcv.notify_one();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ extern const std::map<std::string_view, int> g_prx_list
|
|||
{ "libcelpenc.sprx", 0 },
|
||||
{ "libddpdec.sprx", 0 },
|
||||
{ "libdivxdec.sprx", 0 },
|
||||
{ "libdmux.sprx", 0 },
|
||||
{ "libdmux.sprx", 1 },
|
||||
{ "libdmuxpamf.sprx", 1 },
|
||||
{ "libdtslbrdec.sprx", 0 },
|
||||
{ "libfiber.sprx", 0 },
|
||||
|
|
|
|||
Loading…
Reference in a new issue