335 lines
12 KiB
C
335 lines
12 KiB
C
#include <dolphin/gx.h>
|
|
#include <dolphin/os.h>
|
|
|
|
#include <dolphin/gx/GXPriv.h>
|
|
|
|
#if DEBUG
|
|
#define GX_WRITE_SOME_REG5(a, b) \
|
|
do { \
|
|
GX_WRITE_U8(a); \
|
|
GX_WRITE_U32(b); \
|
|
__gxVerif->rasRegs[(b >> 24) & 0xFF] = b; \
|
|
} while (0)
|
|
#else
|
|
#define GX_WRITE_SOME_REG5(a, b) \
|
|
do { \
|
|
GX_WRITE_U8(a); \
|
|
GX_WRITE_U32(b); \
|
|
} while (0)
|
|
#endif
|
|
|
|
void GXSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexFormat format, GXIndTexBiasSel bias_sel, GXIndTexMtxID matrix_sel,
|
|
GXIndTexWrap wrap_s, GXIndTexWrap wrap_t, GXBool add_prev, GXBool utc_lod, GXIndTexAlphaSel alpha_sel)
|
|
{
|
|
u32 reg;
|
|
|
|
CHECK_GXBEGIN(0x92, "GXInitIndTexture");
|
|
reg = 0;
|
|
SET_REG_FIELD(0x81, reg, 2, 0, ind_stage);
|
|
SET_REG_FIELD(0x82, reg, 2, 2, format);
|
|
SET_REG_FIELD(0x83, reg, 3, 4, bias_sel);
|
|
SET_REG_FIELD(0x84, reg, 2, 7, alpha_sel);
|
|
SET_REG_FIELD(0x85, reg, 4, 9, matrix_sel);
|
|
SET_REG_FIELD(0x86, reg, 3, 13, wrap_s);
|
|
SET_REG_FIELD(0x87, reg, 3, 16, wrap_t);
|
|
SET_REG_FIELD(0x88, reg, 1, 19, utc_lod);
|
|
SET_REG_FIELD(0x89, reg, 1, 20, add_prev);
|
|
SET_REG_FIELD(0x8A, reg, 8, 24, tev_stage + 16);
|
|
GX_WRITE_SOME_REG5(0x61, reg);
|
|
gx->bpSentNot = 0;
|
|
}
|
|
|
|
void GXSetIndTexMtx(GXIndTexMtxID mtx_id, f32 offset[2][3], s8 scale_exp)
|
|
{
|
|
s32 mtx[6];
|
|
u32 reg;
|
|
u32 id;
|
|
|
|
CHECK_GXBEGIN(0xBA, "GXSetIndTexMtx");
|
|
|
|
switch (mtx_id) {
|
|
case GX_ITM_0:
|
|
case GX_ITM_1:
|
|
case GX_ITM_2:
|
|
id = mtx_id - 1;
|
|
break;
|
|
case GX_ITM_S0:
|
|
case GX_ITM_S1:
|
|
case GX_ITM_S2:
|
|
id = mtx_id - 5;
|
|
break;
|
|
case GX_ITM_T0:
|
|
case GX_ITM_T1:
|
|
case GX_ITM_T2:
|
|
id = mtx_id - 9;
|
|
break;
|
|
default:
|
|
id = 0;
|
|
break;
|
|
}
|
|
|
|
mtx[0] = (int)(1024.0f * offset[0][0]) & 0x7FF;
|
|
mtx[1] = (int)(1024.0f * offset[1][0]) & 0x7FF;
|
|
scale_exp += 0x11;
|
|
reg = 0;
|
|
SET_REG_FIELD(0xBD, reg, 11, 0, mtx[0]);
|
|
SET_REG_FIELD(0xBE, reg, 11, 11, mtx[1]);
|
|
SET_REG_FIELD(0xBF, reg, 2, 22, scale_exp & 3);
|
|
SET_REG_FIELD(0xC0, reg, 8, 24, id * 3 + 6);
|
|
GX_WRITE_SOME_REG5(0x61, reg);
|
|
|
|
mtx[2] = (int)(1024.0f * offset[0][1]) & 0x7FF;
|
|
mtx[3] = (int)(1024.0f * offset[1][1]) & 0x7FF;
|
|
reg = 0;
|
|
SET_REG_FIELD(0xC6, reg, 11, 0, mtx[2]);
|
|
SET_REG_FIELD(0xC7, reg, 11, 11, mtx[3]);
|
|
SET_REG_FIELD(0xC8, reg, 2, 22, (scale_exp >> 2) & 3);
|
|
SET_REG_FIELD(0xC9, reg, 8, 24, id * 3 + 7);
|
|
GX_WRITE_SOME_REG5(0x61, reg);
|
|
|
|
mtx[4] = (int)(1024.0f * offset[0][2]) & 0x7FF;
|
|
mtx[5] = (int)(1024.0f * offset[1][2]) & 0x7FF;
|
|
reg = 0;
|
|
SET_REG_FIELD(0xCF, reg, 11, 0, mtx[4]);
|
|
SET_REG_FIELD(0xD0, reg, 11, 11, mtx[5]);
|
|
SET_REG_FIELD(0xD1, reg, 2, 22, (scale_exp >> 4) & 3);
|
|
SET_REG_FIELD(0xD2, reg, 8, 24, id * 3 + 8);
|
|
GX_WRITE_SOME_REG5(0x61, reg);
|
|
|
|
gx->bpSentNot = 0;
|
|
}
|
|
|
|
void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXIndTexScale scale_t)
|
|
{
|
|
CHECK_GXBEGIN(0xF9, "GXSetIndTexScale");
|
|
|
|
switch (ind_state) {
|
|
case GX_INDTEXSTAGE0:
|
|
SET_REG_FIELD(0xEA, gx->IndTexScale0, 4, 0, scale_s);
|
|
SET_REG_FIELD(0xEB, gx->IndTexScale0, 4, 4, scale_t);
|
|
SET_REG_FIELD(0xEC, gx->IndTexScale0, 8, 24, 0x25);
|
|
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale0);
|
|
break;
|
|
case GX_INDTEXSTAGE1:
|
|
SET_REG_FIELD(0xF0, gx->IndTexScale0, 4, 8, scale_s);
|
|
SET_REG_FIELD(0xF1, gx->IndTexScale0, 4, 12, scale_t);
|
|
SET_REG_FIELD(0xF2, gx->IndTexScale0, 8, 24, 0x25);
|
|
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale0);
|
|
break;
|
|
case GX_INDTEXSTAGE2:
|
|
SET_REG_FIELD(0xF6, gx->IndTexScale1, 4, 0, scale_s);
|
|
SET_REG_FIELD(0xF7, gx->IndTexScale1, 4, 4, scale_t);
|
|
SET_REG_FIELD(0xF8, gx->IndTexScale1, 8, 24, 0x26);
|
|
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale1);
|
|
break;
|
|
case GX_INDTEXSTAGE3:
|
|
SET_REG_FIELD(0xFC, gx->IndTexScale1, 4, 8, scale_s);
|
|
SET_REG_FIELD(0xFD, gx->IndTexScale1, 4, 12, scale_t);
|
|
SET_REG_FIELD(0xFE, gx->IndTexScale1, 8, 24, 0x26);
|
|
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale1);
|
|
break;
|
|
default:
|
|
ASSERTMSGLINE(0x115, 0, "GXSetIndTexCoordScale: Invalid Indirect Stage Id");
|
|
break;
|
|
}
|
|
gx->bpSentNot = 0;
|
|
}
|
|
|
|
void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMapID tex_map)
|
|
{
|
|
CHECK_GXBEGIN(0x12E, "GXSetIndTexOrder");
|
|
|
|
ASSERTMSGLINE(0x11D, tex_map < 8, "GXSetIndTexOrder: Invalid direct texture Id");
|
|
ASSERTMSGLINE(0x11E, tex_coord < 8, "GXSetIndTexOrder: Invalid texture coord");
|
|
switch (ind_stage) {
|
|
case GX_INDTEXSTAGE0:
|
|
SET_REG_FIELD(0x122, gx->iref, 3, 0, tex_map);
|
|
SET_REG_FIELD(0x123, gx->iref, 3, 3, tex_coord);
|
|
break;
|
|
case GX_INDTEXSTAGE1:
|
|
SET_REG_FIELD(0x126, gx->iref, 3, 6, tex_map);
|
|
SET_REG_FIELD(0x127, gx->iref, 3, 9, tex_coord);
|
|
break;
|
|
case GX_INDTEXSTAGE2:
|
|
SET_REG_FIELD(0x12A, gx->iref, 3, 12, tex_map);
|
|
SET_REG_FIELD(0x12B, gx->iref, 3, 15, tex_coord);
|
|
break;
|
|
case GX_INDTEXSTAGE3:
|
|
SET_REG_FIELD(0x12E, gx->iref, 3, 18, tex_map);
|
|
SET_REG_FIELD(0x12F, gx->iref, 3, 21, tex_coord);
|
|
break;
|
|
default:
|
|
ASSERTMSGLINE(0x132, 0, "GXSetIndTexOrder: Invalid Indirect Stage Id");
|
|
break;
|
|
}
|
|
GX_WRITE_SOME_REG5(0x61, gx->iref);
|
|
gx->dirtyState |= 3;
|
|
gx->bpSentNot = 0;
|
|
}
|
|
|
|
void GXSetNumIndStages(u8 nIndStages)
|
|
{
|
|
CHECK_GXBEGIN(0x144, "GXSetNumIndStages");
|
|
ASSERTMSGLINE(0x146, nIndStages <= 4, "GXSetNumIndStages: Exceeds max. number of indirect texture stages");
|
|
SET_REG_FIELD(0x147, gx->genMode, 3, 16, nIndStages);
|
|
gx->dirtyState |= 6;
|
|
}
|
|
|
|
#pragma dont_inline on
|
|
void GXSetTevDirect(GXTevStageID tev_stage)
|
|
{
|
|
CHECK_GXBEGIN(0x158, "GXSetTevDirect");
|
|
GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 0U, 0, 0);
|
|
}
|
|
|
|
void GXSetTevIndWarp(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u8 signed_offset, u8 replace_mode, GXIndTexMtxID matrix_sel)
|
|
{
|
|
GXIndTexWrap wrap = (replace_mode != 0) ? GX_ITW_0 : GX_ITW_OFF;
|
|
|
|
CHECK_GXBEGIN(0x16E, "GXSetTevIndWarp");
|
|
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, (signed_offset != 0) ? GX_ITB_STU : GX_ITB_NONE, matrix_sel, wrap, wrap, 0U, 0, 0);
|
|
}
|
|
|
|
void GXSetTevIndTile(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u16 tilesize_s, u16 tilesize_t, u16 tilespacing_s, u16 tilespacing_t,
|
|
GXIndTexFormat format, GXIndTexMtxID matrix_sel, GXIndTexBiasSel bias_sel, GXIndTexAlphaSel alpha_sel)
|
|
{
|
|
GXIndTexWrap wrap_s;
|
|
GXIndTexWrap wrap_t;
|
|
f32 mtx[2][3];
|
|
|
|
CHECK_GXBEGIN(0x190, "GXSetTevIndTile");
|
|
ASSERTMSGLINE(0x191, tev_stage < 16, "GXSetTevIndTile: Invalid tev stage id");
|
|
ASSERTMSGLINE(0x192, ind_stage < 4, "GXSetTevIndTile: Invalid indirect stage id");
|
|
switch (tilesize_s) {
|
|
case 256:
|
|
wrap_s = GX_ITW_256;
|
|
break;
|
|
case 128:
|
|
wrap_s = GX_ITW_128;
|
|
break;
|
|
case 64:
|
|
wrap_s = GX_ITW_64;
|
|
break;
|
|
case 32:
|
|
wrap_s = GX_ITW_32;
|
|
break;
|
|
case 16:
|
|
wrap_s = GX_ITW_16;
|
|
break;
|
|
default:
|
|
ASSERTMSGLINE(0x19B, 0, "GXSetTevIndTile: Invalid tilesize for S coordinate");
|
|
wrap_s = GX_ITW_OFF;
|
|
break;
|
|
}
|
|
switch (tilesize_t) {
|
|
case 256:
|
|
wrap_t = GX_ITW_256;
|
|
break;
|
|
case 128:
|
|
wrap_t = GX_ITW_128;
|
|
break;
|
|
case 64:
|
|
wrap_t = GX_ITW_64;
|
|
break;
|
|
case 32:
|
|
wrap_t = GX_ITW_32;
|
|
break;
|
|
case 16:
|
|
wrap_t = GX_ITW_16;
|
|
break;
|
|
default:
|
|
ASSERTMSGLINE(0x1A7, 0, "GXSetTevIndTile: Invalid tilesize for T coordinate");
|
|
wrap_t = GX_ITW_OFF;
|
|
break;
|
|
}
|
|
mtx[0][0] = tilespacing_s / 1024.0f;
|
|
mtx[0][1] = mtx[0][2] = 0.0f;
|
|
mtx[1][1] = tilespacing_t / 1024.0f;
|
|
mtx[1][0] = mtx[1][2] = 0.0f;
|
|
GXSetIndTexMtx(matrix_sel, mtx, 0xA);
|
|
GXSetTevIndirect(tev_stage, ind_stage, format, bias_sel, matrix_sel, wrap_s, wrap_t, 0U, 1, alpha_sel);
|
|
}
|
|
#pragma dont_inline off
|
|
|
|
void GXSetTevIndBumpST(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel)
|
|
{
|
|
GXIndTexMtxID sm;
|
|
GXIndTexMtxID tm;
|
|
|
|
CHECK_GXBEGIN(0x1CF, "GXSetTevIndBumpST");
|
|
switch (matrix_sel) {
|
|
case GX_ITM_0:
|
|
sm = GX_ITM_S0;
|
|
tm = GX_ITM_T0;
|
|
break;
|
|
case GX_ITM_1:
|
|
sm = GX_ITM_S1;
|
|
tm = GX_ITM_T1;
|
|
break;
|
|
case GX_ITM_2:
|
|
sm = GX_ITM_S2;
|
|
tm = GX_ITM_T2;
|
|
break;
|
|
default:
|
|
ASSERTMSGLINE(0x1E0, 0, "GXSetTevIndBumpST: Invalid matrix selection");
|
|
break;
|
|
}
|
|
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_ST, sm, GX_ITW_0, GX_ITW_0, 0U, 0, 0);
|
|
GXSetTevIndirect(tev_stage + 1, ind_stage, GX_ITF_8, GX_ITB_ST, tm, GX_ITW_0, GX_ITW_0, 1U, 0, 0);
|
|
GXSetTevIndirect(tev_stage + 2, ind_stage, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 1U, 0, 0);
|
|
}
|
|
|
|
void GXSetTevIndBumpXYZ(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel)
|
|
{
|
|
CHECK_GXBEGIN(0x214, "GXSetTevIndBumpXYZ");
|
|
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_STU, matrix_sel, GX_ITW_OFF, GX_ITW_OFF, 0U, 0, 0);
|
|
}
|
|
|
|
void GXSetTevIndRepeat(GXTevStageID tev_stage)
|
|
{
|
|
CHECK_GXBEGIN(0x231, "GXSetTevIndRepeat");
|
|
GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_0, GX_ITW_0, 1U, 0, 0);
|
|
}
|
|
|
|
void __GXUpdateBPMask(void)
|
|
{
|
|
u32 nIndStages;
|
|
u32 i;
|
|
u32 tmap;
|
|
u32 new_imask;
|
|
u32 nStages;
|
|
u32 new_dmask;
|
|
|
|
new_imask = 0;
|
|
new_dmask = 0;
|
|
nIndStages = GET_REG_FIELD(gx->genMode, 3, 16);
|
|
for (i = 0; i < nIndStages; i++) {
|
|
switch (i) {
|
|
case 0:
|
|
tmap = GET_REG_FIELD(gx->iref, 3, 0);
|
|
break;
|
|
case 1:
|
|
tmap = GET_REG_FIELD(gx->iref, 3, 6);
|
|
break;
|
|
case 2:
|
|
tmap = GET_REG_FIELD(gx->iref, 3, 12);
|
|
break;
|
|
case 3:
|
|
tmap = GET_REG_FIELD(gx->iref, 3, 18);
|
|
break;
|
|
}
|
|
new_imask |= 1 << tmap;
|
|
}
|
|
|
|
if ((u8)gx->bpMask != new_imask) {
|
|
SET_REG_FIELD(0x26E, gx->bpMask, 8, 0, new_imask);
|
|
GX_WRITE_SOME_REG5(0x61, gx->bpMask);
|
|
gx->bpSentNot = 0;
|
|
}
|
|
}
|
|
|
|
void __GXFlushTextureState(void)
|
|
{
|
|
GX_WRITE_SOME_REG5(0x61, gx->bpMask);
|
|
gx->bpSentNot = 0;
|
|
}
|