From 6c5ed3a266ff5a66f70a269655057d7efbb1afa7 Mon Sep 17 00:00:00 2001 From: robojumper Date: Wed, 26 Mar 2025 23:58:09 +0100 Subject: [PATCH] A bit of LightTexture --- config/SOUE01/symbols.txt | 26 ++--- include/egg/egg_types.h | 2 +- include/egg/gfx/eggLightObject.h | 17 +++ include/egg/gfx/eggLightTexture.h | 34 +++++- src/egg/gfx/eggLightTexture.cpp | 167 +++++++++++++++++++++++++++++- 5 files changed, 230 insertions(+), 16 deletions(-) diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index ad595dbb..45bb9ebe 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -26643,8 +26643,8 @@ initialize__Q23EGG12LightTextureFUsPQ23EGG4Heap = .text:0x804AB780; // type:func __ct__Q23EGG12LightTextureFPCcPCQ23EGG19LightTextureManager = .text:0x804AB9F0; // type:function size:0x284 __dt__Q23EGG12LightTextureFv = .text:0x804ABC80; // type:function size:0x90 configure__Q23EGG12LightTextureFv = .text:0x804ABD10; // type:function size:0x6C -EGG__LightTexture__loadTextureData = .text:0x804ABD80; // type:function size:0x10C -EGG__LightTexture__loadCpuTextureFromBti = .text:0x804ABE90; // type:function size:0xC +loadTextureData__Q23EGG12LightTextureFiPv9_GXTexFmt = .text:0x804ABD80; // type:function size:0x10C +loadTextureFromResTimg__Q23EGG12LightTextureFiPQ23EGG7ResTIMG = .text:0x804ABE90; // type:function size:0xC initDrawSetting__Q23EGG12LightTextureFUsUsUsUs = .text:0x804ABEA0; // type:function size:0x1A4 FUN_804ac050 = .text:0x804AC050; // type:function size:0x4C FUN_804ac0a0 = .text:0x804AC0A0; // type:function size:0x34 @@ -29170,7 +29170,7 @@ zeroVec__3EGG = .rodata:0x804FBC88; // type:object size:0xC data:float lbl_804FBC98 = .rodata:0x804FBC98; // type:object size:0xC data:4byte lbl_804FBCA4 = .rodata:0x804FBCA4; // type:object size:0xC data:4byte lbl_804FBCB0 = .rodata:0x804FBCB0; // type:object size:0x10 data:4byte -lbl_804FBCC0 = .rodata:0x804FBCC0; // type:object size:0x48 data:4byte +sCpuTexGradientOp__3EGG = .rodata:0x804FBCC0; // type:object size:0x48 data:4byte lbl_804FBD08 = .rodata:0x804FBD08; // type:object size:0x48 data:float lbl_804FBD50 = .rodata:0x804FBD50; // type:object size:0x10 data:float lbl_804FBD60 = .rodata:0x804FBD60; // type:object size:0x10 data:float @@ -41159,15 +41159,15 @@ lbl_80576830 = .sbss:0x80576830; // type:object size:0x8 data:4byte spScreen__Q23EGG15GlobalDrawState = .sbss:0x80576838; // type:object size:0x4 data:4byte sCameraId__Q23EGG15GlobalDrawState = .sbss:0x8057683C; // type:object size:0x2 data:2byte sDrawFlag__Q23EGG15GlobalDrawState = .sbss:0x80576840; // type:object size:0x4 data:4byte -lbl_80576848 = .sbss:0x80576848; // type:object size:0x2 data:2byte -lbl_8057684A = .sbss:0x8057684A; // type:object size:0x2 data:2byte -lbl_8057684C = .sbss:0x8057684C; // type:object size:0x2 data:2byte -lbl_8057684E = .sbss:0x8057684E; // type:object size:0x2 data:2byte -lbl_80576850 = .sbss:0x80576850; // type:object size:0x2 data:2byte -lbl_80576852 = .sbss:0x80576852; // type:object size:0x2 data:2byte -lbl_80576854 = .sbss:0x80576854; // type:object size:0x2 data:2byte -lbl_80576856 = .sbss:0x80576856; // type:object size:0x2 data:2byte -lbl_80576858 = .sbss:0x80576858; // type:object size:0x4 data:4byte +sDrawWidth__Q23EGG12LightTexture = .sbss:0x80576848; // type:object size:0x2 data:2byte +sDrawHeight__Q23EGG12LightTexture = .sbss:0x8057684A; // type:object size:0x2 data:2byte +sDrawPosX__Q23EGG12LightTexture = .sbss:0x8057684C; // type:object size:0x2 data:2byte +sDrawPosY__Q23EGG12LightTexture = .sbss:0x8057684E; // type:object size:0x2 data:2byte +sTexWidth__Q23EGG12LightTexture = .sbss:0x80576850; // type:object size:0x2 data:2byte +sTexHeight__Q23EGG12LightTexture = .sbss:0x80576852; // type:object size:0x2 data:2byte +sDrawNumX__Q23EGG12LightTexture = .sbss:0x80576854; // type:object size:0x2 data:2byte +sDrawNumY__Q23EGG12LightTexture = .sbss:0x80576856; // type:object size:0x2 data:2byte +spNormalEnvironment__Q23EGG12LightTexture = .sbss:0x80576858; // type:object size:0x4 data:4byte lbl_8057685C = .sbss:0x8057685C; // type:object size:0x1 data:byte lbl_80576860 = .sbss:0x80576860; // type:object size:0x1 data:byte lbl_80576861 = .sbss:0x80576861; // type:object size:0x7 data:byte @@ -49801,7 +49801,7 @@ s_DL__Q23EGG6DrawGX = .bss:0x80674D68; // type:object size:0x90 s_cameraMtx__Q23EGG6DrawGX = .bss:0x80674DF8; // type:object size:0x30 data:float sDummyTexObj__Q23EGG6DrawGX = .bss:0x80674E28; // type:object size:0x20 sMtx__Q23EGG15GlobalDrawState = .bss:0x80674E48; // type:object size:0x30 -CPU_TEX_ARR = .bss:0x80674E78; // type:object size:0x48 data:4byte +sCpuTexArray__3EGG = .bss:0x80674E78; // type:object size:0x48 data:4byte sMtx__3EGG = .bss:0x80674EC0; // type:object size:0x30 data:float lbl_80674EF0 = .bss:0x80674EF0; // type:object size:0xC data:float @LOCAL@Initialize__Q23EGG6ScreenFPCUsPCUsPQ23EGG6Screen@defaultRoot = .bss:0x80674F00; // type:object size:0x88 data:4byte diff --git a/include/egg/egg_types.h b/include/egg/egg_types.h index f3f96c61..d72a6037 100644 --- a/include/egg/egg_types.h +++ b/include/egg/egg_types.h @@ -25,7 +25,7 @@ class GXUtility; class IDrawGX; class IScnProc; class IScnProcModel; -class LightObj; +class LightObject; class LightManager; class LightTexture; class LightTextureManager; diff --git a/include/egg/gfx/eggLightObject.h b/include/egg/gfx/eggLightObject.h index afef331c..b2cc876c 100644 --- a/include/egg/gfx/eggLightObject.h +++ b/include/egg/gfx/eggLightObject.h @@ -62,6 +62,10 @@ public: void SetPosAt(nw4r::math::VEC3 const &, nw4r::math::VEC3 const &); void SetDist(f32); + f32 getField0x30() const { + return field_0x30; + } + int getField0x3C() const { return field_0x3C; } @@ -106,13 +110,26 @@ public: return (mFlags & 2) != 0; } + bool CheckFlag0x20() const { + return (mFlags & 0x20) != 0; + } + u16 GetField0x06() const { return field_0x06; } + u16 GetIndex() const { + return mIndex; + } + void UpdatePosAt(LightObject &other) { SetPosAt(other.mPos, other.mAt); } + + const GXColor &GetBlack() const { + return mBlack; + } + private: /* 0x04 */ u16 mIndex; diff --git a/include/egg/gfx/eggLightTexture.h b/include/egg/gfx/eggLightTexture.h index 59bf0907..bb52ed78 100644 --- a/include/egg/gfx/eggLightTexture.h +++ b/include/egg/gfx/eggLightTexture.h @@ -2,9 +2,12 @@ #define EGG_LIGHT_TEXTURE_H #include "common.h" +#include "egg/egg_types.h" #include "egg/gfx/eggCapTexture.h" +#include "egg/gfx/eggTexture.h" #include "egg/math/eggVector.h" #include "egg/prim/eggBinary.h" +#include "rvl/GX/GXTypes.h" namespace EGG { @@ -49,6 +52,13 @@ public: virtual size_t GetBinarySize() const override; static void initialize(u16 textureSize, Heap *pHeap); + static void loadTextureFromResTimg(int index, EGG::ResTIMG *img); + static void initDrawSetting(u16, u16, u16, u16); + void addLight(const EGG::LightObject&); + + void draw(int); + void beginDebugDraw(); + void debugDraw(int); const char *getName() const { return mName1; @@ -58,8 +68,13 @@ public: return mpFloatData[idx]; } + private: + static void fn_804AB270(); + static void fn_804AC0A0(int, int*, int*); + static void loadTextureData(int index, void *data, GXTexFmt fmt); + u8 getByte1(u16 idx) const { return mpByteData1[idx]; } @@ -68,6 +83,11 @@ private: return mpByteData2[idx]; } + // TODO enum + int GetLightType() const { + return mLightType; + } + /* 0x30 */ const LightTextureManager *mpMgr; /* 0x34 */ u8 mNumData; /* 0x35 */ u8 field_0x35; @@ -76,15 +96,27 @@ private: /* 0x38 */ Vector3f field_0x38; /* 0x44 */ f32 *mpFloatData; /* 0x48 */ char *mpByteData1; - /* 0x4C */ char *mpByteData2; + /* 0x4C */ u8 *mpByteData2; /* 0x50 */ f32 field_0x50; /* 0x54 */ char mName1[0x20]; /* 0x74 */ char mName2[0x20]; /* 0x94 */ u16 field_0x94; /* 0x98 */ f32 field_0x98; /* 0x9C */ u8 field_0x9C; + /* 0x9D */ u8 field_0x9D; + /* 0x9E */ u8 field_0x9E; + /* 0x9F */ u8 field_0x9F; static u16 sTextureSize; + + static u16 sDrawWidth; + static u16 sDrawHeight; + static u16 sDrawPosX; + static u16 sDrawPosY; + static u16 sTexWidth; + static u16 sTexHeight; + static u16 sDrawNumX; + static u16 sDrawNumY; static CpuTexture *spNormalEnvironment; }; diff --git a/src/egg/gfx/eggLightTexture.cpp b/src/egg/gfx/eggLightTexture.cpp index 768b447f..b4827998 100644 --- a/src/egg/gfx/eggLightTexture.cpp +++ b/src/egg/gfx/eggLightTexture.cpp @@ -5,8 +5,18 @@ #include "egg/gfx/eggCapTexture.h" #include "egg/gfx/eggCpuTexture.h" #include "egg/gfx/eggDrawGX.h" +#include "egg/gfx/eggLightObject.h" #include "egg/gfx/eggLightTextureMgr.h" +#include "egg/gfx/eggStateGX.h" +#include "nw4r/math/math_types.h" +#include "rvl/GX/GXBump.h" +#include "rvl/GX/GXGeometry.h" +#include "rvl/GX/GXTev.h" +#include "rvl/GX/GXTransform.h" #include "rvl/GX/GXTypes.h" +#include "rvl/GX/GXVert.h" +#include "rvl/MTX/mtx.h" +#include "rvl/MTX/mtx44.h" #include @@ -121,7 +131,7 @@ LightTexture::LightTexture(const char *name, const LightTextureManager *mgr) field_0x9C = 0; mpFloatData = new float[mNumData]; mpByteData1 = new char[mNumData]; - mpByteData2 = new char[mNumData]; + mpByteData2 = new u8[mNumData]; for (int i = 0; i < mNumData; i++) { mpByteData2[i] = 0; mpFloatData[i] = 1.0f; @@ -148,6 +158,161 @@ void LightTexture::configure() { setPixModeSync(false); } +void LightTexture::loadTextureData(int index, void *data, GXTexFmt fmt) { + CpuTexture *pTex = sCpuTexArray[index]; + CpuTexture tmpTex(64, 4, fmt); + tmpTex.configure(); + tmpTex.setBuffer(data); + for (u32 y = 0; y < 4; y++) { + for (int x = 0; x < 32; x++) { + pTex->setColor(x, y, tmpTex.getColor(x + 32, y)); + } + for (int x = 0; x < 32; x++) { + pTex->setColor(x + 32, y, tmpTex.getColor(x, y)); + } + } + pTex->flush(); +} + +void LightTexture::loadTextureFromResTimg(int index, EGG::ResTIMG *img) { + loadTextureData(index, img + 1, static_cast(img->format)); +} + +void LightTexture::initDrawSetting(u16 u1, u16 u2, u16 u3, u16 u4) { + static const u8 sVtxBuf[] = {0, 0, 0, 1, 1, 1, 1, 0}; + + nw4r::math::MTX44 mtx; + C_MTXOrtho(mtx, u4, 0.0f, 0.0f, u3, 0.0f, 1.0f); + StateGX::GXSetProjection_(mtx, GX_ORTHOGRAPHIC); + StateGX::GXSetViewport_(u1, u2, u3, u4, 0.0f, 1.0f); + StateGX::GXSetScissor_(u1, u2, u3, u4); + StateGX::GXSetScissorBoxOffset_(0, 0); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX8); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetArray(GX_VA_POS, sVtxBuf, 2); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGB, GX_RGB565, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_F32, 0); + + sTexWidth = sTextureSize; + sDrawNumX = u3 / sTextureSize; + sTexHeight = sTextureSize; + sDrawNumY = u4 / sTextureSize; + sDrawWidth = u3; + sDrawHeight = u4; + sDrawPosX = u1; + sDrawPosY = u2; + + fn_804AB270(); + GXSetCurrentMtx(0); + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); +} + +void LightTexture::draw(int i) {} + +void LightTexture::beginDebugDraw() { + DrawGX::SetMat_ColorChannel(DrawGX::COLORCHAN_1); + DrawGX::SetMat_TexGen(DrawGX::TEXGEN_1); + DrawGX::SetMat_Ind(); + DrawGX::SetMat_PE(DrawGX::ZMODE_0, DrawGX::BLEND_14); + GXSetNumTevStages(1); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); +} + +void LightTexture::debugDraw(int i) { + StateGX::ScopedDither ditherGuard(false); + field_0x9F = 0; + int u1, u2; + fn_804AC0A0(i, &u1, &u2); + load(GX_TEXMAP0); + nw4r::math::MTX34 mtx; + PSMTXScale(mtx, sTexWidth, sTexHeight, 1.0f); + + mtx._03 = u1; + mtx._13 = sDrawHeight - (u2 + sTexHeight); + + GXLoadPosMtxImm(mtx, 0); + GXLoadTexMtxImm(sMtx, 0x1E, GX_MTX_2x4); + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + GXPosition1x8(0); + GXPosition2f32(0.0f, 1.0f); + + GXPosition1x8(1); + GXPosition2f32(0.0f, 0.0f); + + GXPosition1x8(2); + GXPosition2f32(1.0f, 0.0f); + + GXPosition1x8(3); + GXPosition2f32(1.0f, 1.0f); +} + +void LightTexture::addLight(const EGG::LightObject &obj) { + // NONMATCHING + if (!(obj.CheckFlag1() && obj.CheckFlag0x20() && (mpByteData1[obj.GetIndex()] & 1) != 0 && + (field_0x9F < 2 || mLightType != 1))) { + return; + } + + nw4r::math::VEC3 vec; + GXColor color; + obj.fn_804A9C30(this, &vec, &color); + int remainder = field_0x9F % field_0x9D; + if (field_0x9F == field_0x9D) { + GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); + } + sCpuTexArray[mpByteData2[obj.GetIndex()]]->load(static_cast(field_0x9E + remainder)); + + // TODO + GXColor blackColor = obj.GetBlack(); + // Sorry clang-format, what is this formatting??? + blackColor = (GXColor + ){blackColor.r * obj.getField0x30(), blackColor.g * obj.getField0x30(), blackColor.b * obj.getField0x30(), + blackColor.a}; + GXSetTevColor(static_cast(GX_TEVREG0 + remainder), color); + GXSetTevKColor(static_cast(GX_KCOLOR0 + remainder), blackColor); + if (GetLightType() == 0 || GetLightType() == 2) { + f32 mtx[2][3]; + mtx[0][0] = -vec.x * 0.485f; + mtx[0][1] = -vec.y * 0.485f; + mtx[0][2] = -vec.z * 0.485f; + mtx[1][0] = 0.0f; + mtx[1][1] = 0.0f; + mtx[1][2] = 0.0f; + + static const GXIndTexMtxID sIds[] = {GX_ITM_0, GX_ITM_1, GX_ITM_2}; + + GXSetIndTexMtx(sIds[remainder], mtx, -1); + } + + if (remainder == field_0x9D - 1) { + f32 v = GetLightType() != 2 ? 0.0f : 0.5f; + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + GXPosition1x8(0); + GXPosition2f32(v, v); + + GXPosition1x8(1); + GXPosition2f32(v, v - 0.99f); + + GXPosition1x8(2); + GXPosition2f32(v + 0.99f, v - 0.99f); + + GXPosition1x8(3); + GXPosition2f32(v + 0.99f, v); + } + + field_0x9F++; +} + void LightTexture::SetBinaryInner(const Bin &bin) { // Not bothering with version differences right now, // since the game uses V3 and GetBinaryInner is enough