diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index aaa90544..26b5813a 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -9,8 +9,8 @@ #include #include -#include "Objects/video_out_ctx.h" +#include "Objects/video_out_ctx.h" #include "Util/Singleton.h" namespace HLE::Libs::Graphics::VideoOut { @@ -59,6 +59,11 @@ void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attr attribute->option = SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_NONE; } +static void flip_reset_event_func(HLE::Kernel::Objects::EqueueEvent* event) { + event->isTriggered = false; + event->event.fflags = 0; + event->event.data = 0; +} s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue eq, s32 handle, void* udata) { PRINT_FUNCTION_NAME(); auto* videoOut = Singleton::Instance(); @@ -82,7 +87,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue event.event.fflags = 0; event.event.data = 0; // event.filter.delete_event_func = flip_event_delete_func;//called in sceKernelDeleteEvent //TODO - // event.filter.reset_event_func = flip_event_reset_func;//called in sceKernelWaitEqueue //TODO + event.filter.reset_event_func = flip_reset_event_func; // event.filter.trigger_event_func = flip_event_trigger_func;//called in sceKernelTriggerEvent //TODO event.filter.data = ctx; diff --git a/src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp b/src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp index 7b60822d..a92e9040 100644 --- a/src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp +++ b/src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp @@ -1,5 +1,7 @@ #include "event_queue.h" +#include + #include "debug.h" namespace HLE::Kernel::Objects { @@ -21,4 +23,51 @@ int EqueueInternal::addEvent(const EqueueEvent& event) { return 0; } +int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) { + Lib::LockMutexGuard lock(m_mutex); + + u32 timeElapsed = 0; + Lib::Timer t; + t.Start(); + + for (;;) { + int ret = getTriggeredEvents(ev, num); + + if (ret > 0 || (timeElapsed >= micros && micros != 0)) { + return ret; + } + + if (micros == 0) { + m_cond.WaitCondVar(&m_mutex); + } else { + m_cond.WaitCondVarFor(&m_mutex, micros - timeElapsed); + } + + timeElapsed = static_cast(t.GetTimeSec() * 1000000.0); + } + + return 0; +} + +int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) { + Lib::LockMutexGuard lock(m_mutex); + + int ret = 0; + + if (m_events.size() > 1) { + BREAKPOINT(); // we currently support one event + } + auto& event = m_events[0]; + + if (event.isTriggered) { + ev[ret++] = event.event; + + if (event.filter.reset_event_func != nullptr) { + event.filter.reset_event_func(&event); + } + } + + return ret; +} + }; // namespace HLE::Kernel::Objects \ No newline at end of file diff --git a/src/Core/PS4/HLE/Kernel/Objects/event_queue.h b/src/Core/PS4/HLE/Kernel/Objects/event_queue.h index 8e5bdd76..577d3627 100644 --- a/src/Core/PS4/HLE/Kernel/Objects/event_queue.h +++ b/src/Core/PS4/HLE/Kernel/Objects/event_queue.h @@ -50,7 +50,7 @@ struct SceKernelEvent { struct Filter { void* data = nullptr; TriggerFunc trigger_event_func = nullptr; - ResetFunc reset__event_func = nullptr; + ResetFunc reset_event_func = nullptr; DeleteFunc delete_event_func = nullptr; }; @@ -66,9 +66,12 @@ class EqueueInternal { virtual ~EqueueInternal(); void setName(const std::string& m_name) { this->m_name = m_name; } int addEvent(const EqueueEvent& event); + int waitForEvents(SceKernelEvent* ev, int num, u32 micros); + int getTriggeredEvents(SceKernelEvent* ev, int num); private: std::string m_name; Lib::Mutex m_mutex; std::vector m_events; + Lib::ConditionVariable m_cond; }; }; // namespace HLE::Kernel::Objects \ No newline at end of file diff --git a/src/Core/PS4/HLE/Kernel/event_queues.cpp b/src/Core/PS4/HLE/Kernel/event_queues.cpp index 15940584..dc26f820 100644 --- a/src/Core/PS4/HLE/Kernel/event_queues.cpp +++ b/src/Core/PS4/HLE/Kernel/event_queues.cpp @@ -51,7 +51,7 @@ int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, HLE::Kernel::Objects::S return SCE_KERNEL_ERROR_EINVAL; } if (timo == nullptr) { // wait until an event arrives without timing out - // BREAKPOINT();//NOT supported yet TODO + *out = eq->waitForEvents(ev, num, 0); } if (timo != nullptr) { if (*timo == 0) {//only events that have already arrived at the time of this function call can be received