diff options
| author | LagoLunatic <LagoLunatic@users.noreply.github.com> | 2024-09-07 17:31:29 -0400 |
|---|---|---|
| committer | LagoLunatic <LagoLunatic@users.noreply.github.com> | 2024-09-07 17:31:29 -0400 |
| commit | 3e7ece6ff50f48dbce8b044cfcc0851ce4859789 (patch) | |
| tree | 6ae26e70f5d6e3ad9c2497538ff54a6dbe82e77f /src | |
| parent | 340d18c6bcc8d6e0640748273109c55ab058df7b (diff) | |
Copy dolphin/gx progress from TP
Diffstat (limited to 'src')
| -rw-r--r-- | src/JSystem/J3DGraphBase/J3DGD.cpp | 2 | ||||
| -rw-r--r-- | src/JSystem/J3DGraphBase/J3DSys.cpp | 2 | ||||
| -rw-r--r-- | src/JSystem/JParticle/JPADraw.cpp | 16 | ||||
| -rw-r--r-- | src/d/d_kankyo_data.cpp | 4 | ||||
| -rw-r--r-- | src/dolphin/gx/GXAttr.c | 751 | ||||
| -rw-r--r-- | src/dolphin/gx/GXBump.c | 194 | ||||
| -rw-r--r-- | src/dolphin/gx/GXDisplayList.c | 21 | ||||
| -rw-r--r-- | src/dolphin/gx/GXDraw.c | 71 | ||||
| -rw-r--r-- | src/dolphin/gx/GXFifo.c | 337 | ||||
| -rw-r--r-- | src/dolphin/gx/GXFrameBuf.c | 638 | ||||
| -rw-r--r-- | src/dolphin/gx/GXGeometry.c | 149 | ||||
| -rw-r--r-- | src/dolphin/gx/GXInit.c | 561 | ||||
| -rw-r--r-- | src/dolphin/gx/GXLight.c | 294 | ||||
| -rw-r--r-- | src/dolphin/gx/GXMisc.c | 266 | ||||
| -rw-r--r-- | src/dolphin/gx/GXPerf.c | 384 | ||||
| -rw-r--r-- | src/dolphin/gx/GXPixel.c | 235 | ||||
| -rw-r--r-- | src/dolphin/gx/GXTev.c | 366 | ||||
| -rw-r--r-- | src/dolphin/gx/GXTexture.c | 593 | ||||
| -rw-r--r-- | src/dolphin/gx/GXTransform.c | 316 | ||||
| -rw-r--r-- | src/m_Do/m_Do_graphic.cpp | 4 |
20 files changed, 5190 insertions, 14 deletions
diff --git a/src/JSystem/J3DGraphBase/J3DGD.cpp b/src/JSystem/J3DGraphBase/J3DGD.cpp index 95d501a8..555558cf 100644 --- a/src/JSystem/J3DGraphBase/J3DGD.cpp +++ b/src/JSystem/J3DGraphBase/J3DGD.cpp @@ -502,7 +502,7 @@ void J3DGDSetFog(GXFogType type, f32 startZ, f32 endZ, f32 nearZ, f32 farZ, GXCo void J3DGDSetFogRangeAdj(u8 enabled, u16 center, GXFogAdjTable* pFogAdjTable) { if (enabled) { for (s32 i = 0; i < 10; i += 2) { - J3DGDWriteBPCmd((0xe9 + i / 2) << 24 | pFogAdjTable->r[i + 1] << 12 | pFogAdjTable->r[i] << 0); + J3DGDWriteBPCmd((0xe9 + i / 2) << 24 | pFogAdjTable->fogVals[i + 1] << 12 | pFogAdjTable->fogVals[i] << 0); } } diff --git a/src/JSystem/J3DGraphBase/J3DSys.cpp b/src/JSystem/J3DGraphBase/J3DSys.cpp index 3ef85963..8e910641 100644 --- a/src/JSystem/J3DGraphBase/J3DSys.cpp +++ b/src/JSystem/J3DGraphBase/J3DSys.cpp @@ -148,7 +148,7 @@ void J3DSys::setTexCacheRegion(GXTexCacheSize size) { /* 802D8EE0-802D956C .text drawInit__6J3DSysFv */ void J3DSys::drawInit() { - GXSetMisc(2, 0); + GXSetMisc(GX_MT_DL_SAVE_CONTEXT, 0); GXInvalidateVtxCache(); GXSetCurrentMtx(GX_PNMTX0); GXSetCullMode(GX_CULL_BACK); diff --git a/src/JSystem/JParticle/JPADraw.cpp b/src/JSystem/JParticle/JPADraw.cpp index 5aeea12d..ac9a624a 100644 --- a/src/JSystem/JParticle/JPADraw.cpp +++ b/src/JSystem/JParticle/JPADraw.cpp @@ -822,7 +822,7 @@ void JPADraw::drawParticle() { GXSetCullMode(GX_CULL_NONE); if (dc.pbsp->isClipOn()) { GXSetClipMode(GX_CLIP_ENABLE); - GXSetMisc(1, 8); + GXSetMisc(GX_MT_XF_FLUSH, 8); } else { GXSetClipMode(GX_CLIP_DISABLE); } @@ -845,7 +845,7 @@ void JPADraw::drawParticle() { } } - GXSetMisc(1, 0); + GXSetMisc(GX_MT_XF_FLUSH, 0); } /* 8026BC2C-8026BF88 .text drawChild__7JPADrawFv */ @@ -871,7 +871,7 @@ void JPADraw::drawChild() { if (dc.pssp->isClipOn()) { GXSetClipMode(GX_CLIP_ENABLE); - GXSetMisc(1, 8); + GXSetMisc(GX_MT_XF_FLUSH, 8); } else { GXSetClipMode(GX_CLIP_DISABLE); } @@ -894,7 +894,7 @@ void JPADraw::drawChild() { } } - GXSetMisc(1, 0); + GXSetMisc(GX_MT_XF_FLUSH, 0); } /* 8026BF88-8026C024 .text zDraw__7JPADrawFv */ @@ -922,7 +922,7 @@ void JPADraw::zDrawParticle() { GXSetCullMode(GX_CULL_NONE); if (dc.pbsp->isClipOn()) { GXSetClipMode(GX_CLIP_ENABLE); - GXSetMisc(1, 8); + GXSetMisc(GX_MT_XF_FLUSH, 8); } else { GXSetClipMode(GX_CLIP_DISABLE); } @@ -945,7 +945,7 @@ void JPADraw::zDrawParticle() { } } - GXSetMisc(1, 0); + GXSetMisc(GX_MT_XF_FLUSH, 0); } /* 8026C24C-8026C4DC .text zDrawChild__7JPADrawFv */ @@ -971,7 +971,7 @@ void JPADraw::zDrawChild() { if (dc.pssp->isClipOn()) { GXSetClipMode(GX_CLIP_ENABLE); - GXSetMisc(1, 8); + GXSetMisc(GX_MT_XF_FLUSH, 8); } else { GXSetClipMode(GX_CLIP_DISABLE); } @@ -994,7 +994,7 @@ void JPADraw::zDrawChild() { } } - GXSetMisc(1, 0); + GXSetMisc(GX_MT_XF_FLUSH, 0); } /* 8026C4DC-8026C640 .text loadYBBMtx__7JPADrawFPA4_f */ diff --git a/src/d/d_kankyo_data.cpp b/src/d/d_kankyo_data.cpp index a173a6d8..6107f5fd 100644 --- a/src/d/d_kankyo_data.cpp +++ b/src/d/d_kankyo_data.cpp @@ -441,7 +441,7 @@ dKyd_Schedule* dKyd_schejule_menu_getp() { /* 80086F34-80086F74 .text dKyd_xfog_table_set__FUc */ void dKyd_xfog_table_set(u8 i_idx) { for (int i = 0; i < 10; i++) { - u16 fogAdjTableEntry = S_xfog_table_data[i_idx].r[i]; - g_env_light.mFogAdjTable.r[i] = fogAdjTableEntry; + u16 fogAdjTableEntry = S_xfog_table_data[i_idx].fogVals[i]; + g_env_light.mFogAdjTable.fogVals[i] = fogAdjTableEntry; } } diff --git a/src/dolphin/gx/GXAttr.c b/src/dolphin/gx/GXAttr.c new file mode 100644 index 00000000..724710e9 --- /dev/null +++ b/src/dolphin/gx/GXAttr.c @@ -0,0 +1,751 @@ +#include "dolphin/gx/GXAttr.h" +#include "dolphin/gx/GX.h" + +static inline void SETVCDATTR(GXAttr name, GXAttrType type) { + switch (name) { + case GX_VA_PNMTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_POSMTXIDX_ST, GX_CP_VCD_LO_POSMTXIDX_END); + break; + case GX_VA_TEX0MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX0MTXIDX_ST, + GX_CP_VCD_LO_TEX0MTXIDX_END); + break; + case GX_VA_TEX1MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX1MTXIDX_ST, + GX_CP_VCD_LO_TEX1MTXIDX_END); + break; + case GX_VA_TEX2MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX2MTXIDX_ST, + GX_CP_VCD_LO_TEX2MTXIDX_END); + break; + case GX_VA_TEX3MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX3MTXIDX_ST, + GX_CP_VCD_LO_TEX3MTXIDX_END); + break; + case GX_VA_TEX4MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX4MTXIDX_ST, + GX_CP_VCD_LO_TEX4MTXIDX_END); + break; + case GX_VA_TEX5MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX5MTXIDX_ST, + GX_CP_VCD_LO_TEX5MTXIDX_END); + break; + case GX_VA_TEX6MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX6MTXIDX_ST, + GX_CP_VCD_LO_TEX6MTXIDX_END); + break; + case GX_VA_TEX7MTXIDX: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX7MTXIDX_ST, + GX_CP_VCD_LO_TEX7MTXIDX_END); + break; + case GX_VA_POS: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END); + break; + case GX_VA_NRM: + if (type != GX_NONE) { + __GXData->hasNrms = TRUE; + __GXData->hasBiNrms = FALSE; + __GXData->nrmType = type; + } else { + __GXData->hasNrms = FALSE; + } + break; + case GX_VA_NBT: + if (type != GX_NONE) { + __GXData->hasBiNrms = TRUE; + __GXData->hasNrms = FALSE; + __GXData->nrmType = type; + } else { + __GXData->hasBiNrms = FALSE; + } + break; + case GX_VA_CLR0: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_CLRDIF_ST, GX_CP_VCD_LO_CLRDIF_END); + break; + case GX_VA_CLR1: + GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_CLRSPEC_ST, GX_CP_VCD_LO_CLRSPEC_END); + break; + case GX_VA_TEX0: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX0COORD_ST, GX_CP_VCD_HI_TEX0COORD_END); + break; + case GX_VA_TEX1: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX1COORD_ST, GX_CP_VCD_HI_TEX1COORD_END); + break; + case GX_VA_TEX2: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX2COORD_ST, GX_CP_VCD_HI_TEX2COORD_END); + break; + case GX_VA_TEX3: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX3COORD_ST, GX_CP_VCD_HI_TEX3COORD_END); + break; + case GX_VA_TEX4: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX4COORD_ST, GX_CP_VCD_HI_TEX4COORD_END); + break; + case GX_VA_TEX5: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX5COORD_ST, GX_CP_VCD_HI_TEX5COORD_END); + break; + case GX_VA_TEX6: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX6COORD_ST, GX_CP_VCD_HI_TEX6COORD_END); + break; + case GX_VA_TEX7: + GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX7COORD_ST, GX_CP_VCD_HI_TEX7COORD_END); + break; + } +} + +void GXSetVtxDesc(GXAttr name, GXAttrType type) { + SETVCDATTR(name, type); + + // Set normal data type if enabled + if (__GXData->hasNrms || __GXData->hasBiNrms) { + GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, __GXData->nrmType); + } else { + GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, 0); + } + + __GXData->dirtyState |= GX_DIRTY_VCD; +} + +void GXSetVtxDescv(GXVtxDescList* list) { + for (; list->attr != GX_VA_NULL; list++) { + SETVCDATTR(list->attr, list->type); + } + + // Set normal data type if enabled + if (__GXData->hasNrms || __GXData->hasBiNrms) { + GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, __GXData->nrmType); + } else { + GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, 0); + } + + __GXData->dirtyState |= GX_DIRTY_VCD; +} + +static void __GXXfVtxSpecs(void) { + u32 normCount, colorCount, texCount; + + normCount = __GXData->hasBiNrms ? 2 : (__GXData->hasNrms ? 1 : 0); + + // Both fields in one access + colorCount = 33 - __cntlzw((__GXData->vcdLo & (0xf << 0xd)) >> 0xd); + colorCount /= 2; // equivalent to /=2 and >>= 1 + + // All 16 assigned bits in VCD_Hi + texCount = 33 - __cntlzw((__GXData->vcdHi & (0xffff << 0)) >> 0); + texCount /= 2; // equivalent to /=2 and >>= 1 + + GX_XF_LOAD_REG(GX_XF_REG_INVERTEXSPEC, (colorCount) | (normCount << 2) | (texCount << 4)); + __GXData->bpSentNot = GX_TRUE; + + return; +} + +void __GXSetVCD(void) { + GX_CP_LOAD_REG(GX_CP_REG_VCD_LO, __GXData->vcdLo); + GX_CP_LOAD_REG(GX_CP_REG_VCD_HI, __GXData->vcdHi); + + __GXXfVtxSpecs(); +} + +void __GXCalculateVLim(void) { + static u8 tbl1[] = {0, 4, 1, 2}; + static u8 tbl2[] = {0, 8, 1, 2}; + static u8 tbl3[] = {0, 12, 1, 2}; + + u32 vlim; + u32 vcdLoReg; + u32 vcdHiReg; + s32 compCnt; + + if (__GXData->vNum == 0) { + return; + } + + vcdLoReg = __GXData->vcdLo; + vcdHiReg = __GXData->vcdHi; + + // GXCompCnt bit of normal parameters + compCnt = __GXData->vatA[GX_VTXFMT0]; + compCnt = (compCnt & 0x200) >> 9; + + vlim = GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_POSMTXIDX_ST, GX_CP_VCD_LO_POSMTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX0MTXIDX_ST, GX_CP_VCD_LO_TEX0MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX1MTXIDX_ST, GX_CP_VCD_LO_TEX1MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX2MTXIDX_ST, GX_CP_VCD_LO_TEX2MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX3MTXIDX_ST, GX_CP_VCD_LO_TEX3MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX4MTXIDX_ST, GX_CP_VCD_LO_TEX4MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX5MTXIDX_ST, GX_CP_VCD_LO_TEX5MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX6MTXIDX_ST, GX_CP_VCD_LO_TEX6MTXIDX_END); + vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX7MTXIDX_ST, GX_CP_VCD_LO_TEX7MTXIDX_END); + + vlim += tbl3[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END)]; + vlim += tbl3[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_NRM_ST, GX_CP_VCD_LO_NRM_END)] * + (compCnt == GX_NRM_NBT ? 3 : 1); + vlim += tbl1[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_CLRDIF_ST, GX_CP_VCD_LO_CLRDIF_END)]; + vlim += tbl1[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_CLRSPEC_ST, GX_CP_VCD_LO_CLRSPEC_END)]; + + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX0COORD_ST, GX_CP_VCD_HI_TEX0COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX1COORD_ST, GX_CP_VCD_HI_TEX1COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX2COORD_ST, GX_CP_VCD_HI_TEX2COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX3COORD_ST, GX_CP_VCD_HI_TEX3COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX4COORD_ST, GX_CP_VCD_HI_TEX4COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX5COORD_ST, GX_CP_VCD_HI_TEX5COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX6COORD_ST, GX_CP_VCD_HI_TEX6COORD_END)]; + vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX7COORD_ST, GX_CP_VCD_HI_TEX7COORD_END)]; + + __GXData->vLim = vlim; +} + +void GXGetVtxDesc(int param_0, GXAttrType* param_1) { + int local_38; + + switch (param_0) { + case 0: + local_38 = __GXData->vcdLo & 1; + break; + case 1: + local_38 = (__GXData->vcdLo & 2) >> 1; + break; + case 2: + local_38 = (__GXData->vcdLo & 4) >> 2; + break; + case 3: + local_38 = (__GXData->vcdLo & 8) >> 3; + break; + case 4: + local_38 = (__GXData->vcdLo & 0x10) >> 4; + break; + case 5: + local_38 = (__GXData->vcdLo & 0x20) >> 5; + break; + case 6: + local_38 = (__GXData->vcdLo & 0x40) >> 6; + break; + case 7: + local_38 = (__GXData->vcdLo & 0x80) >> 7; + break; + case 8: + local_38 = (__GXData->vcdLo & 0x100) >> 8; + break; + case 9: + local_38 = (__GXData->vcdLo & 0x600) >> 9; + break; + case 10: + if (__GXData->hasNrms != 0) { + local_38 = (__GXData->vcdLo & 0x1800) >> 11; + } else { + local_38 = 0; + } + break; + case 0x19: + if (__GXData->hasBiNrms != 0) { + local_38 = (__GXData->vcdLo & 0x1800) >> 11; + } else { + local_38 = 0; + } + break; + case 11: + local_38 = (__GXData->vcdLo & 0x6000) >> 13; + break; + case 12: + local_38 = (__GXData->vcdLo & 0x18000) >> 15; + break; + case 13: + local_38 = (__GXData->vcdHi & 3); + break; + case 14: + local_38 = (__GXData->vcdHi & 0xC) >> 2; + break; + case 15: + local_38 = (__GXData->vcdHi & 0x30) >> 4; + break; + case 16: + local_38 = (__GXData->vcdHi & 0xC0) >> 6; + break; + case 17: + local_38 = (__GXData->vcdHi & 0x300) >> 8; + break; + case 18: + local_38 = (__GXData->vcdHi & 0xC00) >> 10; + break; + case 19: + local_38 = (__GXData->vcdHi & 0x3000) >> 12; + break; + case 20: + local_38 = (__GXData->vcdHi & 0xC000) >> 14; + break; + default: + local_38 = 0; + break; + } + + *param_1 = local_38; +} + +void GXGetVtxDescv(GXVtxDescList* attrPtr) { + int i; + + for (i = 0; i <= 0x14; i++) { + attrPtr[i].attr = (GXAttr)i; + GXGetVtxDesc(i, &attrPtr[i].type); + } + + attrPtr[i].attr = (GXAttr)0x19; + GXGetVtxDesc(0x19, &attrPtr[i].type); + + i++; + attrPtr[i].attr = (GXAttr)0xFF; +} + +void GXClearVtxDesc(void) { + __GXData->vcdLo = 0; + GX_BITFIELD_SET(__GXData->vcdLo, 0x15, 2, GX_DIRECT); + __GXData->vcdHi = 0; + __GXData->hasNrms = FALSE; + __GXData->hasBiNrms = FALSE; + __GXData->dirtyState |= GX_DIRTY_VCD; +} + +/* ############################################################################################## */ + +static inline void SETVAT(u32* vatA, u32* vatB, u32* vatC, GXAttr attr, GXCompCnt compCnt, + GXCompType compType, u8 shift) { + switch (attr) { + case GX_VA_POS: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_POS_CNT_ST, GX_CP_VAT_GRP0_POS_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_POS_TYPE_ST, GX_CP_VAT_GRP0_POS_TYPE_END); + GX_SET_REG(*vatA, shift, GX_CP_VAT_GRP0_POS_SHIFT_ST, GX_CP_VAT_GRP0_POS_SHIFT_END); + break; + case GX_VA_NRM: + case GX_VA_NBT: + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_NRM_TYPE_ST, GX_CP_VAT_GRP0_NRM_TYPE_END); + if (compCnt == GX_NRM_NBT3) { + // Probably because the compCnt can only be one bit? + GX_SET_REG(*vatA, GX_NRM_NBT, GX_CP_VAT_GRP0_NRM_CNT_ST, GX_CP_VAT_GRP0_NRM_CNT_END); + GX_SET_REG(*vatA, TRUE, GX_CP_VAT_GRP0_NRMIDX3_ST, GX_CP_VAT_GRP0_NRMIDX3_END); + } else { + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_NRM_CNT_ST, GX_CP_VAT_GRP0_NRM_CNT_END); + GX_SET_REG(*vatA, FALSE, GX_CP_VAT_GRP0_NRMIDX3_ST, GX_CP_VAT_GRP0_NRMIDX3_END); + } + break; + case GX_VA_CLR0: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_CLRDIFF_CNT_ST, GX_CP_VAT_GRP0_CLRDIFF_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_CLRDIFF_TYPE_ST, + GX_CP_VAT_GRP0_CLRDIFF_TYPE_END); + break; + case GX_VA_CLR1: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_CLRSPEC_CNT_ST, GX_CP_VAT_GRP0_CLRSPEC_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_CLRSPEC_TYPE_ST, + GX_CP_VAT_GRP0_CLRSPEC_TYPE_END); + break; + case GX_VA_TEX0: + GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_TXC0_CNT_ST, GX_CP_VAT_GRP0_TXC0_CNT_END); + GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_TXC0_TYPE_ST, GX_CP_VAT_GRP0_TXC0_TYPE_END); + GX_SET_REG(*vatA, shift, GX_CP_VAT_GRP0_TXC0_SHIFT_ST, GX_CP_VAT_GRP0_TXC0_SHIFT_END); + break; + case GX_VA_TEX1: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC1_CNT_ST, GX_CP_VAT_GRP1_TXC1_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC1_TYPE_ST, GX_CP_VAT_GRP1_TXC1_TYPE_END); + GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC1_SHIFT_ST, GX_CP_VAT_GRP1_TXC1_SHIFT_END); + break; + case GX_VA_TEX2: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC2_CNT_ST, GX_CP_VAT_GRP1_TXC2_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC2_TYPE_ST, GX_CP_VAT_GRP1_TXC2_TYPE_END); + GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC2_SHIFT_ST, GX_CP_VAT_GRP1_TXC2_SHIFT_END); + break; + case GX_VA_TEX3: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC3_CNT_ST, GX_CP_VAT_GRP1_TXC3_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC3_TYPE_ST, GX_CP_VAT_GRP1_TXC3_TYPE_END); + GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC3_SHIFT_ST, GX_CP_VAT_GRP1_TXC3_SHIFT_END); + break; + case GX_VA_TEX4: + GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC4_CNT_ST, GX_CP_VAT_GRP1_TXC4_CNT_END); + GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC4_TYPE_ST, GX_CP_VAT_GRP1_TXC4_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC4_SHIFT_ST, GX_CP_VAT_GRP2_TXC4_SHIFT_END); + break; + case GX_VA_TEX5: + GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC5_CNT_ST, GX_CP_VAT_GRP2_TXC5_CNT_END); + GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC5_TYPE_ST, GX_CP_VAT_GRP2_TXC5_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC5_SHIFT_ST, GX_CP_VAT_GRP2_TXC5_SHIFT_END); + break; + case GX_VA_TEX6: + GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC6_CNT_ST, GX_CP_VAT_GRP2_TXC6_CNT_END); + GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC6_TYPE_ST, GX_CP_VAT_GRP2_TXC6_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC6_SHIFT_ST, GX_CP_VAT_GRP2_TXC6_SHIFT_END); + break; + case GX_VA_TEX7: + GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC7_CNT_ST, GX_CP_VAT_GRP2_TXC7_CNT_END); + GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC7_TYPE_ST, GX_CP_VAT_GRP2_TXC7_TYPE_END); + GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC7_SHIFT_ST, GX_CP_VAT_GRP2_TXC7_SHIFT_END); + break; + } +} + +void GXSetVtxAttrFmt(GXVtxFmt format, GXAttr attr, GXCompCnt count, GXCompType type, u8 frac) { + u32* vA = (u32*)&__GXData->vatA[format]; + u32* vB = (u32*)&__GXData->vatB[format]; + u32* vC = &__GXData->vatC[format]; + + SETVAT(vA, vB, vC, attr, count, type, frac); + + __GXData->dirtyState |= GX_DIRTY_VAT; + __GXData->dirtyVAT |= (u8)(1 << (u8)format); +} + +void GXSetVtxAttrFmtv(GXVtxFmt format, GXVtxAttrFmtList* list) { + u32* vatA; + u32* vatB; + u32* vatC; + + vatA = (u32*)&__GXData->vatA[format]; + vatB = (u32*)&__GXData->vatB[format]; + vatC = &__GXData->vatC[format]; + + for (; list->mAttrib != GX_VA_NULL; list++) { + SETVAT(vatA, vatB, vatC, list->mAttrib, list->mCompCnt, list->mCompType, list->mCompShift); + } + + __GXData->dirtyState |= GX_DIRTY_VAT; + __GXData->dirtyVAT |= (u8)(1 << (u8)format); +} + +void __GXSetVAT(void) { + u32 i = 0; + u32 dirtyVAT = __GXData->dirtyVAT; + do { + if (dirtyVAT & (1)) { + GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP0 | i, __GXData->vatA[i]); + GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP1 | i, __GXData->vatB[i]); + GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP2 | i, __GXData->vatC[i]); + } + dirtyVAT >>= 1; + i++; + } while (dirtyVAT != 0); + + __GXData->dirtyVAT = 0; +} + +static u8 GetFracForNrm(int param_0) { + int var_r31; + + switch (param_0) { + case 1: + var_r31 = 6; + break; + case 3: + var_r31 = 14; + break; + default: + case 2: + var_r31 = 0; + break; + } + + return var_r31; +} + +void GXGetVtxAttrFmtv(GXVtxFmt param_0, GXVtxAttrFmtList* param_1) { + s32 tmp; + s32 tmp2; + s32 tmp3; + int i; + +#ifdef DEBUG + // not fully matching + /* tmp = 1; + if (data_8074d3c8 != 0) { + OSPanic("GXAttr.c", 941, "\'GXGetVtxAttrFmtv\' is not allowed between GXBegin/GXEnd"); + tmp = 0; + } + + tmp2 = 1; + if (param_1 == NULL) { + OSPanic("GXAttr.c", 942, "GXSetVtxAttrFmt: list pointer is NULL"); + tmp2 = 0; + } + + tmp3 = 1; + if (param_0 >= 8) { + OSPanic("GXAttr.c", 943, "GXSetVtxAttrFmt: Format Index is out of range"); + tmp3 = 0; + } */ +#endif + + for (i = 9; i <= 0x14; i++) { + param_1->mAttrib = i; + GXGetVtxAttrFmt(param_0, i, ¶m_1->mCompCnt, ¶m_1->mCompType, ¶m_1->mCompShift); + param_1++; + } + + param_1->mAttrib = 0xFF; +} + +void GXGetVtxAttrFmt(GXVtxFmt param_0, int param_1, GXCompCnt* param_2, GXCompType* param_3, + u8* param_4) { + s32 tmp; + s32 tmp2; + GXCompCnt* tmp_1; + GXCompCnt* tmp_2; + u32* tmp_3; + +#ifdef DEBUG + // not fully matching + /* tmp = 1; + if (data_8074d3c8) { + OSPanic("GXAttr.c", 844, "\'GXGetVtxAttrFmt\' is not allowed between GXBegin/GXEnd"); + tmp = 0; + } + + tmp2 = 1; + if (param_0 >= 8) { + OSPanic("GXAttr.c", 845, "GXSetVtxAttrFmt: Format Index is out of range"); + tmp2 = 0; + } */ +#endif + + tmp_1 = (GXCompCnt*)&__GXData->vatA[param_0]; + tmp_2 = (GXCompCnt*)&__GXData->vatB[param_0]; + tmp_3 = &__GXData->vatC[param_0]; + + switch (param_1) { + case 9: + *param_2 = *tmp_1 & 1; + *param_3 = (*tmp_1 & 0xE) >> 1; + *param_4 = (*tmp_1 & 0x1F0) >> 4; + break; + case 10: + case 0x19: + *param_2 = (*tmp_1 & 0x200) >> 9; + if (*param_2 == 1 && ((*tmp_1 & 0x80000000) >> 31) != 0) { + *param_2 = 2; + } + + *param_3 = (*tmp_1 & 0x1C00) >> 10; + *param_4 = GetFracForNrm(*param_3); + break; + case 11: + *param_2 = (*tmp_1 & 0x2000) >> 0xd; + *param_3 = (*tmp_1 & 0x1C000) >> 0xe; + *param_4 = 0; + break; + case 12: + *param_2 = (*tmp_1 & 0x20000) >> 0x11; + *param_3 = (*tmp_1 & 0x1C0000) >> 0x12; + *param_4 = 0; + break; + case 13: + *param_2 = (*tmp_1 & 0x200000) >> 0x15; + *param_3 = (*tmp_1 & 0x1C00000) >> 0x16; + *param_4 = ((*tmp_1 & 0x3e000000)) >> 25; + break; + case 14: + *param_2 = *tmp_2 & 1; + *param_3 = (*tmp_2 & 0xE) >> 1; + *param_4 = (*tmp_2 & 0x1F0) >> 4; + break; + case 15: + *param_2 = (*tmp_2 & 0x200) >> 9; + *param_3 = (*tmp_2 & 0x1C00) >> 10; + *param_4 = (*tmp_2 & 0x3E000) >> 13; + break; + case 16: + *param_2 = (*tmp_2 & 0x40000) >> 0x12; + *param_3 = (*tmp_2 & 0x380000) >> 0x13; + *param_4 = (*tmp_2 & 0x7C00000) >> 0x16; + break; + case 17: + *param_2 = (*tmp_2 & 0x8000000) >> 0x1B; + *param_3 = (*tmp_2 & 0x70000000) >> 0x1C; + *param_4 = (*tmp_3 & 0x1F); + break; + case 18: + *param_2 = (*tmp_3 & 0x20) >> 5; + *param_3 = (*tmp_3 & 0x1C0) >> 6; + *param_4 = (*tmp_3 & 0x3E00) >> 9; + break; + case 19: + *param_2 = (*tmp_3 & 0x4000) >> 0xe; + *param_3 = (*tmp_3 & 0x38000) >> 0xf; + *param_4 = (*tmp_3 & 0x7c0000) >> 0x12; + break; + case 20: + *param_2 = (*tmp_3 & 0x800000) >> 0x17; + *param_3 = (*tmp_3 & 0x7000000) >> 0x18; + *param_4 = (*tmp_3 & 0xF8000000) >> 0x1b; + break; + default: + *param_2 = 1; + *param_3 = 0; + *param_4 = 0; + } +} + +void GXSetArray(GXAttr attr, void* basePtr, u8 stride) { + s32 newAttr; + s32 attrReg; + + newAttr = attr; + if (newAttr == GX_VA_NBT) { + newAttr = GX_VA_NRM; + } + + attrReg = newAttr - GX_VA_POS; + + GX_CP_LOAD_REG(GX_BP_REG_SETMODE0_TEX4 | attrReg, + // Address -> offset? + (u32)basePtr & ~0xC0000000); + + GX_CP_LOAD_REG(GX_BP_REG_SETIMAGE2_TEX4 | attrReg, stride); +} + +void GXInvalidateVtxCache(void) { + GXFIFO.u8 = GX_FIFO_CMD_INVAL_VTX; +} + +void GXSetTexCoordGen2(GXTexCoordID id, GXTexGenType type, GXTexGenSrc src, u32 texMtxIdx, + GXBool normalize, u32 dualTexMtxIdx) { + u32 reg; + u32 inputRow; + GXXfTexReg inputForm; + + reg = 0; + inputForm = GX_XF_TEX_FORM_AB11; + inputRow = 5; + + switch (src) { + case GX_TG_POS: + inputRow = 0; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_NRM: + inputRow = 1; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_BINRM: + inputRow = 3; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_TANGENT: + inputRow = 4; + inputForm = GX_XF_TEX_FORM_ABC1; + break; + case GX_TG_COLOR0: + inputRow = 2; + break; + case GX_TG_COLOR1: + inputRow = 2; + break; + case GX_TG_TEX0: + inputRow = 5; + break; + case GX_TG_TEX1: + inputRow = 6; + break; + case GX_TG_TEX2: + inputRow = 7; + break; + case GX_TG_TEX3: + inputRow = 8; + break; + case GX_TG_TEX4: + inputRow = 9; + break; + case GX_TG_TEX5: + inputRow = 10; + break; + case GX_TG_TEX6: + inputRow = 11; + break; + case GX_TG_TEX7: + inputRow = 12; + break; + } + + switch (type) { + case GX_TG_NRM: + GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST, + GX_XF_TEX_PROJTYPE_END); // 2x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + GX_SET_REG(reg, GX_TG_POS, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + break; + case GX_TG_POS: + GX_SET_REG(reg, GX_XF_TEX_PROJ_STQ, GX_XF_TEX_PROJTYPE_ST, + GX_XF_TEX_PROJTYPE_END); // 3x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + GX_SET_REG(reg, GX_TG_POS, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + break; + case GX_TG_BUMP0: + case GX_TG_BUMP1: + case GX_TG_BUMP2: + case GX_TG_BUMP3: + case GX_TG_BUMP4: + case GX_TG_BUMP5: + case GX_TG_BUMP6: + case GX_TG_BUMP7: + GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST, + GX_XF_TEX_PROJTYPE_END); // 2x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + GX_SET_REG(reg, GX_TG_NRM, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + GX_SET_REG(reg, src - GX_TG_TEXCOORD0, GX_XF_TEX_BUMPSRCTEX_ST, GX_XF_TEX_BUMPSRCTEX_END); + GX_SET_REG(reg, type - GX_TG_BUMP0, GX_XF_TEX_BUMPSRCLIGHT_ST, GX_XF_TEX_BUMPSRCLIGHT_END); + break; + case GX_TG_SRTG: + GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST, + GX_XF_TEX_PROJTYPE_END); // 2x4 projection + GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END); + + if (src == GX_TG_COLOR0) { + GX_SET_REG(reg, GX_XF_TG_CLR0, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + } else { + GX_SET_REG(reg, GX_XF_TG_CLR1, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END); + } + GX_SET_REG(reg, 2, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END); + break; + default: + break; + } + + GX_XF_LOAD_REG(GX_XF_REG_TEX0 + id, reg); + + reg = 0; + GX_SET_REG(reg, dualTexMtxIdx - 0x40, GX_XF_MTXIDX0_GEOM_ST, GX_XF_MTXIDX0_GEOM_END); + GX_SET_REG(reg, normalize, GX_XF_DUALTEX_NORMALISE_ST, GX_XF_DUALTEX_NORMALISE_END); + + GX_XF_LOAD_REG(GX_XF_REG_DUALTEX0 + id, reg); + + switch (id) { + case GX_TEXCOORD0: + GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX0_ST, GX_XF_MTXIDX0_TEX0_END); + break; + case GX_TEXCOORD1: + GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX1_ST, GX_XF_MTXIDX0_TEX1_END); + break; + case GX_TEXCOORD2: + GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX2_ST, GX_XF_MTXIDX0_TEX2_END); + break; + case GX_TEXCOORD3: + GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX3_ST, GX_XF_MTXIDX0_TEX3_END); + break; + case GX_TEXCOORD4: + GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX4_ST, GX_XF_MTXIDX1_TEX4_END); + break; + case GX_TEXCOORD5: + GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX5_ST, GX_XF_MTXIDX1_TEX5_END); + break; + case GX_TEXCOORD6: + GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX6_ST, GX_XF_MTXIDX1_TEX6_END); + break; + default: + GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX7_ST, GX_XF_MTXIDX1_TEX7_END); + break; + } + __GXSetMatrixIndex(id + 1); +} + +void GXSetNumTexGens(u8 count) { + GX_SET_REG(__GXData->genMode, count, GX_BP_GENMODE_NUMTEX_ST, GX_BP_GENMODE_NUMTEX_END); + GX_XF_LOAD_REG(GX_XF_REG_NUMTEX, count); + __GXData->dirtyState |= GX_DIRTY_GEN_MODE; +} diff --git a/src/dolphin/gx/GXBump.c b/src/dolphin/gx/GXBump.c new file mode 100644 index 00000000..8c1084df --- /dev/null +++ b/src/dolphin/gx/GXBump.c @@ -0,0 +1,194 @@ +/** + * GXBump.c + * Description: + */ + +#include "dolphin/gx/GXBump.h" +#include "dolphin/gx/GX.h" + +void GXSetTevIndirect(GXTevStageID tevStage, GXIndTexStageID texStage, GXIndTexFormat texFmt, + GXIndTexBiasSel biasSel, GXIndTexMtxID mtxID, GXIndTexWrap wrapS, + GXIndTexWrap wrapT, u8 addPrev, u8 utcLod, GXIndTexAlphaSel alphaSel) { + u32 field = 0; + u32 stage = tevStage + 0x10; + + GX_BITFIELD_SET(field, 30, 2, texStage); + GX_BITFIELD_SET(field, 28, 2, texFmt); + GX_BITFIELD_SET(field, 25, 3, biasSel); + GX_BITFIELD_SET(field, 23, 2, alphaSel); + GX_BITFIELD_SET(field, 19, 4, mtxID); + GX_BITFIELD_SET(field, 16, 3, wrapS); + GX_BITFIELD_SET(field, 13, 3, wrapT); + GX_BITFIELD_SET(field, 12, 1, utcLod); + GX_BITFIELD_SET(field, 11, 1, addPrev); + GX_BITFIELD_SET(field, 0, 8, stage); + + GXFIFO.u8 = 0x61; + GXFIFO.s32 = field; + + __GXData->bpSentNot = 0; +} + +void GXSetIndTexMtx(GXIndTexMtxID mtxID, f32 offset[6], s8 scale_exp) { + u32 val; + u32 field; + f32 mtx2[6]; + + scale_exp += 17; + + switch (mtxID) { + case GX_ITM_0: + case GX_ITM_1: + case GX_ITM_2: + val = mtxID - 1; + break; + case GX_ITM_S0: + case GX_ITM_S1: + case GX_ITM_S2: + val = mtxID - 5; + break; + case GX_ITM_T0: + case GX_ITM_T1: + case GX_ITM_T2: + val = mtxID - 9; + break; + case GX_ITM_3: + case GX_ITM_S3: + default: + val = 0; + } + + field = 0; + GX_BITFIELD_SET(field, 21, 11, 1024.0f * offset[0]); + GX_BITFIELD_SET(field, 10, 11, 1024.0f * offset[3]); + GX_BITFIELD_SET(field, 8, 2, (scale_exp >> 0) & 3); + GX_BITFIELD_SET(field, 0, 8, val * 3 + 6); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = field; + + field = 0; + GX_BITFIELD_SET(field, 21, 11, 1024.0f * offset[1]); + GX_BITFIELD_SET(field, 10, 11, 1024.0f * offset[4]); + GX_BITFIELD_SET(field, 8, 2, (scale_exp >> 2) & 3); + GX_BITFIELD_SET(field, 0, 8, val * 3 + 7); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = field; + + field = 0; + GX_BITFIELD_SET(field, 21, 11, 1024.0f * offset[2]); + GX_BITFIELD_SET(field, 10, 11, 1024.0f * offset[5]); + GX_BITFIELD_SET(field, 8, 2, (scale_exp >> 4) & 3); + GX_BITFIELD_SET(field, 0, 8, val * 3 + 8); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = field; + + __GXData->bpSentNot = 0; +} + +void GXSetIndTexCoordScale(GXIndTexStageID texStage, GXIndTexScale scaleS, GXIndTexScale scaleT) { + GXData* data; + + switch (texStage) { + case GX_INDTEXSTAGE0: + data = __GXData; + GX_BITFIELD_SET(data->IndTexScale0, 28, 4, scaleS); + GX_BITFIELD_SET(data->IndTexScale0, 24, 4, scaleT); + GX_BITFIELD_SET(data->IndTexScale0, 0, 8, 0x25); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = data->IndTexScale0; + break; + case GX_INDTEXSTAGE1: + data = __GXData; + GX_BITFIELD_SET(data->IndTexScale0, 20, 4, scaleS); + GX_BITFIELD_SET(data->IndTexScale0, 16, 4, scaleT); + GX_BITFIELD_SET(data->IndTexScale0, 0, 8, 0x25); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = data->IndTexScale0; + break; + case GX_INDTEXSTAGE2: + data = __GXData; + GX_BITFIELD_SET(data->IndTexScale1, 28, 4, scaleS); + GX_BITFIELD_SET(data->IndTexScale1, 24, 4, scaleT); + GX_BITFIELD_SET(data->IndTexScale1, 0, 8, 0x26); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = data->IndTexScale1; + break; + case GX_INDTEXSTAGE3: + data = __GXData; + GX_BITFIELD_SET(data->IndTexScale1, 20, 4, scaleS); + GX_BITFIELD_SET(data->IndTexScale1, 16, 4, scaleT); + GX_BITFIELD_SET(data->IndTexScale1, 0, 8, 0x26); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = data->IndTexScale1; + break; + } + + __GXData->bpSentNot = 0; +} + +void GXSetIndTexOrder(GXIndTexStageID stage, GXTexCoordID coord, GXTexMapID map) { + GXData* data; + + if (map == 0xFF) { + map = GX_TEXMAP0; + } + + if (coord == 0xFF) { + coord = GX_TEXCOORD0; + } + + switch (stage) { + case GX_INDTEXSTAGE0: + data = __GXData; + GX_BITFIELD_SET(data->iref, 29, 3, map); + GX_BITFIELD_SET(data->iref, 26, 3, coord); + break; + case GX_INDTEXSTAGE1: + data = __GXData; + GX_BITFIELD_SET(data->iref, 23, 3, map); + GX_BITFIELD_SET(data->iref, 20, 3, coord); + break; + case GX_INDTEXSTAGE2: + data = __GXData; + GX_BITFIELD_SET(data->iref, 17, 3, map); + GX_BITFIELD_SET(data->iref, 14, 3, coord); + break; + case GX_INDTEXSTAGE3: + data = __GXData; + GX_BITFIELD_SET(data->iref, 11, 3, map); + GX_BITFIELD_SET(data->iref, 8, 3, coord); + break; + } + + GXFIFO.u8 = 0x61; + GXFIFO.s32 = __GXData->iref; + GXSetWasteFlags(); +} + +void GXSetNumIndStages(u8 num) { + GXData* data = __GXData; + GX_BITFIELD_SET(data->genMode, 13, 3, num); + data->dirtyState |= GX_DIRTY_BP_MASK | GX_DIRTY_GEN_MODE; +} + +void GXSetTevDirect(GXTevStageID stage) { + GXSetTevIndirect(stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, + GX_ITW_OFF, FALSE, FALSE, GX_ITBA_OFF); +} + +void __GXUpdateBPMask(void) {} + +void __GXSetIndirectMask(u32 mask) { + GXData* data = __GXData; + + GX_BITFIELD_SET(data->bpMask, 24, 8, mask); + GXFIFO.u8 = 0x61; + GXFIFO.s32 = data->bpMask; + data->bpSentNot = 0; +} + +void __GXFlushTextureState(void) { + GXFIFO.u8 = 0x61; + GXFIFO.s32 = __GXData->bpMask; + __GXData->bpSentNot = 0; +} diff --git a/src/dolphin/gx/GXDisplayList.c b/src/dolphin/gx/GXDisplayList.c new file mode 100644 index 00000000..eaebb628 --- /dev/null +++ b/src/dolphin/gx/GXDisplayList.c @@ -0,0 +1,21 @@ +/** + * GXDisplayList.c + * Description: + */ + +#include "dolphin/gx/GXDisplayList.h" +#include "dolphin/gx/GX.h" + +void GXCallDisplayList(void* list, u32 nbytes) { + if (__GXData->dirtyState != 0) { + __GXSetDirtyState(); + } + + if (*(u32*)__GXData == 0) { + __GXSendFlushPrim(); + } + + GXFIFO.u8 = 0x40; + GXFIFO.u32 = (u32)list; + GXFIFO.u32 = nbytes; +} diff --git a/src/dolphin/gx/GXDraw.c b/src/dolphin/gx/GXDraw.c new file mode 100644 index 00000000..22311b3b --- /dev/null +++ b/src/dolphin/gx/GXDraw.c @@ -0,0 +1,71 @@ +#include "dolphin/gx/GXDraw.h" +#include "dolphin/gx/GX.h" + +static GXVtxDescList vcd[27]; +static GXVtxAttrFmtList vat[27]; + +void GetVertState(void) { + GXGetVtxDescv(vcd); + GXGetVtxAttrFmtv(GX_VTXFMT3, vat); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_NRM, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); +} + +void RestoreVertState(void) { + GXSetVtxDescv(vcd); + GXSetVtxAttrFmtv(GX_VTXFMT3, vat); +} + +// doesn't fully match debug +void GXDrawCylinder(u8 numEdges) { + f32 temp_f29; + f32 temp_f30; + f32 temp_f31; + + s32 i; + + f32 sp1A0[100]; + f32 sp10[100]; + + temp_f31 = 1.0f; + temp_f30 = -temp_f31; + + GetVertState(); + for (i = 0; i <= numEdges; i++) { + temp_f29 = (i * 2.0f * 3.141593f) / numEdges; + sp1A0[i] = cosf(temp_f29); + sp10[i] = sinf(temp_f29); + } + + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numEdges + 1) * 2); + for (i = 0; i <= numEdges; i++) { + GXPosition3f32(sp1A0[i], sp10[i], temp_f30); + GXNormal3f32(sp1A0[i], sp10[i], 0.0f); + GXPosition3f32(sp1A0[i], sp10[i], temp_f31); + GXNormal3f32(sp1A0[i], sp10[i], 0.0f); + } + GXEnd(); + + GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2); + GXPosition3f32(0.0f, 0.0f, temp_f31); + GXNormal3f32(0.0f, 0.0f, 1.0f); + for (i = 0; i <= numEdges; i++) { + GXPosition3f32(sp1A0[i], -sp10[i], temp_f31); + GXNormal3f32(0.0f, 0.0f, 1.0f); + } + GXEnd(); + + GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2); + GXPosition3f32(0.0f, 0.0f, temp_f30); + GXNormal3f32(0.0f, 0.0f, -1.0f); + for (i = 0; i <= numEdges; i++) { + GXPosition3f32(sp1A0[i], sp10[i], temp_f30); + GXNormal3f32(0.0f, 0.0f, -1.0f); + } + GXEnd(); + + RestoreVertState(); +}
\ No newline at end of file diff --git a/src/dolphin/gx/GXFifo.c b/src/dolphin/gx/GXFifo.c new file mode 100644 index 00000000..7ff20556 --- /dev/null +++ b/src/dolphin/gx/GXFifo.c @@ -0,0 +1,337 @@ +#include "dolphin/gx/GXFifo.h" +#include "dolphin/gx/GX.h" +#include "dolphin/os/OS.h" + +static void GXInitFifoLimits(GXFifoObj* fifo, u32 hi_watermark, u32 lo_watermark); + +static GXFifoObj* CPUFifo; + +static GXFifoObj* GPFifo; + +static OSThread* __GXCurrentThread; + +static GXBool data_80451954; + +static u32 GXOverflowSuspendInProgress; + +static GXBreakPtCallback BreakPointCB; + +static u32 __GXOverflowCount; + +static void GXOverflowHandler() { + __GXOverflowCount += 1; + __GXWriteFifoIntEnable(0, 1); + __GXWriteFifoIntReset(1, 0); + GXOverflowSuspendInProgress = TRUE; + OSSuspendThread(__GXCurrentThread); +} + +static void GXUnderflowHandler() { + OSResumeThread(__GXCurrentThread); + GXOverflowSuspendInProgress = FALSE; + __GXWriteFifoIntReset(1, 1); + __GXWriteFifoIntEnable(1, 0); +} + +static void GXBreakPointHandler(OSContext* context) { + OSContext bpContext; + + FAST_FLAG_SET(__GXData->cpEnable, 0, 5, 1); + GX_SET_CP_REG(1, __GXData->cpEnable); + + if (BreakPointCB) { + OSClearContext(&bpContext); + OSSetCurrentContext(&bpContext); + BreakPointCB(); + OSClearContext(&bpContext); + OSSetCurrentContext(context); + } +} + +static void GXCPInterruptHandler(s16 p1, OSContext* context) { + __GXData->cpStatus = GX_GET_CP_REG(0); + + if ((__GXData->cpEnable >> 3 & 1) && (__GXData->cpStatus >> 1 & 1)) { + GXUnderflowHandler(); + } + + if ((__GXData->cpEnable >> 2 & 1) && (__GXData->cpStatus >> 0 & 1)) { + GXOverflowHandler(); + } + + if ((__GXData->cpEnable >> 5 & 1) && (__GXData->cpStatus >> 4 & 1)) { + GXBreakPointHandler(context); + } +} + +void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size) { + fifo->base = base; + fifo->end = (void*)((u32)base + size - 4); + fifo->size = size; + fifo->rw_dst = 0; + GXInitFifoLimits(fifo, size - 0x4000, OSRoundDown32B(size / 2)); + GXInitFifoPtrs(fifo, base, base); +} + +void GXInitFifoPtrs(GXFifoObj* fifo, void* readPtr, void* writePtr) { + int interrupts = OSDisableInterrupts(); + fifo->read_ptr = readPtr; + fifo->write_ptr = writePtr; + fifo->rw_dst = (u32)writePtr - (u32)readPtr; + if (fifo->rw_dst < 0) { + fifo->rw_dst += fifo->size; + } + OSRestoreInterrupts(interrupts); +} + +static void GXInitFifoLimits(GXFifoObj* fifo, u32 hi_watermark, u32 lo_watermark) { + fifo->high_wtrmark = hi_watermark; + fifo->low_wtrmark = lo_watermark; +} + +void GXSetCPUFifo(GXFifoObj* fifo) { + BOOL interrupts; + interrupts = OSDisableInterrupts(); + + CPUFifo = fifo; + + if (fifo == GPFifo) { + u32 reg; + GX_SET_PI_REG(3, (u32)fifo->base & 0x3FFFFFFF); + GX_SET_PI_REG(4, (u32)fifo->end & 0x3FFFFFFF); + reg = 0; + GX_BITFIELD_SET(reg, 6, 21, (u32)fifo->write_ptr >> 5); + GX_BITFIELD_SET(reg, 5, 1, 0); + GX_SET_PI_REG(5, reg); + + data_80451954 = GX_TRUE; + + __GXWriteFifoIntReset(1, 1); + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } else { + u32 reg; + if (data_80451954) { + __GXFifoLink(0); + data_80451954 = GX_FALSE; + } + __GXWriteFifoIntEnable(0, 0); + + GX_SET_PI_REG(3, (u32)fifo->base & 0x3FFFFFFF); + GX_SET_PI_REG(4, (u32)fifo->end & 0x3FFFFFFF); + reg = 0; + GX_BITFIELD_SET(reg, 6, 21, (u32)fifo->write_ptr >> 5); + GX_BITFIELD_SET(reg, 5, 1, 0); + GX_SET_PI_REG(5, reg); + } + + PPCSync(); + + OSRestoreInterrupts(interrupts); +} + +void GXSetGPFifo(GXFifoObj* fifo) { + int interrupts = OSDisableInterrupts(); + u32 reg; + __GXFifoReadDisable(); + __GXWriteFifoIntEnable(0, 0); + GPFifo = fifo; + GX_SET_CP_REG(16, (u16)fifo->base); + GX_SET_CP_REG(18, (u16)fifo->end); + GX_SET_CP_REG(24, (u16)fifo->rw_dst); + GX_SET_CP_REG(26, (u16)fifo->write_ptr); + GX_SET_CP_REG(28, (u16)fifo->read_ptr); + GX_SET_CP_REG(20, (u16)fifo->high_wtrmark); + GX_SET_CP_REG(22, (u16)fifo->low_wtrmark); + + GX_SET_CP_REG(17, ((u32)fifo->base & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(19, ((u32)fifo->end & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(25, (fifo->rw_dst) >> 16); + GX_SET_CP_REG(27, ((u32)fifo->write_ptr & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(29, ((u32)fifo->read_ptr & 0x3FFFFFFF) >> 16); + GX_SET_CP_REG(21, (fifo->high_wtrmark) >> 16); + GX_SET_CP_REG(23, (fifo->low_wtrmark) >> 16); + + PPCSync(); + + if (CPUFifo == GPFifo) { + data_80451954 = 1; + __GXWriteFifoIntEnable(1, 0); + __GXFifoLink(1); + } else { + data_80451954 = 0; + __GXWriteFifoIntEnable(0, 0); + __GXFifoLink(0); + } + reg = __GXData->cpEnable; + GX_BITFIELD_SET(reg, 0x1e, 1, 0); + GX_BITFIELD_SET(reg, 0x1a, 1, 0); + GX_SET_CP_REG(1, reg); + GX_SET_CP_REG(1, __GXData->cpEnable); + __GXWriteFifoIntReset(1, 1); + __GXFifoReadEnable(); + OSRestoreInterrupts(interrupts); +} + +void GXSaveCPUFifo(GXFifoObj* fifo) { + GXFlush(); + __GXSaveCPUFifoAux(fifo); +} + +void __GXSaveCPUFifoAux(GXFifoObj* fifo) { + int interrupts = OSDisableInterrupts(); + fifo->base = OSPhysicalToCached(GX_GET_PI_REG(3)); + fifo->end = OSPhysicalToCached(GX_GET_PI_REG(4)); + fifo->write_ptr = OSPhysicalToCached(GX_GET_PI_REG(5) & ~0x4000000); + if (data_80451954 != 0) { + u32 reg2 = GX_GET_CP_REG(28) | (GX_GET_CP_REG(29) << 16); + fifo->read_ptr = (void*)(reg2 + -0x80000000); + fifo->rw_dst = (((u32)GX_GET_CP_REG(24) | (GX_GET_CP_REG(25) << 16))); + } else { + fifo->rw_dst = (u32)fifo->write_ptr - (u32)fifo->read_ptr; + if (fifo->rw_dst < 0) { + fifo->rw_dst += fifo->size; + } + } + OSRestoreInterrupts(interrupts); +} + +void GXGetGPStatus(GXBool* overhi, GXBool* underlow, GXBool* readIdle, GXBool* cmdIdle, + GXBool* brkpt) { + __GXData->cpStatus = GX_GET_CP_REG(0); + *overhi = __GXData->cpStatus & 1; + *underlow = (__GXData->cpStatus >> 1) & 1; + *readIdle = (__GXData->cpStatus >> 2) & 1; + *cmdIdle = (__GXData->cpStatus >> 3) & 1; + *brkpt = (__GXData->cpStatus >> 4) & 1; +} + +void* GXGetFifoBase(GXFifoObj* fifo) { + return fifo->base; +} + +u32 GXGetFifoSize(GXFifoObj* fifo) { + return fifo->size; +} + +GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb) { + GXBreakPtCallback oldCallback = BreakPointCB; + int interrupts = OSDisableInterrupts(); + BreakPointCB = cb; + OSRestoreInterrupts(interrupts); + return oldCallback; +} + +void __GXFifoInit(void) { + __OSSetInterruptHandler(0x11, GXCPInterruptHandler); + __OSUnmaskInterrupts(0x4000); + __GXCurrentThread = OSGetCurrentThread(); + GXOverflowSuspendInProgress = 0; + CPUFifo = NULL; + GPFifo = NULL; +} + +void __GXFifoReadEnable(void) { + FAST_FLAG_SET(__GXData->cpEnable, 1, 0, 1); + GX_SET_CP_REG(1, __GXData->cpEnable); +} + +void __GXFifoReadDisable(void) { + FAST_FLAG_SET(__GXData->cpEnable, 0, 0, 1); + GX_SET_CP_REG(1, __GXData->cpEnable); +} + +void __GXFifoLink(u8 link) { + u32 b; + if (link) { + b = 1; + } else { + b = 0; + } + FAST_FLAG_SET(__GXData->cpEnable, b, 4, 1); + GX_SET_CP_REG(1, __GXData->cpEnable); +} + +void __GXWriteFifoIntEnable(u32 p1, u32 p2) { + FAST_FLAG_SET(__GXData->cpEnable, p1, 2, 1); + FAST_FLAG_SET(__GXData->cpEnable, (u8)p2, 3, 1); + GX_SET_CP_REG(1, __GXData->cpEnable); +} + +void __GXWriteFifoIntReset(u32 p1, u32 p2) { + FAST_FLAG_SET(__GXData->cpClr, p1, 0, 1); + FAST_FLAG_SET(__GXData->cpClr, (u8)p2, 1, 1); + GX_SET_CP_REG(2, __GXData->cpClr); +} + +void __GXCleanGPFifo(void) { + BOOL interrupts; + GXFifoObj tempObj; // 0x14 + u32 i, j, k; // stack alloc + GXFifoObj* gpFifo; // r31 + GXFifoObj* cpuFifo; // r30 + void* tempPtr; // r29 + + gpFifo = GXGetGPFifo(); + if (!gpFifo) { + return; + } + + cpuFifo = GXGetCPUFifo(); + tempPtr = gpFifo->base; + + tempObj = *gpFifo; + + interrupts = OSDisableInterrupts(); + + tempObj.read_ptr = tempPtr; + tempObj.write_ptr = tempPtr; + tempObj.rw_dst = 0; + if (tempObj.rw_dst < 0) { + tempObj.rw_dst += tempObj.size; + } + + OSRestoreInterrupts(interrupts); + + GXSetGPFifo(&tempObj); + + if (cpuFifo == gpFifo) { + GXSetCPUFifo(&tempObj); + } + + interrupts = OSDisableInterrupts(); + + gpFifo->read_ptr = tempPtr; + gpFifo->write_ptr = tempPtr; + gpFifo->rw_dst = 0; + + if (gpFifo->rw_dst < 0) { + gpFifo->rw_dst += gpFifo->size; + } + OSRestoreInterrupts(interrupts); + + GXSetGPFifo(gpFifo); + if (cpuFifo == gpFifo) { + GXSetCPUFifo(cpuFifo); + } +} + +OSThread* GXSetCurrentGXThread(void) { + BOOL interrupts = OSDisableInterrupts(); + OSThread* prevThread = __GXCurrentThread; + __GXCurrentThread = OSGetCurrentThread(); + OSRestoreInterrupts(interrupts); + return prevThread; +} + +OSThread* GXGetCurrentGXThread(void) { + return *(OSThread**)(&__GXCurrentThread); +} + +GXFifoObj* GXGetCPUFifo(void) { + return *(GXFifoObj**)(&CPUFifo); +} + +GXFifoObj* GXGetGPFifo(void) { + return GPFifo; +} diff --git a/src/dolphin/gx/GXFrameBuf.c b/src/dolphin/gx/GXFrameBuf.c new file mode 100644 index 00000000..3cedf7e6 --- /dev/null +++ b/src/dolphin/gx/GXFrameBuf.c @@ -0,0 +1,638 @@ +#include "dolphin/gx/GXFrameBuf.h" +#include "dolphin/gx/GX.h" + +GXRenderModeObj GXNtsc480IntDf = { + VI_TVMODE_NTSC_INT, + 640, + 480, + 480, + 40, + 0, + 640, + 480, + VI_XFBMODE_DF, + GX_FALSE, + GX_FALSE, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 8, + 8, + 10, + 12, + 10, + 8, + 8, +}; + +GXRenderModeObj GXNtsc480Int = { + VI_TVMODE_NTSC_INT, + 640, + 480, + 480, + 40, + 0, + 640, + 480, + VI_XFBMODE_DF, + GX_FALSE, + GX_FALSE, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 0, + 0, + 21, + 22, + 21, + 0, + 0, +}; + +GXRenderModeObj GXMpal480IntDf = { + VI_TVMODE_MPAL_INT, + 640, + 480, + 480, + 40, + 0, + 640, + 480, + VI_XFBMODE_DF, + GX_FALSE, + GX_FALSE, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 8, + 8, + 10, + 12, + 10, + 8, + 8, +}; + +GXRenderModeObj GXPal528IntDf = { + VI_TVMODE_PAL_INT, + 640, + 528, + 528, + 40, + 23, + 640, + 528, + VI_XFBMODE_DF, + GX_FALSE, + GX_FALSE, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 8, + 8, + 10, + 12, + 10, + 8, + 8, +}; + +GXRenderModeObj GXEurgb60Hz480IntDf = { + VI_TVMODE_EURGB60_INT, + 640, + 480, + 480, + 40, + 0, + 640, + 480, + VI_XFBMODE_DF, + GX_FALSE, + GX_FALSE, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 6, + 8, + 8, + 10, + 12, + 10, + 8, + 8, +}; + +void GXSetDispCopySrc(u16 left, u16 top, u16 width, u16 height) { + __GXData->cpDispSrc = 0; + GX_BITFIELD_SET(__GXData->cpDispSrc, 22, 10, left); + GX_BITFIELD_SET(__GXData->cpDispSrc, 12, 10, top); + GX_BITFIELD_SET(__GXData->cpDispSrc, 0, 8, 73); + + __GXData->cpDispSize = 0; + GX_BITFIELD_SET(__GXData->cpDispSize, 22, 10, width - 1); + GX_BITFIELD_SET(__GXData->cpDispSize, 12, 10, height - 1); + GX_BITFIELD_SET(__GXData->cpDispSize, 0, 8, 74); +} + +void GXSetTexCopySrc(u16 left, u16 top, u16 width, u16 height) { + __GXData->cpTexSrc = 0; + GX_BITFIELD_SET(__GXData->cpTexSrc, 22, 10, left); + GX_BITFIELD_SET(__GXData->cpTexSrc, 12, 10, top); + GX_BITFIELD_SET(__GXData->cpTexSrc, 0, 8, 0x49); + __GXData->cpTexSize = 0; + GX_BITFIELD_SET(__GXData->cpTexSize, 22, 10, width - 1); + GX_BITFIELD_SET(__GXData->cpTexSize, 12, 10, height - 1); + GX_BITFIELD_SET(__GXData->cpTexSize, 0, 8, 0x4A); +} + +void GXSetDispCopyDst(u16 arg0, u16 arg1) { + s32 val = (s32)((arg0 << 1) & 0xFFFE) >> 5; + __GXData->cpDispStride = 0; + GX_BITFIELD_SET(__GXData->cpDispStride, 22, 10, val); + GX_BITFIELD_SET(__GXData->cpDispStride, 0, 8, 0x4D); +} + +void GXSetTexCopyDst(u16 width, u16 height, GXTexFmt format, GXBool useMIPmap) { + u32 sp20, sp1C, sp18; + u32 value; + u8 depthRelated; + + __GXData->cpTexZ = GX_NONE; + + depthRelated = format & 0xf; + if (format == GX_TF_Z16) { + depthRelated = 0xb; + } + + switch (format) { + case GX_TF_I4: + case GX_TF_I8: + case GX_TF_IA4: + case GX_TF_IA8: + case GX_CTF_A8: + GX_SET_REG(__GXData->cpTex, 3, 15, 16); + break; + default: + GX_SET_REG(__GXData->cpTex, 2, 15, 16); + break; + } + + __GXData->cpTexZ = (format & 0x10) == 0x10; + + value = depthRelated >> 3; + + GX_SET_REG(__GXData->cpTex, value, 28, 28); + + depthRelated &= 7; + + __GetImageTileCount(format, width, height, &sp20, &sp1C, &sp18); + + __GXData->cpTexStride = GX_NONE; + GX_SET_REG(__GXData->cpTexStride, sp20 * sp18, 22, 31); + GX_SET_REG(__GXData->cpTexStride, 0x4D, 0, 7); + + GX_SET_REG(__GXData->cpTex, useMIPmap, 22, 22); + GX_SET_REG(__GXData->cpTex, depthRelated, 25, 27); +} + +void GXSetDispCopyFrame2Field(GXCopyMode arg0) { + GX_BITFIELD_SET(__GXData->cpDisp, 18, 2, arg0); + GX_BITFIELD_SET(__GXData->cpTex, 18, 2, 0); +} + +// clang-format off +#define INSERT_FIELD(reg, value, nbits, shift) \ + (reg) = ((u32) (reg) & ~(((1 << (nbits)) - 1) << (shift))) | \ + ((u32) (value) << (shift)); +// clang-format on + +void GXSetCopyClamp(GXFBClamp clamp) { + u8 isTop = (clamp & GX_CLAMP_TOP) == GX_CLAMP_TOP; + u8 isBottom = (clamp & GX_CLAMP_BOTTOM) == GX_CLAMP_BOTTOM; + __GXData->cpDisp = __rlwimi(__GXData->cpDisp, isTop, 0, 31, 31); + __GXData->cpDisp = __rlwimi(__GXData->cpDisp, isBottom, 1, 30, 30); + __GXData->cpTex = __rlwimi(__GXData->cpTex, isTop, 0, 31, 31); + __GXData->cpTex = __rlwimi(__GXData->cpTex, isBottom, 1, 30, 30); +} + +static u32 __GXGetNumXfbLines(u32 height, u32 scale) { + u32 numLines; + u32 actualHeight; + u32 newScale; + + numLines = (height - 1) * 0x100; + actualHeight = (numLines / scale) + 1; + + newScale = scale; + + if (newScale > 0x80 && newScale < 0x100) { + while (newScale % 2 == 0) { + newScale /= 2; + } + + if (height % newScale == 0) { + actualHeight++; + } + } + + if (actualHeight > 0x400) { + actualHeight = 0x400; + } + + return actualHeight; +} + +u16 GXGetNumXfbLines(const u16 efbHeight, f32 yScale) { + u32 scale = (u32)(256.0f / yScale) & 0x1FF; + + return __GXGetNumXfbLines(efbHeight, scale); +} + +f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight) { + u32 scale; + u32 height1; + u32 height2; + f32 scale2; + f32 scale1; + + height1 = xfbHeight; + scale1 = (f32)xfbHeight / (f32)efbHeight; + scale = (u32)(256.0f / scale1) & 0x1FF; + height2 = __GXGetNumXfbLines(efbHeight, scale); + + while (height2 > xfbHeight) { + height1--; + scale1 = (f32)height1 / (f32)efbHeight; + scale = (u32)(256.0f / scale1) & 0x1FF; + height2 = __GXGetNumXfbLines(efbHeight, scale); + } + + scale2 = scale1; + while (height2 < xfbHeight) { + scale2 = scale1; + height1++; + scale1 = (f32)height1 / (f32)efbHeight; + scale = (u32)(256.0f / scale1) & 0x1FF; + height2 = __GXGetNumXfbLines(efbHeight, scale); + } + + return scale2; +} + +u32 GXSetDispCopyYScale(f32 vertScale) { + u32 scale; + GXBool check; + u32 height; + u32 reg; + + scale = (u32)(256.0f / vertScale) & 0x1FF; + check = (scale != 0x100); + + reg = 0; + GX_SET_REG(reg, scale, 23, 31); + GX_SET_REG(reg, 0x4E, 0, 7); + GX_BP_LOAD_REG(reg); + __GXData->bpSentNot = GX_FALSE; + + GX_SET_REG(__GXData->cpDisp, check, 21, 21); + + height = (__GXData->cpDispSize >> 10 & 0x3FF) + 1; + + return __GXGetNumXfbLines(height, scale); +} + +void GXSetCopyClear(GXColor color, u32 clear_z) { + u32 r6 = 0; + GX_BITFIELD_SET(r6, 24, 8, color.r); + GX_BITFIELD_SET(r6, 16, 8, color.a); + GX_BITFIELD_SET(r6, 0, 8, 0x4f); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = r6; + + r6 = 0; + GX_BITFIELD_SET(r6, 24, 8, color.b); + GX_BITFIELD_SET(r6, 16, 8, color.g); + GX_BITFIELD_SET(r6, 0, 8, 0x50); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = r6; + + r6 = 0; + GX_BITFIELD_SET(r6, 8, 24, clear_z); + GX_BITFIELD_SET(r6, 0, 8, 0x51); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = r6; + + __GXData->bpSentNot = 0; +} + +void GXSetCopyFilter(GXBool useAA, u8 samplePattern[12][2], GXBool doVertFilt, u8 vFilt[7]) { + u32 vals[4]; + u32 unk1; + u32 unk2; + + if (useAA) { + vals[0] = 0; + GX_SET_REG(vals[0], samplePattern[0][0], 28, 31); + GX_SET_REG(vals[0], samplePattern[0][1], 24, 27); + GX_SET_REG(vals[0], samplePattern[1][0], 20, 23); + GX_SET_REG(vals[0], samplePattern[1][1], 16, 19); + GX_SET_REG(vals[0], samplePattern[2][0], 12, 15); + GX_SET_REG(vals[0], samplePattern[2][1], 8, 11); + GX_SET_REG(vals[0], 1, 0, 7); + + vals[1] = 0; + GX_SET_REG(vals[1], samplePattern[3][0], 28, 31); + GX_SET_REG(vals[1], samplePattern[3][1], 24, 27); + GX_SET_REG(vals[1], samplePattern[4][0], 20, 23); + GX_SET_REG(vals[1], samplePattern[4][1], 16, 19); + GX_SET_REG(vals[1], samplePattern[5][0], 12, 15); + GX_SET_REG(vals[1], samplePattern[5][1], 8, 11); + GX_SET_REG(vals[1], 2, 0, 7); + + vals[2] = 0; + GX_SET_REG(vals[2], samplePattern[6][0], 28, 31); + GX_SET_REG(vals[2], samplePattern[6][1], 24, 27); + GX_SET_REG(vals[2], samplePattern[7][0], 20, 23); + GX_SET_REG(vals[2], samplePattern[7][1], 16, 19); + GX_SET_REG(vals[2], samplePattern[8][0], 12, 15); + GX_SET_REG(vals[2], samplePattern[8][1], 8, 11); + GX_SET_REG(vals[2], 3, 0, 7); + + vals[3] = 0; + GX_SET_REG(vals[3], samplePattern[9][0], 28, 31); + GX_SET_REG(vals[3], samplePattern[9][1], 24, 27); + GX_SET_REG(vals[3], samplePattern[10][0], 20, 23); + GX_SET_REG(vals[3], samplePattern[10][1], 16, 19); + GX_SET_REG(vals[3], samplePattern[11][0], 12, 15); + GX_SET_REG(vals[3], samplePattern[11][1], 8, 11); + GX_SET_REG(vals[3], 4, 0, 7); + } else { + vals[0] = 0x01666666; + vals[1] = 0x02666666; + vals[2] = 0x03666666; + vals[3] = 0x04666666; + } + + GX_BP_LOAD_REG(vals[0]); + GX_BP_LOAD_REG(vals[1]); + GX_BP_LOAD_REG(vals[2]); + GX_BP_LOAD_REG(vals[3]); + + unk1 = 0; + GX_SET_REG(unk1, 0x53, 0, 7); + unk2 = 0; + GX_SET_REG(unk2, 0x54, 0, 7); + + if (doVertFilt) { + GX_SET_REG(unk1, vFilt[0], 26, 31); + GX_SET_REG(unk1, vFilt[1], 20, 25); + GX_SET_REG(unk1, vFilt[2], 14, 19); + GX_SET_REG(unk1, vFilt[3], 8, 13); + GX_SET_REG(unk2, vFilt[4], 26, 31); + GX_SET_REG(unk2, vFilt[5], 20, 25); + GX_SET_REG(unk2, vFilt[6], 14, 19); + + } else { + GX_SET_REG(unk1, 0, 26, 31); + GX_SET_REG(unk1, 0, 20, 25); + GX_SET_REG(unk1, 21, 14, 19); + GX_SET_REG(unk1, 22, 8, 13); + GX_SET_REG(unk2, 21, 26, 31); + GX_SET_REG(unk2, 0, 20, 25); + GX_SET_REG(unk2, 0, 14, 19); + } + + GX_BP_LOAD_REG(unk1); + GX_BP_LOAD_REG(unk2); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetDispCopyGamma(GXGamma gamma) { + GX_BITFIELD_SET(__GXData->cpDisp, 23, 2, gamma); +} + +void GXCopyDisp(void* dest, GXBool doClear) { + u32 reg; + u32 newDest; + GXBool check; + + if (doClear) { + reg = __GXData->zmode; + GX_SET_REG(reg, 1, 31, 31); + GX_SET_REG(reg, 7, 28, 30); + GX_BP_LOAD_REG(reg); + + reg = __GXData->cmode0; + GX_SET_REG(reg, 0, 31, 31); + GX_SET_REG(reg, 0, 30, 30); + GX_BP_LOAD_REG(reg); + } + + check = GX_FALSE; + if ((doClear || (__GXData->peCtrl & 0x7) == 3) && (__GXData->peCtrl >> 6 & 0x1) == 1) { + check = GX_TRUE; + reg = __GXData->peCtrl; + GX_SET_REG(reg, 0, 25, 25); + GX_BP_LOAD_REG(reg); + } + + GX_BP_LOAD_REG(__GXData->cpDispSrc); + GX_BP_LOAD_REG(__GXData->cpDispSize); + GX_BP_LOAD_REG(__GXData->cpDispStride); + + newDest = (u32)dest & 0x3FFFFFFF; + reg = 0; + GX_SET_REG(reg, newDest >> 5, 11, 31); + GX_SET_REG(reg, 0x4B, 0, 7); + GX_BP_LOAD_REG(reg); + + GX_SET_REG(__GXData->cpDisp, doClear, 20, 20); + GX_SET_REG(__GXData->cpDisp, 1, 17, 17); + GX_SET_REG(__GXData->cpDisp, 0x52, 0, 7); + GX_BP_LOAD_REG(__GXData->cpDisp); + + if (doClear) { + GX_BP_LOAD_REG(__GXData->zmode); + GX_BP_LOAD_REG(__GXData->cmode0); + } + + if (check) { + GX_BP_LOAD_REG(__GXData->peCtrl); + } + + __GXData->bpSentNot = GX_FALSE; +} + +void GXCopyTex(void* dest, GXBool doClear) { + u32 reg; + u32 reg2; + u32 newDest; + GXBool check; + + if (doClear) { + reg = __GXData->zmode; + GX_SET_REG(reg, 1, 31, 31); + GX_SET_REG(reg, 7, 28, 30); + GX_BP_LOAD_REG(reg); + + reg = __GXData->cmode0; + GX_SET_REG(reg, 0, 31, 31); + GX_SET_REG(reg, 0, 30, 30); + GX_BP_LOAD_REG(reg); + } + + check = GX_FALSE; + reg2 = __GXData->peCtrl; + if (__GXData->cpTexZ && (reg2 & 0x7) != 3) { + check = GX_TRUE; + GX_SET_REG(reg2, 3, 29, 31); + } + + if ((doClear || (reg2 & 0x7) == 3) && (reg2 >> 6 & 0x1) == 1) { + check = GX_TRUE; + GX_SET_REG(reg2, 0, 25, 25); + } + + if (check) { + GX_BP_LOAD_REG(reg2); + } + + GX_BP_LOAD_REG(__GXData->cpTexSrc); + GX_BP_LOAD_REG(__GXData->cpTexSize); + GX_BP_LOAD_REG(__GXData->cpTexStride); + + newDest = (u32)dest & 0x3FFFFFFF; + reg = 0; + GX_SET_REG(reg, newDest >> 5, 11, 31); + GX_SET_REG(reg, 0x4B, 0, 7); + GX_BP_LOAD_REG(reg); + + GX_SET_REG(__GXData->cpTex, doClear, 20, 20); + GX_SET_REG(__GXData->cpTex, 0, 17, 17); + GX_SET_REG(__GXData->cpTex, 0x52, 0, 7); + GX_BP_LOAD_REG(__GXData->cpTex); + + if (doClear) { + GX_BP_LOAD_REG(__GXData->zmode); + GX_BP_LOAD_REG(__GXData->cmode0); + } + + if (check) { + GX_BP_LOAD_REG(__GXData->peCtrl); + } + + __GXData->bpSentNot = GX_FALSE; +} + +void GXClearBoundingBox(void) { + GXFIFO.u8 = GX_LOAD_BP_REG; + GXFIFO.u32 = 0x550003FF; + GXFIFO.u8 = GX_LOAD_BP_REG; + GXFIFO.u32 = 0x560003FF; + set_x2(GX_FALSE); +} diff --git a/src/dolphin/gx/GXGeometry.c b/src/dolphin/gx/GXGeometry.c new file mode 100644 index 00000000..a6de9560 --- /dev/null +++ b/src/dolphin/gx/GXGeometry.c @@ -0,0 +1,149 @@ +/** + * GXGeometry.c + * Description: + */ + +#include "dolphin/gx/GXGeometry.h" +#include "dolphin/gx/GX.h" + +void __GXSetDirtyState(void) { + u32 dirtyFlags = __GXData->dirtyState; + + if (dirtyFlags & GX_DIRTY_SU_TEX) { + __GXSetSUTexRegs(); + } + + if (dirtyFlags & GX_DIRTY_BP_MASK) { + __GXUpdateBPMask(); + } + + if (dirtyFlags & GX_DIRTY_GEN_MODE) { + __GXSetGenMode(); + } + + if (dirtyFlags & GX_DIRTY_VCD) { + __GXSetVCD(); + } + + if (dirtyFlags & GX_DIRTY_VAT) { + __GXSetVAT(); + } + + if (dirtyFlags & GX_DIRTY_VLIM) { + __GXCalculateVLim(); + } + + __GXData->dirtyState = 0; +} + +void GXBegin(GXPrimitive type, GXVtxFmt fmt, u16 vert_num) { + GXData* data = __GXData; + u32 dirtyFlags = data->dirtyState; + + if (data->dirtyState != 0) { + if (dirtyFlags & GX_DIRTY_SU_TEX) { + __GXSetSUTexRegs(); + } + + if (dirtyFlags & GX_DIRTY_BP_MASK) { + __GXUpdateBPMask(); + } + + if (dirtyFlags & GX_DIRTY_GEN_MODE) { + __GXSetGenMode(); + } + + if (dirtyFlags & GX_DIRTY_VCD) { + __GXSetVCD(); + } + + if (dirtyFlags & GX_DIRTY_VAT) { + __GXSetVAT(); + } + + if (dirtyFlags & GX_DIRTY_VLIM) { + __GXCalculateVLim(); + } + + __GXData->dirtyState = 0; + } + + if (*(u32*)__GXData == 0) { + __GXSendFlushPrim(); + } + + GXFIFO.u8 = fmt | type; + GXFIFO.u16 = vert_num; +} + +void __GXSendFlushPrim(void) { + u32 i; + u32 sz = __GXData->vNum * __GXData->vLim; + + GXFIFO.u8 = 0x98; + GXFIFO.u16 = __GXData->vNum; + + for (i = 0; i < sz; i += 4) { + GXFIFO.s32 = 0; + } + + __GXData->bpSentNot = 1; +} + +void GXSetLineWidth(u8 width, GXTexOffset offsets) { + GXData* data = __GXData; + + GX_BITFIELD_SET(data->lpSize, 24, 8, width); + GX_BITFIELD_SET(data->lpSize, 13, 3, offsets); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = data->lpSize; + data->bpSentNot = 0; +} + +void GXSetPointSize(u8 size, GXTexOffset offsets) { + GXData* data = __GXData; + + GX_BITFIELD_SET(data->lpSize, 16, 8, size); + GX_BITFIELD_SET(data->lpSize, 10, 3, offsets); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = data->lpSize; + data->bpSentNot = 0; +} + +void GXEnableTexOffsets(GXTexCoordID coord, GXBool line, GXBool point) { + GXData* data = __GXData; + + GX_BITFIELD_SET(data->suTs0[coord], 13, 1, line); + GX_BITFIELD_SET(data->suTs0[coord], 12, 1, point); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = data->suTs0[coord]; + data->bpSentNot = 0; +} + +void GXSetCullMode(GXCullMode mode) { + GXData* data; + GXCullMode mode2; + data = __GXData; + + mode2 = (mode >> 1) & 1; + GX_BITFIELD_SET(mode2, 30, 1, mode); + + GX_BITFIELD_SET(data->genMode, 16, 2, mode2); + data->dirtyState |= GX_DIRTY_GEN_MODE; +} + +void GXSetCoPlanar(GXBool enable) { + GXData* data = __GXData; + + GX_BITFIELD_SET(data->genMode, 12, 1, enable); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = 0xFE080000; + GXFIFO.u8 = 0x61; + GXFIFO.u32 = data->genMode; +} + +void __GXSetGenMode(void) { + GXFIFO.u8 = 0x61; + GXFIFO.u32 = __GXData->genMode; + __GXData->bpSentNot = 0; +} diff --git a/src/dolphin/gx/GXInit.c b/src/dolphin/gx/GXInit.c new file mode 100644 index 00000000..f8e47061 --- /dev/null +++ b/src/dolphin/gx/GXInit.c @@ -0,0 +1,561 @@ +#include "dolphin/gx/GX.h" +#include "dolphin/os/OS.h" +#include "dolphin/vi/vi.h" + +char* __GXVersion = "<< Dolphin SDK - GX release build: Nov 10 2004 06:27:12 (0x2301) >>"; + +static GXFifoObj FifoObj; + +static GXData gxData; + +GXData* const __GXData = &gxData; + +GXTexRegion* __GXDefaultTexRegionCallback(const GXTexObj* obj, GXTexMapID id) { + GXTexFmt format; // r31 + GXBool isMipMap; // r3 + + format = GXGetTexObjFmt(obj); + isMipMap = GXGetTexObjMipMap(obj); + id = (GXTexMapID)(id % GX_MAX_TEXMAP); + + switch (format) { + case GX_TF_RGBA8: + if (isMipMap) { + return &__GXData->TexRegions2[id]; + } + return &__GXData->TexRegions1[id]; + + case GX_TF_C4: + case GX_TF_C8: + case GX_TF_C14X2: + return &__GXData->TexRegions0[id]; + + default: + if (isMipMap) { + return &__GXData->TexRegions1[id]; + } + return &__GXData->TexRegions0[id]; + } +} + +GXTlutRegion* __GXDefaultTlutRegionCallback(u32 tlut) { + if (tlut >= 0x14) { + return NULL; + } else { + return &__GXData->TlutRegions[tlut]; + } +} + +u32 resetFuncRegistered; + +u32 calledOnce; + +OSTime time; + +u32 peCount; + +vu16* __memReg; + +u16* __peReg; + +u16* __cpReg; + +/* ############################################################################################## */ +u32* __piReg; + +BOOL __GXShutdown(BOOL final) { + u32 val; + u32 newPeCount; + OSTime newTime; + + if (!final) { + if (!calledOnce) { + peCount = GXReadMEMReg(0x28, 0x27); + time = OSGetTime(); + calledOnce = 1; + return FALSE; + } + + newTime = OSGetTime(); + newPeCount = GXReadMEMReg(0x28, 0x27); + + if (newTime - time < 10) { + return FALSE; + } + + if (newPeCount != peCount) { + peCount = newPeCount; + time = newTime; + return FALSE; + } + + } else { + GXSetBreakPtCallback(NULL); + GXSetDrawSyncCallback(NULL); + GXSetDrawDoneCallback(NULL); + + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + + PPCSync(); + + GX_SET_CP_REG(1, 0); + GX_SET_CP_REG(2, 3); + + __GXData->abtWaitPECopy = GX_TRUE; + + __GXAbort(); + } + + return TRUE; +} + +void __GXInitRevisionBits(void) { + u32 i; + for (i = 0; i < 8; i++) { + FAST_FLAG_SET(__GXData->vatA[i], 1, 30, 33); + FAST_FLAG_SET(__GXData->vatB[i], 1, 31, 33); + + GX_WRITE_U8(0x8); + GX_WRITE_U8(i | 0x80); + GX_WRITE_U32(__GXData->vatB[i]); + } + + { + u32 reg1 = 0; + u32 reg2 = 0; + + FAST_FLAG_SET(reg1, 1, 0, 1); + FAST_FLAG_SET(reg1, 1, 1, 1); + FAST_FLAG_SET(reg1, 1, 2, 1); + FAST_FLAG_SET(reg1, 1, 3, 1); + FAST_FLAG_SET(reg1, 1, 4, 1); + FAST_FLAG_SET(reg1, 1, 5, 1); + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1000); + GX_WRITE_U32(reg1); + + FAST_FLAG_SET(reg2, 1, 0, 1); + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1012); + GX_WRITE_U32(reg2); + } + + { + u32 reg = 0; + FAST_FLAG_SET(reg, 1, 0, 1); + FAST_FLAG_SET(reg, 1, 1, 1); + FAST_FLAG_SET(reg, 1, 2, 1); + FAST_FLAG_SET(reg, 1, 3, 1); + FAST_FLAG_SET(reg, 0x58, 24, 8); + GX_WRITE_U8(0x61); + GX_WRITE_U32(reg); + } +} + +static u16 DefaultTexData[] ALIGN_DECL(32) = { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, +}; + +static GXVtxAttrFmtList GXDefaultVATList[] = { + {GX_VA_POS, GX_POS_XYZ, GX_F32, 0}, + {GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0}, + {GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0}, + {GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0}, + {GX_VA_TEX0, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX1, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX2, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX3, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX4, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX5, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX6, GX_TEX_ST, GX_F32, 0}, + {GX_VA_TEX7, GX_TEX_ST, GX_F32, 0}, + {GX_VA_NULL, GX_COMPCNT_NULL, GX_COMP_NULL, 0}, +}; + +static f32 GXDefaultProjData[] = {1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -2.0f, 0.0f}; + +static u32 GXTexRegionAddrTable[] = { + 0x00000, 0x10000, 0x20000, 0x30000, 0x40000, 0x50000, 0x60000, 0x70000, 0x08000, 0x18000, + 0x28000, 0x38000, 0x48000, 0x58000, 0x68000, 0x78000, 0x00000, 0x90000, 0x20000, 0xB0000, + 0x40000, 0x98000, 0x60000, 0xB8000, 0x80000, 0x10000, 0xA0000, 0x30000, 0x88000, 0x50000, + 0xA8000, 0x70000, 0x00000, 0x90000, 0x20000, 0xB0000, 0x40000, 0x90000, 0x60000, 0xB0000, + 0x80000, 0x10000, 0xA0000, 0x30000, 0x80000, 0x50000, 0xA0000, 0x70000, +}; + +static OSResetFunctionInfo GXResetFuncInfo = {__GXShutdown, OS_RESET_PRIO_GX}; + +static void EnableWriteGatherPipe() { + u32 hid2; // r31 + hid2 = PPCMfhid2(); + PPCMtwpar(OSUncachedToPhysical((void*)GXFIFO_ADDR)); + hid2 |= 0x40000000; + PPCMthid2(hid2); +} + +GXFifoObj* GXInit(void* base, u32 size) { + u32 i; + u32 pad2; // for stack matching + + OSRegisterVersion(__GXVersion); + __GXData->inDispList = GX_FALSE; + __GXData->dlSaveContext = GX_TRUE; + __GXData->abtWaitPECopy = GX_TRUE; + + __GXData->tcsManEnab = 0; + __GXData->tevTcEnab = 0; + + GXSetMisc(GX_MT_XF_FLUSH, 0); + + __piReg = (void*)OSPhysicalToUncached(GX_PI_ADDR); + __cpReg = (void*)OSPhysicalToUncached(GX_CP_ADDR); + __peReg = (void*)OSPhysicalToUncached(GX_PE_ADDR); + __memReg = (void*)OSPhysicalToUncached(GX_MEM_ADDR); + + __GXFifoInit(); + + GXInitFifoBase(&FifoObj, base, size); + GXSetCPUFifo(&FifoObj); + GXSetGPFifo(&FifoObj); + + if (!resetFuncRegistered) { + OSRegisterResetFunction(&GXResetFuncInfo); + resetFuncRegistered = 1; + } + + __GXPEInit(); + EnableWriteGatherPipe(); + + __GXData->genMode = 0; + FAST_FLAG_SET(__GXData->genMode, 0, 24, 8); + + __GXData->bpMask = 255; + FAST_FLAG_SET(__GXData->bpMask, 0xF, 24, 8); + + __GXData->lpSize = 0; + FAST_FLAG_SET(__GXData->lpSize, 34, 24, 8); + + for (i = 0; i < GX_MAX_TEVSTAGE; i++) { + __GXData->tevc[i] = 0; + __GXData->teva[i] = 0; + __GXData->tref[i / 2] = 0; + __GXData->texmapId[i] = GX_TEXMAP_NULL; + + FAST_FLAG_SET(__GXData->tevc[i], 0xC0 + i * 2, 24, 8); + FAST_FLAG_SET(__GXData->teva[i], 0xC1 + i * 2, 24, 8); + FAST_FLAG_SET(__GXData->tevKsel[i / 2], 0xF6 + i / 2, 24, 8); + FAST_FLAG_SET(__GXData->tref[i / 2], 0x28 + i / 2, 24, 8); + } + + __GXData->iref = 0; + FAST_FLAG_SET(__GXData->iref, 0x27, 24, 8); + + for (i = 0; i < GX_MAXCOORD; i++) { + __GXData->suTs0[i] = 0; + __GXData->suTs1[i] = 0; + + FAST_FLAG_SET(__GXData->suTs0[i], 0x30 + i * 2, 24, 8); + FAST_FLAG_SET(__GXData->suTs1[i], 0x31 + i * 2, 24, 8); + } + + FAST_FLAG_SET(__GXData->suScis0, 0x20, 24, 8); + FAST_FLAG_SET(__GXData->suScis1, 0x21, 24, 8); + + FAST_FLAG_SET(__GXData->cmode0, 0x41, 24, 8); + FAST_FLAG_SET(__GXData->cmode1, 0x42, 24, 8); + + FAST_FLAG_SET(__GXData->zmode, 0x40, 24, 8); + FAST_FLAG_SET(__GXData->peCtrl, 0x43, 24, 8); + + FAST_FLAG_SET(__GXData->cpTex, 0, 7, 2); + + __GXData->zScale = 1.6777216E7f; + __GXData->zOffset = 0.0f; + + __GXData->dirtyState = 0; + __GXData->dirtyVAT = 0; + + { + u32 val1; + u32 val2; + + val2 = OS_BUS_CLOCK / 500; + + __GXFlushTextureState(); + + val1 = (val2 / 2048) | 0x69000400; + + GX_WRITE_U8(0x61); + GX_WRITE_U32(val1); + + __GXFlushTextureState(); + + val1 = (val2 / 4224) | 0x46000200; + GX_WRITE_U8(0x61); + GX_WRITE_U32(val1); + } + + __GXInitRevisionBits(); + + for (i = 0; i < GX_MAX_TEXMAP; i++) { + GXInitTexCacheRegion(&__GXData->TexRegions0[i], GX_FALSE, GXTexRegionAddrTable[i], + GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 8], GX_TEXCACHE_32K); + GXInitTexCacheRegion(&__GXData->TexRegions1[i], GX_FALSE, GXTexRegionAddrTable[i + 16], + GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 24], GX_TEXCACHE_32K); + GXInitTexCacheRegion(&__GXData->TexRegions2[i], GX_TRUE, GXTexRegionAddrTable[i + 32], + GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 40], GX_TEXCACHE_32K); + } + + for (i = 0; i < GX_MAX_TLUT; i++) { + GXInitTlutRegion(&__GXData->TlutRegions[i], 0xC0000 + 0x2000 * i, GX_TLUT_256); + } + + for (i = 0; i < GX_MAX_BIGTLUT; i++) { + GXInitTlutRegion(&__GXData->TlutRegions[i + 16], 0xE0000 + 0x8000 * i, GX_TLUT_1K); + } + + GX_SET_CP_REG(3, 0); + + FAST_FLAG_SET(__GXData->perfSel, 0, 4, 4); + + GX_WRITE_U8(0x8); + GX_WRITE_U8(0x20); + GX_WRITE_U32(__GXData->perfSel); + + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23000000); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x24000000); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000000); + + __GXSetIndirectMask(0); + __GXSetTmemConfig(2); + __GXInitGX(); + + return &FifoObj; +} + +void __GXInitGX(void) { + GXRenderModeObj* renderObj; + GXTexObj texObj; + Mtx ident; + GXColor clearColor = {64, 64, 64, 255}; + GXColor ambColor = {0, 0, 0, 0}; + GXColor matColor = {255, 255, 255, 255}; + u32 i; + + switch (VIGetTvFormat()) { + case VI_NTSC: + renderObj = &GXNtsc480IntDf; + break; + + case VI_PAL: + renderObj = &GXPal528IntDf; + break; + + case VI_EURGB60: + renderObj = &GXEurgb60Hz480IntDf; + break; + + case VI_MPAL: + renderObj = &GXMpal480IntDf; + break; + + default: + renderObj = &GXNtsc480IntDf; + break; + } + + GXSetCopyClear(clearColor, 0xFFFFFF); + + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + GXSetTexCoordGen2(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + + GXSetNumTexGens(1); + GXClearVtxDesc(); + GXInvalidateVtxCache(); + + for (i = GX_VA_POS; i <= GX_LIGHT_ARRAY; i++) { + GXSetArray((GXAttr)i, __GXData, 0); + } + + for (i = 0; i < GX_MAX_VTXFMT; i++) { + GXSetVtxAttrFmtv((GXVtxFmt)i, GXDefaultVATList); + } + + GXSetLineWidth(6, GX_TO_ZERO); + GXSetPointSize(6, GX_TO_ZERO); + GXEnableTexOffsets(GX_TEXCOORD0, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD1, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD2, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD3, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD4, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD5, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD6, GX_FALSE, GX_FALSE); + GXEnableTexOffsets(GX_TEXCOORD7, GX_FALSE, GX_FALSE); + + ident[0][0] = 1.0f; + ident[0][1] = 0.0f; + ident[0][2] = 0.0f; + ident[0][3] = 0.0f; + + ident[1][0] = 0.0f; + ident[1][1] = 1.0f; + ident[1][2] = 0.0f; + ident[1][3] = 0.0f; + + ident[2][0] = 0.0f; + ident[2][1] = 0.0f; + ident[2][2] = 1.0f; + ident[2][3] = 0.0f; + + GXLoadPosMtxImm(ident, GX_PNMTX0); + GXLoadNrmMtxImm(ident, GX_PNMTX0); + GXSetCurrentMtx(GX_PNMTX0); + + GXLoadTexMtxImm(ident, GX_IDENTITY, GX_MTX3x4); + GXLoadTexMtxImm(ident, GX_PTIDENTITY, GX_MTX3x4); + + GXSetViewport(0.0f, 0.0f, renderObj->fb_width, renderObj->xfb_height, 0.0f, 1.0f); + + GXSetProjectionv(GXDefaultProjData); + + GXSetCoPlanar(GX_FALSE); + GXSetCullMode(GX_CULL_BACK); + GXSetClipMode(GX_CLIP_ENABLE); + + GXSetScissor(0, 0, renderObj->fb_width, renderObj->efb_height); + GXSetScissorBoxOffset(0, 0); + + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR0A0, ambColor); + GXSetChanMatColor(GX_COLOR0A0, matColor); + + GXSetChanCtrl(GX_COLOR1A1, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR1A1, ambColor); + GXSetChanMatColor(GX_COLOR1A1, matColor); + + GXInvalidateTexAll(); + GXSetTexRegionCallback(__GXDefaultTexRegionCallback); + GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback); + + GXInitTexObj(&texObj, DefaultTexData, 4, 4, GX_TF_IA8, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXLoadTexObj(&texObj, GX_TEXMAP0); + GXLoadTexObj(&texObj, GX_TEXMAP1); + GXLoadTexObj(&texObj, GX_TEXMAP2); + GXLoadTexObj(&texObj, GX_TEXMAP3); + GXLoadTexObj(&texObj, GX_TEXMAP4); + GXLoadTexObj(&texObj, GX_TEXMAP5); + GXLoadTexObj(&texObj, GX_TEXMAP6); + GXLoadTexObj(&texObj, GX_TEXMAP7); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0); + + GXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE10, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE11, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE12, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE13, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE14, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE15, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + + GXSetNumTevStages(1); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); + + for (i = 0; i < GX_MAX_TEVSTAGE; i++) { + GXSetTevKColorSel((GXTevStageID)i, GX_TEV_KCSEL_1_4); + GXSetTevKAlphaSel((GXTevStageID)i, GX_TEV_KASEL_1); + GXSetTevSwapMode((GXTevStageID)i, GX_TEV_SWAP0, GX_TEV_SWAP0); + } + + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); + + for (i = 0; i < GX_MAX_TEVSTAGE; i++) { + GXSetTevDirect((GXTevStageID)i); + } + + GXSetNumIndStages(0); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE2, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE3, GX_ITS_1, GX_ITS_1); + + GXSetFog(GX_FOG_NONE, 0.0f, 1.0f, 0.1f, 1.0f, ambColor); + GXSetFogRangeAdj(GX_FALSE, 0, NULL); + + GXSetBlendMode(GX_BM_NONE, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_CLEAR); + + GXSetColorUpdate(GX_TRUE); + GXSetAlphaUpdate(GX_TRUE); + + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetZCompLoc(GX_TRUE); + + GXSetDither(GX_TRUE); + + GXSetDstAlpha(GX_FALSE, 0); + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GXSetFieldMask(GX_TRUE, GX_TRUE); + GXSetFieldMode( + (GXBool)renderObj->field_rendering, + (GXBool)((renderObj->vi_height == 2 * renderObj->xfb_height) ? GX_TRUE : GX_FALSE)); + + GXSetDispCopySrc(0, 0, renderObj->fb_width, renderObj->efb_height); + GXSetDispCopyDst(renderObj->fb_width, renderObj->efb_height); + GXSetDispCopyYScale((f32)renderObj->xfb_height / (f32)renderObj->efb_height); + GXSetCopyClamp(GX_CLAMP_BOTH); + + GXSetCopyFilter(renderObj->antialiasing, renderObj->sample_pattern, GX_TRUE, + renderObj->vfilter); + GXSetDispCopyGamma(GX_GM_1_0); + GXSetDispCopyFrame2Field(GX_COPY_PROGRESSIVE); + GXClearBoundingBox(); + + GXPokeColorUpdate(GX_TRUE); + GXPokeAlphaUpdate(GX_TRUE); + GXPokeDither(GX_FALSE); + GXPokeBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ONE, GX_LO_SET); + GXPokeAlphaMode(GX_ALWAYS, 0); + GXPokeAlphaRead(GX_READ_FF); + GXPokeDstAlpha(GX_FALSE, 0); + GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); + GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE); + GXClearGPMetric(); +}
\ No newline at end of file diff --git a/src/dolphin/gx/GXLight.c b/src/dolphin/gx/GXLight.c new file mode 100644 index 00000000..a90c2a21 --- /dev/null +++ b/src/dolphin/gx/GXLight.c @@ -0,0 +1,294 @@ +/** + * GXLight.c + * Description: + */ + +#include "dolphin/gx/GXLight.h" +#include "dolphin/gx/GX.h" +#include "math.h" + +void GXInitLightAttn(GXLightObj* obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) { + obj->a0 = a0; + obj->a1 = a1; + obj->a2 = a2; + obj->k0 = k0; + obj->k1 = k1; + obj->k2 = k2; +} + +void GXInitLightSpot(GXLightObj* obj, f32 cutoff, GXSpotFn spot_fn) { + f32 rad; + f32 a, b, c, d; + + if (cutoff <= 0.0f || cutoff > 90.0f) { + spot_fn = GX_SP_OFF; + } + + rad = cosf((3.1415927f * cutoff) / 180.0f); + + switch (spot_fn) { + case GX_SP_FLAT: + a = -1000.0f * rad; + b = 1000.0f; + c = 0.0f; + break; + case GX_SP_COS: + b = 1.0f / (1.0f - rad); + a = -rad * b; + c = 0.0f; + break; + case GX_SP_COS2: + c = 1.0f / (1.0f - rad); + a = 0.0f; + b = -rad * c; + break; + case GX_SP_SHARP: + d = 1.0f / ((1.0f - rad) * (1.0f - rad)); + a = (rad * (rad - 2.0f)) * d; + b = 2.0f * d; + c = -d; + break; + case GX_SP_RING1: + d = 1.0f / ((1.0f - rad) * (1.0f - rad)); + c = -4.0f * d; + a = c * rad; + b = 4.0f * (1.0f + rad) * d; + break; + case GX_SP_RING2: + d = 1.0f / ((1.0f - rad) * (1.0f - rad)); + a = 1.0f - 2.0f * rad * rad * d; + b = 4.0f * rad * d; + c = -2.0f * d; + break; + case GX_SP_OFF: + default: + a = 1.0f; + b = 0.0f; + c = 0.0f; + break; + } + + obj->a0 = a; + obj->a1 = b; + obj->a2 = c; +} + +void GXInitLightDistAttn(GXLightObj* obj, f32 dist, f32 brightness, GXDistAttnFn dist_fn) { + f32 a, b, c; + + if (dist < 0.0f) { + dist_fn = GX_DA_OFF; + } + + if (brightness <= 0.0f || brightness >= 1.0f) { + dist_fn = GX_DA_OFF; + } + + switch (dist_fn) { + case GX_DA_GENTLE: + a = 1.0f; + b = (1.0f - brightness) / (brightness * dist); + c = 0.0f; + break; + case GX_DA_MEDIUM: + a = 1.0f; + b = (0.5f * (1.0f - brightness)) / (brightness * dist); + c = (0.5f * (1.0f - brightness)) / (dist * (brightness * dist)); + break; + case GX_DA_STEEP: + a = 1.0f; + b = 0.0f; + c = (1.0f - brightness) / (dist * (brightness * dist)); + break; + case GX_DA_OFF: + default: + a = 1.0f; + b = 0.0f; + c = 0.0f; + break; + } + + obj->k0 = a; + obj->k1 = b; + obj->k2 = c; +} + +void GXInitLightPos(GXLightObj* obj, f32 x, f32 y, f32 z) { + obj->posX = x; + obj->posY = y; + obj->posZ = z; +} + +void GXInitLightDir(GXLightObj* obj, f32 x, f32 y, f32 z) { + obj->dirX = -x; + obj->dirY = -y; + obj->dirZ = -z; +} + +void GXInitLightColor(GXLightObj* obj, GXColor color) { + *(u32*)&obj->color = *(u32*)&color; +} + +static inline void PushLight(const register GXLightObj* lt_obj, register void* dest) { + register u32 zero, color; + register f32 a0_a1, a2_k0, k1_k2; + register f32 px_py, pz_dx, dy_dz; +#ifdef __MWERKS__ // clang-format off + asm { + lwz color, 12(lt_obj) + xor zero, zero, zero + psq_l a0_a1, 16(lt_obj), 0, 0 + psq_l a2_k0, 24(lt_obj), 0, 0 + psq_l k1_k2, 32(lt_obj), 0, 0 + psq_l px_py, 40(lt_obj), 0, 0 + psq_l pz_dx, 48(lt_obj), 0, 0 + psq_l dy_dz, 56(lt_obj), 0, 0 + + stw zero, 0(dest) + stw zero, 0(dest) + stw zero, 0(dest) + stw color, 0(dest) + psq_st a0_a1, 0(dest), 0, 0 + psq_st a2_k0, 0(dest), 0, 0 + psq_st k1_k2, 0(dest), 0, 0 + psq_st px_py, 0(dest), 0, 0 + psq_st pz_dx, 0(dest), 0, 0 + psq_st dy_dz, 0(dest), 0, 0 + } +#endif // clang-format on +} + +void GXLoadLightObjImm(GXLightObj* obj, GXLightID light) { + u32 addr; + u32 idx; + GXLightObj* pObj = (GXLightObj*)obj; + + idx = 31 - __cntlzw(light); + idx &= 7; + + addr = 0x600 + idx * 0x10; + + GX_XF_LOAD_REG_HDR(addr | (0x10 - 1) << 16); + + PushLight(pObj, (void*)GXFIFO_ADDR); + __GXData->bpSentNot = 1; +} + +void GXSetChanAmbColor(GXChannelID channel, GXColor color) { + u32 reg; + u32 colorID; + u8 alpha; + + switch (channel) { + case GX_COLOR0: + reg = __GXData->ambColor[GX_COLOR0]; + reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23); + colorID = GX_COLOR0; + break; + case GX_COLOR1: + reg = __GXData->ambColor[GX_COLOR1]; + reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23); + colorID = GX_COLOR1; + break; + case GX_ALPHA0: + reg = __GXData->ambColor[GX_COLOR0]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR0; + break; + case GX_ALPHA1: + reg = __GXData->ambColor[GX_COLOR1]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR1; + break; + case GX_COLOR0A0: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR0; + break; + case GX_COLOR1A1: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR1; + break; + default: + return; + } + + GX_XF_LOAD_REG(GX_XF_REG_AMBIENT0 + colorID, reg); + __GXData->bpSentNot = GX_TRUE; + __GXData->ambColor[colorID] = reg; +} + +void GXSetChanMatColor(GXChannelID channel, GXColor color) { + u32 reg = 0; + GXChannelID colorID; + + switch (channel) { + case GX_COLOR0: + reg = __GXData->matColor[GX_COLOR0]; + reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23); + colorID = GX_COLOR0; + break; + case GX_COLOR1: + reg = __GXData->matColor[GX_COLOR1]; + reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23); + colorID = GX_COLOR1; + break; + case GX_ALPHA0: + reg = __GXData->matColor[GX_COLOR0]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR0; + break; + case GX_ALPHA1: + reg = __GXData->matColor[GX_COLOR1]; + reg = GX_SET_TRUNC(reg, color.a, 24, 31); + colorID = GX_COLOR1; + break; + case GX_COLOR0A0: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR0; + break; + case GX_COLOR1A1: + reg = GXCOLOR_AS_U32(color); + colorID = GX_COLOR1; + break; + default: + return; + } + + GX_XF_LOAD_REG(GX_XF_REG_MATERIAL0 + colorID, reg); + __GXData->bpSentNot = GX_TRUE; + __GXData->matColor[colorID] = reg; +} + +void GXSetNumChans(u8 count) { + GX_SET_REG(__GXData->genMode, count, 25, 27); + GX_XF_LOAD_REG(GX_XF_REG_NUMCOLORS, count); + __GXData->dirtyState |= GX_DIRTY_GEN_MODE; +} + +void GXSetChanCtrl(GXChannelID channel, GXBool doEnable, GXColorSrc ambSrc, GXColorSrc matSrc, + u32 mask, GXDiffuseFn diffFunc, GXAttnFn attnFunc) { + const u32 colorID = (u32)channel & 0x3; + u32 reg = 0; + + GX_SET_REG(reg, doEnable, GX_XF_CLR0CTRL_LIGHT_ST, GX_XF_CLR0CTRL_LIGHT_END); + GX_SET_REG(reg, matSrc, GX_XF_CLR0CTRL_MTXSRC_ST, GX_XF_CLR0CTRL_MTXSRC_END); + GX_SET_REG(reg, ambSrc, GX_XF_CLR0CTRL_AMBSRC_ST, GX_XF_CLR0CTRL_AMBSRC_END); + GX_SET_REG(reg, (attnFunc == GX_AF_SPEC ? GX_DF_NONE : diffFunc), GX_XF_CLR0CTRL_DIFATTN_ST, + GX_XF_CLR0CTRL_DIFATTN_END); + GX_SET_REG(reg, (attnFunc != GX_AF_NONE), GX_XF_CLR0CTRL_ATTNENABLE_ST, + GX_XF_CLR0CTRL_ATTNENABLE_END); + GX_SET_REG(reg, (attnFunc != GX_AF_SPEC), GX_XF_CLR0CTRL_ATTNSEL_ST, + GX_XF_CLR0CTRL_ATTNSEL_END); + GX_BITFIELD_SET(reg, 26, 4, (u32)mask); + reg = __rlwimi(reg, (u32)mask, 7, 0x11, 0x14); + + GX_XF_LOAD_REG(GX_XF_REG_COLOR0CNTRL + colorID, reg); + + if (channel == GX_COLOR0A0) { + GX_XF_LOAD_REG(GX_XF_REG_ALPHA0CNTRL, reg); + } else if (channel == GX_COLOR1A1) { + GX_XF_LOAD_REG(GX_XF_REG_ALPHA1CNTRL, reg); + } + + __GXData->bpSentNot = GX_TRUE; +} diff --git a/src/dolphin/gx/GXMisc.c b/src/dolphin/gx/GXMisc.c new file mode 100644 index 00000000..468192ea --- /dev/null +++ b/src/dolphin/gx/GXMisc.c @@ -0,0 +1,266 @@ +#include "dolphin/gx/GXMisc.h" +#include "dolphin/gx/GX.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/os/OSReset.h" +#include "dolphin/os/OSTime.h" + +static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext* context); +static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext* pContext); + +void GXSetMisc(GXMiscToken token, u32 val) { + switch (token) { + case GX_MT_NULL: + break; + + case GX_MT_XF_FLUSH: + __GXData->vNum = val; + __GXData->vNumNot = !__GXData->vNum; + __GXData->bpSentNot = GX_TRUE; + + if (__GXData->vNum) { + __GXData->dirtyState |= GX_DIRTY_VCD; + } + break; + + case GX_MT_DL_SAVE_CONTEXT: + __GXData->dlSaveContext = (val != 0); + break; + + case GX_MT_ABORT_WAIT_COPYOUT: + __GXData->abtWaitPECopy = (val != 0); + break; + } +} + +void GXFlush(void) { + if (__GXData->dirtyState) { + __GXSetDirtyState(); + } + + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + GXFIFO.u32 = 0; + + PPCSync(); +} + +static void __GXAbortWait(u32 clocks) { + OSTime time0, time1; + time0 = OSGetTime(); + + do { + time1 = OSGetTime(); + } while (time1 - time0 <= clocks / 4); +} + +static void __GXAbortWaitPECopyDone(void) { + u32 peCnt0, peCnt1; + + peCnt0 = GXReadMEMReg(0x28, 0x27); + do { + peCnt1 = peCnt0; + __GXAbortWait(32); + + peCnt0 = GXReadMEMReg(0x28, 0x27); + } while (peCnt0 != peCnt1); +} + +void __GXAbort(void) { + if (__GXData->abtWaitPECopy && GXGetGPFifo()) { + __GXAbortWaitPECopyDone(); + } + + __PIRegs[0x18 / 4] = 1; + __GXAbortWait(200); + __PIRegs[0x18 / 4] = 0; + __GXAbortWait(20); +} + +void GXAbortFrame(void) { + __GXAbort(); + if (GXGetGPFifo()) { + __GXCleanGPFifo(); + __GXInitRevisionBits(); + __GXData->dirtyState = 0; + GXFlush(); + } +} + +/* ############################################################################################## */ +static GXDrawSyncCallback TokenCB; + +static GXDrawDoneCallback DrawDoneCB; + +static GXBool DrawDone; + +void GXSetDrawDone(void) { + u8 padding[8]; + BOOL restore = OSDisableInterrupts(); + GFWriteBPCmd(0x45000002); + GXFlush(); + DrawDone = 0; + OSRestoreInterrupts(restore); +} + +/* ############################################################################################## */ +static OSThreadQueue FinishQueue; + +static void GXWaitDrawDone(void) { + BOOL restore = OSDisableInterrupts(); + while (DrawDone == 0) { + OSSleepThread(&FinishQueue); + } + OSRestoreInterrupts(restore); +} + +void GXDrawDone(void) { + u8 padding[8]; + GXSetDrawDone(); + GXWaitDrawDone(); +} + +void GXPixModeSync(void) { + GXFIFO.u8 = 0x61; + GXFIFO.u32 = __GXData->peCtrl; + __GXData->bpSentNot = 0; +} + +void GXPokeAlphaMode(GXCompare comp, u8 threshold) { + __peReg[3] = (comp << 8) | threshold; +} + +void GXPokeAlphaRead(GXAlphaReadMode mode) { + u32 val = 0; + GX_BITFIELD_SET(val, 0x1e, 2, mode); + GX_BITFIELD_SET(val, 0x1d, 1, 1); + __peReg[4] = val; +} + +void GXPokeAlphaUpdate(GXBool enable_update) { + GX_BITFIELD_SET(__peReg[1], 0x1b, 1, enable_update); +} + +void GXPokeBlendMode(GXBlendMode mode, GXBlendFactor srcFactor, GXBlendFactor destFactor, + GXLogicOp op) { + u32 reg; + + reg = GX_GET_PE_REG(1); + GX_SET_REG(reg, (mode == GX_BM_BLEND) || (mode == GX_BM_SUBTRACT), 31, 31); + GX_SET_REG(reg, (mode == GX_BM_SUBTRACT), 20, 20); + GX_SET_REG(reg, (mode == GX_BM_LOGIC), 30, 30); + GX_SET_REG(reg, op, 16, 19); + GX_SET_REG(reg, srcFactor, 21, 23); + GX_SET_REG(reg, destFactor, 24, 26); + GX_SET_REG(reg, 0x41, 0, 7); + GX_SET_PE_REG(1, reg); +} + +void GXPokeColorUpdate(GXBool enable_update) { + GX_BITFIELD_SET(__peReg[1], 0x1c, 1, enable_update); +} + +void GXPokeDstAlpha(GXBool enable, u8 alpha) { + u32 val = 0; + GX_BITFIELD_SET(val, 0x18, 8, alpha); + GX_BITFIELD_SET(val, 0x17, 1, enable); + __peReg[2] = val; +} + +void GXPokeDither(GXBool enable) { + GX_BITFIELD_SET(__peReg[1], 0x1d, 1, enable); +} + +void GXPokeZMode(GXBool enable_compare, GXCompare comp, GXBool update_enable) { + u32 val = 0; + GX_BITFIELD_SET(val, 0x1f, 1, enable_compare); + GX_BITFIELD_SET(val, 0x1c, 3, comp); + GX_BITFIELD_SET(val, 0x1b, 1, update_enable); + __peReg[0] = val; +} + +void GXPeekZ(u16 x, u16 y, u32* z) { + u32 addr = 0xc8000000; + GX_BITFIELD_SET(addr, 0x14, 10, x); + GX_BITFIELD_SET(addr, 0xa, 10, y); + GX_BITFIELD_SET(addr, 8, 2, 1); + *z = *(u32*)addr; +} + +GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback callback) { + BOOL restore; + GXDrawSyncCallback prevCb = TokenCB; + restore = OSDisableInterrupts(); + TokenCB = callback; + OSRestoreInterrupts(restore); + return prevCb; +} + +static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext* context) { + u16 token; + OSContext exceptContext; + u32 reg; + + token = GX_GET_PE_REG(7); + + if (TokenCB) { + OSClearContext(&exceptContext); + OSSetCurrentContext(&exceptContext); + TokenCB(token); + OSClearContext(&exceptContext); + OSSetCurrentContext(context); + } + + reg = GX_GET_PE_REG(5); + GX_SET_REG(reg, 1, 29, 29); + GX_SET_PE_REG(5, reg); +} + +GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback callback) { + BOOL restore; + GXDrawDoneCallback prevCb = DrawDoneCB; + restore = OSDisableInterrupts(); + DrawDoneCB = callback; + OSRestoreInterrupts(restore); + return prevCb; +} + +static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext* context) { + OSContext exceptContext; + u32 reg; + + reg = GX_GET_PE_REG(5); + GX_SET_REG(reg, 1, 28, 28); + GX_SET_PE_REG(5, reg); + + DrawDone = GX_TRUE; + + if (DrawDoneCB) { + OSClearContext(&exceptContext); + OSSetCurrentContext(&exceptContext); + DrawDoneCB(); + OSClearContext(&exceptContext); + OSSetCurrentContext(context); + } + + OSWakeupThread(&FinishQueue); +} + +void __GXPEInit(void) { + u32 val; + __OSSetInterruptHandler(OS_INTR_PI_PE_TOKEN, GXTokenInterruptHandler); + __OSSetInterruptHandler(OS_INTR_PI_PE_FINISH, GXFinishInterruptHandler); + OSInitThreadQueue(&FinishQueue); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_PE_TOKEN); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_PE_FINISH); + val = __peReg[5]; + GX_BITFIELD_SET(val, 0x1d, 1, 1); + GX_BITFIELD_SET(val, 0x1c, 1, 1); + GX_BITFIELD_SET(val, 0x1f, 1, 1); + GX_BITFIELD_SET(val, 0x1e, 1, 1); + __peReg[5] = val; +} diff --git a/src/dolphin/gx/GXPerf.c b/src/dolphin/gx/GXPerf.c new file mode 100644 index 00000000..60591b0b --- /dev/null +++ b/src/dolphin/gx/GXPerf.c @@ -0,0 +1,384 @@ +#include "dolphin/gx/GXPerf.h" +#include "dolphin/gx/GX.h" + +void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) { + switch (__GXData->perf0) { + case GX_PERF0_VERTICES: + case GX_PERF0_CLIP_VTX: + case GX_PERF0_CLIP_CLKS: + case GX_PERF0_XF_WAIT_IN: + case GX_PERF0_XF_WAIT_OUT: + case GX_PERF0_XF_XFRM_CLKS: + case GX_PERF0_XF_LIT_CLKS: + case GX_PERF0_XF_BOT_CLKS: + case GX_PERF0_XF_REGLD_CLKS: + case GX_PERF0_XF_REGRD_CLKS: + case GX_PERF0_CLIP_RATIO: + case GX_PERF0_CLOCKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0); + break; + + case GX_PERF0_TRIANGLES: + case GX_PERF0_TRIANGLES_CULLED: + case GX_PERF0_TRIANGLES_PASSED: + case GX_PERF0_TRIANGLES_SCISSORED: + case GX_PERF0_TRIANGLES_0TEX: + case GX_PERF0_TRIANGLES_1TEX: + case GX_PERF0_TRIANGLES_2TEX: + case GX_PERF0_TRIANGLES_3TEX: + case GX_PERF0_TRIANGLES_4TEX: + case GX_PERF0_TRIANGLES_5TEX: + case GX_PERF0_TRIANGLES_6TEX: + case GX_PERF0_TRIANGLES_7TEX: + case GX_PERF0_TRIANGLES_8TEX: + case GX_PERF0_TRIANGLES_0CLR: + case GX_PERF0_TRIANGLES_1CLR: + case GX_PERF0_TRIANGLES_2CLR: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23000000); + break; + + case GX_PERF0_QUAD_0CVG: + case GX_PERF0_QUAD_NON0CVG: + case GX_PERF0_QUAD_1CVG: + case GX_PERF0_QUAD_2CVG: + case GX_PERF0_QUAD_3CVG: + case GX_PERF0_QUAD_4CVG: + case GX_PERF0_AVG_QUAD_CNT: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x24000000); + break; + + case GX_PERF0_NONE: + break; + } + + switch (__GXData->perf1) { + case GX_PERF1_TEXELS: + case GX_PERF1_TX_IDLE: + case GX_PERF1_TX_REGS: + case GX_PERF1_TX_MEMSTALL: + case GX_PERF1_TC_CHECK1_2: + case GX_PERF1_TC_CHECK3_4: + case GX_PERF1_TC_CHECK5_6: + case GX_PERF1_TC_CHECK7_8: + case GX_PERF1_TC_MISS: + case GX_PERF1_CLOCKS: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000000); + break; + + case GX_PERF1_VC_ELEMQ_FULL: + case GX_PERF1_VC_MISSQ_FULL: + case GX_PERF1_VC_MEMREQ_FULL: + case GX_PERF1_VC_STATUS7: + case GX_PERF1_VC_MISSREP_FULL: + case GX_PERF1_VC_STREAMBUF_LOW: + case GX_PERF1_VC_ALL_STALLS: + case GX_PERF1_VERTICES: + FAST_FLAG_SET(__GXData->perfSel, 0, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + + case GX_PERF1_FIFO_REQ: + case GX_PERF1_CALL_REQ: + case GX_PERF1_VC_MISS_REQ: + case GX_PERF1_CP_ALL_REQ: + GX_SET_CP_REG(3, 0); + break; + + case GX_PERF1_NONE: + break; + } + + __GXData->perf0 = perf0; + + switch (__GXData->perf0) { + case GX_PERF0_VERTICES: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x273); + break; + case GX_PERF0_CLIP_VTX: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x14A); + break; + case GX_PERF0_CLIP_CLKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x16B); + break; + case GX_PERF0_XF_WAIT_IN: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x84); + break; + case GX_PERF0_XF_WAIT_OUT: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0xC6); + break; + case GX_PERF0_XF_XFRM_CLKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x210); + break; + case GX_PERF0_XF_LIT_CLKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x252); + break; + case GX_PERF0_XF_BOT_CLKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x231); + break; + case GX_PERF0_XF_REGLD_CLKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x1AD); + break; + case GX_PERF0_XF_REGRD_CLKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x1CE); + break; + case GX_PERF0_CLOCKS: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x21); + break; + case GX_PERF0_CLIP_RATIO: + GX_WRITE_U8(0x10); + GX_WRITE_U32(0x1006); + GX_WRITE_U32(0x153); + break; + + case GX_PERF0_TRIANGLES: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AE7F); + break; + case GX_PERF0_TRIANGLES_CULLED: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23008E7F); + break; + case GX_PERF0_TRIANGLES_PASSED: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23009E7F); + break; + case GX_PERF0_TRIANGLES_SCISSORED: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23001E7F); + break; + case GX_PERF0_TRIANGLES_0TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AC3F); + break; + case GX_PERF0_TRIANGLES_1TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AC7F); + break; + case GX_PERF0_TRIANGLES_2TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300ACBF); + break; + case GX_PERF0_TRIANGLES_3TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300ACFF); + break; + case GX_PERF0_TRIANGLES_4TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AD3F); + break; + case GX_PERF0_TRIANGLES_5TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AD7F); + break; + case GX_PERF0_TRIANGLES_6TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300ADBF); + break; + case GX_PERF0_TRIANGLES_7TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300ADFF); + break; + case GX_PERF0_TRIANGLES_8TEX: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AE3F); + break; + case GX_PERF0_TRIANGLES_0CLR: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300A27F); + break; + case GX_PERF0_TRIANGLES_1CLR: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300A67F); + break; + case GX_PERF0_TRIANGLES_2CLR: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2300AA7F); + break; + + case GX_PERF0_QUAD_0CVG: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C0C6); + break; + case GX_PERF0_QUAD_NON0CVG: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C16B); + break; + case GX_PERF0_QUAD_1CVG: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C0E7); + break; + case GX_PERF0_QUAD_2CVG: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C108); + break; + case GX_PERF0_QUAD_3CVG: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C129); + break; + case GX_PERF0_QUAD_4CVG: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C14A); + break; + case GX_PERF0_AVG_QUAD_CNT: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C1AD); + break; + + case GX_PERF0_NONE: + break; + } + + __GXData->perf1 = perf1; + + switch (__GXData->perf1) { + case GX_PERF1_TEXELS: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000042); + break; + case GX_PERF1_TX_IDLE: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000084); + break; + case GX_PERF1_TX_REGS: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000063); + break; + case GX_PERF1_TX_MEMSTALL: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000129); + break; + case GX_PERF1_TC_MISS: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000252); + break; + case GX_PERF1_CLOCKS: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000021); + break; + case GX_PERF1_TC_CHECK1_2: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x6700014B); + break; + case GX_PERF1_TC_CHECK3_4: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x6700018D); + break; + case GX_PERF1_TC_CHECK5_6: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x670001CF); + break; + case GX_PERF1_TC_CHECK7_8: + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x67000211); + break; + + case GX_PERF1_VC_ELEMQ_FULL: + FAST_FLAG_SET(__GXData->perfSel, 2, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VC_MISSQ_FULL: + FAST_FLAG_SET(__GXData->perfSel, 3, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VC_MEMREQ_FULL: + FAST_FLAG_SET(__GXData->perfSel, 4, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VC_STATUS7: + FAST_FLAG_SET(__GXData->perfSel, 5, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VC_MISSREP_FULL: + FAST_FLAG_SET(__GXData->perfSel, 6, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VC_STREAMBUF_LOW: + FAST_FLAG_SET(__GXData->perfSel, 7, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VC_ALL_STALLS: + FAST_FLAG_SET(__GXData->perfSel, 9, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + case GX_PERF1_VERTICES: + FAST_FLAG_SET(__GXData->perfSel, 8, 4, 4); + GX_WRITE_U8(8); + GX_WRITE_U8(32); + GX_WRITE_U32(__GXData->perfSel); + break; + + case GX_PERF1_FIFO_REQ: + GX_SET_CP_REG(3, 2); + break; + case GX_PERF1_CALL_REQ: + GX_SET_CP_REG(3, 3); + break; + case GX_PERF1_VC_MISS_REQ: + GX_SET_CP_REG(3, 4); + break; + case GX_PERF1_CP_ALL_REQ: + GX_SET_CP_REG(3, 5); + break; + + case GX_PERF1_NONE: + break; + } + + __GXData->bpSentNot = GX_FALSE; +} + +void GXClearGPMetric(void) { + GX_SET_CP_REG(2, 4); +} + +#pragma scheduling off +void GXReadXfRasMetric(u32* xfWaitIn, u32* xfWaitOut, u32* rasBusy, u32* clocks) { + *rasBusy = GXReadCPReg(32, 33); + *clocks = GXReadCPReg(34, 35); + *xfWaitIn = GXReadCPReg(36, 37); + *xfWaitOut = GXReadCPReg(38, 39); +} +#pragma scheduling reset diff --git a/src/dolphin/gx/GXPixel.c b/src/dolphin/gx/GXPixel.c new file mode 100644 index 00000000..f3448bc3 --- /dev/null +++ b/src/dolphin/gx/GXPixel.c @@ -0,0 +1,235 @@ +#include "dolphin/gx/GXPixel.h" +#include "dolphin/gx/GX.h" + +void GXSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) { + f32 a, c; + u32 a_bits, c_bits; + + u32 fogColorReg = 0; + u32 fogParamReg0 = 0; + u32 fogParamReg1 = 0; + u32 fogParamReg2 = 0; + u32 fogParamReg3 = 0; + + u32 fsel = type & 7; + BOOL isOrtho = (type >> 3) & 1; + u32 col; + + if (isOrtho) { + if (farz == nearz || endz == startz) { + a = 0.0f; + c = 0.0f; + } else { + a = (1.0f / (endz - startz)) * (farz - nearz); + c = (1.0f / (endz - startz)) * (startz - nearz); + } + } else { + f32 tmpA, tmpB, tmpC; + u32 expB, magB, shiftB; + + if (farz == nearz || endz == startz) { + tmpA = 0.0f; + tmpB = 0.5f; + tmpC = 0.0f; + } else { + tmpA = (farz * nearz) / ((farz - nearz) * (endz - startz)); + tmpB = farz / (farz - nearz); + tmpC = startz / (endz - startz); + } + + expB = 0; + while (tmpB > 1.0) { + tmpB /= 2.0f; + expB++; + } + while (tmpB > 0.0f && tmpB < 0.5) { + tmpB *= 2.0f; + expB--; + } + + a = tmpA / (1 << expB + 1); + magB = 8388638.0f * tmpB; + shiftB = expB + 1; + c = tmpC; + + GX_SET_REG(fogParamReg1, magB, GX_BP_FOGPARAM1_B_MAG_ST, GX_BP_FOGPARAM1_B_MAG_END); + GX_SET_REG(fogParamReg2, shiftB, GX_BP_FOGPARAM2_B_SHIFT_ST, GX_BP_FOGPARAM2_B_SHIFT_END); + + GX_SET_REG(fogParamReg1, GX_BP_REG_FOGPARAM1, 0, 7); + GX_SET_REG(fogParamReg2, GX_BP_REG_FOGPARAM2, 0, 7); + } + + a_bits = *(u32*)&a; + c_bits = *(u32*)&c; + + GX_SET_REG(fogParamReg0, a_bits >> 12, GX_BP_FOGPARAM0_A_MANT_ST, GX_BP_FOGPARAM0_A_MANT_END); + GX_SET_REG(fogParamReg0, a_bits >> 23, GX_BP_FOGPARAM0_A_EXP_ST, GX_BP_FOGPARAM0_A_EXP_END); + GX_SET_REG(fogParamReg0, a_bits >> 31, GX_BP_FOGPARAM0_A_SIGN_ST, GX_BP_FOGPARAM0_A_SIGN_END); + GX_SET_REG(fogParamReg0, GX_BP_REG_FOGPARAM0, 0, 7); + + GX_SET_REG(fogParamReg3, c_bits >> 12, GX_BP_FOGPARAM3_C_MANT_ST, GX_BP_FOGPARAM3_C_MANT_END); + GX_SET_REG(fogParamReg3, c_bits >> 23, GX_BP_FOGPARAM3_C_EXP_ST, GX_BP_FOGPARAM3_C_EXP_END); + GX_SET_REG(fogParamReg3, c_bits >> 31, GX_BP_FOGPARAM3_C_SIGN_ST, GX_BP_FOGPARAM3_C_SIGN_END); + GX_SET_REG(fogParamReg3, isOrtho, GX_BP_FOGPARAM3_PROJ_ST, GX_BP_FOGPARAM3_PROJ_END); + GX_SET_REG(fogParamReg3, fsel, GX_BP_FOGPARAM3_FSEL_ST, GX_BP_FOGPARAM3_FSEL_END); + GX_SET_REG(fogParamReg3, GX_BP_REG_FOGPARAM3, 0, 7); + + col = *(u32*)&color; + GX_SET_REG(fogColorReg, col >> 8, GX_BP_FOGCOLOR_RGB_ST, GX_BP_FOGCOLOR_RGB_END); + GX_SET_REG(fogColorReg, GX_BP_REG_FOGCOLOR, 0, 7); + + GX_BP_LOAD_REG(fogParamReg0); + GX_BP_LOAD_REG(fogParamReg1); + GX_BP_LOAD_REG(fogParamReg2); + GX_BP_LOAD_REG(fogParamReg3); + GX_BP_LOAD_REG(fogColorReg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetFogRangeAdj(GXBool enable, u16 center, GXFogAdjTable* table) { + u32 fogRangeReg; + u32 fogRangeRegK; + u32 i; + + if (enable) { + for (i = 0; i < 10; i += 2) { + fogRangeRegK = 0; + GX_SET_REG(fogRangeRegK, table->fogVals[i], GX_BP_FOGRANGEK_HI_ST, + GX_BP_FOGRANGEK_HI_END); + GX_SET_REG(fogRangeRegK, table->fogVals[i + 1], GX_BP_FOGRANGEK_LO_ST, + GX_BP_FOGRANGEK_LO_END); + GX_SET_REG(fogRangeRegK, GX_BP_REG_FOGRANGEK0 + (i / 2), 0, 7); + GX_BP_LOAD_REG(fogRangeRegK); + } + } + + fogRangeReg = 0; + GX_SET_REG(fogRangeReg, center + 342, GX_BP_FOGRANGE_CENTER_ST, GX_BP_FOGRANGE_CENTER_END); + GX_SET_REG(fogRangeReg, enable, GX_BP_FOGRANGE_ENABLED_ST, GX_BP_FOGRANGE_ENABLED_END); + GX_SET_REG(fogRangeReg, GX_BP_REG_FOGRANGE, 0, 7); + GX_BP_LOAD_REG(fogRangeReg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, + GXLogicOp op) { + u32 blendModeReg = __GXData->cmode0; + GX_SET_REG(blendModeReg, type == GX_BM_SUBTRACT, GX_BP_BLENDMODE_SUBTRACT_ST, + GX_BP_BLENDMODE_SUBTRACT_END); + GX_SET_REG(blendModeReg, type, GX_BP_BLENDMODE_ENABLE_ST, GX_BP_BLENDMODE_ENABLE_END); + GX_SET_REG(blendModeReg, type == GX_BM_LOGIC, GX_BP_BLENDMODE_LOGIC_OP_ST, + GX_BP_BLENDMODE_LOGIC_OP_END); + GX_SET_REG(blendModeReg, op, GX_BP_BLENDMODE_LOGICMODE_ST, GX_BP_BLENDMODE_LOGICMODE_END); + GX_SET_REG(blendModeReg, src_factor, GX_BP_BLENDMODE_SRCFACTOR_ST, + GX_BP_BLENDMODE_SRCFACTOR_END); + GX_SET_REG(blendModeReg, dst_factor, GX_BP_BLENDMODE_DSTFACTOR_ST, + GX_BP_BLENDMODE_DSTFACTOR_END); + + GX_BP_LOAD_REG(blendModeReg); + __GXData->cmode0 = blendModeReg; + + __GXData->bpSentNot = FALSE; +} + +void GXSetColorUpdate(GXBool updateEnable) { + u32 blendModeReg = __GXData->cmode0; + GX_SET_REG(blendModeReg, updateEnable, GX_BP_BLENDMODE_COLOR_UPDATE_ST, + GX_BP_BLENDMODE_COLOR_UPDATE_END); + GX_BP_LOAD_REG(blendModeReg); + __GXData->cmode0 = blendModeReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetAlphaUpdate(GXBool updateEnable) { + u32 blendModeReg = __GXData->cmode0; + GX_SET_REG(blendModeReg, updateEnable, GX_BP_BLENDMODE_ALPHA_UPDATE_ST, + GX_BP_BLENDMODE_ALPHA_UPDATE_END); + GX_BP_LOAD_REG(blendModeReg); + __GXData->cmode0 = blendModeReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetZMode(GXBool compareEnable, GXCompare func, GXBool updateEnable) { + u32 zModeReg = __GXData->zmode; + GX_SET_REG(zModeReg, compareEnable, GX_BP_ZMODE_TEST_ENABLE_ST, GX_BP_ZMODE_TEST_ENABLE_END); + GX_SET_REG(zModeReg, func, GX_BP_ZMODE_COMPARE_ST, GX_BP_ZMODE_COMPARE_END); + GX_SET_REG(zModeReg, updateEnable, GX_BP_ZMODE_UPDATE_ENABLE_ST, GX_BP_ZMODE_UPDATE_ENABLE_END); + GX_BP_LOAD_REG(zModeReg); + __GXData->zmode = zModeReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetZCompLoc(GXBool beforeTex) { + GX_SET_REG(__GXData->peCtrl, beforeTex, GX_BP_ZCONTROL_BEFORE_TEX_ST, + GX_BP_ZCONTROL_BEFORE_TEX_END); + GX_BP_LOAD_REG(__GXData->peCtrl); + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetPixelFmt(GXPixelFmt pixelFmt, GXZFmt16 zFmt) { + GXBool isZ16; + static u32 p2f[GX_PF_MAX] = {GX_PF_RGB8_Z24, GX_PF_RGBA6_Z24, GX_PF_RGB565_Z16, GX_PF_Z24, + GX_PF_Y8, GX_PF_Y8, GX_PF_Y8, GX_PF_U8}; + + const u32 zControlRegOld = __GXData->peCtrl; + + GX_SET_REG(__GXData->peCtrl, p2f[pixelFmt], GX_BP_ZCONTROL_PIXEL_FMT_ST, + GX_BP_ZCONTROL_PIXEL_FMT_END); + GX_SET_REG(__GXData->peCtrl, zFmt, GX_BP_ZCONTROL_Z_FMT_ST, GX_BP_ZCONTROL_Z_FMT_END); + + if (zControlRegOld != __GXData->peCtrl) { + GX_BP_LOAD_REG(__GXData->peCtrl); + isZ16 = (pixelFmt == GX_PF_RGB565_Z16) ? GX_TRUE : GX_FALSE; + GX_SET_REG(__GXData->genMode, isZ16, GX_BP_GENMODE_MULTISAMPLE_ST, + GX_BP_GENMODE_MULTISAMPLE_END); + __GXData->dirtyState |= GX_DIRTY_GEN_MODE; + } + + if (p2f[pixelFmt] == GX_PF_Y8) { + GX_SET_REG(__GXData->cmode1, pixelFmt - GX_PF_Y8, GX_BP_DSTALPHA_YUV_FMT_ST, + GX_BP_DSTALPHA_YUV_FMT_END); + GX_SET_REG(__GXData->cmode1, GX_BP_REG_DSTALPHA, 0, 7); + GX_BP_LOAD_REG(__GXData->cmode1); + } + + __GXData->bpSentNot = FALSE; +} + +void GXSetDither(GXBool dither) { + u32 blendModeReg = __GXData->cmode0; + GX_SET_REG(blendModeReg, dither, GX_BP_BLENDMODE_DITHER_ST, GX_BP_BLENDMODE_DITHER_END); + GX_BP_LOAD_REG(blendModeReg); + __GXData->cmode0 = blendModeReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetDstAlpha(GXBool enable, u8 alpha) { + u32 dstAlpha = __GXData->cmode1; + GX_SET_REG(dstAlpha, alpha, GX_BP_DSTALPHA_ALPHA_ST, GX_BP_DSTALPHA_ALPHA_END); + GX_SET_REG(dstAlpha, enable, GX_BP_DSTALPHA_ENABLE_ST, GX_BP_DSTALPHA_ENABLE_END); + GX_BP_LOAD_REG(dstAlpha); + __GXData->cmode1 = dstAlpha; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetFieldMask(GXBool enableEven, GXBool enableOdd) { + u32 fieldMaskReg = 0; + GX_SET_REG(fieldMaskReg, enableOdd, GX_BP_FIELDMASK_ODD_ST, GX_BP_FIELDMASK_ODD_END); + GX_SET_REG(fieldMaskReg, enableEven, GX_BP_FIELDMASK_EVEN_ST, GX_BP_FIELDMASK_EVEN_END); + GX_SET_REG(fieldMaskReg, GX_BP_REG_FIELDMASK, 0, 7); + + GX_BP_LOAD_REG(fieldMaskReg); + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetFieldMode(GXBool texLOD, GXBool adjustAR) { + GX_SET_REG(__GXData->lpSize, adjustAR, GX_BP_LINEPTWIDTH_ADJUST_ST, + GX_BP_LINEPTWIDTH_ADJUST_END); + GX_BP_LOAD_REG(__GXData->lpSize); + + __GXFlushTextureState(); + GX_BP_LOAD_REG(GX_BP_REG_FIELDMODE << 24 | texLOD); + __GXFlushTextureState(); +} diff --git a/src/dolphin/gx/GXTev.c b/src/dolphin/gx/GXTev.c new file mode 100644 index 00000000..af060678 --- /dev/null +++ b/src/dolphin/gx/GXTev.c @@ -0,0 +1,366 @@ +#include "dolphin/gx/GXTev.h" +#include "dolphin/gx/GX.h" + +/* ############################################################################################## */ +static u32 TEVCOpTableST0[] = { + 0xC008F8AF, // modulate + 0xC008A89F, // decal + 0xC008AC8F, // blend + 0xC008FFF8, // replace + 0xC008FFFA, // passclr +}; + +static u32 TEVCOpTableST1[] = { + 0xC008F80F, // modulate + 0xC008089F, // decal + 0xC0080C8F, // blend + 0xC008FFF8, // replace + 0xC008FFF0, // passclr +}; + +static u32 TEVAOpTableST0[] = { + 0xC108F2F0, // modulate + 0xC108FFD0, // decal + 0xC108F2F0, // blend + 0xC108FFC0, // replace + 0xC108FFD0, // passclr +}; + +static u32 TEVAOpTableST1[] = { + 0xC108F070, // modulate + 0xC108FF80, // decal + 0xC108F070, // blend + 0xC108FFC0, // replace + 0xC108FF80, // passclr +}; + +void GXSetTevOp(GXTevStageID stage, GXTevMode mode) { + u32* color; + u32* alpha; + u32 tevReg; + + if (stage == GX_TEVSTAGE0) { + color = &TEVCOpTableST0[mode]; + alpha = &TEVAOpTableST0[mode]; + } else { + color = &TEVCOpTableST1[mode]; + alpha = &TEVAOpTableST1[mode]; + } + + tevReg = __GXData->tevc[stage]; + tevReg = (*color & ~0xFF000000) | (tevReg & 0xFF000000); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(tevReg); + + __GXData->tevc[stage] = tevReg; + + tevReg = __GXData->teva[stage]; + tevReg = (*alpha & ~0xFF00000F) | (tevReg & 0xFF00000F); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(tevReg); + + __GXData->teva[stage] = tevReg; + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, + GXTevColorArg d) { + u32 tevReg; + + tevReg = __GXData->tevc[stage]; + + FAST_FLAG_SET(tevReg, a, 12, 4); + FAST_FLAG_SET(tevReg, b, 8, 4); + FAST_FLAG_SET(tevReg, c, 4, 4); + FAST_FLAG_SET(tevReg, d, 0, 4); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(tevReg); + + __GXData->tevc[stage] = tevReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, + GXTevAlphaArg d) { + u32 tevReg; + + tevReg = __GXData->teva[stage]; + + FAST_FLAG_SET(tevReg, a, 13, 3); + FAST_FLAG_SET(tevReg, b, 10, 3); + FAST_FLAG_SET(tevReg, c, 7, 3); + FAST_FLAG_SET(tevReg, d, 4, 3); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(tevReg); + + __GXData->teva[stage] = tevReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, + GXBool doClamp, GXTevRegID outReg) { + u32 tevReg; + + tevReg = __GXData->tevc[stage]; + FAST_FLAG_SET(tevReg, op & 1, 18, 1); + + if (op <= 1) { + FAST_FLAG_SET(tevReg, scale, 20, 2); + FAST_FLAG_SET(tevReg, bias, 16, 2); + } else { + FAST_FLAG_SET(tevReg, (op >> 1) & 3, 20, 2); + FAST_FLAG_SET(tevReg, 3, 16, 2); + } + + FAST_FLAG_SET(tevReg, doClamp, 19, 1); + FAST_FLAG_SET(tevReg, outReg, 22, 2); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(tevReg); + __GXData->tevc[stage] = tevReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, + GXBool doClamp, GXTevRegID outReg) { + u32 tevReg; + + tevReg = __GXData->teva[stage]; + FAST_FLAG_SET(tevReg, op & 1, 18, 1); + + if (op <= 1) { + FAST_FLAG_SET(tevReg, scale, 20, 2); + FAST_FLAG_SET(tevReg, bias, 16, 2); + } else { + FAST_FLAG_SET(tevReg, (op >> 1) & 3, 20, 2); + FAST_FLAG_SET(tevReg, 3, 16, 2); + } + + FAST_FLAG_SET(tevReg, doClamp, 19, 1); + FAST_FLAG_SET(tevReg, outReg, 22, 2); + + GX_WRITE_U8(0x61); + GX_WRITE_U32(tevReg); + __GXData->teva[stage] = tevReg; + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevColor(GXTevRegID reg, GXColor color) { + u32 col = *(u32*)&color; + u32 ra = (0xE0 + reg * 2) << 24; + u32 bg = (0xE1 + reg * 2) << 24; + + GX_SET_REG(ra, col >> 24, 24, 31); + GX_SET_REG(bg, col >> 8, 24, 31); + GX_SET_REG(bg, col >> 16, 12, 19); + GX_SET_REG(ra, col & 0xFF, 12, 19); + + GX_BP_LOAD_REG(ra); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevColorS10(GXTevRegID reg, GXColorS10 color) { + u32 col = *(u32*)&color; + u32 col1 = ((u32*)&color)[1]; + u32 ra = (0xE0 + reg * 2) << 24; + u32 bg = (0xE1 + reg * 2) << 24; + + GX_SET_REG(ra, col >> 16, 21, 31); + GX_SET_REG(bg, col1 >> 16, 21, 31); + GX_SET_REG(bg, col & 0x7FF, 9, 19); + GX_SET_REG(ra, col1 & 0x7FF, 9, 19); + + GX_BP_LOAD_REG(ra); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + GX_BP_LOAD_REG(bg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevKColor(GXTevKColorID id, GXColor color) { + u32 col = *(u32*)&color; + u32 ra; + u32 bg; + + ra = (0xE0 + id * 2) << 24; + GX_SET_REG(ra, col >> 24, 24, 31); + GX_SET_REG(ra, col & 0xFF, 12, 19); + GX_SET_REG(ra, 8, 8, 11); + + bg = (0xE1 + id * 2) << 24; + GX_SET_REG(bg, col >> 8, 24, 31); + GX_SET_REG(bg, col >> 16, 12, 19); + GX_SET_REG(bg, 8, 8, 11); + + GX_BP_LOAD_REG(ra); + GX_BP_LOAD_REG(bg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) { + u32* reg; + + reg = &__GXData->tevKsel[stage >> 1]; + + if (stage & 1) { + GX_SET_REG(*reg, sel, 13, 17); + } else { + GX_SET_REG(*reg, sel, 23, 27); + } + + GX_BP_LOAD_REG(*reg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) { + u32* reg; + + reg = &__GXData->tevKsel[stage >> 1]; + + if (stage & 1) { + GX_SET_REG(*reg, sel, 8, 12); + } else { + GX_SET_REG(*reg, sel, 18, 22); + } + + GX_BP_LOAD_REG(*reg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel rasSel, GXTevSwapSel texSel) { + u32* reg = &__GXData->teva[stage]; + GX_SET_REG(*reg, rasSel, 30, 31); + GX_SET_REG(*reg, texSel, 28, 29); + + GX_BP_LOAD_REG(*reg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorChan green, + GXTevColorChan blue, GXTevColorChan alpha) { + u32* reg; + + reg = &__GXData->tevKsel[table << 1]; + GX_SET_REG(*reg, red, 30, 31); + GX_SET_REG(*reg, green, 28, 29); + + GX_BP_LOAD_REG(*reg); + + reg = &__GXData->tevKsel[(table << 1) + 1]; + GX_SET_REG(*reg, blue, 30, 31); + GX_SET_REG(*reg, alpha, 28, 29); + + GX_BP_LOAD_REG(*reg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) { + u32 reg = 0xF3000000; + + GX_SET_REG(reg, ref0, 24, 31); + GX_SET_REG(reg, ref1, 16, 23); + GX_SET_REG(reg, comp0, 13, 15); + GX_SET_REG(reg, comp1, 10, 12); + GX_SET_REG(reg, op, 8, 9); + + GX_BP_LOAD_REG(reg); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetZTexture(GXZTexOp op, GXTexFmt format, u32 bias) { + u32 val1; + u32 val2; + u32 val3; + + val1 = 0; + GX_SET_REG(val1, bias, 8, 31); + GX_SET_REG(val1, 0xF4, 0, 7); + + val2 = 0; + switch (format) { + case GX_TF_Z8: + val3 = 0; + break; + case GX_TF_Z16: + val3 = 1; + break; + case GX_TF_Z24X8: + val3 = 2; + break; + default: + val3 = 2; + break; + } + + GX_SET_REG(val2, val3, 30, 31); + GX_SET_REG(val2, op, 28, 29); + GX_SET_REG(val2, 0xF5, 0, 7); + + GX_BP_LOAD_REG(val1); + + GX_BP_LOAD_REG(val2); + + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXChannelID color) { + static int c2r[] = {0, 1, 0, 1, 0, 1, 7, 5, 6}; + + u32* reg; + u32 tempMap; + u32 tempCoord; + + reg = &__GXData->tref[stage / 2]; + __GXData->texmapId[stage] = map; + + tempMap = map & ~0x100; + tempMap = (tempMap >= GX_MAX_TEXMAP) ? GX_TEXMAP0 : tempMap; + + if (coord >= GX_MAXCOORD) { + tempCoord = GX_TEXCOORD0; + __GXData->tevTcEnab = __GXData->tevTcEnab & ~(1 << stage); + } else { + tempCoord = coord; + __GXData->tevTcEnab = __GXData->tevTcEnab | (1 << stage); + } + + if (stage & 1) { + GX_SET_REG(*reg, tempMap, 17, 19); + GX_SET_REG(*reg, tempCoord, 14, 16); + GX_SET_REG(*reg, (color == GX_COLOR_NULL ? 7 : c2r[color]), 10, 12); + GX_SET_REG(*reg, ((map != GX_TEXMAP_NULL) && !(map & 0x100)), 13, 13); + + } else { + GX_SET_REG(*reg, tempMap, 29, 31); + GX_SET_REG(*reg, tempCoord, 26, 28); + GX_SET_REG(*reg, (color == GX_COLOR_NULL ? 7 : c2r[color]), 22, 24); + GX_SET_REG(*reg, ((map != GX_TEXMAP_NULL) && !(map & 0x100)), 25, 25); + } + + GX_BP_LOAD_REG(*reg); + + __GXData->bpSentNot = GX_FALSE; + __GXData->dirtyState |= 1; +} + +void GXSetNumTevStages(u8 count) { + GX_SET_REG(__GXData->genMode, count - 1, 18, 21); + + __GXData->dirtyState |= 0x4; +} diff --git a/src/dolphin/gx/GXTexture.c b/src/dolphin/gx/GXTexture.c new file mode 100644 index 00000000..e4b8485d --- /dev/null +++ b/src/dolphin/gx/GXTexture.c @@ -0,0 +1,593 @@ +#include "dolphin/gx/GXTexture.h" +#include "dolphin/gx/GX.h" + +#define GET_TILE_COUNT(a, b) (((a) + (1 << (b)) - 1) >> (b)) + +inline void __GXGetTexTileShift(GXTexFmt format, u32* widthTiles, u32* heightTiles) { + switch (format) { + case GX_TF_I4: + case GX_TF_C4: + case GX_TF_CMPR: + case GX_CTF_R4: + case GX_CTF_Z4: + *widthTiles = 3; + *heightTiles = 3; + break; + + case GX_TF_I8: + case GX_TF_IA4: + case GX_TF_C8: + case GX_TF_Z8: + case GX_CTF_RA4: + case GX_CTF_R8: + case GX_CTF_G8: + case GX_CTF_B8: + case GX_CTF_RG8: + case GX_CTF_Z8M: + case GX_CTF_Z8L: + *widthTiles = 3; + *heightTiles = 2; + break; + + case GX_TF_IA8: + case GX_TF_RGB565: + case GX_TF_RGB5A3: + case GX_TF_RGBA8: + case GX_TF_C14X2: + case GX_TF_Z16: + case GX_TF_Z24X8: + case GX_CTF_RA8: + case GX_CTF_GB8: + case 44: + case GX_CTF_Z16L: + *widthTiles = 2; + *heightTiles = 2; + break; + + default: + *heightTiles = 0; + *widthTiles = 0; + break; + } +} + +u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod) { + u32 widthTiles, heightTiles, tileSize, bufferSize, numX, numY, i; + + __GXGetTexTileShift(format, &widthTiles, &heightTiles); + + if (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) { + tileSize = 0x40; + } else { + tileSize = 0x20; + } + + if (mipmap == GX_TRUE) { + bufferSize = 0; + + for (i = 0; i < max_lod; i++) { + numX = GET_TILE_COUNT(width, widthTiles); + numY = GET_TILE_COUNT(height, heightTiles); + + bufferSize += numX * numY * tileSize; + if (width == 1 && height == 1) { + break; + } + + width = (width > 1) ? (width >> 1) : 1; + height = (height > 1) ? (height >> 1) : 1; + } + + } else { + numX = GET_TILE_COUNT(width, widthTiles); + numY = GET_TILE_COUNT(height, heightTiles); + bufferSize = numX * numY * tileSize; + } + + return bufferSize; +} + +void __GetImageTileCount(GXTexFmt format, u16 width, u16 height, u32* a, u32* b, u32* c) { + u32 widthTiles, heightTiles; + + __GXGetTexTileShift(format, &widthTiles, &heightTiles); + + if (width <= 0) { + width = 1; + } + + if (height <= 0) { + height = 1; + } + + *a = GET_TILE_COUNT(width, widthTiles); + *b = GET_TILE_COUNT(height, heightTiles); + *c = (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) ? 2 : 1; +} + +void GXInitTexObj(GXTexObj* obj, void* imagePtr, u16 width, u16 height, GXTexFmt format, + GXTexWrapMode sWrap, GXTexWrapMode tWrap, GXBool useMIPmap) { + u32 imageBase; + u16 a, b; + u32 c, d; + + GXTexObj* internal = (GXTexObj*)obj; + memset(internal, 0, sizeof(*internal)); + + GX_SET_REG(internal->texture_filter, sWrap, 30, 31); + GX_SET_REG(internal->texture_filter, tWrap, 28, 29); + GX_SET_REG(internal->texture_filter, GX_TRUE, 27, 27); + + if (useMIPmap) { + u32 maxDimSize; + internal->texture_flags |= 1; + if (format == 8 || format == 9 || format == 10) { + GX_SET_REG(internal->texture_filter, 5, 24, 26); + } else { + GX_SET_REG(internal->texture_filter, 6, 24, 26); + } + + maxDimSize = width > height ? 31 - __cntlzw(width) : 31 - __cntlzw(height); + + GX_SET_REG(internal->texture_lod, (maxDimSize) * 16.f, 16, 23); + } else { + GX_SET_REG(internal->texture_filter, 4, 24, 26); + } + + internal->texture_format = format; + GX_SET_REG(internal->texture_size, width - 1, 22, 31); + GX_SET_REG(internal->texture_size, height - 1, 12, 21); + + GX_SET_REG(internal->texture_size, format & 0xf, 8, 11); + imageBase = (u32)imagePtr >> 5; + GX_SET_REG(internal->texture_address, imageBase, 11, 31); + + switch (format & 0xf) { + case 0: + case 8: + internal->texture_tile_type = 1; + a = 3; + b = 3; + break; + case 1: + case 2: + case 9: + internal->texture_tile_type = 2; + a = 3; + b = 2; + break; + case 3: + case 4: + case 5: + case 10: + internal->texture_tile_type = 2; + a = 2; + b = 2; + break; + case 6: + internal->texture_tile_type = 3; + a = 2; + b = 2; + break; + case 0xe: + internal->texture_tile_type = 0; + a = 3; + b = 3; + break; + default: + internal->texture_tile_type = 2; + a = 2; + b = 2; + break; + } + + internal->texture_time_count = (GET_TILE_COUNT(width, a) * GET_TILE_COUNT(height, b)) & 0x7fff; + + internal->texture_flags |= 2; +} + +void GXInitTexObjCI(GXTexObj* obj, void* imagePtr, u16 width, u16 height, GXCITexFmt format, + GXTexWrapMode sWrap, GXTexWrapMode tWrap, GXBool useMIPmap, u32 tlut_name) { + GXTexObj* internal = (GXTexObj*)obj; + + GXInitTexObj(obj, imagePtr, width, height, format, sWrap, tWrap, useMIPmap); + + internal->texture_flags &= ~2; + internal->tlut_name = tlut_name; +} + +u8 GXTexMode0Ids[8] = {0x80, 0x81, 0x82, 0x83, 0xA0, 0xA1, 0xA2, 0xA3}; + +u8 GXTexMode1Ids[8] = {0x84, 0x85, 0x86, 0x87, 0xA4, 0xA5, 0xA6, 0xA7}; + +u8 GXTexImage0Ids[8] = {0x88, 0x89, 0x8a, 0x8b, 0xA8, 0xA9, 0xAa, 0xAb}; + +u8 GXTexImage1Ids[8] = {0x8c, 0x8d, 0x8e, 0x8f, 0xAc, 0xAd, 0xAe, 0xAf}; + +u8 GXTexImage2Ids[8] = {0x90, 0x91, 0x92, 0x93, 0xB0, 0xB1, 0xB2, 0xB3}; + +u8 GXTexImage3Ids[8] = {0x94, 0x95, 0x96, 0x97, 0xB4, 0xB5, 0xB6, 0xB7}; + +u8 GXTexTlutIds[8] = {0x98, 0x99, 0x9a, 0x9b, 0xB8, 0xB9, 0xBa, 0xBb}; + +u8 GX2HWFiltConv[6] = {0x00, 0x04, 0x01, 0x05, 0x02, 0x06}; + +void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilter, GXTexFilter maxFilter, f32 minLOD, + f32 maxLOD, f32 lodBias, GXBool doBiasClamp, GXBool doEdgeLOD, + GXAnisotropy maxAniso) { + GXTexObj* internal = (GXTexObj*)obj; + u8 reg1, reg2; + if (lodBias < -4.0f) { + lodBias = -4.0f; + } else if (lodBias >= 4.0f) { + lodBias = 3.99f; + } + + GX_SET_REG(internal->texture_filter, lodBias * 32.0f, 15, 22); + GX_SET_REG(internal->texture_filter, maxFilter == 1 ? 1 : 0, 27, 27); + GX_SET_REG(internal->texture_filter, GX2HWFiltConv[minFilter], 24, 26); + GX_SET_REG(internal->texture_filter, doEdgeLOD ? 0 : 1, 23, 23); + GX_SET_REG(internal->texture_filter, 0, 14, 14); + GX_SET_REG(internal->texture_filter, 0, 13, 13); + GX_SET_REG(internal->texture_filter, maxAniso, 11, 12); + GX_SET_REG(internal->texture_filter, doBiasClamp, 10, 10); + + if (minLOD < 0.0f) { + minLOD = 0.0f; + } else if (minLOD > 10.0f) { + minLOD = 10.0f; + } + reg1 = minLOD * 16.0f; + + if (maxLOD < 0.0f) { + maxLOD = 0.0f; + } else if (maxLOD > 10.0f) { + maxLOD = 10.0f; + } + reg2 = maxLOD * 16.0f; + + GX_SET_REG(internal->texture_lod, reg1, 24, 31); + GX_SET_REG(internal->texture_lod, reg2, 16, 23); +} + +u16 GXGetTexObjWidth(GXTexObj* obj) { + return (obj->texture_size & 0x3ff) + 1; +} + +u16 GXGetTexObjHeight(GXTexObj* obj) { + return ((obj->texture_size >> 10) & 0x3ff) + 1; +} + +GXTexFmt GXGetTexObjFmt(const GXTexObj* obj) { + return obj->texture_format; +} + +GXTexWrapMode GXGetTexObjWrapS(GXTexObj* obj) { + return obj->texture_filter & 0x3; +} + +GXTexWrapMode GXGetTexObjWrapT(GXTexObj* obj) { + return (obj->texture_filter & 0xc) >> 2; +} + +GXBool GXGetTexObjMipMap(const GXTexObj* obj) { + return (obj->texture_flags & 1) == 1; +} + +u32 GXGetTexObjTlut(GXTexObj* obj) { + return obj->tlut_name; +} + +void GXLoadTexObjPreLoaded(GXTexObj* obj, GXTexRegion* region, GXTexMapID map) { + u8 stackManipulation[0x18]; + + GXTexObj* internalObj = (GXTexObj*)obj; + GXTexRegion* internalRegion = (GXTexRegion*)region; + + GX_SET_REG(internalObj->texture_filter, GXTexMode0Ids[map], 0, 7); + GX_SET_REG(internalObj->texture_lod, GXTexMode1Ids[map], 0, 7); + GX_SET_REG(internalObj->texture_size, GXTexImage0Ids[map], 0, 7); + + GX_SET_REG(internalRegion->unk0, GXTexImage1Ids[map], 0, 7); + GX_SET_REG(internalRegion->unk4, GXTexImage2Ids[map], 0, 7); + + GX_SET_REG(internalObj->texture_address, GXTexImage3Ids[map], 0, 7); + + GX_BP_LOAD_REG(internalObj->texture_filter); + GX_BP_LOAD_REG(internalObj->texture_lod); + GX_BP_LOAD_REG(internalObj->texture_size); + GX_BP_LOAD_REG(internalRegion->unk0); + GX_BP_LOAD_REG(internalRegion->unk4); + GX_BP_LOAD_REG(internalObj->texture_address); + + if ((internalObj->texture_flags & 2) == 0) { + GXTlutObj* tlut = (GXTlutObj*)__GXData->tlutRegionCallback(internalObj->tlut_name); + GX_SET_REG(tlut->address, GXTexTlutIds[map], 0, 7); + + GX_BP_LOAD_REG(tlut->address); + } + + __GXData->tImage0[map] = internalObj->texture_size; + __GXData->tMode0[map] = internalObj->texture_filter; + + __GXData->dirtyState |= GX_DIRTY_SU_TEX; + __GXData->bpSentNot = GX_FALSE; +} + +void GXLoadTexObj(GXTexObj* obj, GXTexMapID map) { + GXTexRegion* ret = (GXTexRegion*)__GXData->texRegionCallback(obj, map); + + GXLoadTexObjPreLoaded(obj, ret, map); +} + +void GXInitTlutObj(GXTlutObj* obj, void* table, GXTlutFmt format, u16 numEntries) { + GXTlutObj* internal = (GXTlutObj*)obj; + + internal->format = 0; + + GX_SET_REG(internal->format, format, 20, 21); + GX_SET_REG(internal->address, (u32)table >> 5, 11, 31); + GX_SET_REG(internal->address, 100, 0, 7); + + internal->numEntries = numEntries; +} + +void GXLoadTlut(GXTlutObj* obj, u32 tlut_name) { + GXTlutObj* internal = (GXTlutObj*)obj; + GXTlutRegion* ret = (GXTlutRegion*)__GXData->tlutRegionCallback(tlut_name); + u32 reg; + + __GXFlushTextureState(); + + GX_BP_LOAD_REG(internal->address); + GX_BP_LOAD_REG(ret->unk0); + + __GXFlushTextureState(); + + reg = ret->unk0; + GX_SET_REG(internal->format, reg, 22, 31); + + ret->tlutObj = *internal; +} + +void GXInitTexCacheRegion(GXTexRegion* region, GXBool is32bMIPmap, u32 memEven, + GXTexCacheSize sizeEven, u32 memOdd, GXTexCacheSize sizeOdd) { + GXTexRegion* internal = (GXTexRegion*)region; + + u32 reg; + switch (sizeEven) { + case 0: + reg = 3; + break; + case 1: + reg = 4; + break; + case 2: + reg = 5; + break; + } + + internal->unk0 = 0; + + GX_SET_REG(internal->unk0, memEven >> 5, 17, 31); + GX_SET_REG(internal->unk0, reg, 14, 16); + GX_SET_REG(internal->unk0, reg, 11, 13); + GX_SET_REG(internal->unk0, 0, 10, 10); + + switch (sizeOdd) { + case 0: + reg = 3; + break; + case 1: + reg = 4; + break; + case 2: + reg = 5; + break; + case 3: + reg = 0; + break; + } + + internal->unk4 = 0; + GX_SET_REG(internal->unk4, memOdd >> 5, 17, 31); + GX_SET_REG(internal->unk4, reg, 14, 16); + GX_SET_REG(internal->unk4, reg, 11, 13); + + internal->unkC = is32bMIPmap; + internal->unkD = 1; +} + +void GXInitTlutRegion(GXTlutRegion* region, u32 memAddr, GXTlutSize tlutSize) { + GXTlutRegion* internal = (GXTlutRegion*)region; + + internal->unk0 = 0; + GX_SET_REG(internal->unk0, (memAddr - 0x80000) >> 9, 22, 31); + GX_SET_REG(internal->unk0, tlutSize, 11, 21); + GX_SET_REG(internal->unk0, 0x65, 0, 7); +} + +void GXInvalidateTexAll(void) { + __GXFlushTextureState(); + GXFIFO.u8 = 0x61; + GXFIFO.u32 = 0x66001000; + GXFIFO.u8 = 0x61; + GXFIFO.u32 = 0x66001100; + __GXFlushTextureState(); +} + +GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback callback) { + GXTexRegionCallback prev = __GXData->texRegionCallback; + __GXData->texRegionCallback = callback; + return prev; +} + +GXTlutRegionCallback GXSetTlutRegionCallback(GXTlutRegionCallback callback) { + GXTlutRegionCallback prev = __GXData->tlutRegionCallback; + __GXData->tlutRegionCallback = callback; + return prev; +} + +void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 s_scale, u16 t_scale) { + /* Nonmatching */ +} + +void __SetSURegs(u32 texImgIndex, u32 setUpRegIndex) { + u16 a1, a2; + GXBool b, c; + + a1 = GX_GET_REG(__GXData->tImage0[texImgIndex], 22, 31); + a2 = (__GXData->tImage0[texImgIndex] & (0x3ff << 10)) >> 10; + + GX_SET_REG(__GXData->suTs0[setUpRegIndex], a1, 16, 31); + GX_SET_REG(__GXData->suTs1[setUpRegIndex], a2, 16, 31); + + b = GX_GET_REG(__GXData->tMode0[texImgIndex], 30, 31) == 1; + c = GX_GET_REG(__GXData->tMode0[texImgIndex], 28, 29) == 1; + + GX_SET_REG(__GXData->suTs0[setUpRegIndex], b, 15, 15); + GX_SET_REG(__GXData->suTs1[setUpRegIndex], c, 15, 15); + + GX_BP_LOAD_REG(__GXData->suTs0[setUpRegIndex]); + GX_BP_LOAD_REG(__GXData->suTs1[setUpRegIndex]); + + __GXData->bpSentNot = GX_FALSE; +} + +#pragma dont_inline on +void __GXSetSUTexRegs(void) { + u32 i; + u32 b; + u32 a; + u32 c; + u32 d; + u32 stackFiller; + if (__GXData->tcsManEnab != 0xff) { + a = GX_GET_REG(__GXData->genMode, 18, 21) + 1; + b = GX_GET_REG(__GXData->genMode, 13, 15); + for (i = 0; i < b; i++) { + switch (i) { + case 0: + c = GX_GET_REG(__GXData->iref, 29, 31); + d = GX_GET_REG(__GXData->iref, 26, 28); + break; + case 1: + c = GX_GET_REG(__GXData->iref, 23, 25); + d = GX_GET_REG(__GXData->iref, 20, 22); + break; + case 2: + c = GX_GET_REG(__GXData->iref, 17, 19); + d = GX_GET_REG(__GXData->iref, 14, 16); + break; + case 3: + c = GX_GET_REG(__GXData->iref, 11, 13); + d = GX_GET_REG(__GXData->iref, 8, 10); + break; + } + + if (!(__GXData->tcsManEnab & (1 << d))) { + __SetSURegs(c, d); + } + } + + for (i = 0; i < a; i++) { + u32* g = &__GXData->tref[i / 2]; + + c = __GXData->texmapId[i] & ~0x100; + + if (i & 1) { + d = GX_GET_REG(*g, 14, 16); + } else { + d = GX_GET_REG(*g, 26, 28); + } + + if (c != 0xff && !(__GXData->tcsManEnab & (1 << d)) && __GXData->tevTcEnab & (1 << i)) { + __SetSURegs(c, d); + } + } + } +} +#pragma dont_inline reset + +void __GXSetTmemConfig(u32 config) { + switch (config) { + case 2: + GX_BP_LOAD_REG(0x8c0d8000); + GX_BP_LOAD_REG(0x900dc000); + + GX_BP_LOAD_REG(0x8d0d8800); + GX_BP_LOAD_REG(0x910dc800); + + GX_BP_LOAD_REG(0x8e0d9000); + GX_BP_LOAD_REG(0x920dd000); + + GX_BP_LOAD_REG(0x8f0d9800); + GX_BP_LOAD_REG(0x930dd800); + + GX_BP_LOAD_REG(0xac0da000); + GX_BP_LOAD_REG(0xb00dc400); + + GX_BP_LOAD_REG(0xad0da800); + GX_BP_LOAD_REG(0xb10dcc00); + + GX_BP_LOAD_REG(0xae0db000); + GX_BP_LOAD_REG(0xb20dd400); + + GX_BP_LOAD_REG(0xaf0db800); + GX_BP_LOAD_REG(0xb30ddc00); + break; + case 1: + GX_BP_LOAD_REG(0x8c0d8000); + GX_BP_LOAD_REG(0x900dc000); + + GX_BP_LOAD_REG(0x8d0d8800); + GX_BP_LOAD_REG(0x910dc800); + + GX_BP_LOAD_REG(0x8e0d9000); + GX_BP_LOAD_REG(0x920dd000); + + GX_BP_LOAD_REG(0x8f0d9800); + GX_BP_LOAD_REG(0x930dd800); + + GX_BP_LOAD_REG(0xac0da000); + GX_BP_LOAD_REG(0xb00de000); + + GX_BP_LOAD_REG(0xad0da800); + GX_BP_LOAD_REG(0xb10de800); + + GX_BP_LOAD_REG(0xae0db000); + GX_BP_LOAD_REG(0xb20df000); + + GX_BP_LOAD_REG(0xaf0db800); + GX_BP_LOAD_REG(0xb30df800); + + break; + case 0: + default: + GX_BP_LOAD_REG(0x8c0d8000); + GX_BP_LOAD_REG(0x900dc000); + + GX_BP_LOAD_REG(0x8d0d8400); + GX_BP_LOAD_REG(0x910dc400); + + GX_BP_LOAD_REG(0x8e0d8800); + GX_BP_LOAD_REG(0x920dc800); + + GX_BP_LOAD_REG(0x8f0d8c00); + GX_BP_LOAD_REG(0x930dcc00); + + GX_BP_LOAD_REG(0xac0d9000); + GX_BP_LOAD_REG(0xb00dd000); + + GX_BP_LOAD_REG(0xad0d9400); + GX_BP_LOAD_REG(0xb10dd400); + + GX_BP_LOAD_REG(0xae0d9800); + GX_BP_LOAD_REG(0xb20dd800); + + GX_BP_LOAD_REG(0xaf0d9c00); + GX_BP_LOAD_REG(0xb30ddc00); + + break; + } +} diff --git a/src/dolphin/gx/GXTransform.c b/src/dolphin/gx/GXTransform.c new file mode 100644 index 00000000..1bf66bbb --- /dev/null +++ b/src/dolphin/gx/GXTransform.c @@ -0,0 +1,316 @@ +#include "dolphin/gx/GXTransform.h" +#include "dolphin/gx/GX.h" +#include "dolphin/os/OS.h" + +void __GXSetMatrixIndex(); + +static void Copy6Floats(register f32 src[6], register f32 dst[6]) { + register f32 ps_0, ps_1, ps_2; + + // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 8(dst), 0, 0 + psq_st ps_2, 16(dst), 0, 0 + } + // clang-format on +} + +static void WriteProjPS(const register f32 src[6], register volatile void* dst) { + register f32 ps_0, ps_1, ps_2; + + // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 0(dst), 0, 0 + psq_st ps_2, 0(dst), 0, 0 + } + // clang-format on +} + +void GXProject(f32 model_x, f32 model_y, f32 model_z, Mtx model_mtx, f32* proj_mtx, f32* viewpoint, + f32* screen_x, f32* screen_y, f32* screen_z) { + f32 sp10[3]; + f32 var_f30; + f32 var_f29; + f32 var_f28; + f32 var_f31; + + ASSERTMSG(proj_mtx != NULL && viewpoint != NULL && screen_x != NULL && screen_y != NULL && screen_z != NULL, "GXGet*: invalid null pointer"); + + sp10[0] = (model_mtx[0][0] * model_x) + (model_mtx[0][1] * model_y) + + (model_mtx[0][2] * model_z) + model_mtx[0][3]; + sp10[1] = (model_mtx[1][0] * model_x) + (model_mtx[1][1] * model_y) + + (model_mtx[1][2] * model_z) + model_mtx[1][3]; + sp10[2] = (model_mtx[2][0] * model_x) + (model_mtx[2][1] * model_y) + + (model_mtx[2][2] * model_z) + model_mtx[2][3]; + + if (proj_mtx[0] == 0.0f) { + var_f30 = (sp10[0] * proj_mtx[1]) + (sp10[2] * proj_mtx[2]); + var_f29 = (sp10[1] * proj_mtx[3]) + (sp10[2] * proj_mtx[4]); + var_f28 = proj_mtx[6] + (sp10[2] * proj_mtx[5]); + var_f31 = 1.0f / -sp10[2]; + } else { + var_f30 = proj_mtx[2] + (sp10[0] * proj_mtx[1]); + var_f29 = proj_mtx[4] + (sp10[1] * proj_mtx[3]); + var_f28 = proj_mtx[6] + (sp10[2] * proj_mtx[5]); + var_f31 = 1.0f; + } + + *screen_x = (viewpoint[2] / 2) + (viewpoint[0] + (var_f31 * (var_f30 * viewpoint[2] / 2))); + *screen_y = (viewpoint[3] / 2) + (viewpoint[1] + (var_f31 * (-var_f29 * viewpoint[3] / 2))); + *screen_z = viewpoint[5] + (var_f31 * (var_f28 * (viewpoint[5] - viewpoint[4]))); +} + +void __GXSetProjection(void) { + GX_XF_LOAD_REGS(6, GX_XF_REG_PROJECTIONA); + WriteProjPS(__GXData->projMtx, (volatile void*)GXFIFO_ADDR); + GX_WRITE_U32(__GXData->projType); +} + +void GXSetProjection(const Mtx44 proj, GXProjectionType type) { + volatile void* fifo; + __GXData->projType = type; + + __GXData->projMtx[0] = proj[0][0]; + __GXData->projMtx[2] = proj[1][1]; + __GXData->projMtx[4] = proj[2][2]; + __GXData->projMtx[5] = proj[2][3]; + + if (type == GX_ORTHOGRAPHIC) { + __GXData->projMtx[1] = proj[0][3]; + __GXData->projMtx[3] = proj[1][3]; + } else { + __GXData->projMtx[1] = proj[0][2]; + __GXData->projMtx[3] = proj[1][2]; + } + + __GXSetProjection(); + + __GXData->bpSentNot = GX_TRUE; +} + +void GXSetProjectionv(f32* proj) { + __GXData->projType = proj[0] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC; + Copy6Floats(&proj[1], __GXData->projMtx); + + __GXSetProjection(); + __GXData->bpSentNot = GX_TRUE; +} + +void GXGetProjectionv(f32* proj) { + *proj = (u32)__GXData->projType != GX_PERSPECTIVE ? 1.0f : 0.0f; + Copy6Floats(__GXData->projMtx, &proj[1]); +} + +static void WriteMTXPS4x3(register volatile void* dst, register const Mtx src) { + register f32 ps_0, ps_1, ps_2, ps_3, ps_4, ps_5; + + // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_l ps_3, 24(src), 0, 0 + psq_l ps_4, 32(src), 0, 0 + psq_l ps_5, 40(src), 0, 0 + + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 0(dst), 0, 0 + psq_st ps_2, 0(dst), 0, 0 + psq_st ps_3, 0(dst), 0, 0 + psq_st ps_4, 0(dst), 0, 0 + psq_st ps_5, 0(dst), 0, 0 + } + // clang-format on +} + +void GXLoadPosMtxImm(Mtx mtx, u32 id) { + GX_XF_LOAD_REGS(4 * 3 - 1, id * 4 + GX_XF_MEM_POSMTX); + WriteMTXPS4x3(&GXFIFO, mtx); +} + +static void WriteMTXPS3x3(register volatile void* dst, register const Mtx src) { + register f32 ps_0, ps_1, ps_2, ps_3, ps_4, ps_5; + + // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + lfs ps_1, 8(src) + psq_l ps_2, 16(src), 0, 0 + lfs ps_3, 24(src) + psq_l ps_4, 32(src), 0, 0 + lfs ps_5, 40(src) + + psq_st ps_0, 0(dst), 0, 0 + stfs ps_1, 0(dst) + psq_st ps_2, 0(dst), 0, 0 + stfs ps_3, 0(dst) + psq_st ps_4, 0(dst), 0, 0 + stfs ps_5, 0(dst) + } + // clang-format on +} + +void GXLoadNrmMtxImm(Mtx mtx, u32 id) { + GX_XF_LOAD_REGS(3 * 3 - 1, id * 3 + GX_XF_MEM_NRMMTX); + WriteMTXPS3x3(&GXFIFO, mtx); +} + +void GXSetCurrentMtx(u32 id) { + GX_SET_REG(__GXData->matIdxA, id, GX_XF_MTXIDX0_GEOM_ST, GX_XF_MTXIDX0_GEOM_END); + __GXSetMatrixIndex(GX_VA_PNMTXIDX); +} + +static void WriteMTXPS4x2(register volatile void* dst, register const Mtx src) { + register f32 ps_0, ps_1, ps_2, ps_3; + + // clang-format off + asm { + psq_l ps_0, 0(src), 0, 0 + psq_l ps_1, 8(src), 0, 0 + psq_l ps_2, 16(src), 0, 0 + psq_l ps_3, 24(src), 0, 0 + + psq_st ps_0, 0(dst), 0, 0 + psq_st ps_1, 0(dst), 0, 0 + psq_st ps_2, 0(dst), 0, 0 + psq_st ps_3, 0(dst), 0, 0 + } + // clang-format on +} + +void GXLoadTexMtxImm(const Mtx mtx, u32 id, GXTexMtxType type) { + u32 addr; + u32 num; + u32 reg; + + // Matrix address in XF memory + addr = id >= GX_PTTEXMTX0 ? (id - GX_PTTEXMTX0) * 4 + GX_XF_MEM_DUALTEXMTX : + id * 4 + (u64)GX_XF_MEM_POSMTX; + + // Number of elements in matrix + num = type == GX_MTX2x4 ? (u64)(2 * 4) : 3 * 4; + + reg = addr | (num - 1) << 16; + + GX_XF_LOAD_REG_HDR(reg); + + if (type == GX_MTX3x4) { + WriteMTXPS4x3(&GXFIFO, mtx); + } else { + WriteMTXPS4x2(&GXFIFO, mtx); + } +} + +void __GXSetViewport(void) { + f32 a, b, c, d, e, f; + f32 near, far; + + a = __GXData->vpWd / 2; + b = -__GXData->vpHt / 2; + d = __GXData->vpLeft + (__GXData->vpWd / 2) + 342.0f; + e = __GXData->vpTop + (__GXData->vpHt / 2) + 342.0f; + + near = __GXData->vpNearz * __GXData->zScale; + far = __GXData->vpFarz * __GXData->zScale; + + c = far - near; + f = far + __GXData->zOffset; + + GX_XF_LOAD_REGS(5, GX_XF_REG_SCALEX); + GX_WRITE_F32(a); + GX_WRITE_F32(b); + GX_WRITE_F32(c); + GX_WRITE_F32(d); + GX_WRITE_F32(e); + GX_WRITE_F32(f); +} + +void GXSetViewport(f32 left, f32 top, f32 width, f32 height, f32 nearZ, f32 farZ) { + __GXData->vpLeft = left; + __GXData->vpTop = top; + __GXData->vpWd = width; + __GXData->vpHt = height; + __GXData->vpNearz = nearZ; + __GXData->vpFarz = farZ; + __GXSetViewport(); + __GXData->bpSentNot = GX_TRUE; +} + +void GXGetViewportv(f32* p) { + Copy6Floats(&__GXData->vpLeft, p); +} + +void GXSetScissor(u32 left, u32 top, u32 width, u32 height) { + u32 y1, x1, y2, x2; + u32 reg; + + y1 = top + 342; + x1 = left + 342; + + GX_SET_REG(__GXData->suScis0, y1, GX_BP_SCISSORTL_TOP_ST, GX_BP_SCISSORTL_TOP_END); + GX_SET_REG(__GXData->suScis0, x1, GX_BP_SCISSORTL_LEFT_ST, GX_BP_SCISSORTL_LEFT_END); + + y2 = y1 + height - 1; + x2 = (x1 + width) - 1; + + GX_SET_REG(__GXData->suScis1, y2, GX_BP_SCISSORBR_BOT_ST, GX_BP_SCISSORBR_BOT_END); + GX_SET_REG(__GXData->suScis1, x2, GX_BP_SCISSORBR_RIGHT_ST, GX_BP_SCISSORBR_RIGHT_END); + + GX_BP_LOAD_REG(__GXData->suScis0); + GX_BP_LOAD_REG(__GXData->suScis1); + __GXData->bpSentNot = FALSE; +} + +void GXGetScissor(u32* left, u32* top, u32* width, u32* height) { + u32 y1 = (__GXData->suScis0 & 0x0007FF) >> 0; + u32 x1 = (__GXData->suScis0 & 0x7FF000) >> 12; + u32 y2 = (__GXData->suScis1 & 0x0007FF) >> 0; + u32 x2 = (__GXData->suScis1 & 0x7FF000) >> 12; + + *left = x1 - 0x156; + *top = y1 - 0x156; + *width = (x2 - x1) + 1; + *height = (y2 - y1) + 1; +} + +void GXSetScissorBoxOffset(s32 x, s32 y) { + u32 cmd = 0; + u32 x1; + u32 y1; + + x1 = (u32)(x + 342) / 2; + y1 = (u32)(y + 342) / 2; + GX_SET_REG(cmd, x1, GX_BP_SCISSOROFS_OX_ST, GX_BP_SCISSOROFS_OX_END); + GX_SET_REG(cmd, y1, GX_BP_SCISSOROFS_OY_ST, GX_BP_SCISSOROFS_OY_END); + + GX_SET_REG(cmd, GX_BP_REG_SCISSOROFFSET, 0, 7); + + GX_BP_LOAD_REG(cmd); + __GXData->bpSentNot = GX_FALSE; +} + +void GXSetClipMode(GXClipMode mode) { + GX_XF_LOAD_REG(GX_XF_REG_CLIPDISABLE, mode); + __GXData->bpSentNot = GX_TRUE; +} + +void __GXSetMatrixIndex(GXAttr index) { + // Tex4 and after is stored in XF MatrixIndex1 + if (index < GX_VA_TEX4MTXIDX) { + GX_CP_LOAD_REG(GX_CP_REG_MTXIDXA, __GXData->matIdxA); + GX_XF_LOAD_REG(GX_XF_REG_MATRIXINDEX0, __GXData->matIdxA); + } else { + GX_CP_LOAD_REG(GX_CP_REG_MTXIDXB, __GXData->matIdxB); + GX_XF_LOAD_REG(GX_XF_REG_MATRIXINDEX1, __GXData->matIdxB); + } + + __GXData->bpSentNot = GX_TRUE; +} diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index 10618b76..9c84bb00 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -522,7 +522,7 @@ void drawDepth(view_class* view, view_port_class* viewport, int depth) { GXCopyTex(zbuf, GX_FALSE); GXSetTexCopySrc(x, y, w, h); - GXSetTexCopyDst(hw, hh, mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); + GXSetTexCopyDst(hw, hh, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE); GXCopyTex(fbbuf, GX_FALSE); GXInitTexObj(mDoGph_gInf_c::getZbufferTexObj(), zbuf, w, h, GX_TF_IA8, GX_CLAMP, GX_CLAMP, GX_FALSE); @@ -933,7 +933,7 @@ bool mDoGph_screenCapture() { setUpRectangle(); GXSetTexCopySrc(centerX - sizeW, centerY - sizeH, sizeW2, sizeH2); - GXSetTexCopyDst(sizeW, sizeH, mCaptureCaptureFormat, GX_TRUE); + GXSetTexCopyDst(sizeW, sizeH, (_GXTexFmt)mCaptureCaptureFormat, GX_TRUE); DCInvalidateRange(mCaptureCaptureBuffer, mCaptureCaptureSize); GXCopyTex(mCaptureCaptureBuffer, GX_FALSE); GXPixModeSync(); |
