diff --git a/src/Core/PS4/HLE/ErrorCodes.h b/src/Core/PS4/HLE/ErrorCodes.h index 2ec6ec15..f80a8e02 100644 --- a/src/Core/PS4/HLE/ErrorCodes.h +++ b/src/Core/PS4/HLE/ErrorCodes.h @@ -8,5 +8,7 @@ constexpr int SCE_KERNEL_ERROR_EAGAIN = 0x80020023; // Memory cannot be a constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = 0x8002003f; // character strings exceeds valid size // videoOut -constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument -constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already opened +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument +constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already opened +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_HANDLE = 0x8029000B; // invalid handle +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = 0x8029000C; // Invalid event queue diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp index cf670a6b..50c6772d 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp @@ -14,7 +14,7 @@ int VideoOutCtx::Open() { int handle = -1; if (!m_video_out_ctx.isOpened) { - handle = 1;//positive return , should be more than 1 ? + handle = 1; // positive return , should be more than 1 ? } m_video_out_ctx.isOpened = true; @@ -26,4 +26,9 @@ int VideoOutCtx::Open() { return handle; } + +VideoConfigInternal* VideoOutCtx::getCtx(int handle) { + if (handle != 1) return nullptr; + return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more +} }; // namespace HLE::Graphics::Objects \ No newline at end of file diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h index a5659fb0..21efccb5 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h @@ -12,6 +12,7 @@ struct VideoConfigInternal { bool isOpened = false; SceVideoOutFlipStatus m_flip_status; SceVideoOutVblankStatus m_vblank_status; + std::vector flip_evtEq; }; class VideoOutCtx { @@ -21,6 +22,7 @@ class VideoOutCtx { virtual ~VideoOutCtx() {} void Init(u32 width, u32 height); int Open(); + VideoConfigInternal* getCtx(int handle); private: Lib::Mutex m_mutex; VideoConfigInternal m_video_out_ctx; diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index 94210c5f..7089506f 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -60,9 +60,40 @@ void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attr } s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue eq, s32 handle, void* udata) { - // BREAKPOINT(); - PRINT_DUMMY_FUNCTION_NAME(); - return 0; + PRINT_FUNCTION_NAME(); + auto* videoOut = Singleton::Instance(); + + auto* ctx = videoOut->getCtx(handle); + + if (ctx == nullptr) + { + return SCE_VIDEO_OUT_ERROR_INVALID_HANDLE; + } + ctx->m_mutex.LockMutex(); + + if (eq == nullptr) { + return SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE; + } + + HLE::Kernel::Objects::EqueueEvent event; + event.isTriggered = false; + event.event.ident = SCE_VIDEO_OUT_EVENT_FLIP; + event.event.filter = HLE::Kernel::Objects::EVFILT_VIDEO_OUT; + event.event.udata = udata; + event.event.fflags = 0; + event.event.data = 0; + // event.filter.delete_event_func = flip_event_delete_func;//called in sceKernelDeleteEvent + // event.filter.reset_event_func = flip_event_reset_func;//called in sceKernelWaitEqueue + // event.filter.trigger_event_func = flip_event_trigger_func;//called in sceKernelTriggerEvent + event.filter.data = ctx; + + int result = 0; // sceKernelAddEvent(eq, event); + + ctx->flip_evtEq.push_back(eq); + + ctx->m_mutex.UnlockMutex(); + + return result; } s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses, s32 bufferNum, diff --git a/src/Core/PS4/HLE/Graphics/video_out.h b/src/Core/PS4/HLE/Graphics/video_out.h index 60c6fc95..09761177 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.h +++ b/src/Core/PS4/HLE/Graphics/video_out.h @@ -35,6 +35,11 @@ constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_NONE = 0; constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_VR = 7; constexpr int SCE_VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_STRICT_COLORIMETRY = 8; +//SceVideoOutEventId +constexpr int SCE_VIDEO_OUT_EVENT_FLIP = 0; +constexpr int SCE_VIDEO_OUT_EVENT_VBLANK = 1; +constexpr int SCE_VIDEO_OUT_EVENT_PRE_VBLANK_START = 2; + enum SceVideoOutTilingMode : s32 { SCE_VIDEO_OUT_TILING_MODE_TILE = 0, SCE_VIDEO_OUT_TILING_MODE_LINEAR = 1 }; enum AspectRatioMode : s32 { SCE_VIDEO_OUT_ASPECT_RATIO_16_9 = 0 }; diff --git a/src/Core/PS4/HLE/Kernel/Objects/event_queue.h b/src/Core/PS4/HLE/Kernel/Objects/event_queue.h index 930848d4..389a66a1 100644 --- a/src/Core/PS4/HLE/Kernel/Objects/event_queue.h +++ b/src/Core/PS4/HLE/Kernel/Objects/event_queue.h @@ -1,7 +1,64 @@ #pragma once +#include + #include namespace HLE::Kernel::Objects { + +constexpr s16 EVFILT_READ = -1; +constexpr s16 EVFILT_WRITE = -2; +constexpr s16 EVFILT_AIO = -3; // attached to aio requests +constexpr s16 EVFILT_VNODE = -4; // attached to vnodes +constexpr s16 EVFILT_PROC = -5; // attached to struct proc +constexpr s16 EVFILT_SIGNAL = -6; // attached to struct proc +constexpr s16 EVFILT_TIMER = -7; // timers +constexpr s16 EVFILT_FS = -9; // filesystem events +constexpr s16 EVFILT_LIO = -10; // attached to lio requests +constexpr s16 EVFILT_USER = -11; // User events +constexpr s16 EVFILT_POLLING = -12; +constexpr s16 EVFILT_VIDEO_OUT = -13; +constexpr s16 EVFILT_GRAPHICS_CORE = -14; +constexpr s16 EVFILT_HRTIMER = -15; +constexpr s16 EVFILT_UVD_TRAP = -16; +constexpr s16 EVFILT_VCE_TRAP = -17; +constexpr s16 EVFILT_SDMA_TRAP = -18; +constexpr s16 EVFILT_REG_EV = -19; +constexpr s16 EVFILT_GPU_EXCEPTION = -20; +constexpr s16 EVFILT_GPU_SYSTEM_EXCEPTION = -21; +constexpr s16 EVFILT_GPU_DBGGC_EV = -22; +constexpr s16 EVFILT_SYSCOUNT = 22; + +class EqueueInternal; +struct EqueueEvent; + +using SceKernelEqueue = Kernel::Objects::EqueueInternal*; + +using trigger_func_ptr = void (*)(EqueueEvent* event, void* trigger_data); +using reset_func_ptr = void (*)(EqueueEvent* event); +using delete_func_ptr = void (*)(SceKernelEqueue eq, EqueueEvent* event); + +struct Event { + u64 ident = 0; /* identifier for this event */ + s16 filter = 0; /* filter for event */ + u16 flags = 0; + u32 fflags = 0; + s64 data = 0; + void* udata = nullptr; /* opaque user data identifier */ +}; + +struct Filter { + void* data = nullptr; + trigger_func_ptr trigger_event_func = nullptr; + reset_func_ptr reset__event_func = nullptr; + delete_func_ptr delete_event_func = nullptr; +}; + +struct EqueueEvent { + bool isTriggered = false; + Event event; + Filter filter; +}; + class EqueueInternal { public: EqueueInternal() = default;