From 8c8676aed1141d47fc529fc447967885527835ac Mon Sep 17 00:00:00 2001 From: robojumper Date: Tue, 25 Mar 2025 22:20:21 +0100 Subject: [PATCH] StateEfb less one regswap --- config/SOUE01/symbols.txt | 14 +- include/egg/gfx/eggFrustum.h | 4 +- include/egg/gfx/eggGlobalDrawState.h | 2 +- include/egg/gfx/eggStateEfb.h | 9 ++ src/egg/gfx/eggCamera.cpp | 3 +- src/egg/gfx/eggStateEfb.cpp | 193 ++++++++++++++++++++++++++- 6 files changed, 211 insertions(+), 14 deletions(-) diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 2b094dbd..ad595dbb 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -26759,11 +26759,11 @@ GetBinarySize__Q23EGG33IBinaryCFv = .text:0x804B3D50; Clean__Q23EGG8StateEfbFv = .text:0x804B3DA0; // type:function size:0x78 captureEfb__Q23EGG8StateEfbFQ33EGG8StateEfb10BufferTypebUl = .text:0x804B3E20; // type:function size:0x3C8 releaseEfb__Q23EGG8StateEfbFQ33EGG8StateEfb10BufferTypeUl = .text:0x804B41F0; // type:function size:0x7C -FUN_804b4270 = .text:0x804B4270; // type:function size:0x98 -FUN_804b4310 = .text:0x804B4310; // type:function size:0x23C -FUN_804b4550 = .text:0x804B4550; // type:function size:0xA0 -FUN_804b45f0 = .text:0x804B45F0; // type:function size:0xC -FUN_804b4600 = .text:0x804B4600; // type:function size:0xC +fn_804B4270__Q23EGG8StateEfbFQ33EGG8StateEfb10BufferTypeUl = .text:0x804B4270; // type:function size:0x98 +fn_804B4310__Q23EGG8StateEfbFQ33EGG8StateEfb10BufferTypeUl = .text:0x804B4310; // type:function size:0x23C +fn_804B4550__Q23EGG8StateEfbFv = .text:0x804B4550; // type:function size:0xA0 +GetShouldCapture__Q23EGG8StateEfbFv = .text:0x804B45F0; // type:function size:0xC +GetUseTfRgb565__Q23EGG8StateEfbFv = .text:0x804B4600; // type:function size:0xC texRegionCallback__24@unnamed@eggStateGX_cpp@FPC9_GXTexObj11_GXTexMapID = .text:0x804B4610; // type:function size:0x28 initialize__Q23EGG7StateGXFUsUs8_GXColor11_GXPixelFmt = .text:0x804B4640; // type:function size:0x114 frameInit__Q23EGG7StateGXFv = .text:0x804B4760; // type:function size:0xA8 @@ -39835,8 +39835,8 @@ lbl_80574F3C = .sdata:0x80574F3C; // type:object size:0xC sByteCodeCalcStr__Q23EGG7ModelEx = .sdata:0x80574F48; // type:object size:0x4 data:4byte lbl_80574F50 = .sdata:0x80574F50; // type:object size:0x8 data:string sByteCodeMixStr__Q23EGG7ModelEx = .sdata:0x80574F58; // type:object size:0x4 data:4byte -lbl_80574F60 = .sdata:0x80574F60; // type:object size:0x4 data:4byte -lbl_80574F64 = .sdata:0x80574F64; // type:object size:0x4 data:4byte +sFlag__Q23EGG8StateEfb = .sdata:0x80574F60; // type:object size:0x4 data:4byte +sWorkBuffer__Q23EGG8StateEfb = .sdata:0x80574F64; // type:object size:0x4 data:4byte sAudioRmtSpeakerWpadVolume__Q23EGG18AudioRmtSpeakerMgr = .sdata:0x80574F68; // type:object size:0x1 data:byte sHBFadeframe__Q33EGG12AudioUtility3HBM = .sdata:0x80574F70; // type:object size:0x4 data:4byte fragmentID = .sdata:0x80574F78; // type:object size:0x4 scope:local data:4byte diff --git a/include/egg/gfx/eggFrustum.h b/include/egg/gfx/eggFrustum.h index 877a4940..5165935c 100644 --- a/include/egg/gfx/eggFrustum.h +++ b/include/egg/gfx/eggFrustum.h @@ -24,8 +24,8 @@ public: CANVASMODE_0, CANVASMODE_1, }; - -protected: + + protected: ProjectionType mProjType; // at 0x0 CanvasMode mCanvasMode; // at 0x4 nw4r::math::VEC2 mSize; // at 0x8 diff --git a/include/egg/gfx/eggGlobalDrawState.h b/include/egg/gfx/eggGlobalDrawState.h index a85dfbb6..19f38fff 100644 --- a/include/egg/gfx/eggGlobalDrawState.h +++ b/include/egg/gfx/eggGlobalDrawState.h @@ -31,10 +31,10 @@ public: sDrawFlag &= ~flag; } + static Screen const *spScreen; private: static u16 sCameraId; static u32 sDrawFlag; - static Screen const *spScreen; // unknown static nw4r::math::MTX34 sMtx; diff --git a/include/egg/gfx/eggStateEfb.h b/include/egg/gfx/eggStateEfb.h index 97e82605..eabf22d2 100644 --- a/include/egg/gfx/eggStateEfb.h +++ b/include/egg/gfx/eggStateEfb.h @@ -30,9 +30,18 @@ class StateEfb { static s32 sPushCount; static u32 sFlag; + static f32 *fn_804B4550(); + static bool GetShouldCapture(); + static bool GetUseTfRgb565(); + public: static void Clean(); + static TextureBuffer *captureEfb(BufferType type, bool, u32 userData); static bool releaseEfb(BufferType type, u32 userData); + + // Unknown names + static void fn_804B4270(BufferType type, u32 userData); + static void fn_804B4310(BufferType type, u32 userData); }; } // namespace EGG diff --git a/src/egg/gfx/eggCamera.cpp b/src/egg/gfx/eggCamera.cpp index ed474b66..2417ba89 100644 --- a/src/egg/gfx/eggCamera.cpp +++ b/src/egg/gfx/eggCamera.cpp @@ -78,14 +78,13 @@ OrthoCamera::OrthoCamera() { } void OrthoCamera::update_parms() { - // NONMATCHING f32 z = field_0x8C; f32 sin = field_0x88.sin(); f32 cos = field_0x88.cos(); - mPos(2) = z; mPos(1) = mAt(1); mPos(0) = mAt(0); + mPos(2) = z; mUp(2) = 0.f; mUp(1) = cos; mUp(0) = sin; diff --git a/src/egg/gfx/eggStateEfb.cpp b/src/egg/gfx/eggStateEfb.cpp index 39a4a588..919d324e 100644 --- a/src/egg/gfx/eggStateEfb.cpp +++ b/src/egg/gfx/eggStateEfb.cpp @@ -1,7 +1,14 @@ #include "egg/gfx/eggStateEfb.h" #include "common.h" +#include "egg/gfx/eggDrawGX.h" +#include "egg/gfx/eggGlobalDrawState.h" +#include "egg/gfx/eggScreen.h" +#include "egg/gfx/eggStateGX.h" #include "egg/gfx/eggTextureBuffer.h" +#include "nw4r/math/math_types.h" +#include "rvl/GX/GXTypes.h" +#include "rvl/MTX/mtx.h" namespace EGG { @@ -19,17 +26,111 @@ void StateEfb::Clean() { sFlag &= ~(1 | 2); sWorkBuffer = -1; sPushCount = 0; - + for (u32 i = 0; i < ARRAY_LENGTH(spBufferSet); i++) { spBufferSet[i].field_0x08 = 0; } - + for (u32 i = 0; i < ARRAY_LENGTH(sWorkSpaceV); i++) { sWorkSpaceV[i] = 0.0f; sWorkSpaceHideV[i] = 0.0f; } } +TextureBuffer *StateEfb::captureEfb(BufferType type, bool noTransparencyMaybe, u32 userData) { + // NONMATCHING - GPR regswaps + const Screen::DataEfb &efb = GlobalDrawState::getScreen().GetDataEfb(); + + if (spBufferSet[type].buf == nullptr) { + f32 x1 = efb.vp.x1; + f32 y1 = efb.vp.y1; + + bool doUpscale = false; + bool doCapture = true; + + switch (type) { + case BUFFER_0: + case BUFFER_1: { + f32 arg; + if (type == BUFFER_0) { + arg = 0.25f; + } else { + arg = 0.5f; + } + + sWorkSpaceV[2] = efb.vp.x2 * arg; + sWorkSpaceV[3] = efb.vp.y2 * arg; + + sWorkSpaceV[2] = (int)sWorkSpaceV[2] + (int)sWorkSpaceV[2] % 2; + sWorkSpaceV[3] = (int)sWorkSpaceV[3] + (int)sWorkSpaceV[3] % 2; + + if (sWorkSpaceV[2] > sWorkSpaceV[3]) { + sWorkSpaceV[3] = sWorkSpaceV[2]; + } else { + sWorkSpaceV[2] = sWorkSpaceV[3]; + } + + sWorkSpaceV[0] = 640.0f - sWorkSpaceV[2]; + sWorkSpaceHideV[0] = sWorkSpaceV[0]; + sWorkSpaceV[1] = 528.0f - sWorkSpaceV[3]; + sWorkSpaceHideV[1] = sWorkSpaceV[1]; + + sWorkSpaceHideV[2] = sWorkSpaceV[2] - (640 - StateGX::s_widthEfb); + sWorkSpaceHideV[3] = sWorkSpaceV[3] - (528 - StateGX::s_heightEfb); + + if (sWorkSpaceHideV[2] < 0.0f) { + sWorkSpaceHideV[2] = 0.0f; + } + if (sWorkSpaceHideV[3] < 0.0f) { + sWorkSpaceHideV[3] = 0.0f; + } + + x1 = sWorkSpaceV[0]; + y1 = sWorkSpaceV[1]; + + TextureBuffer *buf = TextureBuffer::alloc(sWorkSpaceHideV[2], sWorkSpaceHideV[3], GX_TF_RGBA8); + spBufferSet[type].buf = buf; + if (spBufferSet[type].buf != nullptr) { + spBufferSet[type].buf->setPixModeSync(false); + } + doCapture = GetShouldCapture(); + break; + } + + case BUFFER_2: + spBufferSet[type].buf = TextureBuffer::alloc(efb.vp.x2, efb.vp.y2, GX_TF_RGBA8); + spBufferSet[type].buf->setPixModeSync(false); + break; + case BUFFER_3: + spBufferSet[type].buf = TextureBuffer::alloc( + efb.vp.x2 / 2.0f, efb.vp.y2 / 2.0f, GetUseTfRgb565() ? GX_TF_RGB565 : GX_TF_RGBA8 + ); + doUpscale = true; + break; + default: break; + } + + if (spBufferSet[type].buf != nullptr) { + spBufferSet[type].userData = userData; + if (noTransparencyMaybe) { + spBufferSet[type].buf->onCapFlag(0x2); + spBufferSet[type].buf->setClearColor((GXColor){0, 0, 0, 0}); + } + if (x1 < 0.0f) { + x1 = 0.0f; + } + if (y1 < 0.0f) { + y1 = 0.0f; + } + if (doCapture) { + spBufferSet[type].buf->capture(x1, y1, doUpscale, -1); + } + } + } + + return spBufferSet[type].buf; +} + bool StateEfb::releaseEfb(BufferType type, u32 userData) { if (spBufferSet[type].buf != nullptr && spBufferSet[type].userData == userData) { spBufferSet[type].buf->free(); @@ -42,4 +143,92 @@ bool StateEfb::releaseEfb(BufferType type, u32 userData) { } } +void StateEfb::fn_804B4270(BufferType type, u32 userData) { + if (type == BUFFER_0) { + if (sWorkBuffer == 1) { + StateEfb::releaseEfb(BUFFER_0, spBufferSet[0].userData); + } + captureEfb(BUFFER_1, false, userData); + sWorkBuffer = 0; + } else if (type == BUFFER_1 && sWorkBuffer != 0) { + captureEfb(BUFFER_0, false, userData); + sWorkBuffer = 1; + } +} + +void StateEfb::fn_804B4310(BufferType type, u32 userData) { + if (sWorkBuffer != -1) { + BufferType i = static_cast(-1); + if (sWorkBuffer == 0) { + i = BUFFER_1; + } else if (sWorkBuffer == 1) { + i = BUFFER_0; + } + + if (spBufferSet[i].userData == userData) { + if (type == BUFFER_0) { + StateGX::ScopedColor colorGuard(true); + StateGX::ScopedAlpha alphaGuard(true); + StateGX::ScopedDither ditherGuard(false); + + const Screen &parentScreen = GlobalDrawState::getScreen(); + Screen s(parentScreen); + + s.SetFlag(Screen::FLAG_0x40); + s.SetCanvasMode(Screen::CANVASMODE_1); + s.SetProjectionType(Screen::PROJ_ORTHO); + s.SetNearFar(0.0f, 1.0f); + s.SetScale(nw4r::math::VEC3(1.0f, 1.0f, 1.0f)); + s.SetOffset(nw4r::math::VEC2(0.0f, 0.0f)); + + s.SetProjectionGX(); + StateGX::GXSetViewport_( + sWorkSpaceHideV[0], sWorkSpaceHideV[1], sWorkSpaceHideV[2], sWorkSpaceHideV[3], 0.0f, 1.0f + ); + StateGX::GXSetScissor_(sWorkSpaceHideV[0], sWorkSpaceHideV[1], sWorkSpaceHideV[2], sWorkSpaceHideV[3]); + StateGX::GXSetScissorBoxOffset_(0, 0); + + nw4r::math::MTX34 mtx; + PSMTXScale(mtx, parentScreen.GetSize().x, parentScreen.GetSize().y, 1.0f); + + DrawGX::BeginDrawScreen(true, GetShouldCapture(), false); + DrawGX::SetBlendMode(DrawGX::BLEND_14); + if (GetShouldCapture()) { + TextureBuffer *buf = spBufferSet[i].buf; + buf->setFilt(GX_NEAR, GX_NEAR); + buf->load(DrawGX::GetTexMapDefault()); + DrawGX::DrawDL(DrawGX::DL_16, mtx, DrawGX::WHITE); + } + } + releaseEfb((i), spBufferSet[i].userData); + sWorkBuffer = -1; + sPushCount += 1; + } + } +} + +f32 *StateEfb::fn_804B4550() { + const Screen::DataEfb &efb = GlobalDrawState::getScreen().GetDataEfb(); + sUnkBuffer[0] = sWorkSpaceV[0]; + sUnkBuffer[1] = sWorkSpaceV[1]; + sUnkBuffer[2] = efb.vp.x2; + sUnkBuffer[3] = efb.vp.y2; + sUnkBuffer[4] = efb.vp.z1; + sUnkBuffer[5] = efb.vp.z2; + StateGX::GXSetViewport_(sUnkBuffer[0], sUnkBuffer[1], sUnkBuffer[2], sUnkBuffer[3], sUnkBuffer[4], sUnkBuffer[5]); + u32 f[4]; + StateGX::CalculateScreenScissor(sUnkBuffer, f); + StateGX::GXSetScissor_(f[0], f[1], f[2], f[3]); + StateGX::GXSetScissorBoxOffset_(0, 0); + return sUnkBuffer; +} + +bool StateEfb::GetShouldCapture() { + return ((sFlag >> 2) & 1) != 0; +} + +bool StateEfb::GetUseTfRgb565() { + return (sFlag & 8) != 0; +} + } // namespace EGG