diff --git a/src/sysdolphin/baselib/psdisp.c b/src/sysdolphin/baselib/psdisp.c index f79b4255db..832225ba8e 100644 --- a/src/sysdolphin/baselib/psdisp.c +++ b/src/sysdolphin/baselib/psdisp.c @@ -1,7 +1,5 @@ #include "psdisp.h" -#include - #include "baselib/cobj.h" #include "baselib/fog.h" @@ -526,12 +524,10 @@ static inline HSD_Particle* psDispSubPoint(HSD_Particle* pp) HSD_Particle* q; s32 count; s32 i; - f32 fw; s32 w; psSetCurrentMtx(GX_PNMTX0); - fw = (pp->size > 42.5) ? 255.0f : 6.0f * pp->size; - w = (s32) fw; + w = (s32) ((pp->size > 42.5) ? 255.0f : 6.0f * pp->size); if (prevPointSize != (s32) (u8) w) { prevPointSize = (u8) w; GXSetPointSize((u8) w, GX_TO_ONE); @@ -574,9 +570,7 @@ static inline HSD_Particle* psDispSubPoint(HSD_Particle* pp) f32 y = p->y; f32 x = p->x; p++; - GXWGFifo.f32 = x; - GXWGFifo.f32 = y; - GXWGFifo.f32 = z; + GXPosition3f32(x, y, z); if (pp->kind & DispTexture) { GXTexCoord1x8(1); } @@ -604,9 +598,7 @@ static inline HSD_Particle* psDispSubPoint(HSD_Particle* pp) f32 y = p->y; f32 x = p->x; p++; - GXWGFifo.f32 = x; - GXWGFifo.f32 = y; - GXWGFifo.f32 = z; + GXPosition3f32(x, y, z); if (pp->kind & DispTexture) { GXTexCoord1x8(1); } @@ -625,12 +617,11 @@ static inline HSD_Particle* psDispSubPointTrail(HSD_Particle* pp) HSD_Particle* q; s32 count; s32 i; - f32 fw; s32 w; + (void) c; psSetCurrentMtx(GX_PNMTX0); - fw = (pp->size > 42.5) ? 255.0f : 6.0f * pp->size; - w = (s32) fw; + w = (s32) ((pp->size > 42.5) ? 255.0f : 6.0f * pp->size); if (prevLineWidth != (s32) (u8) w) { prevLineWidth = (u8) w; GXSetLineWidth((u8) w, GX_TO_ONE); @@ -703,24 +694,12 @@ static inline HSD_Particle* psDispSubPointTrail(HSD_Particle* pp) } for (i = count; i != 0; i--) { GXPosition3f32(p[1].x, p[1].y, p[1].z); - { - u8 a = c[1].a; - u8 b = c[1].b; - u8 g = c[1].g; - u8 r = c[1].r; - GXColor4u8(r, g, b, a); - } + GXColor4u8(c[1].r, c[1].g, c[1].b, c[1].a); if (pp->kind & DispTexture) { GXTexCoord1x8(0); } GXPosition3f32(p[0].x, p[0].y, p[0].z); - { - u8 a = c[0].a; - u8 b = c[0].b; - u8 g = c[0].g; - u8 r = c[0].r; - GXColor4u8(r, g, b, a); - } + GXColor4u8(c[0].r, c[0].g, c[0].b, c[0].a); if (pp->kind & DispTexture) { GXTexCoord1x8(1); } @@ -749,24 +728,12 @@ static inline HSD_Particle* psDispSubPointTrail(HSD_Particle* pp) } for (i = count; i != 0; i--) { GXPosition3f32(p[1].x, p[1].y, p[1].z); - { - u8 a = c[1].a; - u8 b = c[1].b; - u8 g = c[1].g; - u8 r = c[1].r; - GXColor4u8(r, g, b, a); - } + GXColor4u8(c[1].r, c[1].g, c[1].b, c[1].a); if (pp->kind & DispTexture) { GXTexCoord1x8(0); } GXPosition3f32(p[0].x, p[0].y, p[0].z); - { - u8 a = c[0].a; - u8 b = c[0].b; - u8 g = c[0].g; - u8 r = c[0].r; - GXColor4u8(r, g, b, a); - } + GXColor4u8(c[0].r, c[0].g, c[0].b, c[0].a); if (pp->kind & DispTexture) { GXTexCoord1x8(1); } @@ -774,6 +741,7 @@ static inline HSD_Particle* psDispSubPointTrail(HSD_Particle* pp) c += 2; } } + (void) p; return last; } @@ -806,19 +774,28 @@ static inline void psSetCurrentMtx(GXPosNrmMtx idx) } static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, - f32 y, f32 z, f32 ppvx, f32 ppvy, - f32 ppvz, f32 x0, f32 y0, f32 z0, + f32 y, f32 z, f32 x0, f32 y0, f32 z0, f32 x1, f32 y1, f32 z1) { + GXColor color; f32 prev_x; f32 prev_y; f32 prev_z; + Vec2 right; + f32 right_z; + Vec2 up; + f32 up_z; u8* it = texform; + right.x = x0; + right.y = y0; + right_z = z0; + up.x = x1; + up.y = y1; + up_z = z1; + psSetCurrentMtx(GX_PNMTX0); if (pp->kind & Trail) { - GXColor color; - if (pp->kind & Tornado) { calcTornadoLastPos(pp, &prev_x, &prev_y, &prev_z); } else { @@ -835,19 +812,21 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, setVtxDesc(3); GXBegin(GX_QUADS, GX_VTXFMT3, 4); } - GXPosition3f32(prev_x - x0, prev_y - y0, prev_z - z0); + GXPosition3f32(prev_x - right.x, prev_y - right.y, + prev_z - right_z); { u8 a = color.a; - f32 alpha = (f32) a * pp->trail; u8 b = color.b; u8 g = color.g; u8 r = color.r; - GXColor4u8(r, g, b, (u8) alpha); + GXColor4u8(r, g, b, (u8) ((f32) a * pp->trail)); } if (pp->kind & DispTexture) { - GXWGFifo.u8 = (pp->kind >> 16) & 0xC; + u8 tex_base = (pp->kind >> 16) & 0xC; + + GXWGFifo.u8 = tex_base; } - GXPosition3f32(x - x1, y - y1, z - z1); + GXPosition3f32(x - up.x, y - up.y, z - up_z); { u8 a = color.a; u8 b = color.b; @@ -858,7 +837,7 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 1; } - GXPosition3f32(x + x0, y + y0, z0 + z); + GXPosition3f32(x + right.x, y + right.y, z + right_z); { u8 a = color.a; u8 b = color.b; @@ -869,7 +848,7 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 2; } - GXPosition3f32(prev_x + x1, prev_y + y1, prev_z + z1); + GXPosition3f32(prev_x + up.x, prev_y + up.y, prev_z + up_z); { u8 a = color.a; f32 alpha = (f32) a * pp->trail; @@ -883,12 +862,12 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, } } else { f32 trail_alpha = 255.0f * (1.0f - pp->trail); - f32 up_len = sqrtf(x1 * x1 + y1 * y1 + z1 * z1); + f32 up_len = sqrtf(up.x * up.x + up.y * up.y + up_z * up_z); if (up_len != 0.0f) { + f32 dz = z - prev_z; f32 dx = x - prev_x; f32 dy = y - prev_y; - f32 dz = z - prev_z; f32 xl = dx * dx; f32 yl = dy * dy; f32 zl = dz * dz; @@ -897,16 +876,15 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, u32 primitive_count = *(u32*) it; it += sizeof(u32); - x1 *= ratio; - y1 *= ratio; - z1 *= ratio; + if (primitive_count != 0) { + up.x *= ratio; + up.y *= ratio; + up_z *= ratio; + } for (; primitive_count != 0; primitive_count--) { GXPrimitive primitive = it[0]; u8 count = it[1]; s32 i; - u8 b; - u8 g; - u8 r; it += 4; if (pp->kind & DispTexture) { @@ -916,9 +894,6 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, setVtxDesc(3); GXBegin(primitive, GX_VTXFMT3, count); } - b = color.b; - g = color.g; - r = color.r; for (i = count; i > 0; i--) { f32 s = *(f32*) &it[0]; f32 sx = 2.0f * (s - 0.5f); @@ -932,8 +907,8 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, } t = *(f32*) &it[4]; it += 8; - converted_alpha = (s32) (255.0f - t * trail_alpha); alpha = (s32) (255.0f - t * trail_alpha); + converted_alpha = (s32) (255.0f - t * trail_alpha); if (converted_alpha < 0) { alpha = 0; } @@ -944,10 +919,10 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, if (pp->kind & TexFlipT) { t = 1.0f - t; } - GXWGFifo.f32 = x1 * tx + (x0 * sx + x); - GXWGFifo.f32 = y1 * tx + (y0 * sx + y); - GXWGFifo.f32 = z1 * tx + (z0 * sx + z); - GXColor4u8(r, g, b, alpha); + GXWGFifo.f32 = up.x * tx + (right.x * sx + x); + GXWGFifo.f32 = up.y * tx + (right.y * sx + y); + GXWGFifo.f32 = up_z * tx + (right_z * sx + z); + GXColor4u8(color.r, color.g, color.b, alpha); if (pp->kind & DispTexture) { GXWGFifo.f32 = s; GXWGFifo.f32 = t; @@ -964,19 +939,19 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, setVtxDesc(1); GXBegin(GX_QUADS, GX_VTXFMT1, 4); } - GXPosition3f32(x - x0, y - y0, z - z0); + GXPosition3f32(x - right.x, y - right.y, z - right_z); if (pp->kind & DispTexture) { GXWGFifo.u8 = (pp->kind >> 16) & 0xC; } - GXPosition3f32(x - x1, y - y1, z - z1); + GXPosition3f32(x - up.x, y - up.y, z - up_z); if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 1; } - GXPosition3f32(x + x0, y + y0, z0 + z); + GXPosition3f32(x + right.x, y + right.y, z + right_z); if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 2; } - GXPosition3f32(x1 + x, y1 + y, z1 + z); + GXPosition3f32(x + up.x, y + up.y, z + up_z); if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 3; } @@ -1011,9 +986,9 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, if (pp->kind & TexFlipT) { t = 1.0f - t; } - GXWGFifo.f32 = x + x0 * sx + x1 * tx; - GXWGFifo.f32 = y + y0 * sx + y1 * tx; - GXWGFifo.f32 = z + z0 * sx + z1 * tx; + GXPosition3f32(x + right.x * sx + up.x * tx, + y + right.y * sx + up.y * tx, + z + right_z * sx + up_z * tx); if (pp->kind & DispTexture) { GXWGFifo.f32 = s; GXWGFifo.f32 = t; @@ -1023,9 +998,15 @@ static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, } } +static inline void psMaskAbsF32(f32* value) +{ + *(s32*) value &= 0x7FFFFFFF; +} + static inline void psDispSub(HSD_Particle* pp, u8* texform) { f32 abs_angle; + f32 abs_y; f32 right_y; f32 right_x; f32 right_z; @@ -1036,7 +1017,6 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) f32 x; f32 y; f32 z; - Mtx mtx; x = pp->pos.x; y = pp->pos.y; @@ -1068,13 +1048,10 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) f32 w0inv; f32 w1; f32 w1inv; - f32 cur_y_term; f32 prev_y_terms; - f32 cur_y; - f32 prev_xy; f32 prev_x_sum; - f32 cur_yx; - f32 prev_yx; + f32 pv13; + f32 pv03; if (pp->kind & Tornado) { calcTornadoLastPos(pp, &prev_x, &prev_y, &prev_z); @@ -1090,28 +1067,29 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) return; } w0inv = -1.0f / w0; - w1 = vmtx[2][3] + (vmtx[2][2] * prev_z + - (vmtx[2][0] * prev_x + vmtx[2][1] * prev_y)); + w1 = vmtx[2][3] + (prev_z * vmtx[2][2] + + (vmtx[2][1] * prev_y + prev_x * vmtx[2][0])); if (0.0f == w1) { return; } w1inv = -1.0f / w1; prev_y_terms = pvmtx[1][1] * prev_y; - prev_xy = pvmtx[0][1] * prev_y; - cur_y = pvmtx[0][1] * pp->pos.y; - cur_y_term = pvmtx[1][1] * pp->pos.y; - prev_x_sum = pvmtx[0][0] * prev_x + prev_xy; - prev_yx = prev_x * pvmtx[1][0] + prev_y_terms; - cur_yx = pvmtx[1][0] * pp->pos.x + cur_y_term; - x = w0inv * (pvmtx[0][3] + (pvmtx[0][2] * pp->pos.z + - (pvmtx[0][0] * pp->pos.x + cur_y))) - - w1inv * (pvmtx[0][3] + (pvmtx[0][2] * prev_z + prev_x_sum)); - y = w0inv * (pvmtx[1][3] + (pvmtx[1][2] * pp->pos.z + cur_yx)) - - w1inv * (pvmtx[1][3] + (pvmtx[1][2] * prev_z + prev_yx)); + prev_x_sum = prev_x * pvmtx[0][0] + pvmtx[0][1] * prev_y; + pv03 = pvmtx[0][3]; + pv13 = pvmtx[1][3]; + x = w0inv * (pv03 + (pvmtx[0][2] * pp->pos.z + + (pvmtx[0][0] * pp->pos.x + + pvmtx[0][1] * pp->pos.y))) - + w1inv * (pv03 + (pvmtx[0][2] * prev_z + prev_x_sum)); + y = w0inv * (pv13 + (pp->pos.z * pvmtx[1][2] + + (pvmtx[1][0] * pp->pos.x + + pp->pos.y * pvmtx[1][1]))) - + w1inv * (pv13 + (prev_z * pvmtx[1][2] + + (prev_x * pvmtx[1][0] + prev_y_terms))); } else if (pp->kind & Tornado) { + f32 prev_z; f32 prev_x; f32 prev_y; - f32 prev_z; f32 dx; f32 dy; f32 dz; @@ -1129,8 +1107,8 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) (pvmtx[1][0] * pp->vel.x + pvmtx[1][1] * pp->vel.y); } { - f32 abs_y = y; - *(s32*) &abs_y &= 0x7FFFFFFF; + abs_y = y; + psMaskAbsF32(&abs_y); if (abs_y < FLT_MIN) { angle = (x >= 0.0f) ? 1.5707964f : -1.5707964f; } else { @@ -1144,8 +1122,9 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) angle = pp->rotate; } abs_angle = angle; - *(s32*) &abs_angle &= 0x7FFFFFFF; + psMaskAbsF32(&abs_angle); if (abs_angle > 0.01) { + Mtx mtx; Vec3 axis; f32 t1; @@ -1160,8 +1139,8 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) axis.x = ry * uz - rz * up_y; { - f32 axis_y_product = ux * rz; - axis.y = axis_y_product - rx * uz; + f32 axis_y_product = rx * uz; + axis.y = rz * ux - axis_y_product; } axis.z = rx * up_y - ry * ux; PSMTXRotAxisRad(mtx, &axis, angle); @@ -1176,8 +1155,8 @@ static inline void psDispSub(HSD_Particle* pp, u8* texform) up_y = mtx[1][2] * uz + t2; up_z = mtx[2][2] * uz + t4; } - psDispSubMakePolygon(pp, texform, x, y, z, pp->vel.x, pp->vel.y, pp->vel.z, - right_x, right_y, right_z, up_x, up_y, up_z); + psDispSubMakePolygon(pp, texform, x, y, z, right_x, right_y, right_z, up_x, + up_y, up_z); } static inline void psScaleAppSRTAxes(HSD_Particle* pp, Mtx mtx) @@ -1193,79 +1172,96 @@ static inline void psScaleAppSRTAxes(HSD_Particle* pp, Mtx mtx) mtx[2][2] *= pp->size; } +/** + * @remarks @p always_stamp is a compile-time constant at both call sites: the + * point path stamps @c frameNum unconditionally under its own NULL guard, the + * polygon path only inside the changed-frame block. Both branches fold away. + */ +static inline void psUpdateAppSRT(HSD_Particle* pp, bool always_stamp, + Mtx scratch_mtx, Vec3* scratch_scale) +{ + if (pp->appsrt->frameNum != psFrameNum) { + f32 scale_x; + f32 scale_y; + + if (pp->appsrt->status != PS_APPSTATUS_STILL) { + HSD_psAppSRT* appsrt = pp->appsrt; + Vec3* translate = &appsrt->translate; + Vec3* rotate = (Vec3*) &appsrt->rot; + Vec3* scale = &appsrt->scale; + MtxPtr mmtx = appsrt->mmtx; + + HSD_MtxSRT(mmtx, scale, rotate, translate, NULL); + } + if (pp->appsrt->status == PS_APPSTATUS_ONCE) { + pp->appsrt->status = PS_APPSTATUS_STILL; + } + PSMTXConcat(vmtx, pp->appsrt->mmtx, (MtxPtr) &pp->appsrt->ssx); + scale_x = pp->appsrt->ssx * pp->appsrt->ssx + + pp->appsrt->x74 * pp->appsrt->x74 + + pp->appsrt->x84 * pp->appsrt->x84; + scale_x = sqrtf(scale_x); + pp->appsrt->x94 = scale_x; + scale_y = pp->appsrt->ssy * pp->appsrt->ssy + + pp->appsrt->x78 * pp->appsrt->x78 + + pp->appsrt->x88 * pp->appsrt->x88; + scale_y = sqrtf(scale_y); + pp->appsrt->x98 = scale_y; + if (pp->appsrt->xA2 != 0) { + PSMTXIdentity(scratch_mtx); + scratch_mtx[0][3] = pp->appsrt->translate.x; + scratch_mtx[1][3] = pp->appsrt->translate.y; + scratch_mtx[2][3] = pp->appsrt->translate.z; + PSMTXConcat(vmtx, scratch_mtx, scratch_mtx); + HSD_MtxGetScale(scratch_mtx, scratch_scale); + PSMTXScale((MtxPtr) &pp->appsrt->ssx, scratch_scale->x, + scratch_scale->y, scratch_scale->z); + pp->appsrt->x70 = scratch_mtx[0][3]; + pp->appsrt->x80 = scratch_mtx[1][3]; + pp->appsrt->x90 = scratch_mtx[2][3]; + } + if (!always_stamp) { + pp->appsrt->frameNum = psFrameNum; + } + } + if (always_stamp) { + pp->appsrt->frameNum = psFrameNum; + } +} + static inline void psDispSubAPPSRTPoint(HSD_Particle* pp) { - GXColor draw_color; - Vec3 cur_pos; - Vec3 prev_pos; - f32 ax; + Mtx scratch_mtx; + Vec3 scratch_scale; + f32 cur_x; + f32 cur_y; + f32 cur_z; + f32 prev_x; + f32 prev_y; + f32 prev_z; s32 w; psSetCurrentMtx(GX_PNMTX1); if (pp->appsrt != NULL) { - if (pp->appsrt->frameNum != psFrameNum) { - f32 scale_x; - f32 scale_y; - - if (pp->appsrt->status != PS_APPSTATUS_STILL) { - HSD_psAppSRT* appsrt = pp->appsrt; - Vec3* translate = &appsrt->translate; - Vec3* rotate = (Vec3*) &appsrt->rot; - Vec3* scale = &appsrt->scale; - - HSD_MtxSRT(appsrt->mmtx, scale, rotate, translate, NULL); - } - if (pp->appsrt->status == PS_APPSTATUS_ONCE) { - pp->appsrt->status = PS_APPSTATUS_STILL; - } - PSMTXConcat(vmtx, pp->appsrt->mmtx, (MtxPtr) &pp->appsrt->ssx); - scale_x = pp->appsrt->ssx * pp->appsrt->ssx + - pp->appsrt->x74 * pp->appsrt->x74 + - pp->appsrt->x84 * pp->appsrt->x84; - scale_x = sqrtf(scale_x); - pp->appsrt->x94 = scale_x; - scale_y = pp->appsrt->ssy * pp->appsrt->ssy + - pp->appsrt->x78 * pp->appsrt->x78 + - pp->appsrt->x88 * pp->appsrt->x88; - scale_y = sqrtf(scale_y); - pp->appsrt->x98 = scale_y; - if (pp->appsrt->xA2 != 0) { - Mtx temp_mtx; - Vec3 scale; - - PSMTXIdentity(temp_mtx); - temp_mtx[0][3] = pp->appsrt->translate.x; - temp_mtx[1][3] = pp->appsrt->translate.y; - temp_mtx[2][3] = pp->appsrt->translate.z; - PSMTXConcat(vmtx, temp_mtx, temp_mtx); - HSD_MtxGetScale(temp_mtx, &scale); - PSMTXScale((MtxPtr) &pp->appsrt->ssx, scale.x, scale.y, - scale.z); - pp->appsrt->x70 = temp_mtx[0][3]; - pp->appsrt->x80 = temp_mtx[1][3]; - pp->appsrt->x90 = temp_mtx[2][3]; - } - } - pp->appsrt->frameNum = psFrameNum; + psUpdateAppSRT(pp, true, scratch_mtx, &scratch_scale); } { HSD_psAppSRT* appsrt = pp->appsrt; - f32 pos_y; - f32 transformed_x; - - cur_pos.z = appsrt->x88 * (pos_y = pp->pos.y); - cur_pos.y = appsrt->x78 * pos_y; - cur_pos.x = appsrt->ssy * pos_y; - cur_pos.y = appsrt->x74 * pp->pos.x + cur_pos.y; - cur_pos.z = (cur_pos.x = appsrt->ssx * pp->pos.x + cur_pos.x, - appsrt->x84 * pp->pos.x + cur_pos.z); - transformed_x = appsrt->x6C * pp->pos.z + cur_pos.x; - cur_pos.x = transformed_x; - cur_pos.y = appsrt->x7C * pp->pos.z + cur_pos.y; - cur_pos.z = appsrt->x8C * pp->pos.z + cur_pos.z; - cur_pos.x = appsrt->x70 + cur_pos.x; - cur_pos.y = appsrt->x80 + cur_pos.y; - cur_pos.z = appsrt->x90 + cur_pos.z; + f32 y_component; + + (void) y_component; + cur_x = appsrt->ssy * (y_component = pp->pos.y); + cur_y = appsrt->x78 * y_component; + cur_z = appsrt->x88 * y_component; + cur_x = appsrt->ssx * pp->pos.x + cur_x; + cur_z = (y_component = appsrt->x74 * pp->pos.x + cur_y, + appsrt->x84 * pp->pos.x + cur_z); + cur_z = (cur_x = appsrt->x6C * pp->pos.z + cur_x, + cur_y = appsrt->x7C * pp->pos.z + y_component, + appsrt->x8C * pp->pos.z + cur_z); + cur_x = appsrt->x70 + cur_x; + cur_y = appsrt->x80 + cur_y; + cur_z = appsrt->x90 + cur_z; } if (pp->kind & Tornado) { f32 x; @@ -1273,33 +1269,34 @@ static inline void psDispSubAPPSRTPoint(HSD_Particle* pp) f32 z; calcTornadoLastPos(pp, &x, &y, &z); - prev_pos.x = + prev_x = pp->appsrt->x70 + (pp->appsrt->x6C * z + (pp->appsrt->ssx * x + pp->appsrt->ssy * y)); - prev_pos.y = + prev_y = pp->appsrt->x80 + (pp->appsrt->x7C * z + (pp->appsrt->x74 * x + pp->appsrt->x78 * y)); - prev_pos.z = + prev_z = pp->appsrt->x90 + (pp->appsrt->x8C * z + (pp->appsrt->x84 * x + pp->appsrt->x88 * y)); } else { - f32 dx = pp->pos.x - pp->vel.x; f32 dy = pp->pos.y - pp->vel.y; + f32 dx = pp->pos.x - pp->vel.x; f32 dz = pp->pos.z - pp->vel.z; - prev_pos.x = + prev_x = pp->appsrt->x70 + (pp->appsrt->x6C * dz + (pp->appsrt->ssx * dx + pp->appsrt->ssy * dy)); - prev_pos.y = + prev_y = pp->appsrt->x80 + (pp->appsrt->x7C * dz + - (pp->appsrt->x78 * dy + pp->appsrt->x74 * dx)); - prev_pos.z = + (pp->appsrt->x74 * dx + pp->appsrt->x78 * dy)); + prev_z = pp->appsrt->x90 + (pp->appsrt->x8C * dz + (pp->appsrt->x84 * dx + pp->appsrt->x88 * dy)); } - ax = pp->size > 42.5 ? 255.0f : 6.0f * pp->size; - w = (s32) ax; + w = (s32) ((pp->size > 42.5) ? 255.0f : 6.0f * pp->size); if (pp->kind & Trail) { + GXColor draw_color; + if (prevLineWidth != (s32) (u8) w) { prevLineWidth = (u8) w; GXSetLineWidth((u8) w, GX_TO_ONE); @@ -1312,30 +1309,14 @@ static inline void psDispSubAPPSRTPoint(HSD_Particle* pp) setVtxDesc(3); GXBegin(GX_LINES, GX_VTXFMT3, 2); } - GXWGFifo.f32 = prev_pos.x; - GXWGFifo.f32 = prev_pos.y; - GXWGFifo.f32 = prev_pos.z; - { - u8 a = draw_color.a; - f32 alpha = (f32) a * pp->trail; - u8 b = draw_color.b; - u8 g = draw_color.g; - u8 r = draw_color.r; - GXColor4u8(r, g, b, (u8) alpha); - } + GXPosition3f32(prev_x, prev_y, prev_z); + GXColor4u8(draw_color.r, draw_color.g, draw_color.b, + (u8) ((f32) draw_color.a * pp->trail)); if (pp->kind & DispTexture) { GXTexCoord1x8(0); } - GXWGFifo.f32 = cur_pos.x; - GXWGFifo.f32 = cur_pos.y; - GXWGFifo.f32 = cur_pos.z; - { - u8 a = draw_color.a; - u8 b = draw_color.b; - u8 g = draw_color.g; - u8 r = draw_color.r; - GXColor4u8(r, g, b, a); - } + GXPosition3f32(cur_x, cur_y, cur_z); + GXColor4u8(draw_color.r, draw_color.g, draw_color.b, draw_color.a); if (pp->kind & DispTexture) { GXTexCoord1x8(1); } @@ -1351,9 +1332,7 @@ static inline void psDispSubAPPSRTPoint(HSD_Particle* pp) setVtxDesc(1); GXBegin(GX_POINTS, GX_VTXFMT1, 1); } - GXWGFifo.f32 = cur_pos.x; - GXWGFifo.f32 = cur_pos.y; - GXWGFifo.f32 = cur_pos.z; + GXPosition3f32(cur_x, cur_y, cur_z); if (pp->kind & DispTexture) { GXTexCoord1x8(1); } @@ -1362,81 +1341,39 @@ static inline void psDispSubAPPSRTPoint(HSD_Particle* pp) static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) { - GXColor draw_color; + f32 abs_angle; + f32 abs_v; + Mtx draw_mtx; Vec3 cur_pos; + Vec3 scratch_scale; Vec3 prev_pos; + f32 x_extent; + f32 y_extent; f32 ax; f32 ay; f32 bx; f32 by; - f32 y_extent; f32 angle; - f32 abs_angle; u8* it = texform; - if (pp->appsrt->frameNum != psFrameNum) { - f32 scale_x; - f32 scale_y; - - if (pp->appsrt->status != PS_APPSTATUS_STILL) { - HSD_psAppSRT* appsrt = pp->appsrt; - Vec3* translate = &appsrt->translate; - Vec3* rotate = (Vec3*) &appsrt->rot; - Vec3* scale = &appsrt->scale; - MtxPtr mmtx = appsrt->mmtx; - - HSD_MtxSRT(mmtx, scale, rotate, translate, NULL); - } - if (pp->appsrt->status == PS_APPSTATUS_ONCE) { - pp->appsrt->status = PS_APPSTATUS_STILL; - } - PSMTXConcat(vmtx, pp->appsrt->mmtx, (MtxPtr) &pp->appsrt->ssx); - scale_x = pp->appsrt->ssx * pp->appsrt->ssx + - pp->appsrt->x74 * pp->appsrt->x74 + - pp->appsrt->x84 * pp->appsrt->x84; - scale_x = sqrtf(scale_x); - pp->appsrt->x94 = scale_x; - scale_y = pp->appsrt->ssy * pp->appsrt->ssy + - pp->appsrt->x78 * pp->appsrt->x78 + - pp->appsrt->x88 * pp->appsrt->x88; - scale_y = sqrtf(scale_y); - pp->appsrt->x98 = scale_y; - if (pp->appsrt->xA2 != 0) { - Mtx temp_mtx; - Vec3 scale; - - PSMTXIdentity(temp_mtx); - temp_mtx[0][3] = pp->appsrt->translate.x; - temp_mtx[1][3] = pp->appsrt->translate.y; - temp_mtx[2][3] = pp->appsrt->translate.z; - PSMTXConcat(vmtx, temp_mtx, temp_mtx); - HSD_MtxGetScale(temp_mtx, &scale); - PSMTXScale((MtxPtr) &pp->appsrt->ssx, scale.x, scale.y, scale.z); - pp->appsrt->x70 = temp_mtx[0][3]; - pp->appsrt->x80 = temp_mtx[1][3]; - pp->appsrt->x90 = temp_mtx[2][3]; - } - pp->appsrt->frameNum = psFrameNum; - } + psUpdateAppSRT(pp, false, draw_mtx, &scratch_scale); { - Mtx draw_mtx; f32 app_cur_x; f32 app_cur_y; f32 app_cur_z; + f32 pos_x; + f32 pos_y; PSMTXCopy((MtxPtr) &pp->appsrt->ssx, draw_mtx); - app_cur_z = - draw_mtx[2][3] + - (draw_mtx[2][2] * pp->pos.z + - (draw_mtx[2][0] * pp->pos.x + draw_mtx[2][1] * pp->pos.y)); - app_cur_y = - draw_mtx[1][3] + - (draw_mtx[1][2] * pp->pos.z + - (draw_mtx[1][0] * pp->pos.x + draw_mtx[1][1] * pp->pos.y)); - app_cur_x = - draw_mtx[0][3] + - (draw_mtx[0][2] * pp->pos.z + - (draw_mtx[0][0] * pp->pos.x + draw_mtx[0][1] * pp->pos.y)); + app_cur_x = draw_mtx[0][3] + (draw_mtx[0][2] * pp->pos.z + + (draw_mtx[0][0] * (pos_x = pp->pos.x) + + draw_mtx[0][1] * (pos_y = pp->pos.y))); + app_cur_y = draw_mtx[1][3] + + (draw_mtx[1][2] * pp->pos.z + + (draw_mtx[1][0] * pos_x + draw_mtx[1][1] * pos_y)); + app_cur_z = draw_mtx[2][3] + + (draw_mtx[2][2] * pp->pos.z + + (draw_mtx[2][0] * pos_x + draw_mtx[2][1] * pos_y)); cur_pos.x = app_cur_x; cur_pos.y = app_cur_y; cur_pos.z = app_cur_z; @@ -1456,9 +1393,9 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) draw_mtx[2][3] + (draw_mtx[2][2] * z + (draw_mtx[2][0] * x + draw_mtx[2][1] * y)); } else { + f32 dz = pp->pos.z - pp->vel.z; f32 dx = pp->pos.x - pp->vel.x; f32 dy = pp->pos.y - pp->vel.y; - f32 dz = pp->pos.z - pp->vel.z; prev_pos.x = draw_mtx[0][3] + (draw_mtx[0][2] * dz + @@ -1472,16 +1409,17 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) } psScaleAppSRTAxes(pp, draw_mtx); } - ax = pp->appsrt->x94 * pp->size; - bx = ax; + x_extent = pp->appsrt->x94 * pp->size; y_extent = pp->appsrt->x98 * pp->size; if (it == NULL) { ay = y_extent; by = -ay; + ax = bx = x_extent; } else { ay = 0.0f; + ax = x_extent; by = -y_extent; - bx = 0.0f; + bx = ay; } if ((pp->kind & Trail) || (pp->kind & DirVec)) { f32 vf1; @@ -1504,8 +1442,8 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) f32 f13; f32 f16; f32 f20; - f32 s808; f32 s804; + f32 s808; if (pp->kind & Tornado) { calcTornadoLastPos(pp, &prev_x, &prev_y, &prev_z); @@ -1563,23 +1501,31 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) f32 tz; calcTornadoLastPos(pp, &tx, &ty, &tz); { - f32 dy = pp->pos.y - ty; - f32 dx = pp->pos.x - tx; - f32 dz = pp->pos.z - tz; + f32 dx; + f32 dy; + f32 dz; + + dy = pp->pos.y - ty; + dx = pp->pos.x - tx; + dz = pp->pos.z - tz; vf1 = s7F8 * dz + (s800 * dx + s7FC * dy); vf2 = f20 * dz + (f17 * dx + f18 * dy); } } else { - f32 vy = pp->vel.y; - f32 vx = pp->vel.x; - f32 vz = pp->vel.z; + f32 vz; + f32 vx; + f32 vy; + + vy = pp->vel.y; + vx = pp->vel.x; + vz = pp->vel.z; vf1 = s7F8 * vz + (s800 * vx + s7FC * vy); vf2 = f20 * vz + (f17 * vx + f18 * vy); } } { - f32 abs_v = vf2; - *(s32*) &abs_v &= 0x7FFFFFFF; + abs_v = vf2; + psMaskAbsF32(&abs_v); if (abs_v < FLT_MIN) { angle = (-vf1 >= 0.0f) ? 1.5707964f : -1.5707964f; } else { @@ -1593,7 +1539,7 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) angle = pp->rotate; } abs_angle = angle; - *(s32*) &abs_angle &= 0x7FFFFFFF; + psMaskAbsF32(&abs_angle); if (abs_angle > 0.01) { f32 c = cosf(angle); f32 s = sinf(angle); @@ -1605,12 +1551,14 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) by = s * old_bx + c * by; } psSetCurrentMtx(GX_PNMTX1); - /** @todo Later HSD shares this emission through an AppSRT-aware - * #psDispSubMakePolygon; Melee's emitted code lacks that body. + /** @todo Later HSD shares this emission with the polygon path; Melee's + * emitted code keeps the two separate. * @remarks Positions here stay raw @c GXWGFifo stores, not * @c GXPosition3f32: the inline's argument evaluation forces an extra * live FP register here and grows the frame past the target. */ if (pp->kind & Trail) { + GXColor draw_color; + getClrTrail(pp, &draw_color); if (it == NULL) { if (pp->kind & DispTexture) { @@ -1620,16 +1568,9 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) setVtxDesc(3); GXBegin(GX_QUADS, GX_VTXFMT3, 4U); } + GXPosition3f32(-ax + prev_pos.x, -ay + prev_pos.y, prev_pos.z); { - f32 vx = -ax + prev_pos.x; - f32 vy = -ay + prev_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = prev_pos.z; - } - { - u8 a = draw_color.a; - f32 alpha = (f32) a * pp->trail; + f32 alpha = (f32) draw_color.a * pp->trail; u8 b = draw_color.b; u8 g = draw_color.g; u8 r = draw_color.r; @@ -1638,13 +1579,9 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) if (pp->kind & DispTexture) { GXWGFifo.u8 = (pp->kind >> 16) & 0xC; } - { - f32 vx = -bx + cur_pos.x; - f32 vy = -by + cur_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = cur_pos.z; - } + GXWGFifo.f32 = -bx + cur_pos.x; + GXWGFifo.f32 = -by + cur_pos.y; + GXWGFifo.f32 = cur_pos.z; { u8 a = draw_color.a; u8 b = draw_color.b; @@ -1655,13 +1592,9 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 1; } - { - f32 vx = ax + cur_pos.x; - f32 vy = ay + cur_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = cur_pos.z; - } + GXWGFifo.f32 = ax + cur_pos.x; + GXWGFifo.f32 = ay + cur_pos.y; + GXWGFifo.f32 = cur_pos.z; { u8 a = draw_color.a; u8 b = draw_color.b; @@ -1672,13 +1605,7 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 2; } - { - f32 vx = bx + prev_pos.x; - f32 vy = by + prev_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = prev_pos.z; - } + GXPosition3f32(bx + prev_pos.x, by + prev_pos.y, prev_pos.z); { u8 a = draw_color.a; f32 alpha = (f32) a * pp->trail; @@ -1701,8 +1628,7 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) f32 xl = dx * dx; f32 yl = dy * dy; f32 zl = dz * dz; - f32 segment_len = sqrtf(zl + (xl + yl)); - f32 ratio = segment_len / axis_len; + f32 ratio = sqrtf(zl + (xl + yl)) / axis_len; u32 primitive_count = *(u32*) it; bx *= ratio; @@ -1712,9 +1638,6 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) GXPrimitive primitive = it[0]; u8 count = it[1]; s32 i; - u8 b; - u8 g; - u8 r; it += 4; if (pp->kind & DispTexture) { @@ -1724,9 +1647,6 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) setVtxDesc(3); GXBegin(primitive, GX_VTXFMT3, count); } - b = draw_color.b; - g = draw_color.g; - r = draw_color.r; for (i = count; i > 0; i--) { f32 s = *(f32*) &it[0]; f32 sx = 2.0f * (s - 0.5f); @@ -1740,8 +1660,8 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) } t = *(f32*) &it[4]; it += 8; - converted_alpha = (s32) (255.0f - t * trail_alpha); alpha = (s32) (255.0f - t * trail_alpha); + converted_alpha = (s32) (255.0f - t * trail_alpha); if (converted_alpha < 0) { alpha = 0; } @@ -1755,7 +1675,8 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) GXWGFifo.f32 = cur_pos.x + ax * sx + bx * tx; GXWGFifo.f32 = cur_pos.y + ay * sx + by * tx; GXWGFifo.f32 = cur_pos.z; - GXColor4u8(r, g, b, (u8) alpha); + GXColor4u8(draw_color.r, draw_color.g, draw_color.b, + (u8) alpha); if (pp->kind & DispTexture) { GXWGFifo.f32 = s; GXWGFifo.f32 = t; @@ -1772,43 +1693,27 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) setVtxDesc(1); GXBegin(GX_QUADS, GX_VTXFMT1, 4U); } - { - f32 vx = -ax + cur_pos.x; - f32 vy = -ay + cur_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = cur_pos.z; - } + GXWGFifo.f32 = -ax + cur_pos.x; + GXWGFifo.f32 = -ay + cur_pos.y; + GXWGFifo.f32 = cur_pos.z; if (pp->kind & DispTexture) { GXWGFifo.u8 = (pp->kind >> 16) & 0xC; } - { - f32 vx = -bx + cur_pos.x; - f32 vy = -by + cur_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = cur_pos.z; - } + GXWGFifo.f32 = -bx + cur_pos.x; + GXWGFifo.f32 = -by + cur_pos.y; + GXWGFifo.f32 = cur_pos.z; if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 1; } - { - f32 vx = ax + cur_pos.x; - f32 vy = ay + cur_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = cur_pos.z; - } + GXWGFifo.f32 = ax + cur_pos.x; + GXWGFifo.f32 = ay + cur_pos.y; + GXWGFifo.f32 = cur_pos.z; if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 2; } - { - f32 vx = bx + cur_pos.x; - f32 vy = by + cur_pos.y; - GXWGFifo.f32 = vx; - GXWGFifo.f32 = vy; - GXWGFifo.f32 = cur_pos.z; - } + GXWGFifo.f32 = bx + cur_pos.x; + GXWGFifo.f32 = by + cur_pos.y; + GXWGFifo.f32 = cur_pos.z; if (pp->kind & DispTexture) { GXWGFifo.u8 = ((pp->kind >> 16) & 0xC) + 3; } @@ -1857,82 +1762,25 @@ static inline void psDispSubAppSRT(HSD_Particle* pp, u8* texform) static inline void psUpdateBillboardAxes(const Mtx inv_view) { - f32 right; - f32 up; - - right = inv_view[0][0]; - up = inv_view[0][1]; - HSD_PSDisp_804D7914 = right + up; - HSD_PSDisp_804D7918 = right - up; - right = inv_view[1][0]; - up = inv_view[1][1]; - HSD_PSDisp_804D791C = right + up; - HSD_PSDisp_804D7920 = right - up; - right = inv_view[2][0]; - up = inv_view[2][1]; - HSD_PSDisp_804D7924 = right + up; - HSD_PSDisp_804D7928 = right - up; -} + f32 right_x; + f32 up_x; + f32 right_y; + f32 up_y; + f32 right_z; + f32 up_z; -static inline void psUpdateProjectionCache(f32 perspective) -{ - GXGetProjectionv(prj); - if (perspective == prj[0]) { - f32 w0; - f32 x_scale = prj[1]; - f32 x_offset = prj[2]; - f32 w1; - f32 w2; - f32 w3; - f32 y_scale; - f32 y_offset; - f32 product; - f32 y0; - f32 y1; - f32 y2; - f32 y3; - - w0 = vmtx[2][0]; - product = x_offset * w0; - pvmtx[0][0] = x_scale * vmtx[0][0] + product; - w1 = vmtx[2][1]; - product = x_offset * w1; - pvmtx[0][1] = x_scale * vmtx[0][1] + product; - w2 = vmtx[2][2]; - product = x_offset * w2; - pvmtx[0][2] = x_scale * vmtx[0][2] + product; - w3 = vmtx[2][3]; - product = x_offset * w3; - pvmtx[0][3] = x_scale * vmtx[0][3] + product; - y_scale = prj[3]; - y_offset = prj[4]; - y0 = y_offset * w0; - y1 = y_offset * w1; - y2 = y_offset * w2; - y3 = y_offset * w3; - pvmtx[1][0] = y_scale * vmtx[1][0] + y0; - pvmtx[1][1] = y_scale * vmtx[1][1] + y1; - pvmtx[1][2] = y_scale * vmtx[1][2] + y2; - pvmtx[1][3] = y_scale * vmtx[1][3] + y3; - } else { - f32 x_offset = prj[2]; - f32 x_scale = prj[1]; - f32 y_offset; - f32 y_scale; - - pvmtx[0][0] = x_scale * vmtx[0][0] + x_offset; - pvmtx[0][1] = x_scale * vmtx[0][1] + x_offset; - pvmtx[0][2] = x_scale * vmtx[0][2] + x_offset; - pvmtx[0][3] = x_scale * vmtx[0][3] + x_offset; - y_scale = prj[3]; - y_offset = prj[4]; - pvmtx[1][0] = y_scale * vmtx[1][0] + y_offset; - pvmtx[1][1] = y_scale * vmtx[1][1] + y_offset; - pvmtx[1][2] = y_scale * vmtx[1][2] + y_offset; - pvmtx[1][3] = y_scale * vmtx[1][3] + y_offset; - } - /// @todo Passing @c rvmtx directly swaps the first two axis loads. - psUpdateBillboardAxes(*(const Mtx*) rvmtx); + right_x = inv_view[0][0]; + up_x = inv_view[0][1]; + HSD_PSDisp_804D7914 = right_x + up_x; + HSD_PSDisp_804D7918 = right_x - up_x; + right_y = inv_view[1][0]; + up_y = inv_view[1][1]; + HSD_PSDisp_804D791C = right_y + up_y; + HSD_PSDisp_804D7920 = right_y - up_y; + right_z = inv_view[2][0]; + up_z = inv_view[2][1]; + HSD_PSDisp_804D7924 = right_z + up_z; + HSD_PSDisp_804D7928 = right_z - up_z; } #ifdef MUST_MATCH @@ -1941,32 +1789,26 @@ static inline void psUpdateProjectionCache(f32 perspective) #endif void psDispParticles(u32 target_link, u32 sw) { - GXColor chan_mat_color; - s32 needs_setup; s32 sp7B4; void* sp7B0; u32 sp7AC; u32 sp7A8; u8 sp7A5; u8 sp7A4; - GXColor chan_amb_color; + s32 needs_setup; void* sp79C; psdisp_Tlut tlut_obj; + UNUSED s32 stack_pad; GXTexObj sp764; HSD_Particle* sorted_particles; HSD_Particle* non_edge_particles; psdisp_Mtx billboard_mtx; - f32 sp700; + f32 y2; GXTlutObj gx_tlut_obj; s32 alpha_compare_mode; s32 prev_tex_interp_near; - GXColor sp6D8; - GXColor sp6D4; - GXColor sp6D0; u32 prev_kind; HSD_Particle* pp; - /// @todo Recover this stack space from the original inline hierarchy. - PAD_STACK(0x14); alpha_compare_mode = 0; prev_tex_interp_near = 0; @@ -2000,7 +1842,6 @@ void psDispParticles(u32 target_link, u32 sw) u32 blend_mode; u8 alpha0; u8 alpha1; - Mtx temp_mtx; GXTexWrapMode wrap_s; GXTexWrapMode wrap_t; f32 scale_s; @@ -2028,26 +1869,72 @@ void psDispParticles(u32 target_link, u32 sw) prevChanMat.r = prevChanMat.g = prevChanMat.b = 0xFF; prevChanAmb.r = prevChanAmb.g = prevChanAmb.b = 0xFF; prevChanMat.a = prevChanAmb.a = 0xFF; - chan_mat_color = prevChanMat; - GXSetChanMatColor(GX_COLOR0A0, chan_mat_color); - chan_amb_color = prevChanAmb; - GXSetChanAmbColor(GX_COLOR0A0, chan_amb_color); + GXSetChanMatColor(GX_COLOR0A0, prevChanMat); + GXSetChanAmbColor(GX_COLOR0A0, prevChanAmb); psSetupTevInvalidState(); psSetupTevCommon(); psSetColor(&prevColorPrim, 0xFF); psSetColor(&prevColorEnv, 0); psSetColor(&prevColorMat, 0xFF); - sp6D8 = prevColorPrim; - GXSetTevColor(GX_TEVREG0, sp6D8); - sp6D4 = prevColorEnv; - GXSetTevColor(GX_TEVREG1, sp6D4); - sp6D0 = prevColorMat; - GXSetTevColor(GX_TEVREG2, sp6D0); + GXSetTevColor(GX_TEVREG0, prevColorPrim); + GXSetTevColor(GX_TEVREG1, prevColorEnv); + GXSetTevColor(GX_TEVREG2, prevColorMat); HSD_PSDisp_804D792C = -1; GXSetZCompLoc(GX_FALSE); HSD_CObjGetViewingMtx(HSD_CObjGetCurrent(), vmtx); PSMTXInverse(vmtx, rvmtx); - psUpdateProjectionCache(0.0f); + { + f32 w0; + f32 x_offset; + f32 x_scale; + f32 w1; + f32 y_offset; + f32 y_scale; + f32 w2; + f32 w3; + f32 y0; + f32 y1; + + GXGetProjectionv(prj); + if (0.0f == prj[0]) { + x_scale = prj[1]; + x_offset = prj[2]; + w0 = vmtx[2][0]; + pvmtx[0][0] = + x_scale * vmtx[0][0] + x_offset * w0; + w1 = vmtx[2][1]; + pvmtx[0][1] = + x_scale * vmtx[0][1] + x_offset * w1; + w2 = vmtx[2][2]; + pvmtx[0][2] = + x_scale * vmtx[0][2] + x_offset * w2; + w3 = vmtx[2][3]; + pvmtx[0][3] = + x_scale * vmtx[0][3] + x_offset * w3; + y_scale = prj[3]; + y_offset = prj[4]; + y0 = y_offset * w0; + y1 = y_offset * w1; + y2 = y_offset * w2; + pvmtx[1][0] = y_scale * vmtx[1][0] + y0; + pvmtx[1][1] = y_scale * vmtx[1][1] + y1; + pvmtx[1][2] = y_scale * vmtx[1][2] + y2; + pvmtx[1][3] = + y_scale * vmtx[1][3] + (y_offset * w3); + } else { + pvmtx[0][0] = prj[1] * vmtx[0][0] + prj[2]; + pvmtx[0][1] = prj[1] * vmtx[0][1] + prj[2]; + pvmtx[0][2] = prj[1] * vmtx[0][2] + prj[2]; + pvmtx[0][3] = prj[1] * vmtx[0][3] + prj[2]; + pvmtx[1][0] = prj[3] * vmtx[1][0] + prj[4]; + pvmtx[1][1] = prj[3] * vmtx[1][1] + prj[4]; + pvmtx[1][2] = prj[3] * vmtx[1][2] + prj[4]; + pvmtx[1][3] = prj[3] * vmtx[1][3] + prj[4]; + } + /// @todo Passing @c rvmtx directly swaps the first + /// two axis loads. + psUpdateBillboardAxes(*(const Mtx*) rvmtx); + } GXLoadPosMtxImm(vmtx, GX_PNMTX0); billboard_mtx = HSD_PSDisp_803B9628; GXLoadPosMtxImm(billboard_mtx.mtx, GX_PNMTX1); @@ -2145,12 +2032,13 @@ void psDispParticles(u32 target_link, u32 sw) wrap_t = GX_CLAMP; } if ((pp->kind & (MirrorS | MirrorT)) != sp7A8) { + Mtx temp_mtx; + sp7A8 = pp->kind & (MirrorS | MirrorT); sp7B0 = NULL; PSMTXScale(temp_mtx, scale_s, scale_t, 1.0f); if (pp->kind & MirrorT) { - sp700 = 1.0f; - temp_mtx[1][3] = sp700; + temp_mtx[1][3] = 1.0f; } GXLoadTexMtxImm(temp_mtx, GX_TEXMTX0, GX_MTX2x4); GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, @@ -2197,8 +2085,8 @@ void psDispParticles(u32 target_link, u32 sw) tlut_obj.n_entries); GXLoadTlut(&gx_tlut_obj, tlut_obj.tlut_name); - sp7B0 = NULL; } + sp7B0 = NULL; } } } diff --git a/src/sysdolphin/baselib/psstructs.h b/src/sysdolphin/baselib/psstructs.h index 5d34df57b0..f5bf38635f 100644 --- a/src/sysdolphin/baselib/psstructs.h +++ b/src/sysdolphin/baselib/psstructs.h @@ -300,8 +300,7 @@ static inline void psSetCurrentMtx(GXPosNrmMtx idx); static inline HSD_Particle* psDispSubPoint(HSD_Particle* pp); static inline HSD_Particle* psDispSubPointTrail(HSD_Particle* pp); static inline void psDispSubMakePolygon(HSD_Particle* pp, u8* texform, f32 x, - f32 y, f32 z, f32 ppvx, f32 ppvy, - f32 ppvz, f32 x0, f32 y0, f32 z0, + f32 y, f32 z, f32 x0, f32 y0, f32 z0, f32 x1, f32 y1, f32 z1); static inline void psDispSub(HSD_Particle* pp, u8* texform);