diff --git a/include/dolphin/gx/GX.h b/include/dolphin/gx/GX.h index f8441f3cd..bbb29e653 100644 --- a/include/dolphin/gx/GX.h +++ b/include/dolphin/gx/GX.h @@ -22,27 +22,77 @@ extern "C" { // Pack value into bitfield #define GX_BITFIELD_SET(field, pos, size, value) (field) = __rlwimi((field), (value), 31 - (pos) - (size) + 1, (pos), (pos) + (size)-1) +#define GX_BITFIELD_TRUNC(field, pos, size, value) (__rlwimi((field), (value), 0, (pos), (pos) + (size)-1)) + +#define GX_BITGET(field, pos, size) ((field) >> (31 - (pos) - (size) + 1) & ((1 << (size)) - 1)) +#define GX_GET_REG(reg, st, end) GX_BITGET(reg, st, (end - st + 1)) +#define GX_SET_REG(reg, x, st, end) GX_BITFIELD_SET(reg, st, (end - st + 1), x) +#define GX_SET_TRUNC(reg, x, st, end) GX_BITFIELD_TRUNC((reg), (st), ((end) - (st) + 1), (x)) + +#define GXCOLOR_AS_U32(color) (*((u32*)&(color))) #define INSERT_FIELD(reg, value, nbits, shift) \ (reg) = ((u32) (reg) & ~(((1 << (nbits)) - 1) << (shift))) | \ ((u32) (value) << (shift)); +#define FAST_FLAG_SET(regOrg, newFlag, shift, size) \ + do { \ + (regOrg) = (u32)__rlwimi((int)(regOrg), (int)(newFlag), (shift), (32 - (shift) - (size)), (31 - (shift))); \ + } while (0); + +#define GX_LOAD_BP_REG 0x61 #define GX_NOP 0 typedef union { - u8 u8; - u16 u16; - u32 u32; - u64 u64; - s8 s8; - s16 s16; - s32 s32; - s64 s64; - f32 f32; - f64 f64; + u8 u8; + u16 u16; + u32 u32; + u64 u64; + s8 s8; + s16 s16; + s32 s32; + s64 s64; + f32 f32; + f64 f64; } PPCWGPipe; -volatile PPCWGPipe GXFIFO AT_ADDRESS(0xCC008000); +#define GXFIFO_ADDR 0xCC008000 +volatile PPCWGPipe GXFIFO AT_ADDRESS(GXFIFO_ADDR); + +#define GX_CP_LOAD_REG(addr, data) \ + GXFIFO.s8 = GX_FIFO_CMD_LOAD_CP_REG; \ + GXFIFO.s8 = (addr); \ + GXFIFO.s32 = (data); + +/** + * Header for an XF register load + */ +#define GX_XF_LOAD_REG_HDR(addr) \ + GXFIFO.s8 = GX_FIFO_CMD_LOAD_XF_REG; \ + GXFIFO.s32 = (addr); + +/** + * Load immediate value into XF register + */ +#define GX_XF_LOAD_REG(addr, data) \ + GX_XF_LOAD_REG_HDR(addr); \ + GXFIFO.s32 = (data); + +/** + * Load immediate value into BP register + */ +#define GX_BP_LOAD_REG(data) \ + GXFIFO.s8 = GX_FIFO_CMD_LOAD_BP_REG; \ + GXFIFO.s32 = (data); + +/** + * Load immediate values into multiple XF registers + */ +#define GX_XF_LOAD_REGS(size, addr) \ + { \ + u32 cmd = (size) << 16 | addr; \ + GX_XF_LOAD_REG_HDR(cmd); \ + } // Direct inline void GXPosition2f32(f32 x, f32 z) { @@ -118,8 +168,8 @@ inline void GXTexCoord2u16(u16 x, u16 y) { } inline void GXTexCoord2s16(const s16 u, const s16 v) { - GXFIFO.s16 = u; - GXFIFO.s16 = v; + GXFIFO.s16 = u; + GXFIFO.s16 = v; } // Indexed diff --git a/include/dolphin/gx/GXAttr.h b/include/dolphin/gx/GXAttr.h index 7cebd8d6f..bada1e08b 100644 --- a/include/dolphin/gx/GXAttr.h +++ b/include/dolphin/gx/GXAttr.h @@ -24,7 +24,7 @@ void GXSetVtxDescv(GXVtxDescList* list); void __GXSetVCD(void); void __GXCalculateVLim(void); void GXClearVtxDesc(void); -void GXSetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u32); +void GXSetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 frac); void GXSetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList* list); void __GXSetVAT(void); void GXSetArray(GXAttr attr, void* base, u8); diff --git a/include/dolphin/gx/GXEnum.h b/include/dolphin/gx/GXEnum.h index 0fa10cdbe..1cb56b150 100644 --- a/include/dolphin/gx/GXEnum.h +++ b/include/dolphin/gx/GXEnum.h @@ -228,29 +228,38 @@ typedef enum _GXAttr { } GXAttr; typedef enum _GXCompCnt { - /* 0x0 */ GX_POS_XY = 0, - /* 0x1 */ GX_POS_XYZ = 1, - /* 0x0 */ GX_NRM_XYZ = 0, - /* 0x1 */ GX_NRM_NBT = 1, - /* 0x2 */ GX_NRM_NBT3 = 2, - /* 0x0 */ GX_CLR_RGB = 0, - /* 0x1 */ GX_CLR_RGBA = 1, - /* 0x0 */ GX_TEX_S = 0, - /* 0x1 */ GX_TEX_ST = 1, + GX_POS_XY = 0, // Position X, Y (two components). + GX_POS_XYZ = 1, // Position X, Y, Z (three components). + + GX_NRM_XYZ = 0, // Normal X, Y, Z (three components). + GX_NRM_NBT = 1, // Normal, binormal, tangent (three components). + GX_NRM_NBT3 = 2, // Normal, binormal, tangent (three components). Use when NBT + // normal is indexed independently. + + GX_CLR_RGB = 0, // RGB (three components). + GX_CLR_RGBA = 1, // RGBA (four components). + + GX_TEX_S = 0, // Texture coordinate S (one component). + GX_TEX_ST = 1, // Texture coordinates S, T (two components). + + GX_COMPCNT_NULL = 0, // Null count. } GXCompCnt; typedef enum _GXCompType { - /* 0x0 */ GX_U8, - /* 0x1 */ GX_S8, - /* 0x2 */ GX_U16, - /* 0x3 */ GX_S16, - /* 0x4 */ GX_F32, - /* 0x0 */ GX_RGB565 = 0, - /* 0x1 */ GX_RGB8, - /* 0x2 */ GX_RGBX8, - /* 0x3 */ GX_RGBA4, - /* 0x4 */ GX_RGBA6, - /* 0x5 */ GX_RGBA8, + GX_U8 = 0, // Unsigned 8-bit. + GX_S8 = 1, // Signed 8-bit. + GX_U16 = 2, // Unsigned 16-bit. + GX_S16 = 3, // Signed 16-bit. + GX_F32 = 4, // Floating-point 32-bit. + + GX_RGB565 = 0, // RGB565 16-bit. + GX_RGB8 = 1, // RGB888 24-bit. + GX_RGBX8 = 2, // RGB888x 32-bit. + GX_RGBA4 = 3, // RGBA4444 16-bit. + GX_RGBA6 = 4, // RGBA6666 24-bit. + GX_RGBA8 = 5, // RGBA8888 32-bit. + + GX_COMP_NULL = 0, // Null type. } GXCompType; typedef enum _GXAttrType { @@ -335,28 +344,50 @@ typedef enum _GXTevAlphaArg { /* 0x7 */ GX_CA_ZERO, } GXTevAlphaArg; +/** + * RGB, RGBA, Intensity, Intensity/Alpha, Compressed, and Z texture format + * types. See GXCITexFmt for information on color index formats. The CTF format + * is used only by the GXSetTexCopyDst function to specify how data is copied + * out of the EFB into a texture in main memory. In order to actually use that + * texture, you must specify a non-copy format of matching size. For example, if + * copying using GX_CTF_RG8, you would apply the resulting texture using + * GX_TF_IA8. + */ typedef enum _GXTexFmt { - /* 0x0 */ GX_TF_I4, - /* 0x1 */ GX_TF_I8, - /* 0x2 */ GX_TF_IA4, - /* 0x3 */ GX_TF_IA8, - /* 0x4 */ GX_TF_RGB565, - /* 0x5 */ GX_TF_TGB5A3, - /* 0x6 */ GX_TF_RGBA8, - /* 0x7 */ GX_TF_CI4, - /* 0x8 */ GX_TF_CI8, - /* 0x9 */ GX_TF_CI14, - /* 0xE */ GX_TF_CMPR = 14, - /* 0x10 */ _GX_TF_ZTF = 0x10, - /* 0x11 */ GX_TF_Z8 = (0x1 | _GX_TF_ZTF), - /* 0x13 */ GX_TF_Z16 = (0x3 | _GX_TF_ZTF), - /* 0x16 */ GX_TF_Z24X8 = (0x6 | _GX_TF_ZTF), - /* 0x20 */ _GX_TF_CTF = 0x20, - /* 0x28 */ _GX_CTF_R8 = 0x28, - /* 0x30 */ GX_CTF_Z4 = (0x0 | _GX_TF_ZTF | _GX_TF_CTF), - /* 0x39 */ GX_CTF_Z8M = (0x9 | _GX_TF_ZTF | _GX_TF_CTF), - /* 0x3A */ GX_CTF_Z8L = (0xA | _GX_TF_ZTF | _GX_TF_CTF), - /* 0x3C */ GX_CTF_Z16L = (0xC | _GX_TF_ZTF | _GX_TF_CTF), + // Intensities (I) and RGB/RGBA. + GX_TF_I4 = 0x0, // 4-bit I + GX_TF_I8 = 0x1, // 8-bit I + GX_TF_IA4 = 0x2, // 8-bit I + alpha (4+4). + GX_TF_IA8 = 0x3, // 16-bit I + alpha (8+8). + GX_TF_RGB565 = 0x4, // 16-bit RGB. + GX_TF_RGB5A3 = 0x5, // MSB=1, RGB555 (opaque). MSB=0, RGBA4443 (transparent). + GX_TF_RGBA8 = 0x6, // 32-bit RGB. + GX_TF_CI14 = 0x9, + GX_TF_CMPR = 0xE, // Compressed 4-bit texel. + + // Z-texture format. + GX_TF_Z8 = 0x11, // Unsigned 8-bit Z. For texture copies, specify the upper 8 bits of Z. + GX_TF_Z16 = 0x13, // Unsigned 16-bit Z. For texture copies, specify the upper 16 bits of Z. + GX_TF_Z24X8 = 0x16, // Unsigned 24-bit (32-bit texture) Z. For texture copies, copy the 24-bit + // Z and 0xff. + + // Copy-texture format. + GX_CTF_R4 = 0x20, // 4-bit red. For copying 4 bits from red. + GX_CTF_RA4 = 0x22, // 4-bit red + 4-bit alpha. For copying 4 bits from red, 4 bits from alpha. + GX_CTF_RA8 = 0x23, // 8-bit red + 8-bit alpha. For copying 8 bits from red, 8 bits from alpha. + GX_CTF_YUVA8 = 0x26, // 8-bit YUV + alpha. For copying 8 bits from YUV, 8 bits from alpha. + GX_CTF_A8 = 0x26, // 8-bit alpha. For copying 8 bits from alpha. + GX_CTF_R8 = 0x27, // 8-bit red. For copying 8 bits from red. + GX_CTF_G8 = 0x28, // 8-bit green. For copying 8 bits from green. + GX_CTF_B8 = 0x29, // 8-bit blue. For copying 8 bits from blue. + GX_CTF_RG8 = 0x2A, // 8-bit red +8-bit green. For copying 8 bits from red, 8 bits from green. + GX_CTF_GB8 = 0x2B, // 8-bit green +8-bit blue. For copying 8 bits from green, 8 bits from blue. + + // Copy-Z-texture format. + GX_CTF_Z4 = 0x30, // 4-bit Z. For copying the 4 upper bits from Z. + GX_CTF_Z8M = 0x39, // 8-bit Z (median byte). For copying the middle 8 bits of Z. + GX_CTF_Z8L = 0x3A, // 8-bit Z (lower byte). For copying the lower 8 bits of Z. + GX_CTF_Z16L = 0x3C, // 16-bit Z (lower portion). For copying the lower 16 bits of Z. } GXTexFmt; typedef enum _GXGamma { @@ -388,10 +419,14 @@ typedef enum _GXTlut { /* 0x0D */ GX_TLUT13, /* 0x0E */ GX_TLUT14, /* 0x0F */ GX_TLUT15, - /* 0x10 */ GX_BIGTLUT0, + /* 0x10 */ GX_MAX_TLUT, + /* 0x10 */ GX_BIGTLUT0 = 0x10, /* 0x11 */ GX_BIGTLUT1, /* 0x12 */ GX_BIGTLUT2, /* 0x13 */ GX_BIGTLUT3, + /* 0x13 */ GX_MAX_BIGTLUT = 4, + + GX_MAX_TLUT_ALL = GX_MAX_TLUT + GX_MAX_BIGTLUT, } GXTlut; typedef enum _GXTexWrapMode { @@ -733,6 +768,7 @@ typedef enum _GXFBClamp { /* 0x0 */ GX_CLAMP_NONE, /* 0x1 */ GX_CLAMP_TOP, /* 0x2 */ GX_CLAMP_BOTTOM, + GX_CLAMP_BOTH = GX_CLAMP_TOP | GX_CLAMP_BOTTOM, } GXFBClamp; typedef enum _GXPixelFmt { @@ -744,6 +780,7 @@ typedef enum _GXPixelFmt { /* 0x5 */ GX_PF_U8, /* 0x6 */ GX_PF_V8, /* 0x7 */ GX_PF_YUV420, + /* 0x8 */ GX_PF_MAX, } GXPixelFmt; typedef enum _GXZFmt16 { @@ -795,4 +832,1115 @@ typedef enum _GXTlutSize { /* 0x400 */ GX_TLUT_16K = 1024, } GXTlutSize; +typedef enum _GXDirtyFlag { + GX_DIRTY_SU_TEX = (1 << 0), + GX_DIRTY_BP_MASK = (1 << 1), + GX_DIRTY_GEN_MODE = (1 << 2), + GX_DIRTY_VCD = (1 << 3), + GX_DIRTY_VAT = (1 << 4), + GX_DIRTY_AMB_COLOR0 = (1 << 8), + GX_DIRTY_AMB_COLOR1 = (1 << 9), + GX_DIRTY_MAT_COLOR0 = (1 << 10), + GX_DIRTY_MAT_COLOR1 = (1 << 11), + GX_DIRTY_MTX_IDX = (1 << 26), + GX_DIRTY_PROJECTION = (1 << 27), + GX_DIRTY_VIEWPORT = (1 << 28), + + GX_DIRTY_VLIM = GX_DIRTY_VCD | GX_DIRTY_VAT, + + GX_AMB_MAT_MASK = + GX_DIRTY_AMB_COLOR0 | GX_DIRTY_AMB_COLOR1 | GX_DIRTY_MAT_COLOR0 | GX_DIRTY_MAT_COLOR1, + GX_LIGHT_CHAN_MASK = 0x100F000, + GX_TEX_GEN_MASK = 0x2FF0000, +} GXDirtyFlag; + +// CP locator for vertex descriptor (lo). +typedef enum _GXCPVCDLo { + // Position matrix idx [31] + GX_CP_VCD_LO_POSMTXIDX_ST = 31, + GX_CP_VCD_LO_POSMTXIDX_END = 31, + + // Tex 0 matrix idx [30] + GX_CP_VCD_LO_TEX0MTXIDX_ST = 30, + GX_CP_VCD_LO_TEX0MTXIDX_END = 30, + + // Tex 1 matrix idx [29] + GX_CP_VCD_LO_TEX1MTXIDX_ST = 29, + GX_CP_VCD_LO_TEX1MTXIDX_END = 29, + + // Tex 2 matrix idx [28] + GX_CP_VCD_LO_TEX2MTXIDX_ST = 28, + GX_CP_VCD_LO_TEX2MTXIDX_END = 28, + + // Tex 3 matrix idx [27] + GX_CP_VCD_LO_TEX3MTXIDX_ST = 27, + GX_CP_VCD_LO_TEX3MTXIDX_END = 27, + + // Tex 4 matrix idx [26] + GX_CP_VCD_LO_TEX4MTXIDX_ST = 26, + GX_CP_VCD_LO_TEX4MTXIDX_END = 26, + + // Tex 5 matrix idx [25] + GX_CP_VCD_LO_TEX5MTXIDX_ST = 25, + GX_CP_VCD_LO_TEX5MTXIDX_END = 25, + + // Tex 6 matrix idx [24] + GX_CP_VCD_LO_TEX6MTXIDX_ST = 24, + GX_CP_VCD_LO_TEX6MTXIDX_END = 24, + + // Tex 7 matrix idx [23] + GX_CP_VCD_LO_TEX7MTXIDX_ST = 23, + GX_CP_VCD_LO_TEX7MTXIDX_END = 23, + + // Position [21-22] + GX_CP_VCD_LO_POS_ST = 21, + GX_CP_VCD_LO_POS_END = 22, + + // Normal [19-20] + GX_CP_VCD_LO_NRM_ST = 19, + GX_CP_VCD_LO_NRM_END = 20, + + // Color diffused [17-18] + GX_CP_VCD_LO_CLRDIF_ST = 17, + GX_CP_VCD_LO_CLRDIF_END = 18, + + // Color specular [15-16] + GX_CP_VCD_LO_CLRSPEC_ST = 15, + GX_CP_VCD_LO_CLRSPEC_END = 16, +} GXCPVCDLo; + +// CP locators for vertex descriptor (hi). +typedef enum _GXCPVCDHi { + // Tex0 coordinates [30-31] + GX_CP_VCD_HI_TEX0COORD_ST = 30, + GX_CP_VCD_HI_TEX0COORD_END = 31, + + // Tex1 coordinates [28-29] + GX_CP_VCD_HI_TEX1COORD_ST = 28, + GX_CP_VCD_HI_TEX1COORD_END = 29, + + // Tex2 coordinates [26-27] + GX_CP_VCD_HI_TEX2COORD_ST = 26, + GX_CP_VCD_HI_TEX2COORD_END = 27, + + // Tex3 coordinates [24-25] + GX_CP_VCD_HI_TEX3COORD_ST = 24, + GX_CP_VCD_HI_TEX3COORD_END = 25, + + // Tex4 coordinates [22-23] + GX_CP_VCD_HI_TEX4COORD_ST = 22, + GX_CP_VCD_HI_TEX4COORD_END = 23, + + // Tex5 coordinates [20-21] + GX_CP_VCD_HI_TEX5COORD_ST = 20, + GX_CP_VCD_HI_TEX5COORD_END = 21, + + // Tex6 coordinates [18-19] + GX_CP_VCD_HI_TEX6COORD_ST = 18, + GX_CP_VCD_HI_TEX6COORD_END = 19, + + // Tex7 coordinates [16-17] + GX_CP_VCD_HI_TEX7COORD_ST = 16, + GX_CP_VCD_HI_TEX7COORD_END = 17, +} GXCPVCDHi; + +// Command processor registers. +typedef enum _GXCPRegs { + GX_CP_REG_MTXIDXA = 0x30, // Matrix index A + GX_CP_REG_MTXIDXB = 0x40, // Matrix index B + GX_CP_REG_VCD_LO = 0x50, // Vertex descriptor (lo) + GX_CP_REG_VCD_HI = 0x60, // Vertex descriptor (hi) + GX_CP_REG_VAT_GRP0 = 0x70, // Vertex attribute table (group 0) + GX_CP_REG_VAT_GRP1 = 0x80, // Vertex attribute table (group 1) + GX_CP_REG_VAT_GRP2 = 0x90, // Vertex attribute table (group 2) + GX_CP_REG_ARRAYBASE = 0xA0, // Vertex array start/base + GX_CP_REG_ARRAYSTRIDE = 0xB0, // Vertex array stride +} GXCPRegs; + +// Transform unit registers. +typedef enum _GXXFRegs { + GX_XF_REG_ERROR = 0x1000, + GX_XF_REG_DIAGNOSTICS = 0x1001, + GX_XF_REG_STATE0 = 0x1002, + GX_XF_REG_STATE1 = 0x1003, + GX_XF_REG_CLOCK = 0x1004, + GX_XF_REG_CLIPDISABLE = 0x1005, + GX_XF_REG_PERF0 = 0x1006, + GX_XF_REG_PERF1 = 0x1007, + GX_XF_REG_INVERTEXSPEC = 0x1008, + GX_XF_REG_NUMCOLORS = 0x1009, + GX_XF_REG_AMBIENT0 = 0x100A, + GX_XF_REG_AMBIENT1 = 0x100B, + GX_XF_REG_MATERIAL0 = 0x100C, + GX_XF_REG_MATERIAL1 = 0x100D, + GX_XF_REG_COLOR0CNTRL = 0x100E, + GX_XF_REG_COLOR1CNTRL = 0x100F, + GX_XF_REG_ALPHA0CNTRL = 0x1010, + GX_XF_REG_ALPHA1CNTRL = 0x1011, + GX_XF_REG_DUALTEXTRAN = 0x1012, + GX_XF_REG_MATRIXINDEX0 = 0x1018, + GX_XF_REG_MATRIXINDEX1 = 0x1019, + GX_XF_REG_SCALEX = 0x101A, + GX_XF_REG_SCALEY = 0x101B, + GX_XF_REG_SCALEZ = 0x101C, + GX_XF_REG_OFFSETX = 0x101D, + GX_XF_REG_OFFSETY = 0x101E, + GX_XF_REG_OFFSETZ = 0x101F, + GX_XF_REG_PROJECTIONA = 0x1020, + GX_XF_REG_PROJECTIONB = 0x1021, + GX_XF_REG_PROJECTIONC = 0x1022, + GX_XF_REG_PROJECTIOND = 0x1023, + GX_XF_REG_PROJECTIONE = 0x1024, + GX_XF_REG_PROJECTIONF = 0x1025, + GX_XF_REG_PROJECTORTHO = 0x1026, + GX_XF_REG_NUMTEX = 0x103F, + GX_XF_REG_TEX0 = 0x1040, + GX_XF_REG_TEX1 = 0x1041, + GX_XF_REG_TEX2 = 0x1042, + GX_XF_REG_TEX3 = 0x1043, + GX_XF_REG_TEX4 = 0x1044, + GX_XF_REG_TEX5 = 0x1045, + GX_XF_REG_TEX6 = 0x1046, + GX_XF_REG_TEX7 = 0x1047, + GX_XF_REG_DUALTEX0 = 0x1050, + GX_XF_REG_DUALTEX1 = 0x1051, + GX_XF_REG_DUALTEX2 = 0x1052, + GX_XF_REG_DUALTEX3 = 0x1053, + GX_XF_REG_DUALTEX4 = 0x1054, + GX_XF_REG_DUALTEX5 = 0x1055, + GX_XF_REG_DUALTEX6 = 0x1056, + GX_XF_REG_DUALTEX7 = 0x1057, +} GXXFRegs; + +// Commands for interacting with the GXFifo pipe. +typedef enum _GXFifoCmd { + GX_FIFO_CMD_NOOP = 0x00, // no operation + + GX_FIFO_CMD_LOAD_BP_REG = 0x61, // load blitting processor reg + GX_FIFO_CMD_LOAD_CP_REG = 0x08, // load command processor reg + GX_FIFO_CMD_LOAD_XF_REG = 0x10, // load transform unit reg + + GX_FIFO_CMD_LOAD_INDX_A = 0x20, // load index A + GX_FIFO_CMD_LOAD_INDX_B = 0x28, // load index B + GX_FIFO_CMD_LOAD_INDX_C = 0x30, // load index C + GX_FIFO_CMD_LOAD_INDX_D = 0x38, // load index D + + GX_FIFO_CMD_CALL_DL = 0x40, // call displaylist + GX_FIFO_CMD_INVAL_VTX = 0x48, // invalid vertex + +} GXFifoCmd; + +// CP locator for vertex attribute table (group 0). +typedef enum _GXCPVATGrp0 { + // Position count [31-31] + GX_CP_VAT_GRP0_POS_CNT_ST = 31, + GX_CP_VAT_GRP0_POS_CNT_END = 31, + + // Position type [28-30] + GX_CP_VAT_GRP0_POS_TYPE_ST = 28, + GX_CP_VAT_GRP0_POS_TYPE_END = 30, + + // Position shift [23-27] + GX_CP_VAT_GRP0_POS_SHIFT_ST = 23, + GX_CP_VAT_GRP0_POS_SHIFT_END = 27, + + // Normal count [22-22] + GX_CP_VAT_GRP0_NRM_CNT_ST = 22, + GX_CP_VAT_GRP0_NRM_CNT_END = 22, + + // Normal type [19-21] + GX_CP_VAT_GRP0_NRM_TYPE_ST = 19, + GX_CP_VAT_GRP0_NRM_TYPE_END = 21, + + // Color diffused count [18-18] + GX_CP_VAT_GRP0_CLRDIFF_CNT_ST = 18, + GX_CP_VAT_GRP0_CLRDIFF_CNT_END = 18, + + // Color diffused type [15-17] + GX_CP_VAT_GRP0_CLRDIFF_TYPE_ST = 15, + GX_CP_VAT_GRP0_CLRDIFF_TYPE_END = 17, + + // Color specular count [14-14] + GX_CP_VAT_GRP0_CLRSPEC_CNT_ST = 14, + GX_CP_VAT_GRP0_CLRSPEC_CNT_END = 14, + + // Color specular type [11-13] + GX_CP_VAT_GRP0_CLRSPEC_TYPE_ST = 11, + GX_CP_VAT_GRP0_CLRSPEC_TYPE_END = 13, + + // Tex0 coord count [10-10] + GX_CP_VAT_GRP0_TXC0_CNT_ST = 10, + GX_CP_VAT_GRP0_TXC0_CNT_END = 10, + + // Tex0 coord type [7-9] + GX_CP_VAT_GRP0_TXC0_TYPE_ST = 7, + GX_CP_VAT_GRP0_TXC0_TYPE_END = 9, + + // Tex0 coord shift [2-6] + GX_CP_VAT_GRP0_TXC0_SHIFT_ST = 2, + GX_CP_VAT_GRP0_TXC0_SHIFT_END = 6, + + // Byte dequantised [1-1] + GX_CP_VAT_GRP0_BYTEDEQ_ST = 1, + GX_CP_VAT_GRP0_BYTEDEQ_END = 1, + + // Normal index 3 [0-0] (Input will be treated as three staggered indices (one per triple biased + // by component size) into normal table)) + GX_CP_VAT_GRP0_NRMIDX3_ST = 0, + GX_CP_VAT_GRP0_NRMIDX3_END = 0, +} GXCPVATGrp0; + +// CP locators for vertex attribute table (group 1). +typedef enum _GXCPVATGrp1 { + // Tex1 coord count [31-31] + GX_CP_VAT_GRP1_TXC1_CNT_ST = 31, + GX_CP_VAT_GRP1_TXC1_CNT_END = 31, + + // Tex1 coord type [28-30] + GX_CP_VAT_GRP1_TXC1_TYPE_ST = 28, + GX_CP_VAT_GRP1_TXC1_TYPE_END = 30, + + // Tex1 coord shift [23-27] + GX_CP_VAT_GRP1_TXC1_SHIFT_ST = 23, + GX_CP_VAT_GRP1_TXC1_SHIFT_END = 27, + + // Tex2 coord count [22-22] + GX_CP_VAT_GRP1_TXC2_CNT_ST = 22, + GX_CP_VAT_GRP1_TXC2_CNT_END = 22, + + // Tex2 coord type [19-21] + GX_CP_VAT_GRP1_TXC2_TYPE_ST = 19, + GX_CP_VAT_GRP1_TXC2_TYPE_END = 21, + + // Tex2 coord shift [14-18] + GX_CP_VAT_GRP1_TXC2_SHIFT_ST = 14, + GX_CP_VAT_GRP1_TXC2_SHIFT_END = 18, + + // Tex3 coord count [13-13] + GX_CP_VAT_GRP1_TXC3_CNT_ST = 13, + GX_CP_VAT_GRP1_TXC3_CNT_END = 13, + + // Tex3 coord type [10-12] + GX_CP_VAT_GRP1_TXC3_TYPE_ST = 10, + GX_CP_VAT_GRP1_TXC3_TYPE_END = 12, + + // Tex3 coord shift [5-9] + GX_CP_VAT_GRP1_TXC3_SHIFT_ST = 5, + GX_CP_VAT_GRP1_TXC3_SHIFT_END = 9, + + // Tex4 coord count [4-4] + GX_CP_VAT_GRP1_TXC4_CNT_ST = 4, + GX_CP_VAT_GRP1_TXC4_CNT_END = 4, + + // Tex4 coord type [1-3] + GX_CP_VAT_GRP1_TXC4_TYPE_ST = 1, + GX_CP_VAT_GRP1_TXC4_TYPE_END = 3, + +} GXCPVATGrp1; + +// CP locators for vertex attribute table (group 2). +typedef enum _GXCPVATGrp2 { + // Tex4 coord shift [27-31] + GX_CP_VAT_GRP2_TXC4_SHIFT_ST = 27, + GX_CP_VAT_GRP2_TXC4_SHIFT_END = 31, + + // Tex5 coord count [26-26] + GX_CP_VAT_GRP2_TXC5_CNT_ST = 26, + GX_CP_VAT_GRP2_TXC5_CNT_END = 26, + + // Tex5 coord type [23-25] + GX_CP_VAT_GRP2_TXC5_TYPE_ST = 23, + GX_CP_VAT_GRP2_TXC5_TYPE_END = 25, + + // Tex5 coord shift [18-22] + GX_CP_VAT_GRP2_TXC5_SHIFT_ST = 18, + GX_CP_VAT_GRP2_TXC5_SHIFT_END = 22, + + // Tex6 coord count [17-17] + GX_CP_VAT_GRP2_TXC6_CNT_ST = 17, + GX_CP_VAT_GRP2_TXC6_CNT_END = 17, + + // Tex6 coord type [14-16] + GX_CP_VAT_GRP2_TXC6_TYPE_ST = 14, + GX_CP_VAT_GRP2_TXC6_TYPE_END = 16, + + // Tex6 coord shift [9-13] + GX_CP_VAT_GRP2_TXC6_SHIFT_ST = 9, + GX_CP_VAT_GRP2_TXC6_SHIFT_END = 13, + + // Tex7 coord count [8-8] + GX_CP_VAT_GRP2_TXC7_CNT_ST = 8, + GX_CP_VAT_GRP2_TXC7_CNT_END = 8, + + // Tex7 coord type [5-7] + GX_CP_VAT_GRP2_TXC7_TYPE_ST = 5, + GX_CP_VAT_GRP2_TXC7_TYPE_END = 7, + + // Tex7 coord shift [0-4] + GX_CP_VAT_GRP2_TXC7_SHIFT_ST = 0, + GX_CP_VAT_GRP2_TXC7_SHIFT_END = 4, +} GXCPVATGrp2; + +// BP GenMode locators. +typedef enum _GXBPGenMode { + // Active texture counts [28-31] + GX_BP_GENMODE_NUMTEX_ST = 28, + GX_BP_GENMODE_NUMTEX_END = 31, + + // Color/channel counts [25-27] + GX_BP_GENMODE_NUMCOLORS_ST = 25, + GX_BP_GENMODE_NUMCOLORS_END = 27, + + // Multisample mode [22-22] + GX_BP_GENMODE_MULTISAMPLE_ST = 22, + GX_BP_GENMODE_MULTISAMPLE_END = 22, + + // Cull mode [16-17] + GX_BP_GENMODE_CULLMODE_ST = 16, + GX_BP_GENMODE_CULLMODE_END = 17, + + // Indirect stage counts [13-15] + GX_BP_GENMODE_NUMINDSTAGES_ST = 13, + GX_BP_GENMODE_NUMINDSTAGES_END = 15, + + // Toggle co-planar/Z-freeze [12-12] + GX_BP_GENMODE_COPLANAR_ST = 12, + GX_BP_GENMODE_COPLANAR_END = 12, +} GXBPGenMode; + +// Texture register fields for XF (transform) unit. +typedef enum _GXXfTexReg { + GX_XF_TEX_PROJ_ST = 0, // (s,t) (2x4) + GX_XF_TEX_PROJ_STQ = 1, // (s,t,q) (3x4) + + GX_XF_TEX_FORM_AB11 = 0, // (A, B, 1.0f, 1.0f), used for regular tex src + GX_XF_TEX_FORM_ABC1 = 1, // (A, B, C, 1.0f), used for geometry/normal src +} GXXfTexReg; + +// XF locators for textures. +typedef enum _GXXFTex { + // Projection type [30-30] + GX_XF_TEX_PROJTYPE_ST = 30, + GX_XF_TEX_PROJTYPE_END = 30, + + // Input format [29-29] + GX_XF_TEX_INPUTFORM_ST = 29, + GX_XF_TEX_INPUTFORM_END = 29, + + // Texture gen type [25-27] + GX_XF_TEX_TEXGENTYPE_ST = 25, + GX_XF_TEX_TEXGENTYPE_END = 27, + + // Source row [20-24] + GX_XF_TEX_SRCROW_ST = 20, + GX_XF_TEX_SRCROW_END = 24, + + // Bump source texture [17-19] + GX_XF_TEX_BUMPSRCTEX_ST = 17, + GX_XF_TEX_BUMPSRCTEX_END = 19, + + // Bump source light [14-16] + GX_XF_TEX_BUMPSRCLIGHT_ST = 14, + GX_XF_TEX_BUMPSRCLIGHT_END = 16, +} GXXFTex; + +// XF locators for dual textures. +typedef enum _GXXFDualTex { + // Base row of the transform matrix [26-31] + GX_XF_DUALTEX_BASEROW_ST = 26, + GX_XF_DUALTEX_BASEROW_END = 31, + + // Normalise texcoord before sending transform [23-23] + GX_XF_DUALTEX_NORMALISE_ST = 23, + GX_XF_DUALTEX_NORMALISE_END = 23, +} GXXFDualTex; + +// General texture commands. +typedef enum _GXXfTexGen { + GX_XF_TG_REGULAR = 0, // Regular; transform incoming data. + GX_XF_TG_BUMP = 1, // Texgen bump mapping. + GX_XF_TG_CLR0 = 2, // Color texgen for color 0 (s,t) = (r, g:b) + GX_XF_TG_CLR1 = 3, // Color texgen for color 1 (s,t) = (r, g:b) +} GXXfTexGen; + +// XF locators for matrix index 0. +typedef enum _GXXFMtxIdx0 { + // Geometry [26-31] + GX_XF_MTXIDX0_GEOM_ST = 26, + GX_XF_MTXIDX0_GEOM_END = 31, + + // Tex 0 [20-25] + GX_XF_MTXIDX0_TEX0_ST = 20, + GX_XF_MTXIDX0_TEX0_END = 25, + + // Tex 1 [14-19] + GX_XF_MTXIDX0_TEX1_ST = 14, + GX_XF_MTXIDX0_TEX1_END = 19, + + // Tex 2 [8-13] + GX_XF_MTXIDX0_TEX2_ST = 8, + GX_XF_MTXIDX0_TEX2_END = 13, + + // Tex 3 [2-7] + GX_XF_MTXIDX0_TEX3_ST = 2, + GX_XF_MTXIDX0_TEX3_END = 7, +} GXXFMtxIdx0; + +// XF locators for matrix index 1. +typedef enum _GXXFMtxIdx1 { + // Tex 4 [26-31] + GX_XF_MTXIDX1_TEX4_ST = 26, + GX_XF_MTXIDX1_TEX4_END = 31, + + // Tex 5 [20-25] + GX_XF_MTXIDX1_TEX5_ST = 20, + GX_XF_MTXIDX1_TEX5_END = 25, + + // Tex 6 [14-19] + GX_XF_MTXIDX1_TEX6_ST = 14, + GX_XF_MTXIDX1_TEX6_END = 19, + + // Tex 7 [8-13] + GX_XF_MTXIDX1_TEX7_ST = 8, + GX_XF_MTXIDX1_TEX7_END = 13, +} GXXFMtxIdx1; + +// Blitting processor registers. +typedef enum _GXBPRegs { + // gen mode + GX_BP_REG_GENMODE = 0x0, // gen mode + + // display copy filters + GX_BP_REG_DISPCOPYFILTER0 = 0x1, // display copy filter 0 + GX_BP_REG_DISPCOPYFILTER1 = 0x2, // display copy filter 1 + GX_BP_REG_DISPCOPYFILTER2 = 0x3, // display copy filter 2 + GX_BP_REG_DISPCOPYFILTER3 = 0x4, // display copy filter 3 + + // indirect matrices + GX_BP_REG_INDMTX0A = 0x6, // indirect matrix 0A + GX_BP_REG_INDMTX0B = 0x7, // indirect matrix 0B + GX_BP_REG_INDMTX0C = 0x8, // indirect matrix 0C + GX_BP_REG_INDMTX1A = 0x9, // indirect matrix 1A + GX_BP_REG_INDMTX1B = 0xA, // indirect matrix 1B + GX_BP_REG_INDMTX1C = 0xB, // indirect matrix 1C + GX_BP_REG_INDMTX2A = 0xC, // indirect matrix 2A + GX_BP_REG_INDMTX2B = 0xD, // indirect matrix 2B + GX_BP_REG_INDMTX2C = 0xE, // indirect matrix 2C + GX_BP_REG_INDIMASK = 0xF, // indirect mask + + // indirect TEV stages + GX_BP_REG_INDTEVSTAGE0 = 0x10, // indirect TEV stage 0 + GX_BP_REG_INDTEVSTAGE1 = 0x11, // indirect TEV stage 1 + GX_BP_REG_INDTEVSTAGE2 = 0x12, // indirect TEV stage 2 + GX_BP_REG_INDTEVSTAGE3 = 0x13, // indirect TEV stage 3 + GX_BP_REG_INDTEVSTAGE4 = 0x14, // indirect TEV stage 4 + GX_BP_REG_INDTEVSTAGE5 = 0x15, // indirect TEV stage 5 + GX_BP_REG_INDTEVSTAGE6 = 0x16, // indirect TEV stage 6 + GX_BP_REG_INDTEVSTAGE7 = 0x17, // indirect TEV stage 7 + GX_BP_REG_INDTEVSTAGE8 = 0x18, // indirect TEV stage 8 + GX_BP_REG_INDTEVSTAGE9 = 0x19, // indirect TEV stage 9 + GX_BP_REG_INDTEVSTAGE10 = 0x1A, // indirect TEV stage 10 + GX_BP_REG_INDTEVSTAGE11 = 0x1B, // indirect TEV stage 11 + GX_BP_REG_INDTEVSTAGE12 = 0x1C, // indirect TEV stage 12 + GX_BP_REG_INDTEVSTAGE13 = 0x1D, // indirect TEV stage 13 + GX_BP_REG_INDTEVSTAGE14 = 0x1E, // indirect TEV stage 14 + GX_BP_REG_INDTEVSTAGE15 = 0x1F, // indirect TEV stage 15 + + // performance manips + GX_BP_REG_SCISSORTL = 0x20, // scissor top left + GX_BP_REG_SCISSORBR = 0x21, // scissor bottom right + GX_BP_REG_LINEPTWIDTH = 0x22, // line point width + GX_BP_REG_PERF0TRI = 0x23, // performance 0 (triangle) + GX_BP_REG_PERF0QUAD = 0x24, // performance 0 (quad) + + // rasters + GX_BP_REG_RAS1_SS0 = 0x25, + GX_BP_REG_RAS1_SS1 = 0x26, + GX_BP_REG_RAS1_IREF = 0x27, + GX_BP_REG_RAS1_TREF0 = 0x28, + GX_BP_REG_RAS1_TREF1 = 0x29, + GX_BP_REG_RAS1_TREF2 = 0x2A, + GX_BP_REG_RAS1_TREF3 = 0x2B, + GX_BP_REG_RAS1_TREF4 = 0x2C, + GX_BP_REG_RAS1_TREF5 = 0x2D, + GX_BP_REG_RAS1_TREF6 = 0x2E, + GX_BP_REG_RAS1_TREF7 = 0x2F, + + // setup sizes + GX_BP_REG_SU_SSIZE0 = 0x30, + GX_BP_REG_SU_TSIZE0 = 0x31, + GX_BP_REG_SU_SSIZE1 = 0x32, + GX_BP_REG_SU_TSIZE1 = 0x33, + GX_BP_REG_SU_SSIZE2 = 0x34, + GX_BP_REG_SU_TSIZE2 = 0x35, + GX_BP_REG_SU_SSIZE3 = 0x36, + GX_BP_REG_SU_TSIZE3 = 0x37, + GX_BP_REG_SU_SSIZE4 = 0x38, + GX_BP_REG_SU_TSIZE4 = 0x39, + GX_BP_REG_SU_SSIZE5 = 0x3A, + GX_BP_REG_SU_TSIZE5 = 0x3B, + GX_BP_REG_SU_SSIZE6 = 0x3C, + GX_BP_REG_SU_TSIZE6 = 0x3D, + GX_BP_REG_SU_SSIZE7 = 0x3E, + GX_BP_REG_SU_TSIZE7 = 0x3F, + + // Z and blend controls + GX_BP_REG_ZMODE = 0x40, + GX_BP_REG_BLENDMODE = 0x41, + GX_BP_REG_DSTALPHA = 0x42, + GX_BP_REG_ZCONTROL = 0x43, + GX_BP_REG_FIELDMASK = 0x44, + GX_BP_REG_DRAWDONE = 0x45, + GX_BP_REG_PETOKEN = 0x47, + GX_BP_REG_PETOKENINT = 0x48, + + // copying + GX_BP_REG_TEXCOPYSRCXY = 0x49, + GX_BP_REG_TEXCOPYSRCWH = 0x4A, + GX_BP_REG_TEXCOPYDST = 0x4B, + GX_BP_REG_DISPCOPYSTRIDE = 0x4D, + GX_BP_REG_DISPCOPYSCALEY = 0x4E, + GX_BP_REG_COPYCLEARAR = 0x4F, + GX_BP_REG_COPYCLEARGB = 0x50, + GX_BP_REG_COPYCLEARZ = 0x51, + GX_BP_REG_COPYFILTER0 = 0x53, + GX_BP_REG_COPYFILTER1 = 0x54, + + // + GX_BP_REG_BOUNDINGBOX0 = 0x55, + GX_BP_REG_BOUNDINGBOX1 = 0x56, + + GX_BP_REG_SCISSOROFFSET = 0x59, + + // texture memory + GX_BP_REG_TMEMPRELOADADDR = 0x60, + GX_BP_REG_TMEMPRELOADEVEN = 0x61, + GX_BP_REG_TMEMPRELOADODD = 0x62, + GX_BP_REG_TMEMPRELOADMODE = 0x63, + GX_BP_REG_TMEMTLUTSRC = 0x64, + GX_BP_REG_TMEMTLUTDST = 0x65, + GX_BP_REG_TMEMTEXINVALIDATE = 0x66, + + // performance 1 + GX_BP_REG_PERF1 = 0x67, + GX_BP_REG_FIELDMODE = 0x68, + + // set modes + GX_BP_REG_SETMODE0_TEX0 = 0x80, + GX_BP_REG_SETMODE0_TEX1 = 0x81, + GX_BP_REG_SETMODE0_TEX2 = 0x82, + GX_BP_REG_SETMODE0_TEX3 = 0x83, + GX_BP_REG_SETMODE1_TEX0 = 0x84, + GX_BP_REG_SETMODE1_TEX1 = 0x85, + GX_BP_REG_SETMODE1_TEX2 = 0x86, + GX_BP_REG_SETMODE1_TEX3 = 0x87, + + // set images + GX_BP_REG_SETIMAGE0_TEX0 = 0x88, + GX_BP_REG_SETIMAGE0_TEX1 = 0x89, + GX_BP_REG_SETIMAGE0_TEX2 = 0x8A, + GX_BP_REG_SETIMAGE0_TEX3 = 0x8B, + GX_BP_REG_SETIMAGE1_TEX0 = 0x8C, + GX_BP_REG_SETIMAGE1_TEX1 = 0x8D, + GX_BP_REG_SETIMAGE1_TEX2 = 0x8E, + GX_BP_REG_SETIMAGE1_TEX3 = 0x8F, + GX_BP_REG_SETIMAGE2_TEX0 = 0x90, + GX_BP_REG_SETIMAGE2_TEX1 = 0x91, + GX_BP_REG_SETIMAGE2_TEX2 = 0x92, + GX_BP_REG_SETIMAGE2_TEX3 = 0x93, + GX_BP_REG_SETIMAGE3_TEX0 = 0x94, + GX_BP_REG_SETIMAGE3_TEX1 = 0x95, + GX_BP_REG_SETIMAGE3_TEX2 = 0x96, + GX_BP_REG_SETIMAGE3_TEX3 = 0x97, + + // set texture lookups + GX_BP_REG_SETTLUT_TEX0 = 0x98, + GX_BP_REG_SETTLUT_TEX1 = 0x99, + GX_BP_REG_SETTLUT_TEX2 = 0x9A, + GX_BP_REG_SETTLUT_TEX3 = 0x9B, + + // set modes continued + GX_BP_REG_SETMODE0_TEX4 = 0xA0, + GX_BP_REG_SETMODE0_TEX5 = 0xA1, + GX_BP_REG_SETMODE0_TEX6 = 0xA2, + GX_BP_REG_SETMODE0_TEX7 = 0xA3, + GX_BP_REG_SETMODE1_TEX4 = 0xA4, + GX_BP_REG_SETMODE1_TEX5 = 0xA5, + GX_BP_REG_SETMODE1_TEX6 = 0xA6, + GX_BP_REG_SETMODE1_TEX7 = 0xA7, + + // set images continued + GX_BP_REG_SETIMAGE0_TEX4 = 0xA8, + GX_BP_REG_SETIMAGE0_TEX5 = 0xA9, + GX_BP_REG_SETIMAGE0_TEX6 = 0xAA, + GX_BP_REG_SETIMAGE0_TEX7 = 0xAB, + GX_BP_REG_SETIMAGE1_TEX4 = 0xAC, + GX_BP_REG_SETIMAGE1_TEX5 = 0xAD, + GX_BP_REG_SETIMAGE1_TEX6 = 0xAE, + GX_BP_REG_SETIMAGE1_TEX7 = 0xAF, + GX_BP_REG_SETIMAGE2_TEX4 = 0xB0, + GX_BP_REG_SETIMAGE2_TEX5 = 0xB1, + GX_BP_REG_SETIMAGE2_TEX6 = 0xB2, + GX_BP_REG_SETIMAGE2_TEX7 = 0xB3, + GX_BP_REG_SETIMAGE3_TEX4 = 0xB4, + GX_BP_REG_SETIMAGE3_TEX5 = 0xB5, + GX_BP_REG_SETIMAGE3_TEX6 = 0xB6, + GX_BP_REG_SETIMAGE3_TEX7 = 0xB7, + + // set texture lookups continued + GX_BP_REG_SETTLUT_TEX4 = 0xB8, + GX_BP_REG_SETTLUT_TEX5 = 0xB9, + GX_BP_REG_SETTLUT_TEX6 = 0xBA, + GX_BP_REG_SETTLUT_TEX7 = 0xBB, + + // TEV color manips + GX_BP_REG_TEVCOLORCOMBINER0 = 0xC0, + GX_BP_REG_TEVALPHACOMBINER0 = 0xC1, + GX_BP_REG_TEVCOLORCOMBINER1 = 0xC2, + GX_BP_REG_TEVALPHACOMBINER1 = 0xC3, + GX_BP_REG_TEVCOLORCOMBINER2 = 0xC4, + GX_BP_REG_TEVALPHACOMBINER2 = 0xC5, + GX_BP_REG_TEVCOLORCOMBINER3 = 0xC6, + GX_BP_REG_TEVALPHACOMBINER3 = 0xC7, + GX_BP_REG_TEVCOLORCOMBINER4 = 0xC8, + GX_BP_REG_TEVALPHACOMBINER4 = 0xC9, + GX_BP_REG_TEVCOLORCOMBINER5 = 0xCA, + GX_BP_REG_TEVALPHACOMBINER5 = 0xCB, + GX_BP_REG_TEVCOLORCOMBINER6 = 0xCC, + GX_BP_REG_TEVALPHACOMBINER6 = 0xCD, + GX_BP_REG_TEVCOLORCOMBINER7 = 0xCE, + GX_BP_REG_TEVALPHACOMBINER7 = 0xCF, + GX_BP_REG_TEVCOLORCOMBINER8 = 0xD0, + GX_BP_REG_TEVALPHACOMBINER8 = 0xD1, + GX_BP_REG_TEVCOLORCOMBINER9 = 0xD2, + GX_BP_REG_TEVALPHACOMBINER9 = 0xD3, + GX_BP_REG_TEVCOLORCOMBINER10 = 0xD4, + GX_BP_REG_TEVALPHACOMBINER10 = 0xD5, + GX_BP_REG_TEVCOLORCOMBINER11 = 0xD6, + GX_BP_REG_TEVALPHACOMBINER11 = 0xD7, + GX_BP_REG_TEVCOLORCOMBINER12 = 0xD8, + GX_BP_REG_TEVALPHACOMBINER12 = 0xD9, + GX_BP_REG_TEVCOLORCOMBINER13 = 0xDA, + GX_BP_REG_TEVALPHACOMBINER13 = 0xDB, + GX_BP_REG_TEVCOLORCOMBINER14 = 0xDC, + GX_BP_REG_TEVALPHACOMBINER14 = 0xDD, + GX_BP_REG_TEVCOLORCOMBINER15 = 0xDE, + GX_BP_REG_TEVALPHACOMBINER15 = 0xDF, + + // TEV registers + GX_BP_REG_TEVREG0LO = 0xE0, + GX_BP_REG_TEVREG0HI = 0xE1, + GX_BP_REG_TEVREG1LO = 0xE2, + GX_BP_REG_TEVREG1HI = 0xE3, + GX_BP_REG_TEVREG2LO = 0xE4, + GX_BP_REG_TEVREG2HI = 0xE5, + GX_BP_REG_TEVREG3LO = 0xE6, + GX_BP_REG_TEVREG3HI = 0xE7, + + // fog registers + GX_BP_REG_FOGRANGE = 0xE8, + GX_BP_REG_FOGRANGEK0 = 0xE9, + GX_BP_REG_FOGRANGEK1 = 0xEA, + GX_BP_REG_FOGRANGEK2 = 0xEB, + GX_BP_REG_FOGRANGEK3 = 0xEC, + GX_BP_REG_FOGRANGEK4 = 0xED, + GX_BP_REG_FOGPARAM0 = 0xEE, + GX_BP_REG_FOGPARAM1 = 0xEF, + GX_BP_REG_FOGPARAM2 = 0xF0, + GX_BP_REG_FOGPARAM3 = 0xF1, + GX_BP_REG_FOGCOLOR = 0xF2, + + // performance manip registers + GX_BP_REG_ALPHACOMPARE = 0xF3, + GX_BP_REG_ZTEXTURE0 = 0xF4, + GX_BP_REG_ZTEXTURE1 = 0xF5, + + // TEV K selectors + GX_BP_REG_TEVKSEL0 = 0xF6, + GX_BP_REG_TEVKSEL1 = 0xF7, + GX_BP_REG_TEVKSEL2 = 0xF8, + GX_BP_REG_TEVKSEL3 = 0xF9, + GX_BP_REG_TEVKSEL4 = 0xFA, + GX_BP_REG_TEVKSEL5 = 0xFB, + GX_BP_REG_TEVKSEL6 = 0xFC, + GX_BP_REG_TEVKSEL7 = 0xFD, + + // SS mask + GX_BP_REG_SSMASK = 0xFE, +} GXBPRegs; + +// BP locators for fog parameter 0. +typedef enum _GXBPFogParam0 { + // A mantissa [21-31] + GX_BP_FOGPARAM0_A_MANT_ST = 21, + GX_BP_FOGPARAM0_A_MANT_END = 31, + + // A exponent [13-20] + GX_BP_FOGPARAM0_A_EXP_ST = 13, + GX_BP_FOGPARAM0_A_EXP_END = 20, + + // A sign [12-12] + GX_BP_FOGPARAM0_A_SIGN_ST = 12, + GX_BP_FOGPARAM0_A_SIGN_END = 12, +} GXBPFogParam0; + +// BP locators for fog parameter 1. +typedef enum _GXBPFogParam1 { + // B magnitude [8-31] + GX_BP_FOGPARAM1_B_MAG_ST = 8, + GX_BP_FOGPARAM1_B_MAG_END = 31, +} GXBPFogParam1; + +// BP locators for fog parameter 2. +typedef enum _GXBPFogParam2 { + // B shift [27-31] + GX_BP_FOGPARAM2_B_SHIFT_ST = 27, + GX_BP_FOGPARAM2_B_SHIFT_END = 31, +} GXBPFogParam2; + +// BP locators for fog parameter 3. +typedef enum _GXBPFogParam3 { + // C mantissa [21-31] + GX_BP_FOGPARAM3_C_MANT_ST = 21, + GX_BP_FOGPARAM3_C_MANT_END = 31, + + // C exponent [13-20] + GX_BP_FOGPARAM3_C_EXP_ST = 13, + GX_BP_FOGPARAM3_C_EXP_END = 20, + + // C sign [12-12] + GX_BP_FOGPARAM3_C_SIGN_ST = 12, + GX_BP_FOGPARAM3_C_SIGN_END = 12, + + // Projection [11] + GX_BP_FOGPARAM3_PROJ_ST = 11, + GX_BP_FOGPARAM3_PROJ_END = 11, + + // F select [8-10] + GX_BP_FOGPARAM3_FSEL_ST = 8, + GX_BP_FOGPARAM3_FSEL_END = 10, +} GXBPFogParam3; + +// BP locators for fog color. +typedef enum _GXBPFogColor { + // RGB components of color [8-31] + GX_BP_FOGCOLOR_RGB_ST = 8, + GX_BP_FOGCOLOR_RGB_END = 31, +} GXBPFogColor; + +// BP locators for fog range. +typedef enum _GXBPFogRange { + // Center [22-31] + GX_BP_FOGRANGE_CENTER_ST = 22, + GX_BP_FOGRANGE_CENTER_END = 31, + + // Enabled [21-21] + GX_BP_FOGRANGE_ENABLED_ST = 21, + GX_BP_FOGRANGE_ENABLED_END = 21, +} GXBPFogRange; + +// BP locators for fog range K. +typedef enum _GXBPFogRangeK { + // Hi [20-31] + GX_BP_FOGRANGEK_HI_ST = 20, + GX_BP_FOGRANGEK_HI_END = 31, + + // Lo [8-19] + GX_BP_FOGRANGEK_LO_ST = 8, + GX_BP_FOGRANGEK_LO_END = 19, +} GXBPFogRangeK; + +// BP locators for blend mode. +typedef enum _GXBPBlendMode { + // Blend enable [31-31] + GX_BP_BLENDMODE_ENABLE_ST = 31, + GX_BP_BLENDMODE_ENABLE_END = 31, + + // Logic operation enable [30-30] + GX_BP_BLENDMODE_LOGIC_OP_ST = 30, + GX_BP_BLENDMODE_LOGIC_OP_END = 30, + + // Dither [29-29] + GX_BP_BLENDMODE_DITHER_ST = 29, + GX_BP_BLENDMODE_DITHER_END = 29, + + // Color update [28-28] + GX_BP_BLENDMODE_COLOR_UPDATE_ST = 28, + GX_BP_BLENDMODE_COLOR_UPDATE_END = 28, + + // Alpha update [27-27] + GX_BP_BLENDMODE_ALPHA_UPDATE_ST = 27, + GX_BP_BLENDMODE_ALPHA_UPDATE_END = 27, + + // Destination factor [24-26] + GX_BP_BLENDMODE_DSTFACTOR_ST = 24, + GX_BP_BLENDMODE_DSTFACTOR_END = 26, + + // Source factor [21-23] + GX_BP_BLENDMODE_SRCFACTOR_ST = 21, + GX_BP_BLENDMODE_SRCFACTOR_END = 23, + + // Subtract [20-20] + GX_BP_BLENDMODE_SUBTRACT_ST = 20, + GX_BP_BLENDMODE_SUBTRACT_END = 20, + + // Logic mode [16-19] + GX_BP_BLENDMODE_LOGICMODE_ST = 16, + GX_BP_BLENDMODE_LOGICMODE_END = 19, +} GXBPBlendMode; + +// BP locators for Z mode. +typedef enum _GXBPZMode { + // Test enable [31-31] + GX_BP_ZMODE_TEST_ENABLE_ST = 31, + GX_BP_ZMODE_TEST_ENABLE_END = 31, + + // Compare [28-30] + GX_BP_ZMODE_COMPARE_ST = 28, + GX_BP_ZMODE_COMPARE_END = 30, + + // Update enable [27-27] + GX_BP_ZMODE_UPDATE_ENABLE_ST = 27, + GX_BP_ZMODE_UPDATE_ENABLE_END = 27, +} GXBPZMode; + +// BP locators for Z control. +typedef enum _GXBPZControl { + // Pixel format [29-31] + GX_BP_ZCONTROL_PIXEL_FMT_ST = 29, + GX_BP_ZCONTROL_PIXEL_FMT_END = 31, + + // Z format [26-28] + GX_BP_ZCONTROL_Z_FMT_ST = 26, + GX_BP_ZCONTROL_Z_FMT_END = 28, + + // Whether to do Z-buffering before or after texturing [25-25] + GX_BP_ZCONTROL_BEFORE_TEX_ST = 25, + GX_BP_ZCONTROL_BEFORE_TEX_END = 25, +} GXBPZControl; + +// BP locators for destination alpha. +typedef enum _GXBPDstAlpha { + // Alpha [24-31] + GX_BP_DSTALPHA_ALPHA_ST = 24, + GX_BP_DSTALPHA_ALPHA_END = 31, + + // Enable [23-23] + GX_BP_DSTALPHA_ENABLE_ST = 23, + GX_BP_DSTALPHA_ENABLE_END = 23, + + // YUV format [21-22] + GX_BP_DSTALPHA_YUV_FMT_ST = 21, + GX_BP_DSTALPHA_YUV_FMT_END = 22, +} GXBPDstAlpha; + +// BP locators for field mask. +typedef enum _GXBPFieldMask { + // Whether to write odd fields to the EFB [31-31] + GX_BP_FIELDMASK_ODD_ST = 31, + GX_BP_FIELDMASK_ODD_END = 31, + + // Whether to write even fields to the EFB [30-30] + GX_BP_FIELDMASK_EVEN_ST = 30, + GX_BP_FIELDMASK_EVEN_END = 30, +} GXBPFieldMask; + +// BP locators for line and point settings. +typedef enum _GXBPLinePtWidth { + // Line size/width [24-31] + GX_BP_LINEPTWIDTH_LINESZ_ST = 24, + GX_BP_LINEPTWIDTH_LINESZ_END = 31, + + // Point size [16-23] + GX_BP_LINEPTWIDTH_POINTSZ_ST = 16, + GX_BP_LINEPTWIDTH_POINTSZ_END = 23, + + // Line offset [13-15] + GX_BP_LINEPTWIDTH_LINEOFS_ST = 13, + GX_BP_LINEPTWIDTH_LINEOFS_END = 15, + + // Point offset [10-12] + GX_BP_LINEPTWIDTH_POINTOFS_ST = 10, + GX_BP_LINEPTWIDTH_POINTOFS_END = 12, + + // Interlacing adjustment for aspect ratio [9-9] + GX_BP_LINEPTWIDTH_ADJUST_ST = 9, + GX_BP_LINEPTWIDTH_ADJUST_END = 9, +} GXBPLinePtWidth; + +// Miscellaneous token types. +typedef enum _GXMiscToken { + GX_MT_NULL = 0, + GX_MT_XF_FLUSH = 1, + GX_MT_DL_SAVE_CONTEXT = 2, + GX_MT_ABORT_WAIT_COPYOUT = 3, +} GXMiscToken; + +// Transform memory types. +typedef enum _GXXfMem { + GX_XF_MEM_POSMTX = 0x000, // position coord matrix + GX_XF_MEM_NRMMTX = 0x400, // normal coord matrix + GX_XF_MEM_DUALTEXMTX = 0x500, // dual texture matrix + GX_XF_MEM_LIGHTOBJ = 0x600, // light object +} GXXfMem; + +// BP locators for top-left scissor. +typedef enum _GXBPScissorTL { + // Top component [21-31] + GX_BP_SCISSORTL_TOP_ST = 21, + GX_BP_SCISSORTL_TOP_END = 31, + + // Left component [9-19] + GX_BP_SCISSORTL_LEFT_ST = 9, + GX_BP_SCISSORTL_LEFT_END = 19, +} GXBPScissorTL; + +// BP locators for bottom-right scissor. +typedef enum _GXBPScissorBR { + // Bottom component [21-31] + GX_BP_SCISSORBR_BOT_ST = 21, + GX_BP_SCISSORBR_BOT_END = 31, + + // Right component [9-19] + GX_BP_SCISSORBR_RIGHT_ST = 9, + GX_BP_SCISSORBR_RIGHT_END = 19, +} GXBPScissorBR; + +// BP locators for scissor offset. +typedef enum _GXBPScissorOffset { + // X offset [22-31] + GX_BP_SCISSOROFS_OX_ST = 22, + GX_BP_SCISSOROFS_OX_END = 31, + + // Y offset [12-21] + GX_BP_SCISSOROFS_OY_ST = 12, + GX_BP_SCISSOROFS_OY_END = 21, +} GXBPScissorOffset; + +// Perf-0 types. +typedef enum _GXPerf0 { + GX_PERF0_VERTICES = 0, + GX_PERF0_CLIP_VTX = 1, + GX_PERF0_CLIP_CLKS = 2, + GX_PERF0_XF_WAIT_IN = 3, + GX_PERF0_XF_WAIT_OUT = 4, + GX_PERF0_XF_XFRM_CLKS = 5, + GX_PERF0_XF_LIT_CLKS = 6, + GX_PERF0_XF_BOT_CLKS = 7, + GX_PERF0_XF_REGLD_CLKS = 8, + GX_PERF0_XF_REGRD_CLKS = 9, + GX_PERF0_CLIP_RATIO = 10, + + GX_PERF0_TRIANGLES = 11, + GX_PERF0_TRIANGLES_CULLED = 12, + GX_PERF0_TRIANGLES_PASSED = 13, + GX_PERF0_TRIANGLES_SCISSORED = 14, + GX_PERF0_TRIANGLES_0TEX = 15, + GX_PERF0_TRIANGLES_1TEX = 16, + GX_PERF0_TRIANGLES_2TEX = 17, + GX_PERF0_TRIANGLES_3TEX = 18, + GX_PERF0_TRIANGLES_4TEX = 19, + GX_PERF0_TRIANGLES_5TEX = 20, + GX_PERF0_TRIANGLES_6TEX = 21, + GX_PERF0_TRIANGLES_7TEX = 22, + GX_PERF0_TRIANGLES_8TEX = 23, + GX_PERF0_TRIANGLES_0CLR = 24, + GX_PERF0_TRIANGLES_1CLR = 25, + GX_PERF0_TRIANGLES_2CLR = 26, + + GX_PERF0_QUAD_0CVG = 27, + GX_PERF0_QUAD_NON0CVG = 28, + GX_PERF0_QUAD_1CVG = 29, + GX_PERF0_QUAD_2CVG = 30, + GX_PERF0_QUAD_3CVG = 31, + GX_PERF0_QUAD_4CVG = 32, + GX_PERF0_AVG_QUAD_CNT = 33, + + GX_PERF0_CLOCKS = 34, + GX_PERF0_NONE = 35, +} GXPerf0; + +// Perf-1 types. +typedef enum _GXPerf1 { + GX_PERF1_TEXELS = 0, + GX_PERF1_TX_IDLE = 1, + GX_PERF1_TX_REGS = 2, + GX_PERF1_TX_MEMSTALL = 3, + GX_PERF1_TC_CHECK1_2 = 4, + GX_PERF1_TC_CHECK3_4 = 5, + GX_PERF1_TC_CHECK5_6 = 6, + GX_PERF1_TC_CHECK7_8 = 7, + GX_PERF1_TC_MISS = 8, + + GX_PERF1_VC_ELEMQ_FULL = 9, + GX_PERF1_VC_MISSQ_FULL = 10, + GX_PERF1_VC_MEMREQ_FULL = 11, + GX_PERF1_VC_STATUS7 = 12, + GX_PERF1_VC_MISSREP_FULL = 13, + GX_PERF1_VC_STREAMBUF_LOW = 14, + GX_PERF1_VC_ALL_STALLS = 15, + GX_PERF1_VERTICES = 16, + + GX_PERF1_FIFO_REQ = 17, + GX_PERF1_CALL_REQ = 18, + GX_PERF1_VC_MISS_REQ = 19, + GX_PERF1_CP_ALL_REQ = 20, + + GX_PERF1_CLOCKS = 21, + GX_PERF1_NONE = 22, +} GXPerf1; + +// Vertex cache perf types. +typedef enum _GXVCachePerf { + GX_VC_POS = 0, + GX_VC_NRM = 1, + GX_VC_CLR0 = 2, + GX_VC_CLR1 = 3, + GX_VC_TEX0 = 4, + GX_VC_TEX1 = 5, + GX_VC_TEX2 = 6, + GX_VC_TEX3 = 7, + GX_VC_TEX4 = 8, + GX_VC_TEX5 = 9, + GX_VC_TEX6 = 10, + GX_VC_TEX7 = 11, + + GX_VC_ALL = 15 +} GXVCachePerf; + +// XF locators for Color 0 control. +typedef enum _GXXFClr0Ctrl { + // Matrix source [31-31] + GX_XF_CLR0CTRL_MTXSRC_ST = 31, + GX_XF_CLR0CTRL_MTXSRC_END = 31, + + // Light [30-30] + GX_XF_CLR0CTRL_LIGHT_ST = 30, + GX_XF_CLR0CTRL_LIGHT_END = 30, + + // Light mask (hi) [26-29] + GX_XF_CLR0CTRL_LMASKHI_ST = 26, + GX_XF_CLR0CTRL_LMASKHI_END = 29, + + // Ambient source [25-25] + GX_XF_CLR0CTRL_AMBSRC_ST = 25, + GX_XF_CLR0CTRL_AMBSRC_END = 25, + + // Diffuse attenuation [23-24] + GX_XF_CLR0CTRL_DIFATTN_ST = 23, + GX_XF_CLR0CTRL_DIFATTN_END = 24, + + // Enable attentuation [22-22] + GX_XF_CLR0CTRL_ATTNENABLE_ST = 22, + GX_XF_CLR0CTRL_ATTNENABLE_END = 22, + + // Select attentuation [21-21] + GX_XF_CLR0CTRL_ATTNSEL_ST = 21, + GX_XF_CLR0CTRL_ATTNSEL_END = 21, + + // Light mask (lo) [17-20] + GX_XF_CLR0CTRL_LMASKLO_ST = 17, + GX_XF_CLR0CTRL_LMASKLO_END = 20, +} GXXFClr0Ctrl; + #endif /* GXENUM_H */ diff --git a/include/dolphin/gx/GXFifo.h b/include/dolphin/gx/GXFifo.h index 7bdfceee0..c234c51fe 100644 --- a/include/dolphin/gx/GXFifo.h +++ b/include/dolphin/gx/GXFifo.h @@ -9,27 +9,29 @@ extern "C" { #endif +typedef void (*GXBreakPtCallback)(void); + void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size); void GXInitFifoPtrs(GXFifoObj* fifo, void* read_ptr, void* write_ptr); -void GXSetCPUFifo(void); -void GXSetGPFifo(void); +void GXSetCPUFifo(GXFifoObj* fifo); +void GXSetGPFifo(GXFifoObj* fifo); void GXSaveCPUFifo(GXFifoObj* fifo); void __GXSaveCPUFifoAux(GXFifoObj* fifo); void GXGetGPStatus(GXBool* overhi, GXBool* underlo, GXBool* read_idle, GXBool* cmd_idle, GXBool* breakpoint); void* GXGetFifoBase(GXFifoObj* fifo); u32 GXGetFifoSize(GXFifoObj* fifo); -void GXSetBreakPtCallback(void); +GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb); void __GXFifoInit(void); void __GXFifoReadEnable(void); void __GXFifoReadDisable(void); void __GXFifoLink(u8); -void __GXWriteFifoIntEnable(u8, u8); -void __GXWriteFifoIntReset(u8, u8); +void __GXWriteFifoIntEnable(u32 p1, u32 p2); +void __GXWriteFifoIntReset(u32 p1, u32 p2); void __GXCleanGPFifo(void); OSThread* GXSetCurrentGXThread(void); OSThread* GXGetCurrentGXThread(void); GXFifoObj* GXGetCPUFifo(void); -u32 GXGetGPFifo(void); +GXFifoObj* GXGetGPFifo(void); #ifdef __cplusplus }; diff --git a/include/dolphin/gx/GXFrameBuf.h b/include/dolphin/gx/GXFrameBuf.h index ea4662b53..798cb8c2f 100644 --- a/include/dolphin/gx/GXFrameBuf.h +++ b/include/dolphin/gx/GXFrameBuf.h @@ -17,7 +17,7 @@ extern GXRenderModeObj GXEurgb60Hz480IntDf; void GXSetDispCopySrc(u16 left, u16 top, u16 width, u16 height); void GXSetTexCopySrc(u16 left, u16 top, u16 width, u16 height); void GXSetDispCopyDst(u16 arg0, u16 arg1); -void GXSetTexCopyDst(u16 width, u16 height, s32 fmt, GXBool mipmap); +void GXSetTexCopyDst(u16 width, u16 height, GXTexFmt format, GXBool useMIPmap); void GXSetDispCopyFrame2Field(GXCopyMode mode); void GXSetCopyClamp(GXFBClamp clamp); u16 GXGetNumXfbLines(u16 efb_height, f32 y_scale); diff --git a/include/dolphin/gx/GXInit.h b/include/dolphin/gx/GXInit.h index 72eef5a6c..87e9a754a 100644 --- a/include/dolphin/gx/GXInit.h +++ b/include/dolphin/gx/GXInit.h @@ -5,112 +5,159 @@ #include "dolphin/gx/GXStruct.h" #include "dolphin/mtx/mtx.h" -typedef GXTexRegion (*GXTexRegionCallback)(GXTexObj* obj); -typedef GXTlutRegion* (*GXTlutRegionCallback)(u32 name); +typedef GXTexRegion* (*GXTexRegionCallback)(const GXTexObj* t_obj, GXTexMapID id); +typedef GXTlutRegion* (*GXTlutRegionCallback)(u32 idx); typedef struct _GXData { - /* 0x000 */ u16 field_0x0; - /* 0x002 */ u16 field_0x2; - /* 0x004 */ u16 field_0x4; - /* 0x006 */ u16 field_0x6; - /* 0x008 */ u32 field_0x8; - /* 0x00C */ u32 field_0xc; - /* 0x010 */ u32 field_0x10; - /* 0x014 */ u32 field_0x14; - /* 0x018 */ GXAttrType field_0x18; - /* 0x01C */ GXCompCnt field_0x1c[8]; - /* 0x03C */ GXCompCnt field_0x3c[8]; - /* 0x05C */ u32 field_0x5c[8]; - /* 0x07C */ u32 field_0x7c; - /* 0x080 */ u32 field_0x80; - /* 0x084 */ u32 field_0x84; - /* 0x088 */ u8 field_0x88[0xA8 - 0x88]; - /* 0x0A8 */ GXColor ambColors[2]; - /* 0x0B0 */ GXColor matColors[2]; - /* 0x0B8 */ u32 field_0xb8[8]; // GX_MAX_TEXCOORD - /* 0x0D8 */ u32 field_0xd8[8]; // GX_MAX_TEXCOORD - /* 0x0F8 */ u32 field_0xf8; - /* 0x0FC */ u32 field_0xfc; - /* 0x100 */ u32 field_0x100[GX_MAX_TEVSTAGE / 2]; - /* 0x120 */ u32 field_0x120; - /* 0x124 */ u32 field_0x124; - /* 0x128 */ u32 field_0x128; - /* 0x12C */ u32 field_0x12c; - /* 0x130 */ u32 field_0x130[GX_MAX_TEVSTAGE]; - /* 0x170 */ u32 field_0x170[GX_MAX_TEVSTAGE]; - /* 0x1B0 */ u32 field_0x1b0[GX_MAX_TEVSTAGE / 2]; - /* 0x1D0 */ u32 field_0x1d0; - /* 0x1D4 */ u32 field_0x1d4; - /* 0x1D8 */ u32 field_0x1d8; - /* 0x1DC */ u32 field_0x1dc; - /* 0x1E0 */ u32 field_0x1e0; - /* 0x1E4 */ u32 field_0x1e4; - /* 0x1E8 */ u32 field_0x1e8; - /* 0x1EC */ u32 field_0x1ec; - /* 0x1F0 */ u32 field_0x1f0; - /* 0x1F4 */ u32 field_0x1f4; - /* 0x1F8 */ u32 field_0x1f8; - /* 0x1FC */ u32 field_0x1fc; - /* 0x200 */ u8 field_0x200; - /* 0x204 */ u32 field_0x204; - /* 0x208 */ GXTexRegion field_0x208[8]; - /* 0x288 */ GXTexRegion field_0x288[8]; - /* 0x308 */ GXTexRegion field_0x308[8]; - /* 0x388 */ GXTlutRegion field_0x388[16]; - /* 0x488 */ GXTlutRegion field_0x488[4]; - /* 0x4C8 */ GXTexRegionCallback field_0x4c8; - /* 0x4CC */ GXTlutRegionCallback field_0x4cc; - /* 0x4D0 */ GXAttrType field_0x4d0; - /* 0x4D4 */ u8 field_0x4d4; - /* 0x4D5 */ u8 field_0x4d5; - /* 0x4D8 */ GXProjectionType field_0x4d8; - /* 0x4DC */ Mtx field_0x4dc; - /* 0x50C */ f32 field_0x50c; - /* 0x510 */ f32 field_0x510; - /* 0x514 */ u32 field_0x514[8]; - /* 0x534 */ u32 field_0x534[8]; - /* 0x554 */ u32 field_0x554; - /* 0x558 */ u32 field_0x558[8]; - /* 0x578 */ u8 field_0x578[0x594 - 0x578]; - /* 0x594 */ u32 field_0x594; - /* 0x598 */ u32 field_0x598; - /* 0x59C */ u32 field_0x59c; - /* 0x5A0 */ u8 field_0x5a0[4]; - /* 0x5A4 */ u32 field_0x5a4; - /* 0x5A8 */ u8 field_0x5a8; - /* 0x5A9 */ u8 field_0x5a9; - /* 0x5AA */ u8 field_0x5aa; - /* 0x5AB */ u8 field_0x5ab; - /* 0x5AC */ u32 field_0x5ac; + // Bypass and vertex info + /* 0x000 */ u16 vNumNot; + /* 0x002 */ u16 bpSentNot; + /* 0x004 */ u16 vNum; + /* 0x006 */ u16 vLim; + + // Command process (CP) regs + /* 0x008 */ u32 cpEnable; + /* 0x00C */ u32 cpStatus; + /* 0x010 */ u32 cpClr; + /* 0x014 */ u32 vcdLo; + /* 0x018 */ u32 vcdHi; + /* 0x01C */ u32 vatA[8]; + /* 0x03C */ u32 vatB[8]; + /* 0x05C */ u32 vatC[8]; + /* 0x07C */ u32 lpSize; + /* 0x080 */ u32 matIdxA; + /* 0x084 */ u32 matIdxB; + + // Index loading base/stride regs (pos, nrm, tex, light) + /* 0x088 */ u32 indexBase[4]; + /* 0x098 */ u32 indexStride[4]; + + // Transform and lighting regs + /* 0x0A8 */ u32 ambColor[2]; + /* 0x0B0 */ u32 matColor[2]; + + // Setup regs + /* 0x0B8 */ u32 suTs0[8]; + /* 0x0D8 */ u32 suTs1[8]; + /* 0x0F8 */ u32 suScis0; + /* 0x0FC */ u32 suScis1; + + // Raster regs + /* 0x100 */ u32 tref[8]; + /* 0x120 */ u32 iref; + + // Bump/Indirect texture regs + /* 0x124 */ u32 bpMask; + /* 0x128 */ u32 IndTexScale0; + /* 0x12C */ u32 IndTexScale1; + + // Tev regs + /* 0x130 */ u32 tevc[16]; + /* 0x170 */ u32 teva[16]; + /* 0x1B0 */ u32 tevKsel[8]; + + // Performance regs + /* 0x1D0 */ u32 cmode0; + /* 0x1D4 */ u32 cmode1; + /* 0x1D8 */ u32 zmode; + /* 0x1DC */ u32 peCtrl; + + // Display copy regs + /* 0x1E0 */ u32 cpDispSrc; + /* 0x1E4 */ u32 cpDispSize; + /* 0x1E8 */ u32 cpDispStride; + /* 0x1EC */ u32 cpDisp; + + // Texture copy regs + /* 0x1F0 */ u32 cpTexSrc; + /* 0x1F4 */ u32 cpTexSize; + /* 0x1F8 */ u32 cpTexStride; + /* 0x1FC */ u32 cpTex; + /* 0x200 */ GXBool cpTexZ; + + // General raster mode + /* 0x204 */ u32 genMode; + + // Texture regions + /* 0x208 */ GXTexRegion TexRegions0[GX_MAX_TEXMAP]; + /* 0x288 */ GXTexRegion TexRegions1[GX_MAX_TEXMAP]; + /* 0x308 */ GXTexRegion TexRegions2[GX_MAX_TEXMAP]; + + // Texture lookup table regions + /* 0x388 */ GXTlutRegion TlutRegions[GX_MAX_TLUT_ALL]; + /* 0x4C8 */ GXTexRegionCallback texRegionCallback; + /* 0x4CC */ GXTlutRegionCallback tlutRegionCallback; + + // Command processor vars + /* 0x4D0 */ GXAttrType nrmType; + /* 0x4D4 */ GXBool hasNrms; + /* 0x4D5 */ GXBool hasBiNrms; + /* 0x4D8 */ u32 projType; + /* 0x4DC */ f32 projMtx[6]; + + // Viewport parms + /* 0x4F4 */ f32 vpLeft; + /* 0x4F8 */ f32 vpTop; + /* 0x4FC */ f32 vpWd; + /* 0x500 */ f32 vpHt; + /* 0x504 */ f32 vpNearz; + /* 0x508 */ f32 vpFarz; + /* 0x50C */ f32 zOffset; + /* 0x510 */ f32 zScale; + + // Texture regs + /* 0x514 */ u32 tImage0[8]; + /* 0x534 */ u32 tMode0[8]; + /* 0x554 */ u32 texmapId[16]; + /* 0x594 */ u32 tcsManEnab; + /* 0x598 */ u32 tevTcEnab; + + // Performance metrics + /* 0x59C */ GXPerf0 perf0; + /* 0x5A0 */ GXPerf1 perf1; + /* 0x5A4 */ u32 perfSel; + + // Flags + /* 0x5A8 */ GXBool inDispList; + /* 0x5A9 */ GXBool dlSaveContext; + /* 0x5AA */ GXBool abtWaitPECopy; + /* 0x5AB */ u8 dirtyVAT; + /* 0x5AC */ u32 dirtyState; } GXData; // Size: 0x5B0 STATIC_ASSERT(sizeof(GXData) == 0x5B0); extern GXData* const __GXData; +// Define register addresses. +#define GX_CP_ADDR (0x0C000000) +#define GX_PE_ADDR (0x0C001000) +#define GX_PI_ADDR (0x0C003000) +#define GX_MEM_ADDR (0x0C004000) + extern u32* __piReg; extern u16* __cpReg; -extern u8 __peReg[4]; -extern u8 __memReg[4]; +extern u16* __peReg; +extern vu16* __memReg; inline void GXSetWasteFlags() { - GXData* data = __GXData; - data->field_0x5ac |= 0x3; - data->field_0x2 = 0; + GXData* data = __GXData; + data->dirtyState |= GX_DIRTY_SU_TEX | GX_DIRTY_BP_MASK; + data->bpSentNot = 0; } static inline void set_x2(u16 value) { - __GXData->field_0x2 = value; + __GXData->bpSentNot = value; } #ifdef __cplusplus extern "C" { #endif -GXTexRegion* __GXDefaultTexRegionCallback(GXTexObj* obj, GXTexMapID mapID); +GXTexRegion* __GXDefaultTexRegionCallback(const GXTexObj* obj, GXTexMapID id); GXTlutRegion* __GXDefaultTlutRegionCallback(u32 tlut); -void __GXShutdown(s32); +BOOL __GXShutdown(BOOL final); void __GXInitRevisionBits(void); GXFifoObj* GXInit(void* base, u32 size); void __GXInitGX(void); diff --git a/include/dolphin/gx/GXMisc.h b/include/dolphin/gx/GXMisc.h index 7c4524b65..86213dab4 100644 --- a/include/dolphin/gx/GXMisc.h +++ b/include/dolphin/gx/GXMisc.h @@ -7,7 +7,7 @@ extern "C" { #endif -void GXSetMisc(u32 id, u32 value); +void GXSetMisc(GXMiscToken token, u32 val); void GXFlush(void); void __GXAbort(void); void GXAbortFrame(void); @@ -21,7 +21,7 @@ void GXPokeBlendMode(GXBlendMode mode, GXBlendFactor src_factor, GXBlendFactor d void GXPokeColorUpdate(GXBool enable_update); void GXPokeDstAlpha(GXBool enable, u8 alpha); void GXPokeDither(GXBool enable); -void GXPokeZMode(GXBool enable_compare, GXCompare comp); +void GXPokeZMode(GXBool enable_compare, GXCompare comp, GXBool update_enable); void GXPeekARGB(u16 x, u16 y, u32* color); void GXPeekZ(u16 x, u16 y, u32* z); @@ -30,7 +30,7 @@ GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback callback); void GXSetDrawSync(GXBool enable); typedef void (*GXDrawDoneCallback)(void); -void GXSetDrawDoneCallback(GXDrawDoneCallback callback); +GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback callback); void __GXPEInit(void); #ifdef __cplusplus diff --git a/include/dolphin/gx/GXPerf.h b/include/dolphin/gx/GXPerf.h index 821c81b2b..3edd9ea4f 100644 --- a/include/dolphin/gx/GXPerf.h +++ b/include/dolphin/gx/GXPerf.h @@ -1,13 +1,13 @@ #ifndef GXPERF_H #define GXPERF_H -#include "dolphin/types.h" +#include "dolphin/gx/GXEnum.h" #ifdef __cplusplus extern "C" { #endif -void GXSetGPMetric(u32 perf0, u32 perf1); +void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1); void GXClearGPMetric(void); void GXReadXfRasMetric(u32*, u32*, u32*, u32*); diff --git a/include/dolphin/gx/GXStruct.h b/include/dolphin/gx/GXStruct.h index 57e02316c..146fa09a0 100644 --- a/include/dolphin/gx/GXStruct.h +++ b/include/dolphin/gx/GXStruct.h @@ -2,6 +2,8 @@ #define GXSTRUCT_H #include "global.h" +#include "dolphin/gx/GXEnum.h" +#include "dolphin/vi/vi.h" typedef struct _GXColor { /* 0x0 */ u8 r; @@ -72,18 +74,18 @@ typedef struct _GXLightObj { } GXLightObj; typedef struct _GXFogAdjTable { - /* 0x0 */ u16 r[10]; + /* 0x0 */ u16 fogVals[10]; } GXFogAdjTable; typedef struct _GXFifoObj { /* 0x00 */ void* base; - /* 0x04 */ u32 end; + /* 0x04 */ void* end; /* 0x08 */ u32 size; /* 0x0C */ u32 high_wtrmark; /* 0x10 */ u32 low_wtrmark; /* 0x14 */ void* read_ptr; /* 0x18 */ void* write_ptr; - /* 0x1C */ void* rw_dst; + /* 0x1C */ s32 rw_dst; /* 0x20 */ u8 fifo_wrap; /* 0x21 */ u8 cpu_fifo_ready; /* 0x22 */ u8 gp_fifo_ready; @@ -91,11 +93,16 @@ typedef struct _GXFifoObj { } GXFifoObj; // Size: 0x80 typedef struct _GXTexRegion { - /* 0x00 */ u8 dummy[0x10]; + u32 unk0; // _00 + u32 unk4; // _04 + u32 unk8; // _08 + u8 unkC; // _0C + u8 unkD; // _0D } GXTexRegion; // Size: 0x10 typedef struct _GXTlutRegion { - /* 0x00 */ u8 dummy[0x10]; + /* 0x00 */ u32 unk0; + /* 0x04 */ GXTlutObj tlutObj; } GXTlutRegion; // Size: 0x10 #endif /* GXSTRUCT_H */ diff --git a/include/dolphin/gx/GXTexture.h b/include/dolphin/gx/GXTexture.h index fc039dabc..3c1013060 100644 --- a/include/dolphin/gx/GXTexture.h +++ b/include/dolphin/gx/GXTexture.h @@ -8,7 +8,7 @@ extern "C" { #endif u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod); -void __GetImageTileCount(u32 arg0, s16 arg1, s16 arg2, s32* arg3, s32* arg4, s32* arg5); +void __GetImageTileCount(GXTexFmt format, u16 width, u16 height, u32* a, u32* b, u32* c); void GXInitTexObj(GXTexObj* obj, void* image, u16 width, u16 height, GXTexFmt fmt, GXTexWrapMode wrapS, GXTexWrapMode wrapT, GXBool mipmap); void GXInitTexObjCI(GXTexObj* obj, void* image, u16 width, u16 height, GXCITexFmt format, @@ -19,10 +19,10 @@ void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filter, GXTexFilter max_filt void* GXGetTexObjData(GXTexObj* obj); u16 GXGetTexObjWidth(GXTexObj* obj); u16 GXGetTexObjHeight(GXTexObj* obj); -GXTexFmt GXGetTexObjFmt(GXTexObj* obj); +GXTexFmt GXGetTexObjFmt(const GXTexObj* obj); GXTexWrapMode GXGetTexObjWrapS(GXTexObj* obj); GXTexWrapMode GXGetTexObjWrapT(GXTexObj* obj); -GXBool GXGetTexObjMipMap(GXTexObj* obj); +GXBool GXGetTexObjMipMap(const GXTexObj* obj); u32 GXGetTexObjTlut(GXTexObj* obj); void GXLoadTexObj(GXTexObj* obj, GXTexMapID id); void GXInitTlutObj(GXTlutObj* obj, void* lut, GXTlutFmt fmt, u16 entry_num); diff --git a/include/dolphin/gx/GXTransform.h b/include/dolphin/gx/GXTransform.h index 98462c5de..af4b1ccd4 100644 --- a/include/dolphin/gx/GXTransform.h +++ b/include/dolphin/gx/GXTransform.h @@ -9,18 +9,18 @@ extern "C" { #endif void GXProject(f32 model_x, f32 model_y, f32 model_z, Mtx model_mtx, f32* proj, f32* viewpoint, f32* screen_x, f32* screen_y, f32* screen_z); -void GXSetProjection(Mtx44 mtx, GXProjectionType type); +void GXSetProjection(const Mtx44 proj, GXProjectionType type); void GXSetProjectionv(f32* p); void GXGetProjectionv(f32* p); void GXLoadPosMtxImm(Mtx mtx, u32 id); void GXLoadNrmMtxImm(Mtx mtx, u32 id); void GXSetCurrentMtx(u32 id); -void GXLoadTexMtxImm(Mtx mtx, u32 id, GXTexMtxType type); +void GXLoadTexMtxImm(const Mtx mtx, u32 id, GXTexMtxType type); void GXSetViewport(f32 x_orig, f32 y_orig, f32 width, f32 height, f32 near_z, f32 far_z); void GXGetViewportv(f32* p); void GXSetScissor(u32 left, u32 top, u32 width, u32 height); void GXGetScissor(u32* left, u32* top, u32* width, u32* height); -void GXSetScissorBoxOffset(u32 x_offset, u32 y_offset); +void GXSetScissorBoxOffset(s32 x, s32 y); void GXSetClipMode(GXClipMode mode); #ifdef __cplusplus diff --git a/include/dolphin/os/OSError.h b/include/dolphin/os/OSError.h index 833ce3463..159c32f28 100644 --- a/include/dolphin/os/OSError.h +++ b/include/dolphin/os/OSError.h @@ -41,7 +41,7 @@ typedef enum { EXCEPTION_FLOATING_POINT, EXCEPTION_DECREMENTER, EXCEPTION_SYSTEM_CALL, - EXCEPTION_TRACE , + EXCEPTION_TRACE, EXCEPTION_PERFORMANCE_MONITOR, EXCEPTION_BREAKPOINT, EXCEPTION_RESERVED, diff --git a/include/dolphin/os/OSMessage.h b/include/dolphin/os/OSMessage.h index 25f153616..1e0c09a47 100644 --- a/include/dolphin/os/OSMessage.h +++ b/include/dolphin/os/OSMessage.h @@ -23,7 +23,7 @@ typedef struct OSMessageQueue { #define OS_MESSAGE_BLOCK 1 typedef enum { - OS_MSG_PERSISTENT = (1 << 0), + OS_MSG_PERSISTENT = (1 << 0), } OSMessageFlags; void OSInitMessageQueue(OSMessageQueue* queue, OSMessage* msgArray, s32 msgCount); diff --git a/include/dolphin/vi/vi.h b/include/dolphin/vi/vi.h index 901879e5e..a5bb9b9c7 100644 --- a/include/dolphin/vi/vi.h +++ b/include/dolphin/vi/vi.h @@ -10,37 +10,120 @@ extern "C" { typedef struct _GXRenderModeObj GXRenderModeObj; -#define VI_TVMODE(format, interlace) (((format) << 2) + (interlace)) +#define VI_INTERLACE (0) +#define VI_NON_INTERLACE (1) +#define VI_PROGRESSIVE (2) +#define VI_3D (3) -#define VI_INTERLACE 0 -#define VI_NON_INTERLACE 1 -#define VI_PROGRESSIVE 2 +// Video output formats +#define VI_NTSC (0) +#define VI_PAL (1) +#define VI_MPAL (2) +#define VI_DEBUG (3) +#define VI_DEBUG_PAL (4) +#define VI_EURGB60 (5) +#define VI_GCA (6) -#define VI_NTSC 0 -#define VI_PAL 1 -#define VI_MPAL 2 -#define VI_DEBUG 3 -#define VI_DEBUG_PAL 4 -#define VI_EURGB60 5 +// Conversion to TVMode used in enums +#define VI_TVMODE(FMT, INT) (((FMT) << 2) + (INT)) +// TV Modes typedef enum { - VI_TVMODE_NTSC_INT = VI_TVMODE(VI_NTSC, VI_INTERLACE), - VI_TVMODE_NTSC_DS = VI_TVMODE(VI_NTSC, VI_NON_INTERLACE), - VI_TVMODE_NTSC_PROG = VI_TVMODE(VI_NTSC, VI_PROGRESSIVE), - VI_TVMODE_PAL_INT = VI_TVMODE(VI_PAL, VI_INTERLACE), - VI_TVMODE_PAL_DS = VI_TVMODE(VI_PAL, VI_NON_INTERLACE), - VI_TVMODE_EURGB60_INT = VI_TVMODE(VI_EURGB60, VI_INTERLACE), - VI_TVMODE_EURGB60_DS = VI_TVMODE(VI_EURGB60, VI_NON_INTERLACE), - VI_TVMODE_MPAL_INT = VI_TVMODE(VI_MPAL, VI_INTERLACE), - VI_TVMODE_MPAL_DS = VI_TVMODE(VI_MPAL, VI_NON_INTERLACE), - VI_TVMODE_DEBUG_INT = VI_TVMODE(VI_DEBUG, VI_INTERLACE), - VI_TVMODE_DEBUG_PAL_INT = VI_TVMODE(VI_DEBUG_PAL, VI_INTERLACE), - VI_TVMODE_DEBUG_PAL_DS = VI_TVMODE(VI_DEBUG_PAL, VI_NON_INTERLACE) + // NTSC + VI_TVMODE_NTSC_INT = VI_TVMODE(VI_NTSC, VI_INTERLACE), // 0 + VI_TVMODE_NTSC_DS = VI_TVMODE(VI_NTSC, VI_NON_INTERLACE), // 1 + VI_TVMODE_NTSC_PROG = VI_TVMODE(VI_NTSC, VI_PROGRESSIVE), // 2 + VI_TVMODE_NTSC_3D = VI_TVMODE(VI_NTSC, VI_3D), // 3 + + // PAL + VI_TVMODE_PAL_INT = VI_TVMODE(VI_PAL, VI_INTERLACE), // 4 + VI_TVMODE_PAL_DS = VI_TVMODE(VI_PAL, VI_NON_INTERLACE), // 5 + + // MPAL + VI_TVMODE_MPAL_INT = VI_TVMODE(VI_MPAL, VI_INTERLACE), // 8 + VI_TVMODE_MPAL_DS = VI_TVMODE(VI_MPAL, VI_NON_INTERLACE), // 9 + + // Debug + VI_TVMODE_DEBUG_INT = VI_TVMODE(VI_DEBUG, VI_INTERLACE), // 12 + + // Debug PAL + VI_TVMODE_DEBUG_PAL_INT = VI_TVMODE(VI_DEBUG_PAL, VI_INTERLACE), // 16 + VI_TVMODE_DEBUG_PAL_DS = VI_TVMODE(VI_DEBUG_PAL, VI_NON_INTERLACE), // 17 + + // EU RGB60 + VI_TVMODE_EURGB60_INT = VI_TVMODE(VI_EURGB60, VI_INTERLACE), // 20 + VI_TVMODE_EURGB60_DS = VI_TVMODE(VI_EURGB60, VI_NON_INTERLACE), // 21 + + // GCA + VI_TVMODE_GCA_INT = VI_TVMODE(VI_GCA, VI_INTERLACE), // 24 + VI_TVMODE_GCA_DS = VI_TVMODE(VI_GCA, VI_NON_INTERLACE), // 25 + VI_TVMODE_GCA_PROG = VI_TVMODE(VI_GCA, VI_PROGRESSIVE), // 26 } VITVMode; typedef enum { VI_XFBMODE_SF = 0, VI_XFBMODE_DF } VIXFBMode; typedef void (*VIRetraceCallback)(u32); +typedef void (*VIPositionCallback)(s16 x, s16 y); + +typedef struct VITimingInfo { + u8 equ; // _00 + u16 acv; // _02 + u16 prbOdd; // _04 + u16 prbEven; // _06 + u16 psbOdd; // _08 + u16 psbEven; // _0A + u8 bs1; // _0C + u8 bs2; // _0D + u8 bs3; // _0E + u8 bs4; // _0F + u16 be1; // _10 + u16 be2; // _12 + u16 be3; // _14 + u16 be4; // _16 + u16 numHalfLines; // _18 + u16 hlw; // _1A + u8 hsy; // _1C + u8 hcs; // _1D + u8 hce; // _1E + u8 hbe640; // _1F + u16 hbs640; // _20 + u8 hbeCCIR656; // _24 + u16 hbsCCIR656; // _26 +} VITimingInfo; + +typedef struct VIPositionInfo { + u16 dispPosX; // _00 + u16 dispPosY; // _02 + u16 dispSizeX; // _04 + u16 dispSizeY; // _06 + u16 adjDispPosX; // _08 + u16 adjDispPosY; // _0A + u16 adjDispSizeY; // _0C + u16 adjPanPosY; // _0E + u16 adjPanSizeY; // _10 + u16 fbSizeX; // _12 + u16 fbSizeY; // _14 + u16 panPosX; // _16 + u16 panPosY; // _18 + u16 panSizeX; // _1A + u16 panSizeY; // _1C + VIXFBMode xfbMode; // _20 + u32 nonInter; // _24 + u32 tv; // _28 + u8 wordPerLine; // _2C + u8 std; // _2D + u8 wpl; // _2E + u32 bufAddr; // _30 + u32 tfbb; // _34 + u32 bfbb; // _38 + u8 xof; // _3C + BOOL isBlack; // _40 + BOOL is3D; // _44 + u32 rbufAddr; // _48 + u32 rtfbb; // _4C + u32 rbfbb; // _50 + VITimingInfo* timing; // _54 +} VIPositionInfo; void VIWaitForRetrace(void); void VISetNextFrameBuffer(void*); diff --git a/src/JSystem/J3DGraphBase/J3DGD.cpp b/src/JSystem/J3DGraphBase/J3DGD.cpp index 95d501a86..555558cf2 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 3ef85963a..8e910641c 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 5aeea12db..ac9a624ad 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 a173a6d85..6107f5fdd 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 000000000..724710e96 --- /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 000000000..8c1084df4 --- /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 000000000..eaebb628d --- /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 000000000..22311b3ba --- /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 000000000..7ff20556b --- /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 000000000..3cedf7e68 --- /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 000000000..a6de95607 --- /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 000000000..f8e470614 --- /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 000000000..a90c2a21c --- /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 000000000..468192ea7 --- /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 000000000..60591b0b9 --- /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 000000000..f3448bc3f --- /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 000000000..af060678e --- /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 000000000..e4b8485d7 --- /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 000000000..1bf66bbbe --- /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 10618b763..9c84bb001 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();