#include "JSystem/JSystem.h" // IWYU pragma: keep #include "JSystem/JUtility/JUTVideo.h" #include "JSystem/JUtility/JUTDirectPrint.h" #include "JSystem/JUtility/JUTXfb.h" #include #include #include "JSystem/JKernel/JKRHeap.h" JUTVideo* JUTVideo::sManager; OSTick JUTVideo::sVideoLastTick; OSTick JUTVideo::sVideoInterval; static bool data_80451544; JUTVideo* JUTVideo::createManager(GXRenderModeObj const* param_0) { if (sManager == NULL) { sManager = JKR_NEW JUTVideo(param_0); } return sManager; } void JUTVideo::destroyManager() { if (sManager != NULL) { JKR_DELETE(sManager); sManager = NULL; } } JUTVideo::JUTVideo(GXRenderModeObj const* param_0) { mRenderObj = NULL; VIInit(); mSetBlack = true; mSetBlackFrameCount = 2; setRenderMode(param_0); VISetBlack(1); VIFlush(); field_0x8 = 0; mRetraceCount = VIGetRetraceCount(); field_0x10 = 1; field_0x18 = 0; sVideoLastTick = OSGetTick(); sVideoInterval = 670000; mPreRetraceCallback = VISetPreRetraceCallback(preRetraceProc); mPostRetraceCallback = VISetPostRetraceCallback(postRetraceProc); mPreCallback = NULL; mPostCallback = NULL; OSInitMessageQueue(&mMessageQueue, &mMessage, 1); GXSetDrawDoneCallback(drawDoneCallback); } JUTVideo::~JUTVideo() { VISetPreRetraceCallback(mPreRetraceCallback); VISetPostRetraceCallback(mPostRetraceCallback); } void JUTVideo::preRetraceProc(u32 retrace_count) { #if PLATFORM_GCN if (!sManager) { return; } #endif if (sManager->mPreCallback) { (*sManager->mPreCallback)(retrace_count); } OSTick tick = OSGetTick(); sVideoInterval = tick - sVideoLastTick; sVideoLastTick = tick; JUTXfb* xfb = JUTXfb::getManager(); if (!xfb) { VISetBlack(TRUE); VIFlush(); return; } static void* frameBuffer = NULL; #ifndef TARGET_PC if (frameBuffer) { const GXRenderModeObj* renderMode = JUTGetVideoManager()->getRenderMode(); u16 width = renderMode->fbWidth; u16 height = renderMode->efbHeight; JUTDirectPrint::getManager()->changeFrameBuffer(frameBuffer, width, height); } #endif if (getManager()->mSetBlack == 1) { s32 frame_count = getManager()->mSetBlackFrameCount; if (frame_count > 0) { frame_count--; } getManager()->mSetBlackFrameCount = frame_count; getManager()->mSetBlack = frame_count ? true : false; VISetBlack(TRUE); VIFlush(); return; } if (!xfb) { VISetBlack(TRUE); VIFlush(); return; } if (xfb->getBufferNum() == 3 || xfb->getBufferNum() == 2) { if (!data_80451544) { s16 index = xfb->getDrawnXfbIndex(); xfb->setDisplayingXfbIndex(index); if (index < 0) { VISetBlack(1); VIFlush(); } else { VISetNextFrameBuffer(xfb->getDisplayingXfb()); VIFlush(); VISetBlack(FALSE); frameBuffer = xfb->getDisplayingXfb(); } } } else if (xfb->getBufferNum() == 1) { if (xfb->getSDrawingFlag() == 0) { s16 index = xfb->getDrawnXfbIndex(); if (index >= 0) { xfb->setDisplayingXfbIndex(index); GXCopyDisp(xfb->getDisplayingXfb(), GX_TRUE); GXFlush(); xfb->setSDrawingFlag(2); frameBuffer = xfb->getDisplayingXfb(); if (VIGetNextFrameBuffer()) { VISetBlack(FALSE); } } else { VISetBlack(TRUE); } } VIFlush(); } } void JUTVideo::drawDoneStart() { data_80451544 = true; GXSetDrawDone(); } void JUTVideo::dummyNoDrawWait() { data_80451544 = false; } void JUTVideo::drawDoneCallback() { JUTXfb* xfb = JUTXfb::getManager(); if (!xfb) { return; } data_80451544 = false; if (xfb->getBufferNum() == 1) { if (xfb->getSDrawingFlag() == 1) { xfb->setSDrawingFlag(0); if (xfb->getDrawnXfb()) { VISetNextFrameBuffer(xfb->getDrawnXfb()); VIFlush(); } } } } void JUTVideo::postRetraceProc(u32 retrace_count) { #if PLATFORM_GCN if (!sManager) { return; } #endif if (sManager->mPostCallback != NULL) { sManager->mPostCallback(retrace_count); } #ifndef TARGET_PC // Not read by JFWDisplay waitForTick OSSendMessage(&sManager->mMessageQueue, (OSMessage)(uintptr_t)VIGetRetraceCount(), OS_MESSAGE_NOBLOCK); #endif } void JUTVideo::setRenderMode(GXRenderModeObj const* pObj) { if (mRenderObj != NULL && pObj->viTVmode != mRenderObj->viTVmode) { mSetBlack = true; mSetBlackFrameCount = 4; } mRenderObj = (GXRenderModeObj*)pObj; VIConfigure(mRenderObj); VIFlush(); if (mSetBlack) { VIWaitForRetrace(); VIWaitForRetrace(); } } void JUTVideo::waitRetraceIfNeed() {} #if TARGET_PC void JUTVideo::setRenderSize(u32 width, u32 height) { mRenderWidth = width; mRenderHeight = height; } #endif