From b0cd6e5178d35ccf65b61136bd1147bf96452203 Mon Sep 17 00:00:00 2001
From: georgemoralis <giorgosmrls@gmail.com>
Date: Sun, 7 Apr 2024 09:27:41 +0300
Subject: [PATCH] added sceVideoOutGetVblankStatus

---
 .../HLE/Graphics/Objects/video_out_ctx.cpp    | 12 +++++++++
 .../PS4/HLE/Graphics/Objects/video_out_ctx.h  |  1 +
 src/core/PS4/HLE/Graphics/video_out.cpp       | 25 ++++++++++++++++---
 src/core/PS4/HLE/Graphics/video_out.h         |  1 +
 src/emulator.cpp                              |  1 +
 5 files changed, 37 insertions(+), 3 deletions(-)

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 f150df40..34339649 100644
--- a/src/core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp
+++ b/src/core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp
@@ -56,6 +56,18 @@ void VideoOutCtx::Close(s32 handle) {
     m_video_out_ctx.buffers_registration_index = 0;
 }
 
+void VideoOutCtx::Vblank() {
+    std::scoped_lock lock{m_mutex};
+
+    if (m_video_out_ctx.isOpened) {
+        m_video_out_ctx.m_mutex.lock();
+        m_video_out_ctx.m_vblank_status.count++;
+        m_video_out_ctx.m_vblank_status.processTime =
+            Core::Libraries::LibKernel::sceKernelGetProcessTime();
+        m_video_out_ctx.m_vblank_status.tsc = Core::Libraries::LibKernel::sceKernelReadTsc();
+        m_video_out_ctx.m_mutex.unlock();
+    }
+}
 VideoConfigInternal* VideoOutCtx::getCtx(int handle) {
     if (handle != 1) [[unlikely]] {
         return nullptr;
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 83e30ec3..6e801b35 100644
--- a/src/core/PS4/HLE/Graphics/Objects/video_out_ctx.h
+++ b/src/core/PS4/HLE/Graphics/Objects/video_out_ctx.h
@@ -78,6 +78,7 @@ public:
 
         return m_graphic_ctx;
     }
+    void Vblank();
 
 private:
     std::mutex m_mutex;
diff --git a/src/core/PS4/HLE/Graphics/video_out.cpp b/src/core/PS4/HLE/Graphics/video_out.cpp
index 82c789bb..536c7215 100644
--- a/src/core/PS4/HLE/Graphics/video_out.cpp
+++ b/src/core/PS4/HLE/Graphics/video_out.cpp
@@ -32,6 +32,10 @@ bool videoOutFlip(u32 micros) {
     auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
     return videoOut->getFlipQueue().flip(micros);
 }
+void VideoOutVblank() {
+    auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
+    return videoOut->Vblank();
+}
 
 std::string getPixelFormatString(s32 format) {
     switch (format) {
@@ -127,9 +131,22 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 h
     return result;
 }
 
-s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses,
-                                            s32 bufferNum,
-                                            const SceVideoOutBufferAttribute* attribute) {
+s32 PS4_SYSV_ABI sceVideoOutGetVblankStatus(int handle, SceVideoOutVblankStatus* status) {
+    if (status == nullptr) {
+        return SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS;
+    }
+
+    auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
+    auto* ctx = videoOut->getCtx(handle);
+
+    ctx->m_mutex.lock();
+    *status = ctx->m_vblank_status;
+    ctx->m_mutex.unlock();
+    return SCE_OK;
+}
+
+s32 sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses, s32 bufferNum,
+                               const SceVideoOutBufferAttribute* attribute) {
     auto* videoOut = Common::Singleton<HLE::Graphics::Objects::VideoOutCtx>::Instance();
     auto* ctx = videoOut->getCtx(handle);
 
@@ -346,6 +363,8 @@ void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym) {
     LIB_FUNCTION("N5KDtkIjjJ4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
                  sceVideoOutUnregisterBuffers);
     LIB_FUNCTION("uquVH4-Du78", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutClose);
+    LIB_FUNCTION("1FZBKy8HeNU", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
+                 sceVideoOutGetVblankStatus);
 
     // openOrbis appears to have libSceVideoOut_v1 module libSceVideoOut_v1.1
     LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutOpen);
diff --git a/src/core/PS4/HLE/Graphics/video_out.h b/src/core/PS4/HLE/Graphics/video_out.h
index 3a0e41ac..2086f798 100644
--- a/src/core/PS4/HLE/Graphics/video_out.h
+++ b/src/core/PS4/HLE/Graphics/video_out.h
@@ -110,6 +110,7 @@ void videoOutInit(u32 width, u32 height);
 std::string getPixelFormatString(s32 format);
 void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym);
 bool videoOutFlip(u32 micros);
+void VideoOutVblank();
 
 void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute,
                                                 u32 pixelFormat, u32 tilingMode, u32 aspectRatio,
diff --git a/src/emulator.cpp b/src/emulator.cpp
index 3600f0bc..a4e37976 100644
--- a/src/emulator.cpp
+++ b/src/emulator.cpp
@@ -203,6 +203,7 @@ void emuRun() {
                     calculateFps(0);                                       // TODO: Proper fps
                 }
             }
+            HLE::Libs::Graphics::VideoOut::VideoOutVblank();
         }
     }
 }