mirror of https://github.com/zeldaret/tp.git
334 lines
10 KiB
C
334 lines
10 KiB
C
#include "dolphin/gx/GXTransform.h"
|
|
#include "dolphin/gx.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
|
|
}
|
|
|
|
/* 8035FF60-803600D4 35A8A0 0174+00 0/0 1/1 0/0 .text GXProject */
|
|
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;
|
|
|
|
ASSERT(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);
|
|
}
|
|
|
|
/* 803600D4-80360178 35AA14 00A4+00 0/0 15/15 2/2 .text GXSetProjection */
|
|
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;
|
|
}
|
|
|
|
/* 80360178-80360204 35AAB8 008C+00 0/0 1/1 1/1 .text GXSetProjectionv */
|
|
void GXSetProjectionv(f32* proj) {
|
|
__GXData->projType = proj[0] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC;
|
|
Copy6Floats(&proj[1], __GXData->projMtx);
|
|
|
|
__GXSetProjection();
|
|
__GXData->bpSentNot = GX_TRUE;
|
|
}
|
|
|
|
/* 80360204-8036024C 35AB44 0048+00 0/0 1/1 1/1 .text GXGetProjectionv */
|
|
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
|
|
}
|
|
|
|
/* 8036024C-8036029C 35AB8C 0050+00 0/0 83/83 9/9 .text GXLoadPosMtxImm */
|
|
void GXLoadPosMtxImm(Mtx mtx, u32 id) {
|
|
GX_XF_LOAD_REGS(4 * 3 - 1, id * 4 + GX_XF_MEM_POSMTX);
|
|
WriteMTXPS4x3(&GXWGFifo, 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
|
|
}
|
|
|
|
/* 8036029C-803602EC 35ABDC 0050+00 0/0 11/11 7/7 .text GXLoadNrmMtxImm */
|
|
void GXLoadNrmMtxImm(Mtx mtx, u32 id) {
|
|
GX_XF_LOAD_REGS(3 * 3 - 1, id * 3 + GX_XF_MEM_NRMMTX);
|
|
WriteMTXPS3x3(&GXWGFifo, mtx);
|
|
}
|
|
|
|
/* 803602EC-80360320 35AC2C 0034+00 0/0 51/51 2/2 .text GXSetCurrentMtx */
|
|
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
|
|
}
|
|
|
|
/* 80360320-803603D4 35AC60 00B4+00 0/0 15/15 0/0 .text GXLoadTexMtxImm */
|
|
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(&GXWGFifo, mtx);
|
|
} else {
|
|
WriteMTXPS4x2(&GXWGFifo, mtx);
|
|
}
|
|
}
|
|
|
|
/* 803603D4-80360464 35AD14 0090+00 1/1 0/0 0/0 .text __GXSetViewport */
|
|
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);
|
|
}
|
|
|
|
/* 80360464-803604AC 35ADA4 0048+00 0/0 10/10 1/1 .text GXSetViewport */
|
|
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;
|
|
}
|
|
|
|
/* 803604AC-803604D0 35ADEC 0024+00 0/0 1/1 1/1 .text GXGetViewportv */
|
|
void GXGetViewportv(f32* p) {
|
|
Copy6Floats(&__GXData->vpLeft, p);
|
|
}
|
|
|
|
/* 803604D0-80360548 35AE10 0078+00 0/0 11/11 4/4 .text GXSetScissor */
|
|
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;
|
|
}
|
|
|
|
/* 80360548-80360590 35AE88 0048+00 0/0 6/6 2/2 .text GXGetScissor */
|
|
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;
|
|
}
|
|
|
|
/* 80360590-803605D0 35AED0 0040+00 0/0 1/1 0/0 .text GXSetScissorBoxOffset */
|
|
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;
|
|
}
|
|
|
|
/* 803605D0-803605F8 35AF10 0028+00 0/0 27/27 2/2 .text GXSetClipMode */
|
|
void GXSetClipMode(GXClipMode mode) {
|
|
GX_XF_LOAD_REG(GX_XF_REG_CLIPDISABLE, mode);
|
|
__GXData->bpSentNot = GX_TRUE;
|
|
}
|
|
|
|
/* 803605F8-8036067C 35AF38 0084+00 1/1 1/1 0/0 .text __GXSetMatrixIndex */
|
|
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;
|
|
}
|