Add cellVdec hack (stolen TLS)

This commit is contained in:
Nekotekina 2017-10-01 04:40:51 +03:00
parent 144f6809bf
commit ab4e66a0bf
3 changed files with 39 additions and 3 deletions

View File

@ -3,6 +3,8 @@
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_sync.h" #include "Emu/Cell/lv2/sys_sync.h"
#include "Emu/Cell/lv2/sys_ppu_thread.h"
#include "sysPrxForUser.h"
extern "C" extern "C"
{ {
@ -74,11 +76,14 @@ struct vdec_thread : ppu_thread
u32 frc_set{}; // Frame Rate Override u32 frc_set{}; // Frame Rate Override
u64 next_pts{}; u64 next_pts{};
u64 next_dts{}; u64 next_dts{};
u64 ppu_tid{};
std::mutex mutex; std::mutex mutex;
std::queue<vdec_frame> out; std::queue<vdec_frame> out;
u32 max_frames = 60; u32 max_frames = 60;
atomic_t<u32> au_count{0};
vdec_thread(s32 type, u32 profile, u32 addr, u32 size, vm::ptr<CellVdecCbMsg> func, u32 arg, u32 prio, u32 stack) vdec_thread(s32 type, u32 profile, u32 addr, u32 size, vm::ptr<CellVdecCbMsg> func, u32 arg, u32 prio, u32 stack)
: ppu_thread("HLE Video Decoder", prio, stack) : ppu_thread("HLE Video Decoder", prio, stack)
, type(type) , type(type)
@ -351,6 +356,11 @@ struct vdec_thread : ppu_thread
cb_func(*this, id, vcmd == vdec_cmd::decode ? CELL_VDEC_MSG_TYPE_AUDONE : CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, cb_arg); cb_func(*this, id, vcmd == vdec_cmd::decode ? CELL_VDEC_MSG_TYPE_AUDONE : CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, cb_arg);
lv2_obj::sleep(*this); lv2_obj::sleep(*this);
} }
if (vcmd == vdec_cmd::decode)
{
au_count--;
}
while (std::lock_guard<std::mutex>{mutex}, max_frames && out.size() > max_frames) while (std::lock_guard<std::mutex>{mutex}, max_frames && out.size() > max_frames)
{ {
@ -397,7 +407,7 @@ u32 vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0 */, vm::ptr<C
attr->decoderVerLower = 0x280000; // from dmux attr->decoderVerLower = 0x280000; // from dmux
attr->decoderVerUpper = 0x260000; attr->decoderVerUpper = 0x260000;
attr->memSize = 4 * 1024 * 1024; // 4 MB attr->memSize = 4 * 1024 * 1024; // 4 MB
attr->cmdDepth = 16; attr->cmdDepth = 4;
return CELL_OK; return CELL_OK;
} }
@ -415,7 +425,7 @@ s32 cellVdecQueryAttrEx(vm::cptr<CellVdecTypeEx> type, vm::ptr<CellVdecAttr> att
return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr); return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr);
} }
s32 cellVdecOpen(vm::cptr<CellVdecType> type, vm::cptr<CellVdecResource> res, vm::cptr<CellVdecCb> cb, vm::ptr<u32> handle) s32 cellVdecOpen(ppu_thread& ppu, vm::cptr<CellVdecType> type, vm::cptr<CellVdecResource> res, vm::cptr<CellVdecCb> cb, vm::ptr<u32> handle)
{ {
cellVdec.warning("cellVdecOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle); cellVdec.warning("cellVdecOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
@ -425,12 +435,17 @@ s32 cellVdecOpen(vm::cptr<CellVdecType> type, vm::cptr<CellVdecResource> res, vm
// Hack: store thread id (normally it should be pointer) // Hack: store thread id (normally it should be pointer)
*handle = vdec->id; *handle = vdec->id;
vm::var<u64> _tid;
CALL_FUNC(ppu, sys_ppu_thread_create, ppu, +_tid, 1148, 0, 900, 0x4000, SYS_PPU_THREAD_CREATE_INTERRUPT, vm::null);
vdec->gpr[13] = idm::get<ppu_thread>(*_tid)->gpr[13];
vdec->ppu_tid = *_tid;
vdec->run(); vdec->run();
return CELL_OK; return CELL_OK;
} }
s32 cellVdecOpenEx(vm::cptr<CellVdecTypeEx> type, vm::cptr<CellVdecResourceEx> res, vm::cptr<CellVdecCb> cb, vm::ptr<u32> handle) s32 cellVdecOpenEx(ppu_thread& ppu, vm::cptr<CellVdecTypeEx> type, vm::cptr<CellVdecResourceEx> res, vm::cptr<CellVdecCb> cb, vm::ptr<u32> handle)
{ {
cellVdec.warning("cellVdecOpenEx(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle); cellVdec.warning("cellVdecOpenEx(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
@ -440,6 +455,11 @@ s32 cellVdecOpenEx(vm::cptr<CellVdecTypeEx> type, vm::cptr<CellVdecResourceEx> r
// Hack: store thread id (normally it should be pointer) // Hack: store thread id (normally it should be pointer)
*handle = vdec->id; *handle = vdec->id;
vm::var<u64> _tid;
CALL_FUNC(ppu, sys_ppu_thread_create, ppu, +_tid, 1148, 0, 900, 0x4000, SYS_PPU_THREAD_CREATE_INTERRUPT, vm::null);
vdec->gpr[13] = idm::get<ppu_thread>(*_tid)->gpr[13];
vdec->ppu_tid = *_tid;
vdec->run(); vdec->run();
return CELL_OK; return CELL_OK;
@ -467,6 +487,8 @@ s32 cellVdecClose(ppu_thread& ppu, u32 handle)
vdec->notify(); vdec->notify();
vdec->join(); vdec->join();
idm::remove<ppu_thread>(handle); idm::remove<ppu_thread>(handle);
CALL_FUNC(ppu, sys_interrupt_thread_disestablish, ppu, vdec->ppu_tid);
return CELL_OK; return CELL_OK;
} }
@ -513,6 +535,11 @@ s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::cptr<CellVdecAuInf
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
if (vdec->au_count.fetch_op([](u32& c) { if (c < 4) c++; }) >= 4)
{
return CELL_VDEC_ERROR_BUSY;
}
// TODO: check info // TODO: check info
vdec->cmd_list vdec->cmd_list
({ ({

View File

@ -52,6 +52,9 @@ error_code sys_lwcond_signal_all(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond);
error_code sys_lwcond_signal_to(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id); error_code sys_lwcond_signal_to(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id);
error_code sys_lwcond_wait(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout); error_code sys_lwcond_wait(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::cptr<char> threadname);
error_code sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih);
void sys_ppu_thread_exit(ppu_thread& CPU, u64 val); void sys_ppu_thread_exit(ppu_thread& CPU, u64 val);
void sys_game_process_exitspawn(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags); void sys_game_process_exitspawn(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags);
void sys_game_process_exitspawn2(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags); void sys_game_process_exitspawn2(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags);

View File

@ -130,6 +130,12 @@ error_code _sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih, vm::ptr<u
if (!handler) if (!handler)
{ {
if (const auto thread = idm::withdraw<ppu_thread>(ih))
{
*r13 = thread->gpr[13];
return CELL_OK;
}
return CELL_ESRCH; return CELL_ESRCH;
} }