tp/libs/dolphin/gx/GXLight.c

233 lines
5.7 KiB
C

/**
* GXLight.c
* Description:
*/
#include "dolphin/gx/GXLight.h"
#include "MSL_C/math.h"
#include "dolphin/gx/GX.h"
/* 8035D630-8035D64C 357F70 001C+00 0/0 1/1 0/0 .text GXInitLightAttn */
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;
}
/* 8035D64C-8035D7DC 357F8C 0190+00 1/0 2/2 0/0 .text GXInitLightSpot */
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;
}
/* 8035D7DC-8035D8AC 35811C 00D0+00 0/0 2/2 0/0 .text GXInitLightDistAttn */
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;
}
/* 8035D8AC-8035D8BC 3581EC 0010+00 0/0 3/3 0/0 .text GXInitLightPos */
void GXInitLightPos(GXLightObj* obj, f32 x, f32 y, f32 z) {
obj->posX = x;
obj->posY = y;
obj->posZ = z;
}
/* 8035D8BC-8035D8D8 3581FC 001C+00 0/0 3/3 0/0 .text GXInitLightDir */
void GXInitLightDir(GXLightObj* obj, f32 x, f32 y, f32 z) {
obj->dirX = -x;
obj->dirY = -y;
obj->dirZ = -z;
}
/* 8035D8D8-8035D8E4 358218 000C+00 0/0 3/3 0/0 .text GXInitLightColor */
void GXInitLightColor(GXLightObj* obj, GXColor color) {
*(u32*)&obj->color = *(u32*)&color;
}
/* 8035D8E4-8035D960 358224 007C+00 0/0 4/4 2/2 .text GXLoadLightObjImm */
asm void GXLoadLightObjImm(register GXLightObj* obj, register GXLightID id) {
// clang-format off
nofralloc
cntlzw r0, id
subfic r0, r0, 0x1f
rlwinm r5, r0, 4, 0x19, 0x1b
lis r4, 0xCC01
li r0, 0x10
addi r5, r5, 0x600
stb r0, 0x8000(r4)
oris r0, r5, 0xf
stwu r0, -0x8000(r4)
lwz r0, 0xc(r3)
xor r6, r6, r6
psq_l f5, 16(obj), 0, 0
psq_l f4, 24(obj), 0, 0
psq_l f3, 32(obj), 0, 0
psq_l f2, 40(obj), 0, 0
psq_l f1, 48(obj), 0, 0
psq_l f0, 56(obj), 0, 0
stw r6, 0(r4)
stw r6, 0(r4)
stw r6, 0(r4)
stw r0, 0(r4)
psq_st f5, 0(r4), 0, 0
psq_st f4, 0(r4), 0, 0
psq_st f3, 0(r4), 0, 0
psq_st f2, 0(r4), 0, 0
psq_st f1, 0(r4), 0, 0
psq_st f0, 0(r4), 0, 0
lwz r3, __GXData(r2)
li r0, 1
sth r0, 2(r3)
blr
// clang-format on
}
/* 8035D960-8035DA48 3582A0 00E8+00 0/0 7/7 4/4 .text GXSetChanAmbColor */
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void GXSetChanAmbColor(GXChannelID channel, GXColor color) {
nofralloc
#include "asm/dolphin/gx/GXLight/GXSetChanAmbColor.s"
}
#pragma pop
/* 8035DA48-8035DB30 358388 00E8+00 0/0 20/20 2/2 .text GXSetChanMatColor */
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void GXSetChanMatColor(GXChannelID channel, GXColor color) {
nofralloc
#include "asm/dolphin/gx/GXLight/GXSetChanMatColor.s"
}
#pragma pop
/* 8035DB30-8035DB6C 358470 003C+00 0/0 51/51 6/6 .text GXSetNumChans */
// 1 wrong reg
#ifdef NONMATCHING
void GXSetNumChans(u8 chan_num) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->field_0x204, 25, 3, chan_num);
GXFIFO.u8 = 0x10;
GXFIFO.s32 = 0x1009;
GXFIFO.s32 = chan_num;
data->field_0x5ac |= 0x4;
}
#else
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void GXSetNumChans(u8 chan_num) {
nofralloc
#include "asm/dolphin/gx/GXLight/GXSetNumChans.s"
}
#pragma pop
#endif
/* 8035DB6C-8035DC1C 3584AC 00B0+00 0/0 34/34 4/4 .text GXSetChanCtrl */
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void GXSetChanCtrl(GXChannelID channel, GXBool enable, GXColorSrc amb_src, GXColorSrc mat_src,
u32 light_mask, GXDiffuseFn diff_fn, GXAttnFn attn_fn) {
nofralloc
#include "asm/dolphin/gx/GXLight/GXSetChanCtrl.s"
}
#pragma pop