diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index eabf41fa0f..9f38f371c7 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1318,7 +1318,14 @@ void SPUThread::stop_and_signal(u32 code) throw EXCEPTION("Unexpected SPU Thread Group state (%d)", group->state); } - if (queue->events.empty() || !queue->sq.empty()) + if (queue->events.size()) + { + auto& event = queue->events.front(); + ch_in_mbox.set_values(4, CELL_OK, static_cast(std::get<1>(event)), static_cast(std::get<2>(event)), static_cast(std::get<3>(event))); + + queue->events.pop_front(); + } + else { // add waiter; protocol is ignored in current implementation sleep_queue_entry_t waiter(*this, queue->sq); @@ -1332,23 +1339,8 @@ void SPUThread::stop_and_signal(u32 code) cv.wait(lv2_lock); } - } - if (queue->events.empty()) - { - if (Emu.GetIdManager().check_id(queue->id)) - { - throw EXCEPTION("Unexpected"); - } - - ch_in_mbox.set_values(1, CELL_ECANCELED); - } - else - { - auto& event = queue->events.front(); - ch_in_mbox.set_values(4, CELL_OK, static_cast(std::get<1>(event)), static_cast(std::get<2>(event)), static_cast(std::get<3>(event))); - - queue->events.pop_front(); + // event data must be set by push() } // restore thread group status diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index c0b32bc801..1f4ca70542 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -546,8 +546,10 @@ s32 cellAdecOpenEx(vm::ptr type, vm::ptr res, return CELL_OK; } -s32 _nid_df982d2c(vm::ptr type, vm::ptr res, vm::ptr cb, vm::ptr handle) +s32 cellAdecOpenExt(vm::ptr type, vm::ptr res, vm::ptr cb, vm::ptr handle) { + cellAdec.Warning("cellAdecOpenExt(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle); + return cellAdecOpenEx(type, res, cb, handle); } @@ -868,7 +870,7 @@ Module cellAdec("cellAdec", []() REG_FUNC(cellAdec, cellAdecQueryAttr); REG_FUNC(cellAdec, cellAdecOpen); REG_FUNC(cellAdec, cellAdecOpenEx); - REG_UNNAMED(cellAdec, df982d2c); + REG_FUNC(cellAdec, cellAdecOpenExt); // 0xdf982d2c REG_FUNC(cellAdec, cellAdecClose); REG_FUNC(cellAdec, cellAdecStartSeq); REG_FUNC(cellAdec, cellAdecEndSeq); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 01b3d07417..b884384979 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -826,8 +826,10 @@ s32 cellDmuxOpenEx(vm::cptr type, vm::cptr res return CELL_OK; } -s32 _nid_e075fabc(vm::cptr type, vm::cptr resEx, vm::cptr cb, vm::ptr handle) +s32 cellDmuxOpenExt(vm::cptr type, vm::cptr resEx, vm::cptr cb, vm::ptr handle) { + cellDmux.Warning("cellDmuxOpenExt(type=*0x%x, resEx=*0x%x, cb=*0x%x, handle=*0x%x)", type, resEx, cb, handle); + return cellDmuxOpenEx(type, resEx, cb, handle); } @@ -1184,7 +1186,7 @@ Module cellDmux("cellDmux", []() REG_FUNC(cellDmux, cellDmuxQueryAttr2); REG_FUNC(cellDmux, cellDmuxOpen); REG_FUNC(cellDmux, cellDmuxOpenEx); - REG_UNNAMED(cellDmux, e075fabc); + REG_FUNC(cellDmux, cellDmuxOpenExt); // 0xe075fabc REG_FUNC(cellDmux, cellDmuxOpen2); REG_FUNC(cellDmux, cellDmuxClose); REG_FUNC(cellDmux, cellDmuxSetStream); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 3e7f2261b5..45fe756796 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -769,9 +769,9 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr format, vm::ptr format2, vm::ptr outBuff, u32 arg4) +s32 cellVdecGetPictureExt(PPUThread& CPU, u32 handle, vm::cptr format2, vm::ptr outBuff, u32 arg4) { - cellVdec.Warning("_nid_a21aa896(handle=0x%x, format2=*0x%x, outBuff=*0x%x, arg4=*0x%x)", handle, format2, outBuff, arg4); + cellVdec.Warning("cellVdecGetPictureExt(handle=0x%x, format2=*0x%x, outBuff=*0x%x, arg4=*0x%x)", handle, format2, outBuff, arg4); if (arg4 || format2->unk0 || format2->unk1) { @@ -956,12 +956,16 @@ Module cellVdec("cellVdec", []() REG_FUNC(cellVdec, cellVdecQueryAttrEx); REG_FUNC(cellVdec, cellVdecOpen); REG_FUNC(cellVdec, cellVdecOpenEx); + //REG_FUNC(cellVdec, cellVdecOpenExt); // 0xef4d8ad7 REG_FUNC(cellVdec, cellVdecClose); REG_FUNC(cellVdec, cellVdecStartSeq); + //REG_FUNC(cellVdec, cellVdecStartSeqExt); // 0xebb8e70a REG_FUNC(cellVdec, cellVdecEndSeq); REG_FUNC(cellVdec, cellVdecDecodeAu); REG_FUNC(cellVdec, cellVdecGetPicture); - REG_UNNAMED(cellVdec, a21aa896); + REG_FUNC(cellVdec, cellVdecGetPictureExt); // 0xa21aa896 REG_FUNC(cellVdec, cellVdecGetPicItem); + //REG_FUNC(cellVdec, cellVdecGetPicItemExt); // 0x2cbd9806 REG_FUNC(cellVdec, cellVdecSetFrameRate); + //REG_FUNC(cellVdec, cellVdecSetFrameRateExt); // 0xcffc42a5 }); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index a4a109f178..d52bde0255 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -142,6 +142,7 @@ Module cellVpost("cellVpost", []() REG_FUNC(cellVpost, cellVpostQueryAttr); REG_FUNC(cellVpost, cellVpostOpen); REG_FUNC(cellVpost, cellVpostOpenEx); + //REG_FUNC(cellVpost, cellVpostOpenExt); // 0x9f1795df REG_FUNC(cellVpost, cellVpostClose); REG_FUNC(cellVpost, cellVpostExec); }); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index 0c59923a43..d884c3fe6b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -5,6 +5,7 @@ #include "Emu/SysCalls/SysCalls.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/Cell/SPUThread.h" #include "Emu/Event.h" #include "sys_process.h" #include "sys_event.h" @@ -27,16 +28,48 @@ void lv2_event_queue_t::push(lv2_lock_t& lv2_lock, u64 source, u64 data1, u64 da { CHECK_LV2_LOCK(lv2_lock); - events.emplace_back(source, data1, data2, data3); + // save event if no waiters + if (sq.empty()) + { + return events.emplace_back(source, data1, data2, data3); + } + + if (events.size()) + { + throw EXCEPTION("Unexpected"); + } // notify waiter; protocol is ignored in current implementation - for (auto& waiter : sq) + auto& thread = sq.front(); + + if (type == SYS_PPU_QUEUE && thread->get_type() == CPU_THREAD_PPU) { - if (waiter->signal()) - { - return; - } + // store event data in registers + auto& ppu = static_cast(*thread); + + ppu.GPR[4] = source; + ppu.GPR[5] = data1; + ppu.GPR[6] = data2; + ppu.GPR[7] = data3; } + else if (type == SYS_SPU_QUEUE && thread->get_type() == CPU_THREAD_SPU) + { + // store event data in In_MBox + auto& spu = static_cast(*thread); + + spu.ch_in_mbox.set_values(4, CELL_OK, static_cast(data1), static_cast(data2), static_cast(data3)); + } + else + { + throw EXCEPTION("Unexpected (queue_type=%d, thread_type=%d)", type, thread->get_type()); + } + + if (!sq.front()->signal()) + { + throw EXCEPTION("Thread already signaled"); + } + + return sq.pop_front(); } s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr attr, u64 event_queue_key, s32 size) @@ -106,6 +139,19 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode) // signal all threads to return CELL_ECANCELED for (auto& thread : queue->sq) { + if (queue->type == SYS_PPU_QUEUE && thread->get_type() == CPU_THREAD_PPU) + { + static_cast(*thread).GPR[3] = 1; + } + else if (queue->type == SYS_SPU_QUEUE && thread->get_type() == CPU_THREAD_SPU) + { + static_cast(*thread).ch_in_mbox.set_values(1, CELL_ECANCELED); + } + else + { + throw EXCEPTION("Unexpected (queue_type=%d, thread_type=%d)", queue->type, thread->get_type()); + } + thread->signal(); } @@ -171,34 +217,44 @@ s32 sys_event_queue_receive(PPUThread& ppu, u32 equeue_id, vm::ptr return CELL_EINVAL; } - if (queue->events.empty() || !queue->sq.empty()) + if (queue->events.size()) { - // add waiter; protocol is ignored in current implementation - sleep_queue_entry_t waiter(ppu, queue->sq); + // event data is returned in registers (dummy_event is not used) + std::tie(ppu.GPR[4], ppu.GPR[5], ppu.GPR[6], ppu.GPR[7]) = queue->events.front(); - while (!ppu.unsignal()) + queue->events.pop_front(); + + return CELL_OK; + } + + // cause (if cancelled) will be returned in r3 + ppu.GPR[3] = 0; + + // add waiter; protocol is ignored in current implementation + sleep_queue_entry_t waiter(ppu, queue->sq); + + while (!ppu.unsignal()) + { + CHECK_EMU_STATUS; + + if (timeout) { - CHECK_EMU_STATUS; + const u64 passed = get_system_time() - start_time; - if (timeout) + if (passed >= timeout) { - const u64 passed = get_system_time() - start_time; - - if (passed >= timeout) - { - return CELL_ETIMEDOUT; - } - - ppu.cv.wait_for(lv2_lock, std::chrono::microseconds(timeout - passed)); - } - else - { - ppu.cv.wait(lv2_lock); + return CELL_ETIMEDOUT; } + + ppu.cv.wait_for(lv2_lock, std::chrono::microseconds(timeout - passed)); + } + else + { + ppu.cv.wait(lv2_lock); } } - if (queue->events.empty()) + if (ppu.GPR[3]) { if (Emu.GetIdManager().check_id(equeue_id)) { @@ -208,11 +264,7 @@ s32 sys_event_queue_receive(PPUThread& ppu, u32 equeue_id, vm::ptr return CELL_ECANCELED; } - // event data is returned in registers (dummy_event is not used) - std::tie(ppu.GPR[4], ppu.GPR[5], ppu.GPR[6], ppu.GPR[7]) = queue->events.front(); - - queue->events.pop_front(); - + // r4-r7 registers must be set by push() return CELL_OK; }