#include "dolphin/gx/GXFrameBuf.h" #include "dolphin/gx.h" #include "dolphin/vi.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, }; /* 8035CA04-8035CA80 357344 007C+00 0/0 2/2 0/0 .text GXSetDispCopySrc */ 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); } /* 8035CA80-8035CAFC 3573C0 007C+00 0/0 9/9 0/0 .text GXSetTexCopySrc */ 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); } /* 8035CAFC-8035CB30 35743C 0034+00 0/0 2/2 0/0 .text GXSetDispCopyDst */ 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); } /* 8035CB30-8035CC60 357470 0130+00 0/0 9/9 0/0 .text GXSetTexCopyDst */ 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); } /* 8035CC60-8035CC84 3575A0 0024+00 0/0 1/1 0/0 .text GXSetDispCopyFrame2Field */ 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 /* 8035CC84-8035CCDC 3575C4 0058+00 0/0 2/2 0/0 .text GXSetCopyClamp */ 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; } /* 8035CCDC-8035CD6C 35761C 0090+00 0/0 2/2 0/0 .text GXGetNumXfbLines */ u16 GXGetNumXfbLines(const u16 efbHeight, f32 yScale) { u32 scale = (u32)(256.0f / yScale) & 0x1FF; return __GXGetNumXfbLines(efbHeight, scale); } /* 8035CD6C-8035CFA4 3576AC 0238+00 0/0 2/2 0/0 .text GXGetYScaleFactor */ 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; } /* 8035CFA4-8035D070 3578E4 00CC+00 0/0 2/2 0/0 .text GXSetDispCopyYScale */ 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); } /* 8035D070-8035D0E8 3579B0 0078+00 0/0 2/2 0/0 .text GXSetCopyClear */ 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); GXWGFifo.u8 = 0x61; GXWGFifo.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); GXWGFifo.u8 = 0x61; GXWGFifo.u32 = r6; r6 = 0; GX_BITFIELD_SET(r6, 8, 24, clear_z); GX_BITFIELD_SET(r6, 0, 8, 0x51); GXWGFifo.u8 = 0x61; GXWGFifo.u32 = r6; __GXData->bpSentNot = 0; } /* 8035D0E8-8035D2F0 357A28 0208+00 0/0 4/4 0/0 .text GXSetCopyFilter */ 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; } /* 8035D2F0-8035D304 357C30 0014+00 0/0 2/2 0/0 .text GXSetDispCopyGamma */ void GXSetDispCopyGamma(GXGamma gamma) { GX_BITFIELD_SET(__GXData->cpDisp, 23, 2, gamma); } /* 8035D304-8035D46C 357C44 0168+00 0/0 3/3 0/0 .text GXCopyDisp */ 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; } /* 8035D46C-8035D5F8 357DAC 018C+00 0/0 9/9 0/0 .text GXCopyTex */ 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; } /* 8035D5F8-8035D630 357F38 0038+00 0/0 1/1 0/0 .text GXClearBoundingBox */ void GXClearBoundingBox(void) { GXWGFifo.u8 = GX_LOAD_BP_REG; GXWGFifo.u32 = 0x550003FF; GXWGFifo.u8 = GX_LOAD_BP_REG; GXWGFifo.u32 = 0x560003FF; set_x2(GX_FALSE); }