diff --git a/.vscode/settings.json b/.vscode/settings.json index dcd6c9da..732dd7f6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -53,7 +53,8 @@ "osrtcpriv.h": "c", "osbootinfo.h": "c", "assert.h": "c", - "math.h": "c" + "math.h": "c", + "gxpriv.h": "c" }, "files.autoSave": "onFocusChange", "files.insertFinalNewline": true, diff --git a/configure.py b/configure.py index 46c778d1..b7c11348 100755 --- a/configure.py +++ b/configure.py @@ -764,7 +764,7 @@ LIBS = [ { "lib": "gx", "mwcc_version": "1.2.5", - "cflags": "$cflags_base", + "cflags": "$cflags_base -fp_contract off", "host": False, "objects": [ "Dolphin/gx/GXInit", @@ -773,7 +773,7 @@ LIBS = [ "Dolphin/gx/GXMisc", "Dolphin/gx/GXGeometry", "Dolphin/gx/GXFrameBuf", - "Dolphin/gx/GXLight", + ["Dolphin/gx/GXLight", False], "Dolphin/gx/GXTexture", "Dolphin/gx/GXBump", "Dolphin/gx/GXTev", diff --git a/include/dolphin/gx/GXEnum.h b/include/dolphin/gx/GXEnum.h index 436a7e03..206ca803 100644 --- a/include/dolphin/gx/GXEnum.h +++ b/include/dolphin/gx/GXEnum.h @@ -794,6 +794,96 @@ typedef enum _GXTexCacheSize { GX_TEXCACHE_NONE } GXTexCacheSize; +typedef enum _GXPerf0 { + GX_PERF0_VERTICES, + GX_PERF0_CLIP_VTX, + GX_PERF0_CLIP_CLKS, + GX_PERF0_XF_WAIT_IN, + GX_PERF0_XF_WAIT_OUT, + GX_PERF0_XF_XFRM_CLKS, + GX_PERF0_XF_LIT_CLKS, + GX_PERF0_XF_BOT_CLKS, + GX_PERF0_XF_REGLD_CLKS, + GX_PERF0_XF_REGRD_CLKS, + GX_PERF0_CLIP_RATIO, + + GX_PERF0_TRIANGLES, + GX_PERF0_TRIANGLES_CULLED, + GX_PERF0_TRIANGLES_PASSED, + GX_PERF0_TRIANGLES_SCISSORED, + GX_PERF0_TRIANGLES_0TEX, + GX_PERF0_TRIANGLES_1TEX, + GX_PERF0_TRIANGLES_2TEX, + GX_PERF0_TRIANGLES_3TEX, + GX_PERF0_TRIANGLES_4TEX, + GX_PERF0_TRIANGLES_5TEX, + GX_PERF0_TRIANGLES_6TEX, + GX_PERF0_TRIANGLES_7TEX, + GX_PERF0_TRIANGLES_8TEX, + GX_PERF0_TRIANGLES_0CLR, + GX_PERF0_TRIANGLES_1CLR, + GX_PERF0_TRIANGLES_2CLR, + + GX_PERF0_QUAD_0CVG, + GX_PERF0_QUAD_NON0CVG, + GX_PERF0_QUAD_1CVG, + GX_PERF0_QUAD_2CVG, + GX_PERF0_QUAD_3CVG, + GX_PERF0_QUAD_4CVG, + GX_PERF0_AVG_QUAD_CNT, + + GX_PERF0_CLOCKS, + GX_PERF0_NONE + +} GXPerf0; + +typedef enum _GXPerf1 { + GX_PERF1_TEXELS, + GX_PERF1_TX_IDLE, + GX_PERF1_TX_REGS, + GX_PERF1_TX_MEMSTALL, + GX_PERF1_TC_CHECK1_2, + GX_PERF1_TC_CHECK3_4, + GX_PERF1_TC_CHECK5_6, + GX_PERF1_TC_CHECK7_8, + GX_PERF1_TC_MISS, + + GX_PERF1_VC_ELEMQ_FULL, + GX_PERF1_VC_MISSQ_FULL, + GX_PERF1_VC_MEMREQ_FULL, + GX_PERF1_VC_STATUS7, + GX_PERF1_VC_MISSREP_FULL, + GX_PERF1_VC_STREAMBUF_LOW, + GX_PERF1_VC_ALL_STALLS, + GX_PERF1_VERTICES, + + GX_PERF1_FIFO_REQ, + GX_PERF1_CALL_REQ, + GX_PERF1_VC_MISS_REQ, + GX_PERF1_CP_ALL_REQ, + + GX_PERF1_CLOCKS, + GX_PERF1_NONE + +} GXPerf1; + +typedef enum _GXVCachePerf { + GX_VC_POS, + GX_VC_NRM, + GX_VC_CLR0, + GX_VC_CLR1, + GX_VC_TEX0, + GX_VC_TEX1, + GX_VC_TEX2, + GX_VC_TEX3, + GX_VC_TEX4, + GX_VC_TEX5, + GX_VC_TEX6, + GX_VC_TEX7, + GX_VC_ALL = 0xf + +} GXVCachePerf; + #ifdef __cplusplus } #endif diff --git a/include/dolphin/gx/GXGet.h b/include/dolphin/gx/GXGet.h index 67fdbbfb..1eff8eb2 100644 --- a/include/dolphin/gx/GXGet.h +++ b/include/dolphin/gx/GXGet.h @@ -16,8 +16,8 @@ GXTexWrapMode GXGetTexObjWrapS(const GXTexObj* obj); GXTexWrapMode GXGetTexObjWrapT(const GXTexObj* obj); void* GXGetTexObjData(const GXTexObj* obj); void GXGetProjectionv(f32* p); -void GXGetLightPos(GXLightObj* lt_obj, f32* x, f32* y, f32* z); -void GXGetLightColor(GXLightObj* lt_obj, GXColor* color); +void GXGetLightPos(const GXLightObj* lt_obj, f32* x, f32* y, f32* z); +void GXGetLightColor(const GXLightObj* lt_obj, GXColor* color); void GXGetVtxAttrFmt(GXVtxFmt idx, GXAttr attr, GXCompCnt* compCnt, GXCompType* compType, u8* shift); diff --git a/include/dolphin/gx/GXPriv.h b/include/dolphin/gx/GXPriv.h new file mode 100644 index 00000000..db0286b8 --- /dev/null +++ b/include/dolphin/gx/GXPriv.h @@ -0,0 +1,38 @@ +#ifndef _DOLPHIN_GXPRIV +#define _DOLPHIN_GXPRIV + +#include "dolphin/gx/GXVert.h" + +typedef struct GXLightObj_ { + u32 padding[3]; + u32 color; + float a0; + float a1; + float a2; + float k0; + float k1; + float k2; + float px; + float py; + float pz; + float nx; + float ny; + float nz; +} GXLightObj_; + +#define XF_LIGHT_BASE 0x0600 +#define XF_LIGHT_SIZE 0x10 + +#define GX_FIFO_ADDR 0xCC008000 + +#define GX_WRITE_U8(v) (GXWGFifo.u8 = v) +#define GX_WRITE_U32(v) (GXWGFifo.u32 = v) + +typedef struct GXData { + u16 cpSRreg; + u16 cpCRreg; +} GXData; + +extern GXData* __GXData; + +#endif // _DOLPHIN_GXPRIV diff --git a/include/dolphin/gx/GXStruct.h b/include/dolphin/gx/GXStruct.h index 0bee0fe6..eebc736b 100644 --- a/include/dolphin/gx/GXStruct.h +++ b/include/dolphin/gx/GXStruct.h @@ -97,6 +97,10 @@ typedef struct _GXTexRegion { u32 dummy[4]; } GXTexRegion; +typedef struct _GXTlutRegion { + u32 dummy[4]; +} GXTlutRegion; + #ifdef __cplusplus } #endif diff --git a/src/Dolphin/gx/GXLight.c b/src/Dolphin/gx/GXLight.c new file mode 100644 index 00000000..a41b90e3 --- /dev/null +++ b/src/Dolphin/gx/GXLight.c @@ -0,0 +1,271 @@ +#include "dolphin/gx.h" +#include "dolphin/gx/GXPriv.h" + +extern float cosf(float x); +extern float sqrtf(float x); + +#define GX_LARGE_NUMBER 1.0e+18f; + +void GXInitLightAttn(GXLightObj* lt_obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + obj->a0 = a0; + obj->a1 = a1; + obj->a2 = a2; + obj->k0 = k0; + obj->k1 = k1; + obj->k2 = k2; +} + +void GXInitLightAttnA(GXLightObj* lt_obj, f32 a0, f32 a1, f32 a2) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + obj->a0 = a0; + obj->a1 = a1; + obj->a2 = a2; +} + +void GXGetLightAttnA(const GXLightObj* lt_obj, f32* a0, f32* a1, f32* a2) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + *a0 = obj->a0; + *a1 = obj->a1; + *a2 = obj->a2; +} + +void GXInitLightAttnK(GXLightObj* lt_obj, f32 k0, f32 k1, f32 k2) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + obj->k0 = k0; + obj->k1 = k1; + obj->k2 = k2; +} + +void GXGetLightAttnK(const GXLightObj* lt_obj, f32* k0, f32* k1, f32* k2) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + *k0 = obj->k0; + *k1 = obj->k1; + *k2 = obj->k2; +} + +#define PI 3.14159265358979323846F + +void GXInitLightSpot(GXLightObj* lt_obj, f32 cutoff, GXSpotFn spot_func) { + f32 a0, a1, a2, r, d, cr; + GXLightObj_* obj = (GXLightObj_*)lt_obj; + + if (cutoff <= 0.0f || cutoff > 90.0f) { + spot_func = GX_SP_OFF; + } + + r = cutoff * PI / 180.0f; + cr = cosf(r); + + switch (spot_func) { + case GX_SP_FLAT: + a0 = -1000.0f * cr; + a1 = 1000.0f; + a2 = 0.0f; + break; + case GX_SP_COS: + a1 = 1.0f / (1.0f - cr); + a0 = -cr * a1; + a2 = 0.0f; + break; + case GX_SP_COS2: + a2 = 1.0f / (1.0f - cr); + a0 = 0.0f; + a1 = -cr * a2; + break; + case GX_SP_SHARP: + d = 1.0F / ((1.0F - cr) * (1.0F - cr)); + a0 = cr * (cr - 2.0F) * d; + a1 = 2.0F * d; + a2 = -d; + break; + case GX_SP_RING1: + d = 1.0f / ((1.0f - cr) * (1.0F - cr)); + a2 = -4.0f * d; + a0 = a2 * cr; + a1 = 4.0f * (1.0f + cr) * d; + break; + case GX_SP_RING2: + d = 1.0f / ((1.0f - cr) * (1.0F - cr)); + a0 = 1.0f - 2.0f * cr * cr * d; + a1 = 4.0f * cr * d; + a2 = -2.0f * d; + break; + case GX_SP_OFF: + default: + a0 = 1.0f; + a1 = 0.0f; + a2 = 0.0f; + break; + } + + obj->a0 = a0; + obj->a1 = a1; + obj->a2 = a2; +} + +void GXInitLightDistAttn(GXLightObj* lt_obj, f32 ref_dist, f32 ref_br, GXDistAttnFn dist_func) { + f32 k0, k1, k2; + GXLightObj_* obj = (GXLightObj_*)lt_obj; + + if (ref_dist < 0.0F) { + dist_func = GX_DA_OFF; + } + + if (ref_br <= 0.0F || ref_br >= 1.0F) { + dist_func = GX_DA_OFF; + } + + switch (dist_func) { + case GX_DA_GENTLE: + k0 = 1.0F; + k1 = (1.0F - ref_br) / (ref_br * ref_dist); + k2 = 0.0F; + break; + case GX_DA_MEDIUM: + k0 = 1.0f; + k1 = 0.5f * (1.0f - ref_br) / (ref_br * ref_dist); + k2 = 0.5f * (1.0f - ref_br) / (ref_br * ref_dist * ref_dist); + break; + case GX_DA_STEEP: + k0 = 1.0f; + k1 = 0.0f; + k2 = (1.0f - ref_br) / (ref_br * ref_dist * ref_dist); + break; + case GX_DA_OFF: + default: + k0 = 1.0f; + k1 = 0.0f; + k2 = 0.0f; + break; + } + + obj->k0 = k0; + obj->k1 = k1; + obj->k2 = k2; +} + +void GXInitLightPos(GXLightObj* lt_obj, f32 x, f32 y, f32 z) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + + obj->px = x; + obj->py = y; + obj->pz = z; +} + +void GXGetLightPos(const GXLightObj* lt_obj, f32* x, f32* y, f32* z) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + *x = obj->px; + *y = obj->py; + *z = obj->pz; +} + +void GXInitLightDir(GXLightObj* lt_obj, f32 nx, f32 ny, f32 nz) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + + obj->nx = -nx; + obj->ny = -ny; + obj->nz = -nz; +} + +void GXGetLightDir(const GXLightObj* lt_obj, f32* nx, f32* ny, f32* nz) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + *nx = -(obj->nx); + *ny = -(obj->ny); + *nz = -(obj->nz); +} + +void GXInitSpecularDir(GXLightObj* lt_obj, f32 nx, f32 ny, f32 nz) { + f32 mag; + f32 vx, vy, vz; + GXLightObj_* obj = (GXLightObj_*)lt_obj; + + vx = -nx; + vy = -ny; + vz = (-nz + 1.0F); + mag = vx * vx + vy * vy + vz * vz; + + if (mag != 0.0f) { + mag = 1.0f / sqrtf(mag); + } + + obj->px = vx * mag; + obj->py = vy * mag; + obj->pz = vz * mag; + + obj->nx = nx * -GX_LARGE_NUMBER; + obj->ny = ny * -GX_LARGE_NUMBER; + obj->nz = nz * -GX_LARGE_NUMBER; +} + +void GXInitSpecularDirHA(GXLightObj* lt_obj, f32 nx, f32 ny, f32 nz, f32 hx, f32 hy, f32 hz) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + + obj->nx = hx; + obj->ny = hy; + obj->nz = hz; + + obj->px = nx * -GX_LARGE_NUMBER; + obj->py = ny * -GX_LARGE_NUMBER; + obj->pz = nz * -GX_LARGE_NUMBER; +} + +void GXInitLightColor(GXLightObj* lt_obj, GXColor color) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + obj->color = *(u32*)(&color); +} + +void GXGetLightColor(const GXLightObj* lt_obj, GXColor* color) { + GXLightObj_* obj = (GXLightObj_*)lt_obj; + *(u32*)color = obj->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; + + 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 + } +} + +void GXLoadLightObjImm(GXLightObj* lt_obj, GXLightID light) { + u32 addr; + u32 idx; + GXLightObj_* obj; + obj = (GXLightObj_*)lt_obj; + + idx = 31 - __cntlzw(light); + idx &= 7; + + addr = XF_LIGHT_BASE + idx * XF_LIGHT_SIZE; + + GX_WRITE_U8(16); + GX_WRITE_U32(addr | (XF_LIGHT_SIZE - 1) << 16); + PushLight(obj, (void*)GX_FIFO_ADDR); + __GXData->cpCRreg = 1; +} + +void GXSetChanAmbColor(GXChannelID chan, GXColor color) { + +}