diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index f30c4cc8..784c1f1d 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -26732,7 +26732,7 @@ CopyFromAnother__Q23EGG6ScreenFRCQ23EGG6Screen = .text:0x804B24C0; // type:funct Reset__Q23EGG6ScreenFffffQ33EGG7Frustum10CanvasMode = .text:0x804B2590; // type:function size:0x38 SetParent__Q23EGG6ScreenFPCQ23EGG6Screen = .text:0x804B25D0; // type:function size:0x30 SetUnkFlag8__Q23EGG6ScreenFv = .text:0x804B2600; // type:function size:0x24 -OnDirectEfb__Q23EGG6ScreenFv = .text:0x804B2630; // type:function size:0x4D8 +OnDirectEfb__Q23EGG6ScreenCFv = .text:0x804B2630; // type:function size:0x4D8 GetDataEfb__Q23EGG6ScreenCFv = .text:0x804B2B10; // type:function size:0x5C IsChangeEfb__Q23EGG6ScreenCFv = .text:0x804B2B70; // type:function size:0x2C CalcMatrixForDrawQuad__Q23EGG6ScreenCFPQ34nw4r4math5MTX34ffff = .text:0x804B2BA0; // type:function size:0xA8 @@ -26740,7 +26740,7 @@ FillBufferGX__Q23EGG6ScreenCFUl8_GXColorUl = .text:0x804B2C50; // type:function GetGlobalPos__Q23EGG6ScreenCFPfPf = .text:0x804B2D40; // type:function size:0xB0 SetTVMode__Q23EGG6ScreenFQ33EGG6Screen6TVMode = .text:0x804B2DF0; // type:function size:0xB0 SetTVModeDefault__Q23EGG6ScreenFv = .text:0x804B2EA0; // type:function size:0x34 -FUN_804b2ee0 = .text:0x804B2EE0; // type:function size:0x14C +fn_804B2EE0__Q23EGG6ScreenCFPfPfff = .text:0x804B2EE0; // type:function size:0x14C __sinit_\eggScreen_cpp = .text:0x804B3030; // type:function size:0x84 scope:local __ct__Q23EGG16ScreenEffectBaseFv = .text:0x804B30C0; // type:function size:0x18 __sinit_\eggScreenEffectBase_cpp = .text:0x804B30E0; // type:function size:0xC scope:local @@ -41174,11 +41174,11 @@ lbl_80576861 = .sbss:0x80576861; // type:object size:0x7 data:byte lbl_80576868 = .sbss:0x80576868; // type:object size:0x8 data:float sTVMode__Q23EGG6Screen = .sbss:0x80576870; // type:object size:0x4 data:4byte spRoot__Q23EGG6Screen = .sbss:0x80576874; // type:object size:0x4 data:4byte -lbl_80576878 = .sbss:0x80576878; // type:object size:0x4 data:4byte -lbl_8057687C = .sbss:0x8057687C; // type:object size:0x4 data:4byte -lbl_80576880 = .sbss:0x80576880; // type:object size:0x4 data:float -lbl_80576888 = .sbss:0x80576888; // type:object size:0x4 data:float -lbl_80576890 = .sbss:0x80576890; // type:object size:0x8 data:byte +sChangeTVModeFunc__Q23EGG6Screen = .sbss:0x80576878; // type:object size:0x4 data:4byte +spChangeTVModeFuncInfo__Q23EGG6Screen = .sbss:0x8057687C; // type:object size:0x4 data:4byte +sCanvasScale__Q23EGG6Screen = .sbss:0x80576880; // type:object size:0x8 data:float +sCanvasOffset__Q23EGG6Screen = .sbss:0x80576888; // type:object size:0x8 data:float +@GUARD@Initialize__Q23EGG6ScreenFPCUsPCUsPQ23EGG6Screen@defaultRoot = .sbss:0x80576890; // type:object size:0x1 data:byte lbl_80576898 = .sbss:0x80576898; // type:object size:0x8 data:4byte s_widthEfb__Q23EGG7StateGX = .sbss:0x805768A0; // type:object size:0x2 data:2byte s_heightEfb__Q23EGG7StateGX = .sbss:0x805768A2; // type:object size:0x2 data:2byte diff --git a/include/egg/gfx/eggFrustum.h b/include/egg/gfx/eggFrustum.h index 5adbc40e..877a4940 100644 --- a/include/egg/gfx/eggFrustum.h +++ b/include/egg/gfx/eggFrustum.h @@ -8,6 +8,10 @@ class Frustum { public: enum Flag { FLAG_DIRTY = (1 << 0), + FLAG_0x02 = (1 << 1), + FLAG_0x04 = (1 << 2), + FLAG_0x08 = (1 << 3), + FLAG_0x20 = (1 << 5), FLAG_0x40 = (1 << 6), }; @@ -102,10 +106,8 @@ public: } void SetSize(const nw4r::math::VEC2 &size) { - // ??? - mSize.x = size.x; - SetDirty(true); - mSize.y = size.y; + SetSizeX(size.x); + SetSizeY(size.y); } void SetNearZ(f32 nearZ) { diff --git a/include/egg/gfx/eggScreen.h b/include/egg/gfx/eggScreen.h index df63bf81..f2638357 100644 --- a/include/egg/gfx/eggScreen.h +++ b/include/egg/gfx/eggScreen.h @@ -3,12 +3,18 @@ #include "egg/egg_types.h" #include "egg/gfx/eggFrustum.h" +#include "egg/gfx/eggStateGX.h" namespace EGG { class Screen : public Frustum { public: - enum TVMode { TV_MODE_4_3, TV_MODE_16_9, TV_MODE_UNK_3, TV_MODE_MAX }; + enum TVMode { + TV_MODE_4_3, + TV_MODE_16_9, + TV_MODE_UNK_3, + TV_MODE_MAX + }; typedef void (*ChangeTVModeFunc)(void *); @@ -69,6 +75,14 @@ public: return sTVMode; } + TVMode GetComputedTVMode() const { + if ((mFlags & FLAG_0x20) == 0) { + return (mFlags & FLAG_0x08) == 0 ? sTVMode : TV_MODE_UNK_3; + } else { + return TV_MODE_4_3; + } + } + Screen(); Screen(f32, f32, f32, f32, const Screen *, CanvasMode); Screen(const Screen &); @@ -85,18 +99,27 @@ public: void CopyFromAnother(const Screen &other); void Reset(f32, f32, f32, f32, CanvasMode); - void GetPosSizeInEfb() const; + void OnDirectEfb() const; const DataEfb &GetDataEfb() const; bool IsChangeEfb() const; void CalcMatrixForDrawQuad(nw4r::math::MTX34 *, f32, f32, f32, f32) const; void FillBufferGX(u32, GXColor, u32) const; void GetGlobalPos(f32 *, f32 *) const; + void fn_804B2EE0(f32 *, f32 *, f32, f32) const; + + f32 ScaleByX(f32 val) const { + return val * StateGX::s_widthEfb / GetSizeXMax(GetComputedTVMode()); + } + + f32 ScaleByY(f32 val) const { + return val * StateGX::s_heightEfb / GetSizeYMax(GetComputedTVMode()); + } private: const Screen *mParent; // at 0x3C nw4r::math::VEC2 mPosition; // at 0x40 - nw4r::math::VEC2 field_0x44; - nw4r::math::VEC2 field_0x48; + nw4r::math::VEC2 field_0x48; // at 0x48 + nw4r::math::VEC2 field_0x50; // at 0x50 mutable DataEfb mDataEfb; // at 0x58 static TVMode sTVMode; diff --git a/src/egg/gfx/eggScreen.cpp b/src/egg/gfx/eggScreen.cpp index af26dc25..18c41717 100644 --- a/src/egg/gfx/eggScreen.cpp +++ b/src/egg/gfx/eggScreen.cpp @@ -5,7 +5,6 @@ #include "egg/gfx/eggStateGX.h" #include "rvl/SC/scapi.h" - // ported from OGWS, though this class has evolved a fair bit using namespace nw4r; @@ -37,22 +36,21 @@ math::VEC2 Screen::sCanvasScale(1.0f, 1.0f); math::VEC2 Screen::sCanvasOffset(0.0f, 0.0f); void Screen::Initialize(const u16 *maxX, const u16 *maxY, Screen *userRoot) { - sTVModeInfo[TV_MODE_4_3].width = maxX[0]; sTVModeInfo[TV_MODE_4_3].height = maxY[0]; - + sTVModeInfo[TV_MODE_4_3].ratios.x = (f32)StateGX::s_widthEfb / (f32)sTVModeInfo[TV_MODE_4_3].width; sTVModeInfo[TV_MODE_4_3].ratios.y = (f32)StateGX::s_heightEfb / (f32)sTVModeInfo[TV_MODE_4_3].height; - + sTVModeInfo[TV_MODE_16_9].width = maxX[1]; sTVModeInfo[TV_MODE_16_9].height = maxY[1]; sTVModeInfo[TV_MODE_16_9].ratios.x = (f32)StateGX::s_widthEfb / (f32)sTVModeInfo[TV_MODE_16_9].width; sTVModeInfo[TV_MODE_16_9].ratios.y = (f32)StateGX::s_heightEfb / (f32)sTVModeInfo[TV_MODE_16_9].height; - + sTVModeInfo[TV_MODE_UNK_3].width = StateGX::s_widthEfb; sTVModeInfo[TV_MODE_UNK_3].height = StateGX::s_heightEfb; - + sTVModeInfo[TV_MODE_UNK_3].ratios.x = 1.0f; sTVModeInfo[TV_MODE_UNK_3].ratios.y = 1.0f; @@ -77,10 +75,10 @@ Screen::Screen() mParent = nullptr; mPosition.x = 0.0f; mPosition.y = 0.0f; - field_0x44.x = 0.0f; - field_0x44.y = 0.0f; field_0x48.x = 0.0f; field_0x48.y = 0.0f; + field_0x50.x = 0.0f; + field_0x50.y = 0.0f; SetParent(nullptr); } @@ -89,10 +87,10 @@ Screen::Screen(f32 x, f32 y, f32 w, f32 h, const Screen *userRoot, CanvasMode ca mParent = nullptr; mPosition.x = x; mPosition.y = y; - field_0x44.x = 0.0f; - field_0x44.y = 0.0f; field_0x48.x = 0.0f; field_0x48.y = 0.0f; + field_0x50.x = 0.0f; + field_0x50.y = 0.0f; SetParent(userRoot); } @@ -100,8 +98,8 @@ Screen::Screen(const Screen &other) : Frustum(other), mPosition(other.mPosition), mDataEfb(other.mDataEfb), - field_0x44(other.field_0x44), - field_0x48(other.field_0x48) { + field_0x48(other.field_0x48), + field_0x50(other.field_0x50) { SetParent(other.mParent); } @@ -162,8 +160,8 @@ void Screen::CopyFromAnother(const Screen &other) { Frustum::CopyFromAnother(other); mPosition = other.mPosition; - field_0x44 = other.field_0x44; field_0x48 = other.field_0x48; + field_0x50 = other.field_0x50; mDataEfb = other.mDataEfb; mParent = other.mParent; } @@ -187,77 +185,64 @@ void Screen::SetParent(const Screen *parent) { } void Screen::SetUnkFlag8() { - if ((mFlags & 0x8) == 0) { + if ((mFlags & FLAG_0x08) == 0) { SetDirty(true); } - mFlags |= 0x8; + mFlags |= FLAG_0x08; } -void Screen::GetPosSizeInEfb() const { - // TODO - const TVMode tvMode = (!(mFlags & 0x20)) ? sTVMode : TV_MODE_4_3; - const TVModeInfo &tvRatio = sTVModeInfo[tvMode]; +void Screen::OnDirectEfb() const { + f32 &x1 = mDataEfb.vp.x1; + f32 &y1 = mDataEfb.vp.y1; + if (mParent == nullptr) { + x1 = mPosition.x * sCanvasScale.x; + y1 = mPosition.y * sCanvasScale.y; + } else { + mParent->fn_804B2EE0(&x1, &y1, mPosition.x, mPosition.y); + } - f32 *px = &mDataEfb.vp.x1; - f32 *py = &mDataEfb.vp.y1; - GetGlobalPos(px, py); + // TODO: Make this work without temporaries? - *px = sCanvasScale.x * *px; - *py = sCanvasScale.y * *py; - - *px *= tvRatio.ratios.x; - *py *= tvRatio.ratios.y; + mDataEfb.sc_x = x1 + ScaleByX(field_0x48.x); + mDataEfb.sc_y = y1 + ScaleByY(field_0x48.y); mDataEfb.sc_oy = 0; mDataEfb.sc_ox = 0; - - const f32 x = *px; - if (x < 0.0f) { - *px = 0.0f; - - const s32 lx = static_cast(-x); - mDataEfb.sc_ox = lx - (lx & 0x1); + if (x1 < 0.0f) { + int x1_i = x1; + int x1_in = -x1_i; + mDataEfb.sc_ox = (x1_in - (x1_in & 1)); + x1 = x1 - x1_i; + } + if (y1 < 0.0f) { + int y1_i = y1; + int y1_in = -y1_i; + mDataEfb.sc_oy = (y1_in - (y1_in & 1)); + y1 = y1 - y1_i; } - const f32 y = *py; - if (y < 0.0f) { - *py = 0.0f; - - const s32 ly = static_cast(-y); - mDataEfb.sc_oy = ly - (ly & 0x1); + if ((mFlags & FLAG_0x02) != 0) { + x1 = x1 - (((int)x1) & 1); + y1 = y1 - (((int)y1) & 1); } - if (mFlags & 0x2) { - *px -= static_cast(*px) & 0x1; - *py -= static_cast(*py) & 0x1; + mDataEfb.vp.x2 = ScaleByX(mSize.x); + mDataEfb.vp.y2 = ScaleByY(mSize.y); + + if ((mFlags & FLAG_0x04) != 0) { + mDataEfb.vp.x2 -= ((int)mDataEfb.vp.x2 & 3); + mDataEfb.vp.y2 -= ((int)mDataEfb.vp.y2 & 3); } + mDataEfb.vp.x2 = (int)mDataEfb.vp.x2; + mDataEfb.vp.y2 = (int)mDataEfb.vp.y2; - *px = static_cast(*px); - *py = static_cast(*py); - - mDataEfb.vp.x2 = mSize.x; - mDataEfb.vp.y2 = mSize.y; - - if (!(mFlags & 0x8)) { - mDataEfb.vp.x2 = mSize.x * tvRatio.ratios.x; - mDataEfb.vp.y2 = mSize.y * tvRatio.ratios.y; - } - - if (mFlags & 0x4) { - mDataEfb.vp.x2 -= static_cast(mDataEfb.vp.x2) & 0x3; - mDataEfb.vp.y2 -= static_cast(mDataEfb.vp.y2) & 0x3; - } - - mDataEfb.vp.x2 = (mDataEfb.vp.x2 >= 0.0f) ? mDataEfb.vp.x2 : 0.0f; - mDataEfb.vp.y2 = (mDataEfb.vp.y2 >= 0.0f) ? mDataEfb.vp.y2 : 0.0f; - - mDataEfb.vp.x2 = static_cast(mDataEfb.vp.x2); - mDataEfb.vp.y2 = static_cast(mDataEfb.vp.y2); + mDataEfb.sc_w = mDataEfb.vp.x2 - ScaleByX(field_0x48.x + field_0x50.x); + mDataEfb.sc_h = mDataEfb.vp.y2 - ScaleByY(field_0x48.y + field_0x50.y); } const Screen::DataEfb &Screen::GetDataEfb() const { if (IsChangeEfb()) { - GetPosSizeInEfb(); + OnDirectEfb(); mDataEfb.vp.z1 = 0.0f; mDataEfb.vp.z2 = 1.0f; SetDirty(false); @@ -303,7 +288,7 @@ void Screen::FillBufferGX(u32 flags, GXColor color, u32 r6) const { clone.SetProjectionGX(); clone.CalcMatrixForDrawQuad(&drawMtx, 0.0f, 0.0f, mSize.x, mSize.y); // Ugh - DrawGX::ClearEfb(drawMtx, (flags & 1) != 0, (flags & 2) != 0, (flags & 4) != 0, color, true); + DrawGX::ClearEfb(drawMtx, (flags & 1), (flags & 2), (flags & 4), color, true); } } @@ -318,7 +303,6 @@ void Screen::GetGlobalPos(f32 *ox, f32 *oy) const { *ox += px; *oy += py; } else { - *ox = mPosition.x; *oy = mPosition.y; } @@ -340,4 +324,11 @@ void Screen::SetTVModeDefault() { SetTVMode(SCGetAspectRatio() == SC_ASPECT_STD ? TV_MODE_4_3 : TV_MODE_16_9); } +void Screen::fn_804B2EE0(f32 *ox, f32 *oy, f32 a, f32 b) const { + GetGlobalPos(ox, oy); + ConvertToCanvasLU(a, b, &a, &b); + *ox = ScaleByX((*ox + a)); + *oy = ScaleByY((*oy + b)); +} + } // namespace EGG