#include "gx.hpp" #include "__gx.h" #include "../../gfx/common.hpp" #include "../../gfx/texture.hpp" extern "C" { static inline u8 GetFracForNrm(GXCompType type) { switch (type) { case GX_S8: return 6; case GX_S16: return 14; default: return 0; } } void GXGetVtxDesc(GXAttr attr, GXAttrType* type) { CHECK(type != nullptr, "null vtx desc output"); u32 cpType = 0; switch (attr) { case GX_VA_PNMTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 0); break; case GX_VA_TEX0MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 1); break; case GX_VA_TEX1MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 2); break; case GX_VA_TEX2MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 3); break; case GX_VA_TEX3MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 4); break; case GX_VA_TEX4MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 5); break; case GX_VA_TEX5MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 6); break; case GX_VA_TEX6MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 7); break; case GX_VA_TEX7MTXIDX: cpType = GET_REG_FIELD(__gx->vcdLo, 1, 8); break; case GX_VA_POS: cpType = GET_REG_FIELD(__gx->vcdLo, 2, 9); break; case GX_VA_NRM: cpType = __gx->hasNrms ? GET_REG_FIELD(__gx->vcdLo, 2, 11) : GX_NONE; break; case GX_VA_NBT: cpType = __gx->hasBiNrms ? GET_REG_FIELD(__gx->vcdLo, 2, 11) : GX_NONE; break; case GX_VA_CLR0: cpType = GET_REG_FIELD(__gx->vcdLo, 2, 13); break; case GX_VA_CLR1: cpType = GET_REG_FIELD(__gx->vcdLo, 2, 15); break; case GX_VA_TEX0: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 0); break; case GX_VA_TEX1: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 2); break; case GX_VA_TEX2: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 4); break; case GX_VA_TEX3: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 6); break; case GX_VA_TEX4: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 8); break; case GX_VA_TEX5: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 10); break; case GX_VA_TEX6: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 12); break; case GX_VA_TEX7: cpType = GET_REG_FIELD(__gx->vcdHi, 2, 14); break; default: break; } *type = static_cast(cpType); } void GXGetVtxDescv(GXVtxDescList* vcd) { CHECK(vcd != nullptr, "null vtx desc list"); GXVtxDescList* out = vcd; for (GXAttr attr = GX_VA_PNMTXIDX; attr <= GX_VA_TEX7; attr = static_cast(attr + 1), ++out) { out->attr = attr; GXGetVtxDesc(attr, &out->type); } out->attr = GX_VA_NBT; GXGetVtxDesc(GX_VA_NBT, &out->type); ++out; out->attr = GX_VA_NULL; } void GXGetVtxAttrFmt(GXVtxFmt idx, GXAttr attr, GXCompCnt* compCnt, GXCompType* compType, u8* shift) { CHECK(compCnt != nullptr && compType != nullptr && shift != nullptr, "null vtx attr fmt output"); const u32 va = __gx->vatA[idx]; const u32 vb = __gx->vatB[idx]; const u32 vc = __gx->vatC[idx]; switch (attr) { case GX_VA_POS: *compCnt = static_cast(GET_REG_FIELD(va, 1, 0)); *compType = static_cast(GET_REG_FIELD(va, 3, 1)); *shift = static_cast(GET_REG_FIELD(va, 5, 4)); return; case GX_VA_NRM: case GX_VA_NBT: *compCnt = static_cast(GET_REG_FIELD(va, 1, 9)); if (*compCnt == GX_TEX_ST && GET_REG_FIELD(va, 1, 31) != 0) { *compCnt = GX_NRM_NBT3; } *compType = static_cast(GET_REG_FIELD(va, 3, 10)); *shift = GetFracForNrm(*compType); return; case GX_VA_CLR0: *compCnt = static_cast(GET_REG_FIELD(va, 1, 13)); *compType = static_cast(GET_REG_FIELD(va, 3, 14)); *shift = 0; return; case GX_VA_CLR1: *compCnt = static_cast(GET_REG_FIELD(va, 1, 17)); *compType = static_cast(GET_REG_FIELD(va, 3, 18)); *shift = 0; return; case GX_VA_TEX0: *compCnt = static_cast(GET_REG_FIELD(va, 1, 21)); *compType = static_cast(GET_REG_FIELD(va, 3, 22)); *shift = static_cast(GET_REG_FIELD(va, 5, 25)); return; case GX_VA_TEX1: *compCnt = static_cast(GET_REG_FIELD(vb, 1, 0)); *compType = static_cast(GET_REG_FIELD(vb, 3, 1)); *shift = static_cast(GET_REG_FIELD(vb, 5, 4)); return; case GX_VA_TEX2: *compCnt = static_cast(GET_REG_FIELD(vb, 1, 9)); *compType = static_cast(GET_REG_FIELD(vb, 3, 10)); *shift = static_cast(GET_REG_FIELD(vb, 5, 13)); return; case GX_VA_TEX3: *compCnt = static_cast(GET_REG_FIELD(vb, 1, 18)); *compType = static_cast(GET_REG_FIELD(vb, 3, 19)); *shift = static_cast(GET_REG_FIELD(vb, 5, 22)); return; case GX_VA_TEX4: *compCnt = static_cast(GET_REG_FIELD(vb, 1, 27)); *compType = static_cast(GET_REG_FIELD(vb, 3, 28)); *shift = static_cast(GET_REG_FIELD(vc, 5, 0)); return; case GX_VA_TEX5: *compCnt = static_cast(GET_REG_FIELD(vc, 1, 5)); *compType = static_cast(GET_REG_FIELD(vc, 3, 6)); *shift = static_cast(GET_REG_FIELD(vc, 5, 9)); return; case GX_VA_TEX6: *compCnt = static_cast(GET_REG_FIELD(vc, 1, 14)); *compType = static_cast(GET_REG_FIELD(vc, 3, 15)); *shift = static_cast(GET_REG_FIELD(vc, 5, 18)); return; case GX_VA_TEX7: *compCnt = static_cast(GET_REG_FIELD(vc, 1, 23)); *compType = static_cast(GET_REG_FIELD(vc, 3, 24)); *shift = static_cast(GET_REG_FIELD(vc, 5, 27)); return; default: *compCnt = GX_TEX_ST; *compType = GX_RGB565; *shift = 0; return; } } void GXGetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList* vat) { CHECK(vat != nullptr, "null vtx attr fmt list"); GXVtxAttrFmtList* out = vat; for (GXAttr attr = GX_VA_POS; attr <= GX_VA_TEX7; attr = static_cast(attr + 1), ++out) { out->attr = attr; GXGetVtxAttrFmt(fmt, attr, &out->cnt, &out->type, &out->frac); } out->attr = GX_VA_NULL; } void GXGetLineWidth(u8* width, GXTexOffset* texOffsets) { CHECK(width != nullptr && texOffsets != nullptr, "null line width output"); *width = static_cast(GET_REG_FIELD(__gx->lpSize, 8, 0)); *texOffsets = static_cast(GET_REG_FIELD(__gx->lpSize, 3, 16)); } void GXGetPointSize(u8* pointSize, GXTexOffset* texOffsets) { CHECK(pointSize != nullptr && texOffsets != nullptr, "null point size output"); *pointSize = static_cast(GET_REG_FIELD(__gx->lpSize, 8, 8)); *texOffsets = static_cast(GET_REG_FIELD(__gx->lpSize, 3, 19)); } void GXGetViewportv(f32 *vp) { CHECK(vp != nullptr, "null viewport output"); vp[0] = __gx->vpLeft; vp[1] = __gx->vpTop; vp[2] = __gx->vpWd; vp[3] = __gx->vpHt; vp[4] = __gx->vpNearz; vp[5] = __gx->vpFarz; } void GXGetProjectionv(f32* p) { p[0] = __gx->projType == GX_PERSPECTIVE ? 0.0f : 1.0f; p[1] = __gx->projMtx[0]; p[2] = __gx->projMtx[1]; p[3] = __gx->projMtx[2]; p[4] = __gx->projMtx[3]; p[5] = __gx->projMtx[4]; p[6] = __gx->projMtx[5]; } void GXGetScissor(u32* left, u32* top, u32* wd, u32* ht) { CHECK(left != nullptr && top != nullptr && wd != nullptr && ht != nullptr, "null scissor output"); const u32 tp = GET_REG_FIELD(__gx->suScis0, 11, 0); const u32 lf = GET_REG_FIELD(__gx->suScis0, 11, 12); const u32 bm = GET_REG_FIELD(__gx->suScis1, 11, 0); const u32 rt = GET_REG_FIELD(__gx->suScis1, 11, 12); *left = lf - 342; *top = tp - 342; *wd = rt - lf + 1; *ht = bm - tp + 1; } void GXGetCullMode(GXCullMode* mode) { CHECK(mode != nullptr, "null cull mode output"); const auto hwMode = static_cast(GET_REG_FIELD(__gx->genMode, 2, 14)); switch (hwMode) { case GX_CULL_FRONT: *mode = GX_CULL_BACK; break; case GX_CULL_BACK: *mode = GX_CULL_FRONT; break; default: *mode = hwMode; break; } } void GXGetLightAttnA(GXLightObj* light_, float* a0, float* a1, float* a2) { auto* light = reinterpret_cast(light_); *a0 = light->a0; *a1 = light->a1; *a2 = light->a2; } void GXGetLightAttnK(GXLightObj* light_, float* k0, float* k1, float* k2) { auto* light = reinterpret_cast(light_); *k0 = light->k0; *k1 = light->k1; *k2 = light->k2; } void GXGetLightPos(GXLightObj* light_, float* x, float* y, float* z) { auto* light = reinterpret_cast(light_); *x = light->px; *y = light->py; *z = light->pz; } void GXGetLightDir(GXLightObj* light_, float* nx, float* ny, float* nz) { auto* light = reinterpret_cast(light_); *nx = -light->nx; *ny = -light->ny; *nz = -light->nz; } void GXGetLightColor(GXLightObj* light_, GXColor* col) { auto* light = reinterpret_cast(light_); *col = light->color; } void* GXGetTexObjData(GXTexObj* tex_obj) { return const_cast(reinterpret_cast(tex_obj)->data); } u16 GXGetTexObjWidth(GXTexObj* tex_obj) { return static_cast(reinterpret_cast(tex_obj)->width()); } u16 GXGetTexObjHeight(GXTexObj* tex_obj) { return static_cast(reinterpret_cast(tex_obj)->height()); } GXTexFmt GXGetTexObjFmt(GXTexObj* tex_obj) { return static_cast(reinterpret_cast(tex_obj)->format()); } GXTexWrapMode GXGetTexObjWrapS(GXTexObj* tex_obj) { return reinterpret_cast(tex_obj)->wrap_s(); } GXTexWrapMode GXGetTexObjWrapT(GXTexObj* tex_obj) { return reinterpret_cast(tex_obj)->wrap_t(); } GXBool GXGetTexObjMipMap(GXTexObj* tex_obj) { return reinterpret_cast(tex_obj)->has_mips(); } // TODO GXGetTexObjAll // TODO GXGetTexObjMinFilt // TODO GXGetTexObjMagFilt // TODO GXGetTexObjMinLOD // TODO GXGetTexObjMaxLOD // TODO GXGetTexObjLODBias // TODO GXGetTexObjBiasClamp // TODO GXGetTexObjEdgeLOD // TODO GXGetTexObjMaxAniso // TODO GXGetTexObjLODAll u32 GXGetTexObjTlut(const GXTexObj* tex_obj) { return reinterpret_cast(tex_obj)->tlut; } // TODO GXGetTlutObjData // TODO GXGetTlutObjFmt // TODO GXGetTlutObjNumEntries // TODO GXGetTlutObjAll // TODO GXGetTexRegionAll // TODO GXGetTlutRegionAll }