#pragma once #include "Graphics/GX.hpp" #include "RetroTypes.hpp" namespace metaforce { enum class ERglTevStage : std::underlying_type_t { Stage0 = GX::TEVSTAGE0, Stage1 = GX::TEVSTAGE1, Stage2 = GX::TEVSTAGE2, Stage3 = GX::TEVSTAGE3, Stage4 = GX::TEVSTAGE4, Stage5 = GX::TEVSTAGE5, Stage6 = GX::TEVSTAGE6, Stage7 = GX::TEVSTAGE7, Stage8 = GX::TEVSTAGE8, Stage9 = GX::TEVSTAGE9, Stage10 = GX::TEVSTAGE10, Stage11 = GX::TEVSTAGE11, Stage12 = GX::TEVSTAGE12, Stage13 = GX::TEVSTAGE13, Stage14 = GX::TEVSTAGE14, Stage15 = GX::TEVSTAGE15, Max = GX::MAX_TEVSTAGE, None = GX::NULL_STAGE, }; namespace CTevCombiners { struct CTevOp { bool x0_clamp = true; GX::TevOp x4_op = GX::TevOp::TEV_ADD; GX::TevBias x8_bias = GX::TevBias::TB_ZERO; GX::TevScale xc_scale = GX::TevScale::CS_SCALE_1; GX::TevRegID x10_regId = GX::TevRegID::TEVPREV; constexpr CTevOp() = default; constexpr CTevOp(bool clamp, GX::TevOp op, GX::TevBias bias, GX::TevScale scale, GX::TevRegID regId) : x0_clamp(clamp), x4_op(op), x8_bias(bias), xc_scale(scale), x10_regId(regId) {} constexpr CTevOp(u32 compressedDesc) : x0_clamp((compressedDesc >> 8 & 1) != 0) , x4_op(static_cast(compressedDesc & 0xF)) , x8_bias(static_cast(compressedDesc >> 4 & 3)) , xc_scale(static_cast(compressedDesc >> 6 & 3)) , x10_regId(static_cast(compressedDesc >> 9 & 3)) {} bool operator==(const CTevOp& rhs) const { return x0_clamp == rhs.x0_clamp && x4_op == rhs.x4_op && x8_bias == rhs.x8_bias && xc_scale == rhs.xc_scale; } }; struct ColorPass { GX::TevColorArg x0_a; GX::TevColorArg x4_b; GX::TevColorArg x8_c; GX::TevColorArg xc_d; constexpr ColorPass(GX::TevColorArg a, GX::TevColorArg b, GX::TevColorArg c, GX::TevColorArg d) : x0_a(a), x4_b(b), x8_c(c), xc_d(d) {} constexpr ColorPass(u32 compressedDesc) : x0_a(static_cast(compressedDesc & 0x1F)) , x4_b(static_cast(compressedDesc >> 5 & 0x1F)) , x8_c(static_cast(compressedDesc >> 10 & 0x1F)) , xc_d(static_cast(compressedDesc >> 15 & 0x1F)) {} bool operator==(const ColorPass& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } }; struct AlphaPass { GX::TevAlphaArg x0_a; GX::TevAlphaArg x4_b; GX::TevAlphaArg x8_c; GX::TevAlphaArg xc_d; constexpr AlphaPass(GX::TevAlphaArg a, GX::TevAlphaArg b, GX::TevAlphaArg c, GX::TevAlphaArg d) : x0_a(a), x4_b(b), x8_c(c), xc_d(d) {} constexpr AlphaPass(u32 compressedDesc) : x0_a(static_cast(compressedDesc & 0x1F)) , x4_b(static_cast(compressedDesc >> 5 & 0x1F)) , x8_c(static_cast(compressedDesc >> 10 & 0x1F)) , xc_d(static_cast(compressedDesc >> 15 & 0x1F)) {} bool operator==(const AlphaPass& rhs) const { return memcmp(this, &rhs, sizeof(*this)) == 0; } }; class CTevPass { u32 x0_id; ColorPass x4_colorPass; AlphaPass x14_alphaPass; CTevOp x24_colorOp; CTevOp x38_alphaOp; static u32 sNextUniquePass; public: CTevPass(const ColorPass& colPass, const AlphaPass& alphaPass, const CTevOp& colorOp = {}, const CTevOp& alphaOp = {}) : x0_id(++sNextUniquePass) , x4_colorPass(colPass) , x14_alphaPass(alphaPass) , x24_colorOp(colorOp) , x38_alphaOp(alphaOp) {} void Execute(ERglTevStage stage) const; bool operator==(const CTevPass& rhs) const { return x0_id == rhs.x0_id && x4_colorPass == rhs.x4_colorPass && x14_alphaPass == rhs.x14_alphaPass && x24_colorOp == rhs.x24_colorOp && x38_alphaOp == rhs.x38_alphaOp; } }; extern const CTevPass skPassThru; extern const CTevPass sTevPass804bfcc0; extern const CTevPass sTevPass804bfe68; extern const CTevPass sTevPass805a5698; extern const CTevPass sTevPass805a5e70; extern const CTevPass sTevPass805a5ebc; extern const CTevPass sTevPass805a5f08; extern const CTevPass sTevPass805a5f54; extern const CTevPass sTevPass805a5fa0; extern const CTevPass sTevPass805a5fec; extern const CTevPass sTevPass805a6038; extern const CTevPass sTevPass805a6084; void Init(); void SetupPass(ERglTevStage stage, const CTevPass& pass); void DeletePass(ERglTevStage stage); bool SetPassCombiners(ERglTevStage stage, const CTevPass& pass); void RecomputePasses(); void ResetStates(); } // namespace CTevCombiners } // namespace metaforce