diff --git a/rpcs3/Emu/Cell/Modules/cellVdec.cpp b/rpcs3/Emu/Cell/Modules/cellVdec.cpp index 67c34e739d..c665c4136c 100644 --- a/rpcs3/Emu/Cell/Modules/cellVdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVdec.cpp @@ -3,6 +3,8 @@ #include "Emu/IdManager.h" #include "Emu/Cell/PPUModule.h" #include "Emu/Cell/lv2/sys_sync.h" +#include "Emu/Cell/lv2/sys_ppu_thread.h" +#include "sysPrxForUser.h" extern "C" { @@ -74,11 +76,14 @@ struct vdec_thread : ppu_thread u32 frc_set{}; // Frame Rate Override u64 next_pts{}; u64 next_dts{}; + u64 ppu_tid{}; std::mutex mutex; std::queue out; u32 max_frames = 60; + atomic_t au_count{0}; + vdec_thread(s32 type, u32 profile, u32 addr, u32 size, vm::ptr func, u32 arg, u32 prio, u32 stack) : ppu_thread("HLE Video Decoder", prio, stack) , 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); lv2_obj::sleep(*this); } + + if (vcmd == vdec_cmd::decode) + { + au_count--; + } while (std::lock_guard{mutex}, max_frames && out.size() > max_frames) { @@ -397,7 +407,7 @@ u32 vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0 */, vm::ptrdecoderVerLower = 0x280000; // from dmux attr->decoderVerUpper = 0x260000; attr->memSize = 4 * 1024 * 1024; // 4 MB - attr->cmdDepth = 16; + attr->cmdDepth = 4; return CELL_OK; } @@ -415,7 +425,7 @@ s32 cellVdecQueryAttrEx(vm::cptr type, vm::ptr att return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr); } -s32 cellVdecOpen(vm::cptr type, vm::cptr res, vm::cptr cb, vm::ptr handle) +s32 cellVdecOpen(ppu_thread& ppu, vm::cptr type, vm::cptr res, vm::cptr cb, vm::ptr 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 type, vm::cptr res, vm // Hack: store thread id (normally it should be pointer) *handle = vdec->id; + vm::var _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(*_tid)->gpr[13]; + vdec->ppu_tid = *_tid; + vdec->run(); return CELL_OK; } -s32 cellVdecOpenEx(vm::cptr type, vm::cptr res, vm::cptr cb, vm::ptr handle) +s32 cellVdecOpenEx(ppu_thread& ppu, vm::cptr type, vm::cptr res, vm::cptr cb, vm::ptr 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 type, vm::cptr r // Hack: store thread id (normally it should be pointer) *handle = vdec->id; + vm::var _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(*_tid)->gpr[13]; + vdec->ppu_tid = *_tid; + vdec->run(); return CELL_OK; @@ -467,6 +487,8 @@ s32 cellVdecClose(ppu_thread& ppu, u32 handle) vdec->notify(); vdec->join(); idm::remove(handle); + + CALL_FUNC(ppu, sys_interrupt_thread_disestablish, ppu, vdec->ppu_tid); return CELL_OK; } @@ -513,6 +535,11 @@ s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::cptrau_count.fetch_op([](u32& c) { if (c < 4) c++; }) >= 4) + { + return CELL_VDEC_ERROR_BUSY; + } + // TODO: check info vdec->cmd_list ({ diff --git a/rpcs3/Emu/Cell/Modules/sysPrxForUser.h b/rpcs3/Emu/Cell/Modules/sysPrxForUser.h index 18cbe33375..ecb94d70e4 100644 --- a/rpcs3/Emu/Cell/Modules/sysPrxForUser.h +++ b/rpcs3/Emu/Cell/Modules/sysPrxForUser.h @@ -52,6 +52,9 @@ error_code sys_lwcond_signal_all(ppu_thread& CPU, vm::ptr lwcond); error_code sys_lwcond_signal_to(ppu_thread& CPU, vm::ptr lwcond, u32 ppu_thread_id); error_code sys_lwcond_wait(ppu_thread& CPU, vm::ptr lwcond, u64 timeout); +error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::cptr threadname); +error_code sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih); + void sys_ppu_thread_exit(ppu_thread& CPU, u64 val); void sys_game_process_exitspawn(ppu_thread& ppu, vm::cptr path, vm::cpptr argv, vm::cpptr envp, u32 data, u32 data_size, s32 prio, u64 flags); void sys_game_process_exitspawn2(ppu_thread& ppu, vm::cptr path, vm::cpptr argv, vm::cpptr envp, u32 data, u32 data_size, s32 prio, u64 flags); diff --git a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp index 756aedb55f..df7eaa6aa0 100644 --- a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp @@ -130,6 +130,12 @@ error_code _sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih, vm::ptr(ih)) + { + *r13 = thread->gpr[13]; + return CELL_OK; + } + return CELL_ESRCH; }