From b35d67e5550230075d7b8aa6d121d460a4c6409e Mon Sep 17 00:00:00 2001 From: robojumper Date: Sat, 27 Apr 2024 09:55:06 +0200 Subject: [PATCH] eggAsyncDisplay almost --- config/SOUE01/symbols.txt | 20 +-- include/egg/core/eggAsyncDisplay.h | 16 +- include/rvl/GX/GXTev.h | 2 +- src/egg/core/eggAsyncDisplay.cpp | 226 +++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 22 deletions(-) create mode 100644 src/egg/core/eggAsyncDisplay.cpp diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 7b943c29..5c047dc9 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -21976,9 +21976,9 @@ fn_803A9B10 = .text:0x803A9B10; // type:function size:0x240 fn_803A9D50 = .text:0x803A9D50; // type:function size:0x1D4 __OSModuleInit = .text:0x803A9F30; // type:function size:0x18 scope:global fn_803A9F50 = .text:0x803A9F50; // type:function size:0xA4 -fn_803AA000 = .text:0x803AA000; // type:function size:0x60 -fn_803AA060 = .text:0x803AA060; // type:function size:0xC8 -fn_803AA130 = .text:0x803AA130; // type:function size:0xDC +OSInitMessageQueue = .text:0x803AA000; // type:function size:0x60 +OSSendMessage = .text:0x803AA060; // type:function size:0xC8 +OSReceiveMessage = .text:0x803AA130; // type:function size:0xDC fn_803AA210 = .text:0x803AA210; // type:function size:0xC OSGetPhysicalMem2Size = .text:0x803AA220; // type:function size:0xC scope:global OSGetConsoleSimulatedMem1Size = .text:0x803AA230; // type:function size:0xC scope:global @@ -22052,7 +22052,7 @@ fn_803AD330 = .text:0x803AD330; // type:function size:0xA0 fn_803AD3D0 = .text:0x803AD3D0; // type:function size:0x29C fn_803AD670 = .text:0x803AD670; // type:function size:0x18C OSSleepThread = .text:0x803AD800; // type:function size:0xF0 scope:global -fn_803AD8F0 = .text:0x803AD8F0; // type:function size:0xF8 +OSWakeupThread = .text:0x803AD8F0; // type:function size:0xF8 fn_803AD9F0 = .text:0x803AD9F0; // type:function size:0xEC fn_803ADAE0 = .text:0x803ADAE0; // type:function size:0x8 OSGetTime = .text:0x803ADAF0; // type:function size:0x18 scope:global @@ -22324,7 +22324,7 @@ GXLoadLightObjImm = .text:0x803BE790; // type:function size:0x80 GXSetChanAmbColor = .text:0x803BE810; // type:function size:0xD8 GXSetChanMatColor = .text:0x803BE8F0; // type:function size:0xD8 GXSetNumChans = .text:0x803BE9D0; // type:function size:0x24 -GXSetChanCtr1 = .text:0x803BEA00; // type:function size:0xA4 +GXSetChanCtrl = .text:0x803BEA00; // type:function size:0xA4 GXGetTexBufferSize = .text:0x803BEAB0; // type:function size:0x124 __GetImageTileCount = .text:0x803BEBE0; // type:function size:0xC0 GXInitTexObj = .text:0x803BECA0; // type:function size:0x20C @@ -22386,7 +22386,7 @@ GXSetTevKAlphaSel = .text:0x803C0700; // type:function size:0x50 GXSetTevSwapMode = .text:0x803C0750; // type:function size:0x3C GXSetTevSwapModeTable = .text:0x803C0790; // type:function size:0x7C GXSetAlphaCompare = .text:0x803C0810; // type:function size:0x38 -GXSsetZTexture = .text:0x803C0850; // type:function size:0x84 +GXSetZTexture = .text:0x803C0850; // type:function size:0x84 GXSetTevOrder = .text:0x803C08E0; // type:function size:0x15C GXSetNumTevStages = .text:0x803C0A40; // type:function size:0x24 GXSetFog = .text:0x803C0A70; // type:function size:0x22C @@ -26275,7 +26275,7 @@ getTickPerFrame__Q23EGG7DisplayFv = .text:0x804975F0; // type:function size:0x4 beginFrame__Q23EGG7DisplayFv = .text:0x80497600; // type:function size:0xB8 beginRender__Q23EGG7DisplayFv = .text:0x804976C0; // type:function size:0x4 endRender__Q23EGG7DisplayFv = .text:0x804976D0; // type:function size:0x4 -endgFrame__Q23EGG7DisplayFv = .text:0x804976E0; // type:function size:0x4 +endFrame__Q23EGG7DisplayFv = .text:0x804976E0; // type:function size:0x4 preVRetrace__Q23EGG7DisplayFv = .text:0x804976F0; // type:function size:0xDC copyEFBtoXFB__Q23EGG7DisplayFv = .text:0x804977D0; // type:function size:0x9C calcFrequency__Q23EGG7DisplayFv = .text:0x80497870; // type:function size:0x84 @@ -26290,7 +26290,7 @@ calc__Q23EGG10ColorFaderFv = .text:0x80497AB0; // type:function size:0xE4 draw__Q23EGG10ColorFaderFv = .text:0x80497BA0; // type:function size:0x29C __ct__Q23EGG12AsyncDisplayFUc = .text:0x80497E40; // type:function size:0x78 calcS__Q23EGG12AsyncDisplayFv = .text:0x80497EC0; // type:function size:0x58 -beginFrame__Q23EGG12AsyncDisplayFb = .text:0x80497F20; // type:function size:0x19C +beginFrame__Q23EGG12AsyncDisplayFv = .text:0x80497F20; // type:function size:0x19C endFrame__Q23EGG12AsyncDisplayFv = .text:0x804980C0; // type:function size:0x1C endRender__Q23EGG12AsyncDisplayFv = .text:0x804980E0; // type:function size:0x20 preVRetrace__Q23EGG12AsyncDisplayFv = .text:0x80498100; // type:function size:0x15C @@ -26299,7 +26299,7 @@ getTickPerFrame__Q23EGG12AsyncDisplayFv = .text:0x804982D0; // type:function siz clearEFB__Q23EGG12AsyncDisplayFUsUsUsUsUsUsQ34nw4r2ut5Color = .text:0x804982F0; // type:function size:0x398 initialize__Q23EGG5VideoFP16_GXRenderModeObjPCQ33EGG5Video16RenderModeObjSet = .text:0x80498690; // type:function size:0x54 configure__Q23EGG5VideoFP16_GXRenderModeObjPCQ33EGG5Video16RenderModeObjSet = .text:0x804986F0; // type:function size:0x104 -getTickPerVRetrace__Q23EGG5VideoFUl = .text:0x80498800; // type:function size:0x60 +getTickPerVRetrace__Q23EGG5VideoFUi = .text:0x80498800; // type:function size:0x60 getTickPerVRetrace__Q23EGG5VideoFv = .text:0x80498860; // type:function size:0x24 getStandardRenderModeObj__Q23EGG5VideoFv = .text:0x80498890; // type:function size:0x148 init__Q23EGG3XfbFUsUsPQ23EGG4Heap = .text:0x804989E0; // type:function size:0x74 @@ -37104,7 +37104,7 @@ lbl_8056EA58 = .data:0x8056EA58; // type:object size:0x70 __vt__Q23EGG7Display = .data:0x8056EAC8; // type:object size:0x20 lbl_8056EAE8 = .data:0x8056EAE8; // type:object size:0x38 lbl_8056EB20 = .data:0x8056EB20; // type:object size:0x40 -lbl_8056EB60 = .data:0x8056EB60; // type:object size:0x20 +__vt__Q23EGG12AsyncDisplay = .data:0x8056EB60; // type:object size:0x20 lbl_8056EB80 = .data:0x8056EB80; // type:object size:0x10 lbl_8056EB90 = .data:0x8056EB90; // type:object size:0x18 lbl_8056EBA8 = .data:0x8056EBA8; // type:object size:0xC diff --git a/include/egg/core/eggAsyncDisplay.h b/include/egg/core/eggAsyncDisplay.h index b8d94789..36109cbc 100644 --- a/include/egg/core/eggAsyncDisplay.h +++ b/include/egg/core/eggAsyncDisplay.h @@ -15,12 +15,14 @@ public: /* vt 0x18 | 804982d0 */ virtual u32 getTickPerFrame(); /* vt 0x1C | 80498100 */ virtual void preVRetrace(); +private: + inline void waitForMsg(bool); + public: /* 0x2C */ char field_0x2C[0x60 - 0x2C]; /* 0x60 */ OSThreadQueue mThreadQueue; /* 0x68 */ OSMessageQueue mMesgQueue; - /* 0x88 */ OSMessage mMesg; - /* 0x8C */ char field_0x8C[0x98 - 0x8C]; + /* 0x88 */ OSMessage mMesgBuf[4]; /* 0x98 */ s32 field_0x98; /* 0x9C */ f32 field_0x9C; /* 0xA0 */ f32 field_0xA0; @@ -34,19 +36,11 @@ public: public: /* 80497e40 */ AsyncDisplay(u8 maxRetrace); - /* 80497ec0 */ void calcS(); + /* 80497ec0 */ f32 calcS(); /* 80498260 */ void clearEFB(); /* 804982f0 */ void clearEFB(u16, u16, u16, u16, u16, u16, nw4r::ut::Color); }; } // namespace EGG -#ifdef __cplusplus -extern "C" { -#endif -/* 80576790 */ static EGG::AsyncDisplay *spSelector; -#ifdef __cplusplus -} -#endif - #endif diff --git a/include/rvl/GX/GXTev.h b/include/rvl/GX/GXTev.h index c53c04b6..5e4438b0 100644 --- a/include/rvl/GX/GXTev.h +++ b/include/rvl/GX/GXTev.h @@ -21,7 +21,7 @@ void GXSetTevSwapMode(GXTevStageID, GXTevSwapSel, GXTevSwapSel); void GXSetTevSwapModeTable(GXTevSwapSel, GXTevColorChan, GXTevColorChan, GXTevColorChan, GXTevColorChan); void GXSetAlphaCompare(GXCompare, u8, GXAlphaOp, GXCompare, u8); -void GXSetZTexture(UNKWORD, UNKWORD, UNKWORD); +void GXSetZTexture(UNKWORD, GXTexFmt, u32); void GXSetTevOrder(GXTevStageID, GXTexCoordID, GXTexMapID, GXChannelID); void GXSetNumTevStages(u8); diff --git a/src/egg/core/eggAsyncDisplay.cpp b/src/egg/core/eggAsyncDisplay.cpp new file mode 100644 index 00000000..8aaf943c --- /dev/null +++ b/src/egg/core/eggAsyncDisplay.cpp @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include + +// This file still has incorrect sdata2 + +static EGG::AsyncDisplay *lbl_80576790[2]; + +namespace EGG { + +AsyncDisplay::AsyncDisplay(u8 maxRetrace): Display(maxRetrace) { + this->field_0x98 = 0.0; + this->field_0x9C = 0.0; + this->field_0xA4 = 0; + this->field_0xA8 = 0; + this->field_0xAC = 0; + this->field_0xB8 = 0; + lbl_80576790[0] = this; + OSInitThreadQueue(&this->mThreadQueue); + OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuf, 4); +} + +f32 AsyncDisplay::calcS() { + f32 tmp = this->field_0x9C + this->field_0xA0; + this->field_0x9C = tmp; + if (!(tmp > 1.0f)) { + return tmp; + } + + if (this->mScreenStateFlag.onBit(4)) { + this->field_0x9C = tmp - 1.0f; + this->mScreenStateFlag.resetBit(4); + } else { + this->field_0x9C = tmp - this->field_0xA0; + this->mScreenStateFlag.setBit(4); + } + return tmp; +} + +inline void AsyncDisplay::waitForMsg(bool b) { + // This is really ugly but I couldn't find a different way + // to make the compiler use the registers + XfbManager *xfb; + while (!((xfb = BaseSystem::mConfigData->getXfbMgr(), 1 < xfb->mNumXfbs - this->field_0xAC) && (BaseSystem::mConfigData->getXfbMgr()->mToCopyXfb != nullptr || b))) { + + OSReceiveMessage(&this->mMesgQueue, this->mMesgBuf, 1); + + while (OSReceiveMessage(&this->mMesgQueue, this->mMesgBuf, 0)) {} + } +} + +void AsyncDisplay::beginFrame() { + BaseSystem::mConfigData->getXfbMgr(); + GXDrawDone(); + + if (this->mFlag.onBit(1)) { + OSSleepThread(&this->mThreadQueue); + } + bool b = false; + if (BaseSystem::mConfigData->getXfbMgr()->mNumXfbs == 1) { + s32 tick = OSGetTick(); + s32 lastTick = this->mLastTick; + if (tick - lastTick > Display::sTickPeriod) { + VIWaitForRetrace(); + } + } else { + b = false; + if (this->field_0x98 == 1 && this->mScreenStateFlag.onBit(6)) { + b = true; + } + + this->waitForMsg(b); + } + + if (b) { + this->clearEFB(); + this->mScreenStateFlag.resetBit(6); + GXDrawDone(); + } else { + this->copyEFBtoXFB(); + } + + if (this->field_0x98 == 1) { + this->calcS(); + } + this->field_0xAC++; + this->mFrameCount++; + this->calcFrequency(); +} + +void AsyncDisplay::endFrame() { + if (this->mScreenStateFlag.onBit(4)) { + this->mScreenStateFlag.setBit(5); + } +} + +void AsyncDisplay::endRender() { + if (this->mScreenStateFlag.onBit(5)) { + this->mScreenStateFlag.setBit(6); + this->mScreenStateFlag.resetBit(5); + } +} + +void AsyncDisplay::preVRetrace() { + s32 tick = OSGetTick(); + this->mLastTick = tick; + if (this->field_0x98 == 0) { + u32 a8 = ++this->field_0xA8; + if (a8 - this->field_0xA4 >= this->mMaxRetraces) { + this->field_0xA4 = a8; + this->mScreenStateFlag.setBit(3); + OSSendMessage(&this->mMesgQueue, this->mMesgBuf, 0); + if (this->field_0xAC > 0) { + this->field_0xAC--; + } + } + OSWakeupThread(&this->mThreadQueue); + } + + if (this->mScreenStateFlag.onBit(3)) { + s32 count = VIGetRetraceCount(); + if (count - this->mRetraceCount >= this->mMaxRetraces) { + if (this->mScreenStateFlag.onBit(0)) { + Video *video = BaseSystem::mConfigData->getVideo(); + VISetBlack(video->mFlag.offBit(0)); + if (video->mFlag.offBit(0)) { + video->mFlag.setBit(0); + } else { + video->mFlag.resetBit(0); + } + this->mScreenStateFlag.resetBit(0); + } + XfbManager *xfb = BaseSystem::mConfigData->getXfbMgr(); + xfb->setNextFrameBuffer(); + s32 newCount = VIGetRetraceCount(); + this->mRetraceCount = newCount; + this->mScreenStateFlag.resetBit(3); + } + } +} + +void AsyncDisplay::clearEFB() { + Video *video = BaseSystem::mConfigData->getVideo(); + GXRenderModeObj const *renderMode = video->pRenderMode; + this->clearEFB(renderMode->fbWidth, renderMode->efbHeight, 0, 0, renderMode->fbWidth, renderMode->efbHeight, this->mClearColor); +} + +u32 AsyncDisplay::getTickPerFrame() { + if (this->field_0x98 == 1) { + return Video::getTickPerVRetrace(0); + } else { + return Video::getTickPerVRetrace(); + } +} + +// TODO move +extern "C" { + extern GXTexObj lbl_80673B20, lbl_8056EB20; + extern Matrix34f lbl_80674C00; +} + +void AsyncDisplay::clearEFB(u16 fbWidth, u16 fbHeight, u16 x, u16 y, u16 width, u16 height, nw4r::ut::Color color) { + + GXInitTexObj(&lbl_80673B20, &lbl_8056EB20, 4, 4, GX_TF_Z24X8, GX_REPEAT, GX_REPEAT, 0); + GXInitTexObjLOD(&lbl_80673B20, GX_NEAR, GX_NEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1); + Mtx44 mat; + C_MTXOrtho(mat, 0.0, (float)fbHeight, 0.0, (float)fbWidth, 0.0, 1.0f); + GXSetProjection(mat, GX_ORTHOGRAPHIC); + GXSetViewport(0.0, 0.0, (float)fbWidth, (float)fbHeight, 0.0, 1.0f); + GXSetScissor(0, 0, fbWidth, fbHeight); + lbl_80674C00.loadPosMtx(0); + GXSetCurrentMtx(0); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGBX8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGB565, 0); + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanCtrl(GX_COLOR1A1, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetNumTexGens(1); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c, false, 0x7d); + GXLoadTexObj(&lbl_80673B20, GX_TEXMAP0); + GXSetNumTevStages(1); + GXSetTevColor(GX_TEVREG0, color); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_TEV_SCALE_0, 1, GX_TEVPREV); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + GXSetZTexture(2, GX_TF_Z24X8, 0); + GXSetZCompLoc(false); + GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_NOOP); + GXSetAlphaUpdate(true); + GXSetDstAlpha(true, color.a); + GXSetZMode(true, GX_ALWAYS, true); + GXSetCullMode(GX_CULL_BACK); + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + // The regs are wrong here + WGPIPE.us = x; + WGPIPE.us = y; + WGPIPE.c = 0; + WGPIPE.c = 0; + WGPIPE.us = x + width; + WGPIPE.us = y; + WGPIPE.c = 1; + WGPIPE.c = 0; + WGPIPE.us = x + width; + WGPIPE.us = y + height; + WGPIPE.c = 1; + WGPIPE.c = 1; + WGPIPE.us = width; + WGPIPE.us = y + height; + WGPIPE.c = 0; + WGPIPE.c = 1; + + GXSetZTexture(0, GX_TF_Z24X8, 0); + GXSetZCompLoc(true); + GXSetDstAlpha(false, color.a); +} + +} // namespace EGG