From 4660679da4bdce465916bd1afa97136fc2adc764 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 30 Aug 2022 18:48:44 -0400 Subject: [PATCH] More CGX matches part 2 Former-commit-id: 4758103774fb5c5185cccd1ba737642df87c3baf --- asm/Dolphin/gx/GXTexture.s | 4 +- asm/Kyoto/Graphics/CGX.s | 16 +- asm/MetroidPrime/CNESEmulator.s | 4 +- include/Kyoto/Basics/COsContext.hpp | 2 +- include/Kyoto/Graphics/CGX.hpp | 59 ++++- include/Kyoto/Graphics/CTevCombiners.hpp | 3 +- include/Kyoto/Graphics/CTexture.hpp | 5 +- include/MetaRender/CCubeRenderer.hpp | 3 +- include/dolphin/gx/GXBump.h | 7 +- include/dolphin/gx/GXEnum.h | 2 + include/dolphin/gx/GXTexture.h | 13 +- include/gx_enum.h | 38 --- include/gx_struct.h | 30 --- libc/stddef.h | 2 +- src/Kyoto/Graphics/CGX.cpp | 299 ++++++++++++++++++++++- 15 files changed, 378 insertions(+), 109 deletions(-) delete mode 100644 include/gx_enum.h delete mode 100644 include/gx_struct.h diff --git a/asm/Dolphin/gx/GXTexture.s b/asm/Dolphin/gx/GXTexture.s index d3098c8e..c802d859 100644 --- a/asm/Dolphin/gx/GXTexture.s +++ b/asm/Dolphin/gx/GXTexture.s @@ -1171,8 +1171,8 @@ GXSetTlutRegionCallback: /* 8037A8A8 00377808 7C 03 03 78 */ mr r3, r0 /* 8037A8AC 0037780C 4E 80 00 20 */ blr -.global GXSetTexCoordCylWrap -GXSetTexCoordCylWrap: +.global GXSetTexCoordScaleManually +GXSetTexCoordScaleManually: /* 8037A8B0 00377810 81 02 CE 08 */ lwz r8, lbl_805AEB28@sda21(r2) /* 8037A8B4 00377814 38 00 00 01 */ li r0, 1 /* 8037A8B8 00377818 54 84 06 3F */ clrlwi. r4, r4, 0x18 diff --git a/asm/Kyoto/Graphics/CGX.s b/asm/Kyoto/Graphics/CGX.s index eecfb34c..b1777f28 100644 --- a/asm/Kyoto/Graphics/CGX.s +++ b/asm/Kyoto/Graphics/CGX.s @@ -7,7 +7,7 @@ lbl_ctor: .section .bss .balign 8 -.lcomm lbl_80479BD0, 0xF0, 4 +.lcomm sVtxDescList, 0xF0, 4 .comm sGXState__3CGX, 0x260, 4 .section .sbss2, "", @nobits @@ -275,9 +275,9 @@ SetVtxDescv_Compressed__3CGXFUi: /* 80307F1C 00304E7C 80 BE 00 48 */ lwz r5, 0x48(r30) /* 80307F20 00304E80 7C 1F 28 40 */ cmplw r31, r5 /* 80307F24 00304E84 41 82 00 7C */ beq lbl_80307FA0 -/* 80307F28 00304E88 3C 60 80 48 */ lis r3, lbl_80479BD0@ha +/* 80307F28 00304E88 3C 60 80 48 */ lis r3, sVtxDescList@ha /* 80307F2C 00304E8C 38 00 00 0B */ li r0, 0xb -/* 80307F30 00304E90 38 63 9B D0 */ addi r3, r3, lbl_80479BD0@l +/* 80307F30 00304E90 38 63 9B D0 */ addi r3, r3, sVtxDescList@l /* 80307F34 00304E94 39 00 00 00 */ li r8, 0 /* 80307F38 00304E98 7C 67 1B 78 */ mr r7, r3 /* 80307F3C 00304E9C 38 C0 00 00 */ li r6, 0 @@ -300,10 +300,10 @@ lbl_80307F74: /* 80307F78 00304ED8 39 08 00 01 */ addi r8, r8, 1 /* 80307F7C 00304EDC 42 00 FF CC */ bdnz lbl_80307F48 /* 80307F80 00304EE0 38 00 00 FF */ li r0, 0xff -/* 80307F84 00304EE4 3C 60 80 48 */ lis r3, lbl_80479BD0@ha +/* 80307F84 00304EE4 3C 60 80 48 */ lis r3, sVtxDescList@ha /* 80307F88 00304EE8 90 07 00 00 */ stw r0, 0(r7) /* 80307F8C 00304EEC 38 00 00 00 */ li r0, 0 -/* 80307F90 00304EF0 38 63 9B D0 */ addi r3, r3, lbl_80479BD0@l +/* 80307F90 00304EF0 38 63 9B D0 */ addi r3, r3, sVtxDescList@l /* 80307F94 00304EF4 90 07 00 04 */ stw r0, 4(r7) /* 80307F98 00304EF8 48 06 F2 D1 */ bl GXSetVtxDescv /* 80307F9C 00304EFC 93 FE 00 48 */ stw r31, 0x48(r30) @@ -395,8 +395,8 @@ lbl_803080B4: /* 803080CC 0030502C 38 21 00 10 */ addi r1, r1, 0x10 /* 803080D0 00305030 4E 80 00 20 */ blr -.global sub_803080d4 -sub_803080d4: +.global ResetGXStatesFull__3CGXFv +ResetGXStatesFull__3CGXFv: /* 803080D4 00305034 94 21 FF F0 */ stwu r1, -0x10(r1) /* 803080D8 00305038 7C 08 02 A6 */ mflr r0 /* 803080DC 0030503C 3C 60 80 5A */ lis r3, sGXState__3CGX@ha @@ -506,7 +506,7 @@ lbl_80308254: /* 80308258 003051B8 38 80 00 00 */ li r4, 0 /* 8030825C 003051BC 38 A0 00 00 */ li r5, 0 /* 80308260 003051C0 38 C0 00 00 */ li r6, 0 -/* 80308264 003051C4 48 07 26 4D */ bl GXSetTexCoordCylWrap +/* 80308264 003051C4 48 07 26 4D */ bl GXSetTexCoordScaleManually /* 80308268 003051C8 3B DE 00 01 */ addi r30, r30, 1 /* 8030826C 003051CC 2C 1E 00 08 */ cmpwi r30, 8 /* 80308270 003051D0 41 80 FF E4 */ blt lbl_80308254 diff --git a/asm/MetroidPrime/CNESEmulator.s b/asm/MetroidPrime/CNESEmulator.s index 1b22e68a..dd665cd1 100644 --- a/asm/MetroidPrime/CNESEmulator.s +++ b/asm/MetroidPrime/CNESEmulator.s @@ -137,8 +137,8 @@ lbl_80293C38: /* 80293C6C 00290BCC 38 80 00 00 */ li r4, 0 /* 80293C70 00290BD0 38 A0 00 00 */ li r5, 0 /* 80293C74 00290BD4 38 C0 00 00 */ li r6, 0 -/* 80293C78 00290BD8 48 0E 6C 39 */ bl GXSetTexCoordCylWrap -/* 80293C7C 00290BDC 48 07 44 59 */ bl sub_803080d4 +/* 80293C78 00290BD8 48 0E 6C 39 */ bl GXSetTexCoordScaleManually +/* 80293C7C 00290BDC 48 07 44 59 */ bl ResetGXStatesFull__3CGXFv /* 80293C80 00290BE0 38 60 00 00 */ li r3, 0 /* 80293C84 00290BE4 48 07 51 CD */ bl SetNumChans__3CGXFUc /* 80293C88 00290BE8 38 60 00 01 */ li r3, 1 diff --git a/include/Kyoto/Basics/COsContext.hpp b/include/Kyoto/Basics/COsContext.hpp index 3012bb45..ada9a6ce 100644 --- a/include/Kyoto/Basics/COsContext.hpp +++ b/include/Kyoto/Basics/COsContext.hpp @@ -3,7 +3,7 @@ #include "types.h" -#include "gx_struct.h" +#include class COsContext { public: diff --git a/include/Kyoto/Graphics/CGX.hpp b/include/Kyoto/Graphics/CGX.hpp index 43d2c74a..f386f29e 100644 --- a/include/Kyoto/Graphics/CGX.hpp +++ b/include/Kyoto/Graphics/CGX.hpp @@ -4,6 +4,11 @@ #include "types.h" #include "dolphin/gx.h" +#include + +#ifdef __MWERKS__ +#pragma cpp_extensions on +#endif class CGX { public: @@ -33,24 +38,29 @@ public: f32 xc_fogFarZ; GXColor x10_fogColor; - SFogParams(); /* { - x0_fogStartZ = 0.f; - x4_fogEndZ = 1.f; - x8_fogNearZ = 0.1f; - xc_fogFarZ = 1.f; - }*/ + SFogParams() : x0_fogStartZ(0.f), x4_fogEndZ(1.f), x8_fogNearZ(0.1f), xc_fogFarZ(1.f) { + x10_fogColor.a = 0; + x10_fogColor.b = 0; + x10_fogColor.g = 0; + x10_fogColor.r = 0; + } }; struct SGXState { - void* x0_arrayPtrs[12]; + const void* x0_arrayPtrs[12]; u16 x30_prevChanCtrls[2]; u16 x34_chanCtrls[2]; GXColor x38_chanAmbColors[2]; GXColor x40_chanMatColors[2]; u32 x48_descList; - u8 x4c_ : 5; - u8 x4c_dirtyChanCtrl : 2; - u8 x4c_numChansDirty : 1; + union { + u8 x4c_flags; + struct { + u8 x4c_unk : 5; + u8 x4c_dirtyChanCtrl : 2; + u8 x4c_numChansDirty : 1; + }; + }; u8 x4d_prevNumChans; u8 x4e_numChans; u8 x4f_numTexGens; @@ -77,6 +87,7 @@ public: static void SetNumChans(u8 num); static void SetNumTexGens(u8 num); static void SetNumTevStages(u8 num); + static void SetNumIndStages(u8 num); static void SetChanAmbColor(EChannelId channel, const GXColor& color); static void SetChanMatColor(EChannelId channel, const GXColor& color); static void SetChanCtrl(EChannelId channel, GXBool enable, GXColorSrc ambSrc, GXColorSrc matSrc, GXLightID lights, GXDiffuseFn diffFn, @@ -88,6 +99,28 @@ public: static void SetTevColorOp_Compressed(GXTevStageID stageId, u32 flags); static void SetTevAlphaOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID outReg); static void SetTevAlphaOp_Compressed(GXTevStageID stageId, u32 flags); + static void SetTevKColorSel(GXTevStageID stageId, GXTevKColorSel sel); + static void SetTevKAlphaSel(GXTevStageID stageId, GXTevKAlphaSel sel); + static void SetTevOrder(GXTevStageID stageId, GXTexCoordID texCoord, GXTexMapID texMap, GXChannelID color); + static void SetBlendMode(GXBlendMode mode, GXBlendFactor srcFac, GXBlendFactor dstFac, GXLogicOp op); + static void SetZMode(bool compareEnable, GXCompare func, bool updateEnable); + static void SetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1); + static void SetTevIndirect(GXTevStageID stageId, GXIndTexStageID indStage, GXIndTexFormat fmt, GXIndTexBiasSel biasSel, + GXIndTexMtxID mtxSel, GXIndTexWrap wrapS, GXIndTexWrap wrapT, GXBool addPrev, GXBool indLod, + GXIndTexAlphaSel alphaSel); + static void SetTevDirect(GXTevStageID stageId); + static void SetTexCoordGen(GXTexCoordID dstCoord, GXTexGenType fn, GXTexGenSrc src, GXTexMtx mtx, GXBool normalize, GXPTTexMtx postMtx); + static void SetArray(GXAttr attr, const void* data, u8 stride); + static void SetFog(GXFogType type, f32 startZ, f32 endZ, f32 nearZ, f32 farZ, const GXColor& color); + static void SetLineWidth(u8 width, GXTexOffset offset); + static void SetIndTexMtxSTPointFive(GXIndTexMtxID id, s8 scaleExp); + static void SetVtxDescv_Compressed(u32 flags); + + static void CallDisplayList(const void* ptr, size_t size); + static void Begin(GXPrimitive prim, GXVtxFmt fmt, u16 numVtx); + static void End(); + static void ResetGXStates(); + static void ResetGXStatesFull(); // name? static GXColor GetChanAmbColor(EChannelId channel); @@ -97,9 +130,13 @@ public: static inline void CopyGXColor(GXColor& dst, const GXColor& src) { *reinterpret_cast< u32* >(&dst) = *reinterpret_cast< const u32* >(&src); } - static inline u32 MaskAndShiftLeft(u32 a, u32 b, u32 s) { return (a & b) << s; } + static inline u32 MaskAndShiftLeft(u32 v, u32 m, u32 s) { return (v & m) << s; } + static inline u32 ShiftRightAndMask(u32 v, u32 m, u32 s) { return (v >> s) & m; } private: + static void FlushState(); + static void update_fog(u32 flags); + static SGXState sGXState; }; diff --git a/include/Kyoto/Graphics/CTevCombiners.hpp b/include/Kyoto/Graphics/CTevCombiners.hpp index fbce52f6..3f149ebe 100644 --- a/include/Kyoto/Graphics/CTevCombiners.hpp +++ b/include/Kyoto/Graphics/CTevCombiners.hpp @@ -1,9 +1,10 @@ #ifndef _CTEVCOMBINERS_HPP #define _CTEVCOMBINERS_HPP -#include "gx_enum.h" #include "types.h" +#include + class CTevCombiners { public: enum EColorSrc { diff --git a/include/Kyoto/Graphics/CTexture.hpp b/include/Kyoto/Graphics/CTexture.hpp index 7dbdd7ec..7b6c289b 100644 --- a/include/Kyoto/Graphics/CTexture.hpp +++ b/include/Kyoto/Graphics/CTexture.hpp @@ -1,9 +1,10 @@ #ifndef _CTEXTURE_HPP #define _CTEXTURE_HPP -#include "gx_enum.h" #include "types.h" +#include + class CTexture { public: enum EClampMode { @@ -13,6 +14,8 @@ public: }; void Load(GXTexMapID texMapId, EClampMode clampMode) const; + + static void InvalidateTexmap(GXTexMapID id); }; #endif \ No newline at end of file diff --git a/include/MetaRender/CCubeRenderer.hpp b/include/MetaRender/CCubeRenderer.hpp index 1ff45f3b..df501a96 100644 --- a/include/MetaRender/CCubeRenderer.hpp +++ b/include/MetaRender/CCubeRenderer.hpp @@ -1,9 +1,10 @@ #ifndef _CCUBERENDERER_HPP #define _CCUBERENDERER_HPP -#include "gx_enum.h" #include "types.h" +#include + #include "Kyoto/Graphics/CColor.hpp" #include "Kyoto/Math/CTransform4f.hpp" #include "Kyoto/Math/CVector2f.hpp" diff --git a/include/dolphin/gx/GXBump.h b/include/dolphin/gx/GXBump.h index aee5c668..51b3dd1e 100644 --- a/include/dolphin/gx/GXBump.h +++ b/include/dolphin/gx/GXBump.h @@ -15,11 +15,12 @@ void GXSetIndTexMtx(GXIndTexMtxID mtx_sel, const void* offset, s8 scale_exp); void GXSetIndTexMtx(GXIndTexMtxID mtx_sel, f32 offset[2][3], s8 scale_exp); #endif void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMapID tex_map); -void GXSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexFormat format, - GXIndTexBiasSel bias_sel, GXIndTexMtxID matrix_sel, GXIndTexWrap wrap_s, GXIndTexWrap wrap_t, - GXBool add_prev, GXBool ind_lod, GXIndTexAlphaSel alpha_sel); +void GXSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexFormat format, GXIndTexBiasSel bias_sel, + GXIndTexMtxID matrix_sel, GXIndTexWrap wrap_s, GXIndTexWrap wrap_t, GXBool add_prev, GXBool ind_lod, + GXIndTexAlphaSel alpha_sel); void GXSetTevIndWarp(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXBool signed_offsets, GXBool replace_mode, GXIndTexMtxID matrix_sel); +void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXIndTexScale scale_t); #ifdef __cplusplus } diff --git a/include/dolphin/gx/GXEnum.h b/include/dolphin/gx/GXEnum.h index 3e792fc3..cb9fa9ce 100644 --- a/include/dolphin/gx/GXEnum.h +++ b/include/dolphin/gx/GXEnum.h @@ -122,6 +122,8 @@ typedef enum _GXAttr { GX_VA_NULL = 0xFF, } GXAttr; +#define GX_MAX_VTXDESCLIST_SZ (GX_VA_MAX_ATTR + 1) + typedef enum _GXAttrType { GX_NONE, GX_DIRECT, diff --git a/include/dolphin/gx/GXTexture.h b/include/dolphin/gx/GXTexture.h index 942811bc..970ead25 100644 --- a/include/dolphin/gx/GXTexture.h +++ b/include/dolphin/gx/GXTexture.h @@ -8,19 +8,20 @@ extern "C" { #endif -void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, u32 format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXBool mipmap); -void GXInitTexObjCI(GXTexObj* obj, const void* data, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrapS, - GXTexWrapMode wrapT, GXBool mipmap, u32 tlut); +void GXInitTexObj(GXTexObj* obj, const void* data, u16 width, u16 height, u32 format, GXTexWrapMode wrapS, GXTexWrapMode wrapT, + GXBool mipmap); +void GXInitTexObjCI(GXTexObj* obj, const void* data, u16 width, u16 height, GXCITexFmt format, GXTexWrapMode wrapS, GXTexWrapMode wrapT, + GXBool mipmap, u32 tlut); void GXInitTexObjData(GXTexObj* obj, const void* data); -void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filt, GXTexFilter mag_filt, f32 min_lod, f32 max_lod, f32 lod_bias, - GXBool bias_clamp, GXBool do_edge_lod, GXAnisotropy max_aniso); +void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filt, GXTexFilter mag_filt, f32 min_lod, f32 max_lod, f32 lod_bias, GXBool bias_clamp, + GXBool do_edge_lod, GXAnisotropy max_aniso); void GXLoadTexObj(GXTexObj* obj, GXTexMapID id); u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod); void GXInvalidateTexAll(); void GXInitTexObjWrapMode(GXTexObj* obj, GXTexWrapMode s, GXTexWrapMode t); void GXInitTlutObj(GXTlutObj* obj, const void* data, GXTlutFmt format, u16 entries); void GXLoadTlut(const GXTlutObj* obj, GXTlut idx); +void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 ss, u16 ts); #ifdef __cplusplus } diff --git a/include/gx_enum.h b/include/gx_enum.h deleted file mode 100644 index 497a91eb..00000000 --- a/include/gx_enum.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __GX_ENUM_H__ -#define __GX_ENUM_H__ - -#include "types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum _GXTexMapID { - GX_TEXMAP0, - GX_TEXMAP1, - GX_TEXMAP2, - GX_TEXMAP3, - GX_TEXMAP4, - GX_TEXMAP5, - GX_TEXMAP6, - GX_TEXMAP7, - GX_MAX_TEXMAP, - GX_TEXMAP_NULL = 0xFF, - GX_TEX_DISABLE = 0x100, -} GXTexMapID; - -typedef enum _GXPrimitive { - GX_QUADS = 0x80, - GX_TRIANGLES = 0x90, - GX_TRIANGLESTRIP = 0x98, - GX_TRIANGLEFAN = 0xA0, - GX_LINES = 0xA8, - GX_LINESTRIP = 0xB0, - GX_POINTS = 0xB8, -} GXPrimitive; - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/include/gx_struct.h b/include/gx_struct.h deleted file mode 100644 index 9a0ed1f0..00000000 --- a/include/gx_struct.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __GX_STRUCT_H__ -#define __GX_STRUCT_H__ - -#include "types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _GXRenderModeObj { - u32 viTVMode; - u16 fbWidth; - u16 efbHeight; - u16 xfbHeight; - u16 viXOrigin; - u16 viYOrigin; - u16 viWidth; - u16 viHeight; - u32 xfbMode; - u8 field_rendering; - u8 aa; - u8 sample_pattern[12][2]; - u8 vfilter[7]; -} GXRenderModeObj; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libc/stddef.h b/libc/stddef.h index 010087e2..a1fb6b4b 100644 --- a/libc/stddef.h +++ b/libc/stddef.h @@ -7,7 +7,7 @@ extern "C" { #define offsetof(type, member) ((size_t) & (((type*)0)->member)) -typedef unsigned int size_t; +typedef __typeof__(sizeof(0)) size_t; #ifndef NULL #define NULL 0L diff --git a/src/Kyoto/Graphics/CGX.cpp b/src/Kyoto/Graphics/CGX.cpp index adddd605..68e9dba4 100644 --- a/src/Kyoto/Graphics/CGX.cpp +++ b/src/Kyoto/Graphics/CGX.cpp @@ -1,7 +1,13 @@ #include "Kyoto/Graphics/CGX.hpp" +#include "Kyoto/Alloc/CMemory.hpp" +#include "Kyoto/Graphics/CTexture.hpp" + +#include CGX::SGXState CGX::sGXState; +static GXVtxDescList sVtxDescList[GX_MAX_VTXDESCLIST_SZ]; + void CGX::SetNumChans(u8 num) { sGXState.x4e_numChans = num; sGXState.x4c_numChansDirty = sGXState.x4e_numChans != sGXState.x4d_prevNumChans; @@ -36,8 +42,8 @@ void CGX::SetChanCtrl(EChannelId channel, GXBool enable, GXColorSrc ambSrc, GXCo u16 flags = (lights == GX_LIGHT_NULL ? 0 : enable) & 1 | (ambSrc & 1) << 1 | (matSrc & 1) << 2 | (lights & 0xFF) << 3 | (diffFn & 3) << 11 | (attnFn & 3) << 13; sGXState.x34_chanCtrls[channel] = flags; - sGXState.x4c_dirtyChanCtrl = (((sGXState.x34_chanCtrls[channel] != sGXState.x30_prevChanCtrls[channel]) & 1) << channel) & - (sGXState.x4c_dirtyChanCtrl & ~(1 << channel)); + // sGXState.x4c_dirtyChanCtrl = (((sGXState.x34_chanCtrls[channel] != sGXState.x30_prevChanCtrls[channel]) & 1) << channel) & + // (sGXState.x4c_dirtyChanCtrl & ~(1 << channel)); // if (channel == Channel0) { // sGXState.x4c_dirtyChanCtrl0 = (sGXState.x34_chanCtrls[channel] != sGXState.x30_prevChanCtrls[channel]); // } else { @@ -88,7 +94,13 @@ void CGX::SetTevColorOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias, GXTevS } void CGX::SetTevColorOp_Compressed(GXTevStageID stageId, u32 flags) { - // TODO + STevState& state = sGXState.x68_tevStates[stageId]; + if (flags != state.x8_colorOps) { + state.x8_colorOps = flags; + GXSetTevColorOp(stageId, static_cast< GXTevOp >(ShiftRightAndMask(flags, 0xF, 0)), + static_cast< GXTevBias >(ShiftRightAndMask(flags, 3, 4)), static_cast< GXTevScale >(ShiftRightAndMask(flags, 3, 6)), + static_cast< GXBool >(ShiftRightAndMask(flags, 1, 8)), static_cast< GXTevRegID >(ShiftRightAndMask(flags, 3, 9))); + } } void CGX::SetTevAlphaOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID outReg) { @@ -102,5 +114,284 @@ void CGX::SetTevAlphaOp(GXTevStageID stageId, GXTevOp op, GXTevBias bias, GXTevS } void CGX::SetTevAlphaOp_Compressed(GXTevStageID stageId, u32 flags) { - // TODO + STevState& state = sGXState.x68_tevStates[stageId]; + if (flags != state.xc_alphaOps) { + state.xc_alphaOps = flags; + GXSetTevAlphaOp(stageId, static_cast< GXTevOp >(ShiftRightAndMask(flags, 0xF, 0)), + static_cast< GXTevBias >(ShiftRightAndMask(flags, 3, 4)), static_cast< GXTevScale >(ShiftRightAndMask(flags, 3, 6)), + static_cast< GXBool >(ShiftRightAndMask(flags, 1, 8)), static_cast< GXTevRegID >(ShiftRightAndMask(flags, 3, 9))); + } +} + +void CGX::SetTevKColorSel(GXTevStageID stageId, GXTevKColorSel sel) { + STevState& state = sGXState.x68_tevStates[stageId]; + if (sel != state.x18_kColorSel) { + state.x18_kColorSel = sel; + GXSetTevKColorSel(stageId, sel); + } +} + +void CGX::SetTevKAlphaSel(GXTevStageID stageId, GXTevKAlphaSel sel) { + STevState& state = sGXState.x68_tevStates[stageId]; + if (sel != state.x19_kAlphaSel) { + state.x19_kAlphaSel = sel; + GXSetTevKAlphaSel(stageId, sel); + } +} + +void CGX::SetTevOrder(GXTevStageID stageId, GXTexCoordID texCoord, GXTexMapID texMap, GXChannelID color) { + STevState& state = sGXState.x68_tevStates[stageId]; + u32 flags = MaskAndShiftLeft(texCoord, 0xFF, 0) | MaskAndShiftLeft(texMap, 0xFF, 8) | MaskAndShiftLeft(color, 0xFF, 16); + if (state.x14_tevOrderFlags != flags) { + state.x14_tevOrderFlags = flags; + GXSetTevOrder(stageId, texCoord, texMap, color); + } +} + +void CGX::SetBlendMode(GXBlendMode mode, GXBlendFactor srcFac, GXBlendFactor dstFac, GXLogicOp op) { + u16 flags = MaskAndShiftLeft(mode, 3, 0) | MaskAndShiftLeft(srcFac, 7, 2) | MaskAndShiftLeft(dstFac, 7, 5) | MaskAndShiftLeft(op, 0xF, 8); + if (flags != sGXState.x56_blendMode) { + update_fog(flags); + sGXState.x56_blendMode = flags; + GXSetBlendMode(mode, srcFac, dstFac, op); + } +} + +void CGX::SetZMode(bool compareEnable, GXCompare func, bool updateEnable) { + // ?? + u8 flags = compareEnable | MaskAndShiftLeft(updateEnable, 0xFF, 1) | (func & 0xFF) << 2; + if (flags != sGXState.x52_zmode) { + sGXState.x52_zmode = flags; + GXSetZMode(compareEnable, func, updateEnable); + } +} + +void CGX::SetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) { + u32 flags = MaskAndShiftLeft(comp0, 7, 0) | MaskAndShiftLeft(ref0, 0xFF, 3) | MaskAndShiftLeft(op, 7, 11) | + MaskAndShiftLeft(comp1, 7, 14) | MaskAndShiftLeft(ref1, 0xFF, 17); + if (sGXState.x248_alphaCompare != flags) { + sGXState.x248_alphaCompare = flags; + GXSetAlphaCompare(comp0, ref0, op, comp1, ref1); + GXSetZCompLoc(comp0 == GX_ALWAYS); + } +} + +void CGX::SetTevIndirect(GXTevStageID stageId, GXIndTexStageID indStage, GXIndTexFormat fmt, GXIndTexBiasSel biasSel, GXIndTexMtxID mtxSel, + GXIndTexWrap wrapS, GXIndTexWrap wrapT, GXBool addPrev, GXBool indLod, GXIndTexAlphaSel alphaSel) { + STevState& state = sGXState.x68_tevStates[stageId]; + u32 flags = MaskAndShiftLeft(indStage, 3, 0) | MaskAndShiftLeft(fmt, 3, 2) | MaskAndShiftLeft(biasSel, 7, 4) | + MaskAndShiftLeft(mtxSel, 15, 7) | MaskAndShiftLeft(wrapS, 7, 11) | MaskAndShiftLeft(wrapT, 7, 14) | + MaskAndShiftLeft(addPrev, 1, 17) | MaskAndShiftLeft(indLod, 1, 18) | MaskAndShiftLeft(alphaSel, 3, 19); + if (state.x10_indFlags != flags) { + state.x10_indFlags = flags; + GXSetTevIndirect(stageId, indStage, fmt, biasSel, mtxSel, wrapS, wrapT, addPrev, indLod, alphaSel); + } +} + +void CGX::SetTevDirect(GXTevStageID stageId) { + STevState& state = sGXState.x68_tevStates[stageId]; + if (state.x10_indFlags != 0) { + state.x10_indFlags = 0; + GXSetTevDirect(stageId); + } +} + +void CGX::SetTexCoordGen(GXTexCoordID dstCoord, GXTexGenType fn, GXTexGenSrc src, GXTexMtx mtx, GXBool normalize, GXPTTexMtx postMtx) { + STexState& state = sGXState.x228_texStates[dstCoord]; + u32 vm = (mtx - GX_TEXMTX0) / 3; + u32 vp = postMtx - GX_PTTEXMTX0; +#ifdef NONMATCHING + // Similarly to GXTexMtx, this should also be divided by 3 + vp /= 3; +#endif + u32 flags = MaskAndShiftLeft(fn, 0xF, 0) | MaskAndShiftLeft(src, 0x1F, 4) | MaskAndShiftLeft(vm, 0x1F, 9) | + MaskAndShiftLeft(normalize, 1, 14) | MaskAndShiftLeft(vp, 0x3F, 15); + if (state.x0_coordGen != flags) { + state.x0_coordGen = flags; + GXSetTexCoordGen2(dstCoord, fn, src, mtx, normalize, postMtx); + } +} + +void CGX::SetNumIndStages(u8 num) { + if (sGXState.x51_numIndStages != num) { + sGXState.x51_numIndStages = num; + GXSetNumIndStages(num); + } +} + +void CGX::SetArray(GXAttr attr, const void* data, u8 stride) { + u32 idx = attr - GX_VA_POS; + if (data == nullptr || sGXState.x0_arrayPtrs[idx] == data) { + return; + } + sGXState.x0_arrayPtrs[idx] = data; + GXSetArray(attr, data, stride); +} + +void CGX::CallDisplayList(const void* ptr, size_t size) { + if (sGXState.x4c_flags != 0) { + FlushState(); + } + GXCallDisplayList(ptr, size); +} + +void CGX::Begin(GXPrimitive prim, GXVtxFmt fmt, u16 numVtx) { + if (sGXState.x4c_flags != 0) { + FlushState(); + } + GXBegin(prim, fmt, numVtx); +} + +void CGX::End() {} + +void CGX::SetFog(GXFogType type, f32 startZ, f32 endZ, f32 nearZ, f32 farZ, const GXColor& color) { + sGXState.x53_fogType = type; + sGXState.x24c_fogParams.x0_fogStartZ = startZ; + sGXState.x24c_fogParams.x4_fogEndZ = endZ; + sGXState.x24c_fogParams.x8_fogNearZ = nearZ; + sGXState.x24c_fogParams.xc_fogFarZ = farZ; + CopyGXColor(sGXState.x24c_fogParams.x10_fogColor, color); + GXSetFog(static_cast< GXFogType >(sGXState.x53_fogType), sGXState.x24c_fogParams.x0_fogStartZ, sGXState.x24c_fogParams.x4_fogEndZ, + sGXState.x24c_fogParams.x8_fogNearZ, sGXState.x24c_fogParams.xc_fogFarZ, + (sGXState.x56_blendMode & 0xE0) == 0x20 ? GXColor() : sGXState.x24c_fogParams.x10_fogColor); +} + +void CGX::SetLineWidth(u8 width, GXTexOffset offset) { + u16 flags = width | offset << 8; + if (flags != sGXState.x54_lineWidthAndOffset) { + sGXState.x54_lineWidthAndOffset = flags; + GXSetLineWidth(width, offset); + } +} + +CGX::STevState::STevState() +: x0_colorInArgs(0) +, x4_alphaInArgs(0) +, x8_colorOps(0) +, xc_alphaOps(0) +, x10_indFlags(0) +, x14_tevOrderFlags(UINT_MAX) +, x18_kColorSel(UCHAR_MAX) +, x19_kAlphaSel(UCHAR_MAX) {} + +CGX::STexState::STexState() : x0_coordGen(0) {} + +CGX::SGXState::SGXState() +: x48_descList(0) +, x4d_prevNumChans(2) +, x4e_numChans(0) +, x4f_numTexGens(UCHAR_MAX) +, x50_numTevStages(UCHAR_MAX) +, x51_numIndStages(UCHAR_MAX) +, x52_zmode(UCHAR_MAX) +, x53_fogType(0) +, x54_lineWidthAndOffset(USHRT_MAX) +, x56_blendMode(USHRT_MAX) +, x248_alphaCompare(UINT_MAX) { + const GXColor sGXClear = {0, 0, 0, 0}; + const GXColor sGXWhite = {255, 255, 255, 255}; + for (s32 i = 0; i < 2; ++i) { + x30_prevChanCtrls[i] = USHRT_MAX; + x34_chanCtrls[i] = USHRT_MAX; + x38_chanAmbColors[i] = sGXClear; + x40_chanMatColors[i] = sGXWhite; + } + for (s32 i = 0; i < 4; ++i) { + x58_kColors[i] = sGXClear; + } + SetChanCtrl(Channel0, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + SetChanCtrl(Channel1, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); +} + +void CGX::ResetGXStates() { + sGXState.x48_descList = 0; + GXClearVtxDesc(); + for (s32 i = 0; i < 12; i++) { + sGXState.x0_arrayPtrs[i] = reinterpret_cast< const void* >(1); + } + for (s32 i = 0; i < 8; i++) { + CTexture::InvalidateTexmap(static_cast< GXTexMapID >(i)); + } + for (s32 i = 0; i < 4; i++) { + GXSetTevKColor(static_cast< GXTevKColorID >(i), sGXState.x58_kColors[i]); + } + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_RED); + GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_GREEN); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_BLUE); + SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetCurrentMtx(GX_PNMTX0); + SetNumIndStages(0); + for (s32 i = 0; i < 4; i++) { + GXSetIndTexCoordScale(static_cast< GXIndTexStageID >(i), GX_ITS_1, GX_ITS_1); + } + for (s32 i = 0; i < 16; i++) { + SetTevDirect(static_cast< GXTevStageID >(i)); + } + for (s32 i = 0; i < 8; i++) { + GXSetTexCoordScaleManually(static_cast< GXTexCoordID >(i), false, 0, 0); + } + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); +} + +void CGX::ResetGXStatesFull() { + new (&sGXState) SGXState(); + CGX::ResetGXStates(); +} + +void CGX::FlushState() { + if (sGXState.x4c_numChansDirty) { + GXSetNumChans(sGXState.x4e_numChans); + sGXState.x4d_prevNumChans = sGXState.x4e_numChans; + } + if (sGXState.x4c_flags & 2) { + u16 flags = sGXState.x34_chanCtrls[0]; + GXBool enable = ShiftRightAndMask(flags, 1, 0); + GXColorSrc ambSrc = static_cast< GXColorSrc >(ShiftRightAndMask(flags, 1, 1)); + GXColorSrc matSrc = static_cast< GXColorSrc >(ShiftRightAndMask(flags, 1, 2)); + u32 lightMask = ShiftRightAndMask(flags, 0xFF, 3); + GXDiffuseFn diffFn = static_cast< GXDiffuseFn >(ShiftRightAndMask(flags, 3, 11)); + GXAttnFn attnFn = static_cast< GXAttnFn >(ShiftRightAndMask(flags, 3, 13)); + GXSetChanCtrl(GX_COLOR0, enable, ambSrc, matSrc, lightMask, diffFn, attnFn); + sGXState.x30_prevChanCtrls[0] = sGXState.x34_chanCtrls[0]; + } + if (sGXState.x4c_flags & 4) { + u16 flags = sGXState.x34_chanCtrls[1]; + GXBool enable = ShiftRightAndMask(flags, 1, 0); + GXColorSrc ambSrc = static_cast< GXColorSrc >(ShiftRightAndMask(flags, 1, 1)); + GXColorSrc matSrc = static_cast< GXColorSrc >(ShiftRightAndMask(flags, 1, 2)); + u32 lightMask = ShiftRightAndMask(flags, 0xFF, 3); + GXDiffuseFn diffFn = static_cast< GXDiffuseFn >(ShiftRightAndMask(flags, 3, 11)); + GXAttnFn attnFn = static_cast< GXAttnFn >(ShiftRightAndMask(flags, 3, 13)); + GXSetChanCtrl(GX_COLOR1, enable, ambSrc, matSrc, lightMask, diffFn, attnFn); + sGXState.x30_prevChanCtrls[1] = sGXState.x34_chanCtrls[1]; + } + sGXState.x4c_flags = 0; +} + +void CGX::SetIndTexMtxSTPointFive(GXIndTexMtxID id, s8 scaleExp) { + static const f32 indMtx[2][3] = { + {0.5f, 0.f, 0.f}, + {0.f, 0.5f, 0.f}, + }; + GXSetIndTexMtx(id, const_cast< f32(*)[3] >(indMtx), scaleExp); +} + +void CGX::SetVtxDescv_Compressed(u32 flags) { + if (flags == sGXState.x48_descList) { + return; + } + GXVtxDescList* list = sVtxDescList; + for (u32 idx = 0; idx < 11; ++idx) { + u32 shift = idx * 2; + if ((flags & 3 << shift) == (sGXState.x48_descList & 3 << shift)) { + continue; + } + list->attr = static_cast< GXAttr >(GX_VA_POS + idx); + list->type = static_cast< GXAttrType >(flags >> shift & 3); + ++list; + } + list->attr = GX_VA_NULL; + list->type = GX_NONE; + GXSetVtxDescv(sVtxDescList); + sGXState.x48_descList = flags; }