From c1a0264e6ac151f3a884bc32126de192eede19c7 Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 27 Apr 2025 07:13:47 +0200 Subject: [PATCH] Initial import of JParticle + JSUList from TP --- include/JSystem/JGeometry.h | 508 ++++++ include/JSystem/JMath/JMATrigonometric.h | 136 ++ include/JSystem/JMath/JMath.h | 263 +++ include/JSystem/JMath/random.h | 51 + include/JSystem/JParticle/JPABaseShape.h | 210 +++ include/JSystem/JParticle/JPAChildShape.h | 89 + include/JSystem/JParticle/JPADrawInfo.h | 29 + include/JSystem/JParticle/JPADynamicsBlock.h | 109 ++ include/JSystem/JParticle/JPAEmitter.h | 272 ++++ include/JSystem/JParticle/JPAEmitterManager.h | 49 + include/JSystem/JParticle/JPAExTexShape.h | 45 + include/JSystem/JParticle/JPAExtraShape.h | 112 ++ include/JSystem/JParticle/JPAFieldBlock.h | 174 ++ include/JSystem/JParticle/JPAKeyBlock.h | 21 + include/JSystem/JParticle/JPAList.h | 131 ++ include/JSystem/JParticle/JPAMath.h | 16 + include/JSystem/JParticle/JPAParticle.h | 93 ++ include/JSystem/JParticle/JPARandom.h | 43 + include/JSystem/JParticle/JPAResource.h | 81 + include/JSystem/JParticle/JPAResourceLoader.h | 14 + .../JSystem/JParticle/JPAResourceManager.h | 36 + include/JSystem/JParticle/JPATexture.h | 36 + include/JSystem/JSupport/JSUList.h | 254 +++ include/JSystem/JSupport/JSupport.h | 45 + include/JSystem/JUtility/JUTAssert.h | 64 + include/JSystem/JUtility/JUTTexture.h | 113 ++ include/JSystem/TPosition3.h | 86 + src/JSystem/JParticle/JPABaseShape.cpp | 1449 +++++++++++++++++ src/JSystem/JParticle/JPAChildShape.cpp | 48 + src/JSystem/JParticle/JPADynamicsBlock.cpp | 233 +++ src/JSystem/JParticle/JPAEmitter.cpp | 183 +++ src/JSystem/JParticle/JPAEmitterManager.cpp | 203 +++ src/JSystem/JParticle/JPAExTexShape.cpp | 35 + src/JSystem/JParticle/JPAExtraShape.cpp | 152 ++ src/JSystem/JParticle/JPAFieldBlock.cpp | 299 ++++ src/JSystem/JParticle/JPAKeyBlock.cpp | 25 + src/JSystem/JParticle/JPAMath.cpp | 182 +++ src/JSystem/JParticle/JPAParticle.cpp | 331 ++++ src/JSystem/JParticle/JPAResource.cpp | 1124 +++++++++++++ src/JSystem/JParticle/JPAResourceLoader.cpp | 106 ++ src/JSystem/JParticle/JPAResourceManager.cpp | 84 + src/JSystem/JParticle/JPATexture.cpp | 15 + src/JSystem/JSupport/JSUList.cpp | 162 ++ 43 files changed, 7711 insertions(+) create mode 100644 include/JSystem/JGeometry.h create mode 100644 include/JSystem/JMath/JMATrigonometric.h create mode 100644 include/JSystem/JMath/JMath.h create mode 100644 include/JSystem/JMath/random.h create mode 100644 include/JSystem/JParticle/JPABaseShape.h create mode 100644 include/JSystem/JParticle/JPAChildShape.h create mode 100644 include/JSystem/JParticle/JPADrawInfo.h create mode 100644 include/JSystem/JParticle/JPADynamicsBlock.h create mode 100644 include/JSystem/JParticle/JPAEmitter.h create mode 100644 include/JSystem/JParticle/JPAEmitterManager.h create mode 100644 include/JSystem/JParticle/JPAExTexShape.h create mode 100644 include/JSystem/JParticle/JPAExtraShape.h create mode 100644 include/JSystem/JParticle/JPAFieldBlock.h create mode 100644 include/JSystem/JParticle/JPAKeyBlock.h create mode 100644 include/JSystem/JParticle/JPAList.h create mode 100644 include/JSystem/JParticle/JPAMath.h create mode 100644 include/JSystem/JParticle/JPAParticle.h create mode 100644 include/JSystem/JParticle/JPARandom.h create mode 100644 include/JSystem/JParticle/JPAResource.h create mode 100644 include/JSystem/JParticle/JPAResourceLoader.h create mode 100644 include/JSystem/JParticle/JPAResourceManager.h create mode 100644 include/JSystem/JParticle/JPATexture.h create mode 100644 include/JSystem/JSupport/JSUList.h create mode 100644 include/JSystem/JSupport/JSupport.h create mode 100644 include/JSystem/JUtility/JUTAssert.h create mode 100644 include/JSystem/JUtility/JUTTexture.h create mode 100644 include/JSystem/TPosition3.h create mode 100644 src/JSystem/JParticle/JPABaseShape.cpp create mode 100644 src/JSystem/JParticle/JPAChildShape.cpp create mode 100644 src/JSystem/JParticle/JPADynamicsBlock.cpp create mode 100644 src/JSystem/JParticle/JPAEmitter.cpp create mode 100644 src/JSystem/JParticle/JPAEmitterManager.cpp create mode 100644 src/JSystem/JParticle/JPAExTexShape.cpp create mode 100644 src/JSystem/JParticle/JPAExtraShape.cpp create mode 100644 src/JSystem/JParticle/JPAFieldBlock.cpp create mode 100644 src/JSystem/JParticle/JPAKeyBlock.cpp create mode 100644 src/JSystem/JParticle/JPAMath.cpp create mode 100644 src/JSystem/JParticle/JPAParticle.cpp create mode 100644 src/JSystem/JParticle/JPAResource.cpp create mode 100644 src/JSystem/JParticle/JPAResourceLoader.cpp create mode 100644 src/JSystem/JParticle/JPAResourceManager.cpp create mode 100644 src/JSystem/JParticle/JPATexture.cpp create mode 100644 src/JSystem/JSupport/JSUList.cpp diff --git a/include/JSystem/JGeometry.h b/include/JSystem/JGeometry.h new file mode 100644 index 00000000..5ae2e827 --- /dev/null +++ b/include/JSystem/JGeometry.h @@ -0,0 +1,508 @@ +#ifndef JGEOMETRY_H +#define JGEOMETRY_H + +#include "dolphin/mtx.h" +#include "math.h" +#include "JSystem/JMath/JMath.h" + +namespace JGeometry { + +template +struct TUtil { + static inline T clamp(T v, T min, T max) { + if (v < min) { + return min; + } + if (v > max) { + return max; + } + return v; + } +}; + +template<> +struct TUtil { + static inline f32 clamp(f32 v, f32 min, f32 max) { + if (v < min) { + return min; + } + if (v > max) { + return max; + } + return v; + } + static inline f32 epsilon() { return 32.0f * FLT_EPSILON; } + static inline f32 PI() { return 3.1415927f; } + static inline f32 inv_sqrt(f32 x) { + if (x <= 0.0f) { + return x; + } + f32 root = __frsqrte(x); + root = 0.5f * root * (3.0f - x * (root * root)); + return root; + } +}; + +template<> +struct TUtil { + static inline double epsilon() { return 32.0f * FLT_EPSILON; } + static inline double one() { return 1.0; } + static inline double atan2(double x, double y) { return ::atan2(x, y); } + static inline double asin(double x) { return ::asin(x); } + static inline double halfPI() { return 1.5707963267948966; } +}; + +template +struct TVec3 { + T x; + T y; + T z; + + void set(const TVec3& other) { + x = other.x; + y = other.y; + z = other.z; + } +}; + +template <> +struct TVec3 { + double x, y, z; + + void set(double x_, double y_, double z_) { + x = x_; + y = y_; + z = z_; + } + + inline TVec3& operator*=(double b) { + scale(b); + return *this; + } + + void scale(double b) { + x *= b; + y *= b; + z *= b; + } +}; + +template <> +struct TVec3 { + s16 x, y, z; + + TVec3() {} + + TVec3(s16 x, s16 y, s16 z) { + set(x, y, z); + } + + TVec3& operator=(const TVec3& b) { + // Force copies to use lwz/lha + *((s32*)this) = *((s32*)&b); + z = b.z; + return *this; + } + + void set(s16 x_, s16 y_, s16 z_) { + x = x_; + y = y_; + z = z_; + } +}; + +inline void setTVec3f(const f32* vec_a, f32* vec_b) { + const register f32* v_a = vec_a; + register f32* v_b = vec_b; + + register f32 a_x; + register f32 b_x; + +#ifdef __MWERKS__ + asm { + psq_l a_x, 0(v_a), 0, 0 + lfs b_x, 8(v_a) + psq_st a_x, 0(v_b), 0, 0 + stfs b_x, 8(v_b) + }; +#endif +} + +// Until we figure out TVec3 ctors +inline void setTVec3f(const Vec& vec_a, Vec& vec_b) { + setTVec3f(&vec_a.x, &vec_b.x); +} + +inline float fsqrt_step(float mag) { + f32 root = __frsqrte(mag); + return 0.5f * root * (3.0f - mag * (root * root)); +} + +inline void mulInternal(register const f32* a, register const f32* b, register float* dst) { + register f32 a_x_y; + register f32 b_x_y; + register f32 x_y; + register f32 za; + register f32 zb; + register f32 z; +#ifdef __MWERKS__ + asm { + psq_l a_x_y, 0(a), 0, 0 + psq_l b_x_y, 0(b), 0, 0 + ps_mul x_y, a_x_y, b_x_y + psq_st x_y, 0(dst), 0, 0 + }; + dst[2] = a[2] * b[2]; +#endif +} + +template <> +struct TVec3 : public Vec { + inline TVec3(const Vec& i_vec) { + setTVec3f(&i_vec.x, &x); + } + + inline TVec3(const TVec3& i_vec) { + setTVec3f(&i_vec.x, &x); + } + + template + TVec3(U x, U y, U z) { + set(x, y, z); + } + + TVec3() {} + + operator Vec*() { return (Vec*)&x; } + operator const Vec*() const { return (Vec*)&x; } + + template + void set(const TVec3& other) { + x = other.x; + y = other.y; + z = other.z; + } + + void set(const Vec& other) { + x = other.x; + y = other.y; + z = other.z; + } + + template + void set(U x_, U y_, U z_) { + x = x_; + y = y_; + z = z_; + } + + inline void add(const TVec3& b) { + JMathInlineVEC::C_VECAdd((Vec*)&x, (Vec*)&b.x, (Vec*)&x); + } + + void zero() { x = y = z = 0.0f; } + + void mul(const TVec3& a, const TVec3& b) { + mulInternal(&a.x, &b.x, &this->x); + } + + inline void mul(const TVec3& a) { + mul(*this, a); + } + + inline TVec3& operator=(const Vec& b) { + setTVec3f(&b.x, &this->x); + return *this; + } + + inline TVec3& operator=(const TVec3& b) { + set(b.x, b.y, b.z); + return *this; + } + + inline TVec3& operator+=(const TVec3& b) { + add(b); + return *this; + } + + inline TVec3 operator+(const TVec3& b) { + TVec3 a = *this; + a += b; + return a; + } + + // inline TVec3 operator+(const TVec3& b) { + // TVec3 res(*(Vec*)this); + // res += b; + // return res; + // } + + f32 squared() const { + return JMathInlineVEC::C_VECSquareMag((Vec*)&x); + } + + f32 normalize() { + f32 sq = squared(); + if (sq <= TUtil::epsilon()) { + return 0.0f; + } + f32 inv_norm = TUtil::inv_sqrt(sq); + scale(inv_norm); + return inv_norm * sq; + } + + void normalize(const TVec3& other) { + f32 sq = other.squared(); + if (sq <= TUtil::epsilon()) { + zero(); + return; + } + f32 norm; + if (sq <= 0.0f) { + norm = sq; + } else { + norm = fsqrt_step(sq); + } + scale(norm, other); + } + + f32 length() const { + return VECMag((Vec*)this); + } + + void scale(register f32 sc) { + register f32 z; + register f32 x_y; + register f32* dst = &x; + register f32 zres; +#ifdef __MWERKS__ + asm { + psq_l x_y, 0(dst), 0, 0 + psq_l z, 8(dst), 1, 0 + ps_muls0 x_y, x_y, sc + psq_st x_y, 0(dst), 0, 0 + ps_muls0 zres, z, sc + psq_st zres, 8(dst), 1, 0 + }; +#endif + } + + void scale(register f32 sc, const TVec3& other) { + register const f32* src = &other.x; + register f32 z; + register f32 x_y; + register f32* dst = &x; + register f32 zres; +#ifdef __MWERKS__ + asm { + psq_l x_y, 0(src), 0, 0 + psq_l z, 8(src), 1, 0 + ps_muls0 x_y, x_y, sc + psq_st x_y, 0(dst), 0, 0 + ps_muls0 zres, z, sc + psq_st zres, 8(dst), 1, 0 + }; +#endif + } + + void scaleAdd(register f32 sc, const TVec3& a, const TVec3& b) { + JMAVECScaleAdd(&a, &b, this, sc); + } + + void negateInternal(TVec3* dst) { + register f32* rdst = &dst->x; + const register f32* src = &x; + register f32 x_y; + register f32 z; +#ifdef __MWERKS__ + asm { + psq_l x_y, 0(src), 0, 0 + ps_neg x_y, x_y + psq_st x_y, 0(rdst), 0, 0 + lfs z, 8(src) + fneg z, z + stfs z, 8(rdst) + }; +#endif + } + + void negate() { + negateInternal(this); + } + + void sub(const TVec3& b) { + JMathInlineVEC::C_VECSubtract((Vec*)&x, (Vec*)&b.x, (Vec*)&x); + } + + void sub(const TVec3& a, const TVec3& b) { + JMathInlineVEC::C_VECSubtract((Vec*)&a.x, (Vec*)&b.x, (Vec*)&x); + } + + bool isZero() const { + return squared() <= TUtil::epsilon(); + } + + void cross(const TVec3& a, const TVec3& b) { + VECCrossProduct(a, b, *this); + } + + f32 setLength(f32 len) { + f32 sq = squared(); + if (sq <= TUtil::epsilon()) { + return 0.0f; + } + f32 inv_norm = TUtil::inv_sqrt(sq); + scale(inv_norm * len); + return inv_norm * sq; + } + + f32 setLength(const TVec3& other, f32 len) { + f32 sq = other.squared(); + if (sq <= TUtil::epsilon()) { + zero(); + return 0.0f; + } + f32 inv_norm = TUtil::inv_sqrt(sq); + scale(inv_norm * len, other); + return inv_norm * sq; + } + + f32 dot(const TVec3& other) const { + return JMathInlineVEC::C_VECDotProduct(this, &other); + } + + void cubic(const TVec3& param_1, const TVec3& param_2, const TVec3& param_3, + const TVec3& param_4, f32 param_5) { + f32 fVar5 = param_5 * param_5; + f32 fVar6 = fVar5 * param_5; + f32 fVar8 = 1.0f + (2.0f * fVar6 - 3.0f * fVar5); + f32 fVar9 = -2.0f * fVar6 + 3.0f * fVar5; + f32 fVar7 = param_5 + (fVar6 - 2.0f * fVar5); + f32 fVar4 = fVar6 - fVar5; + x = fVar8 * param_1.x + fVar9 * param_4.x + fVar7 * param_2.x + fVar4 * param_3.x; + y = fVar8 * param_1.y + fVar9 * param_4.y + fVar7 * param_2.y + fVar4 * param_3.y; + z = fVar8 * param_1.z + fVar9 * param_4.z + fVar7 * param_2.z + fVar4 * param_3.z; + } +}; + +template +struct TVec2 { + TVec2() {} + TVec2(T v) { set(v); } + TVec2(T x, T y) { set(x, y); } + + void set(T v) { y = x = v; } + + void set(T x, T y) { + this->x = x; + this->y = y; + } + + void set(const TVec2& other) { + x = other.x; + y = other.y; + } + + void setMin(const TVec2& min) { + if (x >= min.x) + x = min.x; + if (y >= min.y) + y = min.y; + } + + void setMax(const TVec2& max) { + if (x <= max.x) + x = max.x; + if (y <= max.y) + y = max.y; + } + + void add(const TVec2& other) { + x += other.x; + y += other.y; + } + + bool isAbove(const TVec2& other) const { + return (x >= other.x) && (y >= other.y) ? true : false; + } + + f32 dot(const TVec2& other) const { + return x * other.x + y * other.y; + } + + f32 squared() const { + return dot(*this); + } + + f32 length() const { + f32 sqr = squared(); + if (sqr <= 0.0f) { + return sqr; + } + sqr *= fsqrt_step(sqr); + return sqr; + } + + T x; + T y; +}; + +template +struct TBox { + TBox() : i(), f() {} + TBox(const TBox& other) : i(other.i), f(other.f) {} + + T i, f; +}; + +// clang-format off +template<> struct TBox > { + f32 getWidth() const { return f.x - i.x; } + f32 getHeight() const { return f.y - i.y; } + + bool isValid() const { return f.isAbove(i); } + + void addPos(f32 x, f32 y) { + addPos(TVec2(x, y)); + } + + void addPos(const TVec2& pos) { + i.add(pos); + f.add(pos); + } + + bool intersect(const TBox >& other) { + i.setMax(other.i); + f.setMin(other.f); + return isValid(); + } + + TVec2 i, f; +}; + +template +struct TBox2 : TBox > { + TBox2() {} + TBox2(const TVec2& i, const TVec2& f) { set(i, f); } + TBox2(f32 x0, f32 y0, f32 x1, f32 y1) { set(x0, y0, x1, y1); } + + void absolute() { + if (!this->isValid()) { + TBox2 box(*this); + this->i.setMin(box.i); + this->i.setMin(box.f); + this->f.setMax(box.i); + this->f.setMax(box.f); + } + } + + void set(const TBox2& other) { set(other.i, other.f); } + void set(const TVec2& i, const TVec2& f) { this->i.set(i), this->f.set(f); } + void set(f32 x0, f32 y0, f32 x1, f32 y1) { this->i.set(x0, y0); this->f.set(x1, y1); } +}; + +// clang-format on + +} // namespace JGeometry + +#endif diff --git a/include/JSystem/JMath/JMATrigonometric.h b/include/JSystem/JMath/JMATrigonometric.h new file mode 100644 index 00000000..2b162c56 --- /dev/null +++ b/include/JSystem/JMath/JMATrigonometric.h @@ -0,0 +1,136 @@ +#ifndef JMATRIGONOMETRIC_H +#define JMATRIGONOMETRIC_H + +#include "dolphin/types.h" +#include "utility.h" + +template +struct TAngleConstant_; + +/** + * @ingroup jsystem-jmath + * + */ +template<> +struct TAngleConstant_ { + static f32 RADIAN_DEG090() { return 1.5707964f; } + static f32 RADIAN_DEG180() { return 3.1415927f; } + static f32 RADIAN_DEG360() { return 6.2831855f; } + static f32 RADIAN_TO_DEGREE_FACTOR() { return 180.0f / RADIAN_DEG180(); } +}; + +/** + * @ingroup jsystem-jmath + * + */ +template +struct TSinCosTable { + std::pair table[1 << N]; + + T sinShort(s16 v) const { return table[(u16)v >> (16U - N)].first; } + T cosShort(s16 v) const { return table[(u16)v >> (16U - N)].second; } + + inline T sinLap(T v) { + if (v < (T)0.0) { + return -table[(u16)(-(T)(1 << N) * v) & ((1 << N) - 1)].first; + } + return table[(u16)((T)(1 << N) * v) & ((1 << N) - 1)].first; + } + + inline T sinDegree(T degree) { + if (degree < (T)0.0) { + return -table[(u16)(-((T)(1 << N) / (T)360.0) * degree) & ((1 << N) - 1)].first; + } + return table[(u16)(((T)(1 << N) / (T)360.0) * degree) & ((1 << N) - 1)].first; + } + + inline T cosDegree(T degree) { + if (degree < (T)0.0) { + degree = -degree; + } + return table[(u16)(((T)(1 << N) / (T)360.0) * degree) & ((1 << N) - 1)].second; + } + + inline T sinRadian(T radian) { + if (radian < (T)0.0) { + return -table[(u16)(-(T)(1 << N) / TAngleConstant_::RADIAN_DEG360() * radian) & ((1 << N) - 1)].first; + } + return table[(u16)((T)(1 << N) / TAngleConstant_::RADIAN_DEG360() * radian) & ((1 << N) - 1)].first; + } +}; + +/** + * @ingroup jsystem-jmath + * + */ +struct TAtanTable { + f32 table[1025]; + u8 pad[0x1C]; +}; + +/** + * @ingroup jsystem-jmath + * + */ +struct TAsinAcosTable { + f32 table[1025]; + u8 pad[0x1C]; + + f32 acos_(f32 x) { + if (x >= 1.0f) { + return 0.0f; + } else if (x <= -1.0f) { + return TAngleConstant_::RADIAN_DEG180(); + } else if (x < 0.0f) { + return table[(u32)(-x * 1023.5f)] + TAngleConstant_::RADIAN_DEG090(); + } else { + return TAngleConstant_::RADIAN_DEG090() - table[(u32)(x * 1023.5f)]; + } + } + + f32 acosDegree(f32 x) { + return acos_(x) * TAngleConstant_::RADIAN_TO_DEGREE_FACTOR(); + } +}; + +namespace JMath { +extern TSinCosTable<13, f32> sincosTable_; +extern TAtanTable atanTable_; +extern TAsinAcosTable asinAcosTable_; + +inline f32 acosDegree(f32 x) { + return asinAcosTable_.acosDegree(x); +} +}; // namespace JMath + +inline f32 JMASCosShort(s16 v) { + return JMath::sincosTable_.cosShort(v); +} +inline f32 JMASinShort(s16 v) { + return JMath::sincosTable_.sinShort(v); +} + +inline f32 JMASCos(s16 v) { + return JMASCosShort(v); +} +inline f32 JMASSin(s16 v) { + return JMASinShort(v); +} + +inline f32 JMASinLap(f32 v) { + return JMath::sincosTable_.sinLap(v); +} + +inline f32 JMASinDegree(f32 degree) { + return JMath::sincosTable_.sinDegree(degree); +} + +inline f32 JMACosDegree(f32 degree) { + return JMath::sincosTable_.cosDegree(degree); +} + +inline f32 JMASinRadian(f32 radian) { + return JMath::sincosTable_.sinRadian(radian); +} + +#endif /* JMATRIGONOMETRIC_H */ diff --git a/include/JSystem/JMath/JMath.h b/include/JSystem/JMath/JMath.h new file mode 100644 index 00000000..eb7932e8 --- /dev/null +++ b/include/JSystem/JMath/JMath.h @@ -0,0 +1,263 @@ +#ifndef JMATH_H +#define JMATH_H + +#include "dolphin/mtx.h" +#include "math.h" + +void JMAMTXApplyScale(const Mtx, Mtx, f32, f32, f32); +void JMAEulerToQuat(s16 param_0, s16 param_1, s16 param_2, Quaternion* param_3); +void JMAQuatLerp(const Quaternion*, const Quaternion*, f32, Quaternion*); +void JMAFastVECNormalize(register const Vec* src, register Vec* dst); +void JMAVECScaleAdd(register const Vec* vec1, register const Vec* vec2, register Vec* dst, + register f32 scale); + +inline int JMAAbs(int value) { + return __abs(value); +} + +inline f32 JMAFastReciprocal(f32 value) { + return __fres(value); +} + +inline float __frsqrtes(register double f) { + register float out; + // clang-format off +#ifdef __MWERKS__ + asm { + frsqrte out, f + } +#endif + // clang-format on + return out; +} + +inline f32 JMAFastSqrt(register f32 input) { + if (input > 0.0f) { + register f32 out; +#ifdef __MWERKS__ + asm { + frsqrte out, input + } +#endif + return out * input; + } else { + return input; + } +} + +inline f32 JMAHermiteInterpolation(register f32 p1, register f32 p2, register f32 p3, + register f32 p4, register f32 p5, register f32 p6, + register f32 p7) { + register f32 ff25; + register f32 ff31; + register f32 ff30; + register f32 ff29; + register f32 ff28; + register f32 ff27; + register f32 ff26; + // clang-format off +#ifdef __MWERKS__ + asm { + fsubs ff31, p1, p2 + fsubs ff30, p5, p2 + fdivs ff29, ff31, ff30 + fmuls ff28,ff29,ff29 + fadds ff25,ff29,ff29 + fsubs ff27,ff28,ff29 + fsubs ff30, p3, p6 + fmsubs ff26,ff25,ff27,ff28 + fmadds ff25,p4,ff27,p4 + fmadds ff26,ff26,ff30,p3 + fmadds ff25,p7,ff27,ff25 + fmsubs ff25,ff29,p4,ff25 + fnmsubs ff25,ff31,ff25,ff26 + + } +#endif + // clang-format on + return ff25; +} + +namespace JMath { + +inline f32 fastReciprocal(f32 value) { + return JMAFastReciprocal(value); +} + +inline void gekko_ps_copy3(register void* dst, register const void* src) { + register f32 src0; + register f32 src1; +#ifdef __MWERKS__ + asm { + psq_l src0, 0(src), 0, 0 + lfs src1, 8(src) + psq_st src0, 0(dst), 0, 0 + stfs src1, 8(dst) + }; +#endif +} + +inline void gekko_ps_copy6(register void* dst, register const void* src) { + register f32 src0; + register f32 src1; + register f32 src2; +#ifdef __MWERKS__ + asm { + psq_l src0, 0(src), 0, 0 + psq_l src1, 8(src), 0, 0 + psq_l src2, 16(src), 0, 0 + psq_st src0, 0(dst), 0, 0 + psq_st src1, 8(dst), 0, 0 + psq_st src2, 16(dst), 0, 0 + }; +#endif +} + +inline void gekko_ps_copy12(register void* dst, register const void* src) { + register f32 src0; + register f32 src1; + register f32 src2; + register f32 src3; + register f32 src4; + register f32 src5; +#ifdef __MWERKS__ + asm { + psq_l src0, 0(src), 0, 0 + psq_l src1, 8(src), 0, 0 + psq_l src2, 16(src), 0, 0 + psq_l src3, 24(src), 0, 0 + psq_l src4, 32(src), 0, 0 + psq_l src5, 40(src), 0, 0 + psq_st src0, 0(dst), 0, 0 + psq_st src1, 8(dst), 0, 0 + psq_st src2, 16(dst), 0, 0 + psq_st src3, 24(dst), 0, 0 + psq_st src4, 32(dst), 0, 0 + psq_st src5, 40(dst), 0, 0 + }; +#endif +} + +inline void gekko_ps_copy16(register void* dst, register const void* src) { + register f32 src0; + register f32 src1; + register f32 src2; + register f32 src3; + register f32 src4; + register f32 src5; + register f32 src6; + register f32 src7; +#ifdef __MWERKS__ + asm { + psq_l src0, 0(src), 0, 0 + psq_l src1, 8(src), 0, 0 + psq_l src2, 16(src), 0, 0 + psq_l src3, 24(src), 0, 0 + psq_l src4, 32(src), 0, 0 + psq_l src5, 40(src), 0, 0 + psq_l src6, 48(src), 0, 0 + psq_l src7, 56(src), 0, 0 + psq_st src0, 0(dst), 0, 0 + psq_st src1, 8(dst), 0, 0 + psq_st src2, 16(dst), 0, 0 + psq_st src3, 24(dst), 0, 0 + psq_st src4, 32(dst), 0, 0 + psq_st src5, 40(dst), 0, 0 + psq_st src6, 48(dst), 0, 0 + psq_st src7, 56(dst), 0, 0 + }; +#endif +} + +}; // namespace JMath + +namespace JMathInlineVEC { + inline void C_VECAdd(register const Vec* a, register const Vec* b, register Vec* ab) { + register f32 axy; + register f32 bxy; + register f32 az; + register f32 sumz; + register f32 bz; + #ifdef __MWERKS__ + asm { + psq_l axy, 0(a), 0, 0 + psq_l bxy, 0(b), 0, 0 + ps_add bxy, axy, bxy + psq_st bxy, 0(ab), 0, 0 + psq_l az, 8(a), 1, 0 + psq_l bz, 8(b), 1, 0 + ps_add sumz, az, bz + psq_st sumz, 8(ab), 1, 0 + } + #endif + } + + inline void C_VECSubtract(register const Vec* a, register const Vec* b, register Vec* ab) { + register f32 axy; + register f32 bxy; + register f32 az; + register f32 subz; + register f32 bz; + #ifdef __MWERKS__ + asm { + psq_l axy, 0(a), 0, 0 + psq_l bxy, 0(b), 0, 0 + ps_sub bxy, axy, bxy + psq_st bxy, 0(ab), 0, 0 + psq_l az, 8(a), 1, 0 + psq_l bz, 8(b), 1, 0 + ps_sub subz, az, bz + psq_st subz, 8(ab), 1, 0 + } + #endif + } + + inline f32 C_VECSquareMag(register const Vec* v) { + register f32 x_y; + register f32 z; + register f32 res; + #ifdef __MWERKS__ + asm { + psq_l x_y, 0(v), 0, 0 + ps_mul x_y, x_y, x_y + lfs z, 8(v) + ps_madd res, z, z, x_y + ps_sum0 res, res, x_y, x_y + } + #endif + return res; + } + + inline f32 C_VECDotProduct(register const Vec *a, register const Vec *b) { + register f32 res; + register f32 thisyz; + register f32 otheryz; + register f32 otherxy; + register f32 thisxy; +#ifdef __MWERKS__ + asm { + psq_l thisyz, 4(a), 0, 0 + psq_l otheryz, 4(b), 0, 0 + ps_mul thisyz, thisyz, otheryz + psq_l thisxy, 0(a), 0, 0 + psq_l otherxy, 0(b), 0, 0 + ps_madd otheryz, thisxy, otherxy, thisyz + ps_sum0 res, otheryz, thisyz, thisyz + }; +#endif + return res; + } +}; + +template +inline T JMAMax(T param_0, T param_1) { + T ret; + if (param_0 > param_1) { + ret = param_0; + } else { + ret = param_1; + } + return ret; +} + +#endif /* JMATH_H */ diff --git a/include/JSystem/JMath/random.h b/include/JSystem/JMath/random.h new file mode 100644 index 00000000..cfb8ecc1 --- /dev/null +++ b/include/JSystem/JMath/random.h @@ -0,0 +1,51 @@ +#ifndef RANDOM_H +#define RANDOM_H + +#include "dolphin/types.h" + +namespace JMath { + +/** + * @ingroup jsystem-jmath + * + */ +struct TRandom_fast_ { + u32 value; + + TRandom_fast_(u32 value); + u32 get(void) { + value = (value * 0x19660d) + 0x3c6ef35f; + return value; + } + + u32 get_bit32(void) { return this->get(); } + + // due to the float constant, having this function inlined adds that float to data, + // making it not match + float get_ufloat_1(void) { + // !@bug UB: in C++ it's not legal to read from an union member other + // than the last one that was written to. + union { + f32 f; + u32 s; + } out; + out.s = (this->get() >> 9) | 0x3f800000; + return out.f - 1; + } + + void setSeed(u32 seed) { value = seed; } +}; + +template +class TRandom_ : public RandomT { +public: + TRandom_(u32 value) : RandomT(value) {} + + u8 get_uint8(u8 param_0) { + return get_ufloat_1() * param_0; + } +}; + +} // namespace JMath + +#endif /* RANDOM_H */ diff --git a/include/JSystem/JParticle/JPABaseShape.h b/include/JSystem/JParticle/JPABaseShape.h new file mode 100644 index 00000000..3ebff452 --- /dev/null +++ b/include/JSystem/JParticle/JPABaseShape.h @@ -0,0 +1,210 @@ +#ifndef JPABASESHAPE_H +#define JPABASESHAPE_H + +#include + +class JPAEmitterWorkData; +class JPABaseParticle; +class JKRHeap; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPABaseShapeData { + // Common header. + /* 0x00 */ u8 mMagic[4]; + /* 0x04 */ u32 mSize; + + /* 0x08 */ u32 mFlags; + /* 0x0C */ s16 mClrPrmAnmOffset; + /* 0x0E */ s16 mClrEnvAnmOffset; + /* 0x10 */ f32 mBaseSizeX; + /* 0x14 */ f32 mBaseSizeY; + /* 0x18 */ u16 mBlendModeCfg; + /* 0x1A */ u8 mAlphaCompareCfg; + /* 0x1B */ u8 mAlphaRef0; + /* 0x1C */ u8 mAlphaRef1; + /* 0x1D */ u8 mZModeCfg; + /* 0x1E */ u8 mTexFlg; + /* 0x1F */ u8 mTexAnmNum; + /* 0x20 */ u8 mTexIdx; + /* 0x21 */ u8 mClrFlg; + /* 0x22 */ u8 mClrPrmKeyNum; + /* 0x23 */ u8 mClrEnvKeyNum; + /* 0x24 */ s16 mClrAnmFrmMax; + /* 0x26 */ GXColor mClrPrm; + /* 0x2A */ GXColor mClrEnv; + /* 0x2E */ u8 mAnmRndm; + /* 0x2F */ u8 mClrAnmRndmMask; + /* 0x30 */ u8 mTexAnmRndmMask; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPABaseShape { +public: + /* 8027A6DC */ JPABaseShape(u8 const*, JKRHeap*); + /* 8027A7E8 */ void setGX(JPAEmitterWorkData*) const; + + static GXBlendMode st_bm[3]; + static GXBlendFactor st_bf[10]; + static GXLogicOp st_lo[16]; + static GXCompare st_c[8]; + static GXAlphaOp st_ao[4]; + static GXTevColorArg st_ca[6][4]; + static GXTevAlphaArg st_aa[2][4]; + + GXBlendMode getBlendMode() const { return st_bm[mpData->mBlendModeCfg & 0x03]; } + GXBlendFactor getBlendSrc() const { return st_bf[(mpData->mBlendModeCfg >> 2) & 0x0F]; } + GXBlendFactor getBlendDst() const { return st_bf[(mpData->mBlendModeCfg >> 6) & 0x0F]; } + GXLogicOp getLogicOp() const { return st_lo[(mpData->mBlendModeCfg >> 10) & 0x0F]; } + GXBool getZCompLoc() const { return (GXBool)((mpData->mZModeCfg >> 5) & 0x01); } + + GXBool getZEnable() const { return (GXBool)(mpData->mZModeCfg & 0x01); } + GXCompare getZCmp() const { return st_c[(mpData->mZModeCfg >> 1) & 0x07]; } + GXBool getZUpd() const { return (GXBool)((mpData->mZModeCfg >> 4) & 0x01); } + + GXCompare getAlphaCmp0() const { return st_c[mpData->mAlphaCompareCfg & 0x07]; } + u8 getAlphaRef0() const { return mpData->mAlphaRef0; } + GXAlphaOp getAlphaOp() const { return st_ao[(mpData->mAlphaCompareCfg >> 3) & 0x03]; } + GXCompare getAlphaCmp1() const { return st_c[(mpData->mAlphaCompareCfg >> 5) & 0x07]; } + u8 getAlphaRef1() const { return mpData->mAlphaRef1; } + + const GXTevColorArg* getTevColorArg() const { return st_ca[(mpData->mFlags >> 0x0F) & 0x07]; } + const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(mpData->mFlags >> 0x12) & 0x01]; } + + u32 getType() const { return (mpData->mFlags >> 0) & 0x0F; } + u32 getDirType() const { return (mpData->mFlags >> 4) & 0x07; } + u32 getRotType() const { return (mpData->mFlags >> 7) & 0x07; } + u32 getBasePlaneType() const { return (mpData->mFlags >> 10) & 0x01; } + u32 getTilingS() const { return (mpData->mFlags >> 25) & 0x01; } + u32 getTilingT() const { return (mpData->mFlags >> 26) & 0x01; } + BOOL isGlblClrAnm() const { return mpData->mFlags & 0x00001000; } + BOOL isGlblTexAnm() const { return mpData->mFlags & 0x00004000; } + BOOL isPrjTex() const { return mpData->mFlags & 0x00100000; } + bool isDrawFwdAhead() const { return !!(mpData->mFlags & 0x00200000); } + bool isDrawPrntAhead() const { return !!(mpData->mFlags & 0x00400000); } + bool isClipOn() const { return !!(mpData->mFlags & 0x00800000); } + BOOL isTexCrdAnm() const { return mpData->mFlags & 0x01000000; } + bool isNoDrawParent() const { return !!(mpData->mFlags & 0x08000000); } + bool isNoDrawChild() const { return !!(mpData->mFlags & 0x10000000); } + + BOOL isPrmAnm() const { return mpData->mClrFlg & 0x02; } + BOOL isEnvAnm() const { return mpData->mClrFlg & 0x08; } + u8 getClrAnmType() const { return (mpData->mClrFlg >> 4) & 0x07; } + s16 getClrAnmMaxFrm() const { return mpData->mClrAnmFrmMax; } + void getPrmClr(GXColor* dst) { *dst = mpData->mClrPrm; } + void getPrmClr(s16 idx, GXColor* dst) { *dst = mpPrmClrAnmTbl[idx]; } + void getEnvClr(GXColor* dst) { *dst = mpData->mClrEnv; } + void getEnvClr(s16 idx, GXColor* dst) { *dst = mpEnvClrAnmTbl[idx]; } + + BOOL isTexAnm() const { return mpData->mTexFlg & 0x01; } + u8 getTexAnmType() const { return (mpData->mTexFlg >> 2) & 0x07; } + u32 getTexIdx() const { return mpData->mTexIdx; } + u8 getTexIdx(u8 idx) const { return mpTexIdxAnimTbl[idx]; } + + f32 getBaseSizeX() const { return mpData->mBaseSizeX; } + f32 getBaseSizeY() const { return mpData->mBaseSizeY; } + u8 getClrLoopOfstMask() const { return mpData->mClrAnmRndmMask; } + u32 getClrLoopOfst(u32 param_1) const { return getClrLoopOfstMask() & param_1; } + u8 getTexLoopOfstMask() const { return mpData->mTexAnmRndmMask; } + u32 getTexLoopOfst(u8 param_1) const { return getTexLoopOfstMask() & param_1; } + u8 getLoopOfstValue() const { return mpData->mAnmRndm; } + + f32 getIncTransX() const { return ((f32*)mpTexCrdMtxAnmTbl)[5]; } + f32 getInitTransX() const { return ((f32*)mpTexCrdMtxAnmTbl)[0]; } + f32 getIncTransY() const { return ((f32*)mpTexCrdMtxAnmTbl)[6]; } + f32 getInitTransY() const { return ((f32*)mpTexCrdMtxAnmTbl)[1]; } + f32 getIncScaleX() const { return ((f32*)mpTexCrdMtxAnmTbl)[7]; } + f32 getInitScaleX() const { return ((f32*)mpTexCrdMtxAnmTbl)[2]; } + f32 getIncScaleY() const { return ((f32*)mpTexCrdMtxAnmTbl)[8]; } + f32 getInitScaleY() const { return ((f32*)mpTexCrdMtxAnmTbl)[3]; } + f32 getIncRot() const { return ((f32*)mpTexCrdMtxAnmTbl)[9]; } + f32 getInitRot() const { return ((f32*)mpTexCrdMtxAnmTbl)[4]; } + u8 getTexAnmKeyNum() const { return mpData->mTexAnmNum; } + +public: + /* 0x00 */ const JPABaseShapeData* mpData; + /* 0x04 */ const void* mpTexCrdMtxAnmTbl; + /* 0x08 */ const u8* mpTexIdxAnimTbl; + /* 0x0C */ GXColor* mpPrmClrAnmTbl; + /* 0x10 */ GXColor* mpEnvClrAnmTbl; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPAClrAnmKeyData { + /* 0x0 */ s16 index; + /* 0x2 */ GXColor color; +}; + +void JPACalcTexIdxNormal(JPAEmitterWorkData*); +void JPACalcTexIdxRepeat(JPAEmitterWorkData*); +void JPACalcTexIdxReverse(JPAEmitterWorkData*); +void JPACalcTexIdxMerge(JPAEmitterWorkData*); +void JPACalcTexIdxRandom(JPAEmitterWorkData*); +void JPACalcPrm(JPAEmitterWorkData*); +void JPACalcEnv(JPAEmitterWorkData*); +void JPACalcClrIdxNormal(JPAEmitterWorkData*); +void JPACalcClrIdxRepeat(JPAEmitterWorkData*); +void JPACalcClrIdxReverse(JPAEmitterWorkData*); +void JPACalcClrIdxMerge(JPAEmitterWorkData*); +void JPACalcClrIdxRandom(JPAEmitterWorkData*); + +void JPACalcTexIdxNormal(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcTexIdxRepeat(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcTexIdxReverse(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcTexIdxMerge(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcTexIdxRandom(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcPrm(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcEnv(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcClrIdxNormal(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcClrIdxRepeat(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcClrIdxReverse(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcClrIdxMerge(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcClrIdxRandom(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcColorCopy(JPAEmitterWorkData*, JPABaseParticle*); + +void JPADrawStripe(JPAEmitterWorkData*); +void JPADrawStripeX(JPAEmitterWorkData*); +void JPADrawEmitterCallBackB(JPAEmitterWorkData*); +void JPALoadTex(JPAEmitterWorkData*); +void JPALoadTexAnm(JPAEmitterWorkData*); +void JPAGenTexCrdMtxIdt(JPAEmitterWorkData*); +void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData*); +void JPAGenTexCrdMtxAnm(JPAEmitterWorkData*); +void JPAGenTexCrdMtxPrj(JPAEmitterWorkData*); +void JPALoadPosMtxCam(JPAEmitterWorkData*); +void JPASetLineWidth(JPAEmitterWorkData*); +void JPASetPointSize(JPAEmitterWorkData*); +void JPARegistPrm(JPAEmitterWorkData*); +void JPARegistEnv(JPAEmitterWorkData*); +void JPARegistPrmEnv(JPAEmitterWorkData*); + +void JPADrawPoint(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawLine(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawRotBillboard(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawBillboard(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawRotDirection(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawDirection(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawRotation(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawDBillboard(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawRotYBillboard(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawYBillboard(JPAEmitterWorkData*, JPABaseParticle*); +void JPADrawParticleCallBack(JPAEmitterWorkData*, JPABaseParticle*); +void JPALoadTexAnm(JPAEmitterWorkData*, JPABaseParticle*); +void JPASetPointSize(JPAEmitterWorkData*, JPABaseParticle*); +void JPASetLineWidth(JPAEmitterWorkData*, JPABaseParticle*); +void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData*, JPABaseParticle*); +void JPARegistAlpha(JPAEmitterWorkData*, JPABaseParticle*); +void JPARegistEnv(JPAEmitterWorkData*, JPABaseParticle*); +void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*); +void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*); +void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*); + +#endif /* JPABASESHAPE_H */ diff --git a/include/JSystem/JParticle/JPAChildShape.h b/include/JSystem/JParticle/JPAChildShape.h new file mode 100644 index 00000000..2761a567 --- /dev/null +++ b/include/JSystem/JParticle/JPAChildShape.h @@ -0,0 +1,89 @@ +#ifndef JPACHILDSHAPE_H +#define JPACHILDSHAPE_H + +#include + +class JPAEmitterWorkData; +class JPABaseParticle; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPAChildShapeData { + // Common header. + /* 0x00 */ u8 mMagic[4]; + /* 0x04 */ u32 mSize; + + /* 0x08 */ u32 mFlags; + /* 0x0C */ f32 mPosRndm; + /* 0x10 */ f32 mBaseVel; + /* 0x14 */ f32 mBaseVelRndm; + /* 0x18 */ f32 mVelInfRate; + /* 0x1C */ f32 mGravity; + /* 0x20 */ f32 mScaleX; + /* 0x24 */ f32 mScaleY; + /* 0x28 */ f32 mInheritScale; + /* 0x2C */ f32 mInheritAlpha; + /* 0x30 */ f32 mInheritRGB; + /* 0x34 */ GXColor mPrmClr; + /* 0x38 */ GXColor mEnvClr; + /* 0x3C */ f32 mTiming; + /* 0x40 */ s16 mLife; + /* 0x42 */ s16 mRate; + /* 0x44 */ u8 mStep; + /* 0x45 */ u8 mTexIdx; + /* 0x46 */ s16 mRotSpeed; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAChildShape { +public: + /* 8027B038 */ JPAChildShape(u8 const*); + + f32 getPosRndm() const { return mpData->mPosRndm; } + f32 getBaseVel() const { return mpData->mBaseVel; } + f32 getBaseVelRndm() const { return mpData->mBaseVelRndm; } + f32 getVelInhRate() const { return mpData->mVelInfRate; } + f32 getGravity() const { return mpData->mGravity; } + f32 getScaleX() const { return mpData->mScaleX; } + f32 getScaleY() const { return mpData->mScaleY; } + f32 getScaleInhRate() const { return mpData->mInheritScale; } + f32 getAlphaInhRate() const { return mpData->mInheritAlpha; } + f32 getColorInhRate() const { return mpData->mInheritRGB; } + void getPrmClr(GXColor* dst) const { *dst = mpData->mPrmClr; } + u8 getPrmAlpha() const { return mpData->mPrmClr.a; } + void getEnvClr(GXColor* dst) const { *dst = mpData->mEnvClr; } + f32 getTiming() const { return mpData->mTiming; } + s16 getLife() const { return mpData->mLife; } + s16 getRate() const { return mpData->mRate; } + u8 getStep() const { return mpData->mStep; } + u8 getTexIdx() const { return mpData->mTexIdx; } + s16 getRotInitSpeed() const { return mpData->mRotSpeed; } + u32 getType() const { return mpData->mFlags & 0xF; } + u32 getDirType() const { return (mpData->mFlags >> 4) & 7; } + u32 getRotType() const { return (mpData->mFlags >> 7) & 7; } + u32 getBasePlaneType() const { return (mpData->mFlags >> 10) & 1; } + + BOOL isScaleInherited() const { return mpData->mFlags & 0x10000; } + BOOL isAlphaInherited() const { return mpData->mFlags & 0x20000; } + BOOL isColorInherited() const { return mpData->mFlags & 0x40000; } + BOOL isClipOn() const { return mpData->mFlags & 0x100000; } + BOOL isFieldAffected() const { return mpData->mFlags & 0x200000; } + BOOL isScaleOutOn() const { return mpData->mFlags & 0x400000; } + BOOL isAlphaOutOn() const { return mpData->mFlags & 0x800000; } + BOOL isRotateOn() const { return mpData->mFlags & 0x1000000; } + +public: + /* 0x00 */ const JPAChildShapeData* mpData; +}; + +void JPARegistChildPrmEnv(JPAEmitterWorkData*); + +void JPACalcChildAlphaOut(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcChildScaleOut(JPAEmitterWorkData*, JPABaseParticle*); + +#endif /* JPACHILDSHAPE_H */ diff --git a/include/JSystem/JParticle/JPADrawInfo.h b/include/JSystem/JParticle/JPADrawInfo.h new file mode 100644 index 00000000..061783af --- /dev/null +++ b/include/JSystem/JParticle/JPADrawInfo.h @@ -0,0 +1,29 @@ +#ifndef JPADRAWINFO_H +#define JPADRAWINFO_H + +#include "dolphin/mtx.h" + +/** + * @ingroup jsystem-jparticle + * + */ +class JPADrawInfo { +public: + JPADrawInfo(Mtx param_0, f32 fovY, f32 aspect) { + MTXCopy(param_0, mCamMtx); + C_MTXLightPerspective(mPrjMtx, fovY, aspect, 0.5f, -0.5f, 0.5f, 0.5f); + } + + JPADrawInfo(Mtx param_0, f32 top, f32 bottom, f32 left, f32 right) { + MTXCopy(param_0, mCamMtx); + C_MTXLightOrtho(mPrjMtx, top, bottom, left, right, 0.5f, 0.5f, 0.5f, 0.5f); + } + + Mtx mCamMtx; + Mtx mPrjMtx; + + void getCamMtx(Mtx dst) const { MTXCopy(mCamMtx, dst); } + void getPrjMtx(Mtx dst) const { MTXCopy(mPrjMtx, dst); } +}; + +#endif diff --git a/include/JSystem/JParticle/JPADynamicsBlock.h b/include/JSystem/JParticle/JPADynamicsBlock.h new file mode 100644 index 00000000..fc175ff6 --- /dev/null +++ b/include/JSystem/JParticle/JPADynamicsBlock.h @@ -0,0 +1,109 @@ +#ifndef JPADYNAMICSBLOCK_H +#define JPADYNAMICSBLOCK_H + +#include "JSystem/JGeometry.h" + +#include "dolphin/types.h" + +class JPAEmitterWorkData; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPADynamicsBlockData { + // Common header. + /* 0x00 */ u8 mMagic[4]; + /* 0x04 */ u32 mSize; + + /* 0x08 */ u32 mFlags; + /* 0x0C */ u32 mResUserWork; + /* 0x10 */ JGeometry::TVec3 mEmitterScl; + /* 0x1C */ JGeometry::TVec3 mEmitterTrs; + /* 0x28 */ JGeometry::TVec3 mEmitterDir; + /* 0x34 */ f32 mInitialVelOmni; + /* 0x38 */ f32 mInitialVelAxis; + /* 0x3C */ f32 mInitialVelRndm; + /* 0x40 */ f32 mInitialVelDir; + /* 0x44 */ f32 mSpread; + /* 0x48 */ f32 mInitialVelRatio; + /* 0x4C */ f32 mRate; + /* 0x50 */ f32 mRateRndm; + /* 0x54 */ f32 mLifeTimeRndm; + /* 0x58 */ f32 mVolumeSweep; + /* 0x5C */ f32 mVolumeMinRad; + /* 0x60 */ f32 mAirResist; + /* 0x64 */ f32 mMoment; + /* 0x68 */ JGeometry::TVec3 mEmitterRot; + /* 0x6E */ s16 mMaxFrame; + /* 0x70 */ s16 mStartFrame; + /* 0x72 */ s16 mLifeTime; + /* 0x74 */ u16 mVolumeSize; + /* 0x76 */ u16 mDivNumber; + /* 0x78 */ u8 mRateStep; + /* 0x7C */ u32 field_0x7c; +}; + +typedef void (*JPADynamicsCalcVolumeFunc)(JPAEmitterWorkData*); + +enum { + JPADynFlag_FixedDensity = 0x01, + JPADynFlag_FixedInterval = 0x02, + JPADynFlag_InheritScale = 0x04, + JPADynFlag_FollowEmtr = 0x08, + JPADynFlag_FollowEmtrChld = 0x10, +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPADynamicsBlock { +public: + /* 8027BB18 */ JPADynamicsBlock(u8 const*); + /* 8027BB4C */ void init(); + /* 8027BBE8 */ void create(JPAEmitterWorkData*); + + void calc(JPAEmitterWorkData* work) { mpCalcVolumeFunc(work); } + + s16 getStartFrame() const { return mpData->mStartFrame; } + u32 getResUserWork() const { return mpData->mResUserWork; } + u32 getFlag() const { return mpData->mFlags; } + u32 getVolumeType() const { return (mpData->mFlags >> 8) & 0x07; } + u16 getDivNumber() const { return mpData->mDivNumber; } + f32 getRateRndm() const { return mpData->mRateRndm; } + void getEmitterScl(JGeometry::TVec3* vec) const { + vec->set(mpData->mEmitterScl.x, mpData->mEmitterScl.y, mpData->mEmitterScl.z); + } + void getEmitterTrs(JGeometry::TVec3* vec) const { + vec->set(mpData->mEmitterTrs.x, mpData->mEmitterTrs.y, mpData->mEmitterTrs.z); + } + void getEmitterDir(JGeometry::TVec3* vec) const { + vec->set(mpData->mEmitterDir.x, mpData->mEmitterDir.y, mpData->mEmitterDir.z); + } + void getEmitterRot(JGeometry::TVec3* vec) const { + vec->set(mpData->mEmitterRot.x, mpData->mEmitterRot.y, mpData->mEmitterRot.z); + } + s16 getMaxFrame() { return mpData->mMaxFrame; } + s16 getLifetime() { return mpData->mLifeTime; } + u16 getVolumeSize() { return mpData->mVolumeSize; } + f32 getRate() { return mpData->mRate; } + u8 getRateStep() { return mpData->mRateStep; } + f32 getVolumeSweep() { return mpData->mVolumeSweep; } + f32 getVolumeMinRad() { return mpData->mVolumeMinRad; } + f32 getInitVelOmni() { return mpData->mInitialVelOmni; } + f32 getInitVelAxis() { return mpData->mInitialVelAxis; } + f32 getInitVelDir() { return mpData->mInitialVelDir; } + f32 getInitVelDirSp() { return mpData->mSpread; } + f32 getInitVelRndm() { return mpData->mInitialVelRndm; } + f32 getInitVelRatio() const { return mpData->mInitialVelRatio; } + f32 getAirRes() { return mpData->mAirResist; } + f32 getLifetimeRndm() const { return mpData->mLifeTimeRndm; } + f32 getMomentRndm() const { return mpData->mMoment; } + +public: + /* 0x00 */ const JPADynamicsBlockData* mpData; + /* 0x04 */ JPADynamicsCalcVolumeFunc mpCalcVolumeFunc; +}; + +#endif /* JPADYNAMICSBLOCK_H */ diff --git a/include/JSystem/JParticle/JPAEmitter.h b/include/JSystem/JParticle/JPAEmitter.h new file mode 100644 index 00000000..063b7c1f --- /dev/null +++ b/include/JSystem/JParticle/JPAEmitter.h @@ -0,0 +1,272 @@ +#ifndef JPAEMITTER_H +#define JPAEMITTER_H + +#include +#include "JSystem/JParticle/JPAResource.h" +#include "JSystem/JParticle/JPAList.h" +#include "JSystem/JParticle/JPARandom.h" +#include "JSystem/JParticle/JPAMath.h" +#include "JSystem/JParticle/JPADynamicsBlock.h" +#include "JSystem/JSupport/JSUList.h" + +class JPAResourceManager; +class JPABaseEmitter; +class JPAEmitterManager; +class JPAParticleCallBack; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPAEmitterWorkData { + struct JPAVolumeCalcData { + /* 0x00 */ JGeometry::TVec3 mVolumePos; + /* 0x0C */ JGeometry::TVec3 mVelOmni; + /* 0x18 */ JGeometry::TVec3 mVelAxis; + }; + + JPAEmitterWorkData() : mRndm(0) {} + + /* 0x00 */ JPABaseEmitter* mpEmtr; + /* 0x04 */ JPAResource* mpRes; + /* 0x08 */ JPAResourceManager* mpResMgr; + /* 0x0C */ JPARandom mRndm; + /* 0x10 */ JPAVolumeCalcData mVolumeCalcData; + /* 0x34 */ f32 mVolumeSize; + /* 0x38 */ f32 mVolumeMinRad; + /* 0x3C */ f32 mVolumeSweep; + /* 0x40 */ s32 mEmitCount; + /* 0x44 */ s32 mVolumeEmitIdx; + /* 0x48 */ Mtx mDirectionMtx; + /* 0x78 */ Mtx mRotationMtx; + /* 0xA8 */ Mtx mGlobalRot; + /* 0xD8 */ Mtx mGlobalSR; + /* 0x108 */ JGeometry::TVec3 mEmitterPos; + /* 0x114 */ JGeometry::TVec3 mGlobalScl; + /* 0x120 */ JGeometry::TVec3 mGlobalEmtrDir; + /* 0x12C */ JGeometry::TVec3 mPublicScale; + /* 0x138 */ JGeometry::TVec3 mGlobalPos; + /* 0x144 */ JGeometry::TVec2 mGlobalPtclScl; + /* 0x14C */ JGeometry::TVec2 mPivot; + /* 0x154 */ Mtx mYBBCamMtx; + /* 0x184 */ Mtx mPosCamMtx; + /* 0x1B4 */ Mtx mPrjMtx; + /* 0x1E4 */ JPAList* mpAlivePtcl; + /* 0x1E8 */ JPANode* mpCurNode; + /* 0x1EC */ s32 mVolumeAngleNum; + /* 0x1F0 */ s32 mVolumeAngleMax; + /* 0x1F4 */ s32 mVolumeX; + /* 0x1F8 */ s32 mDivNumber; + /* 0x1FC */ f32 mScaleAnm; + /* 0x200 */ u32 mDirType; + /* 0x204 */ u32 mRotType; + /* 0x208 */ u32 mPlaneType; + /* 0x20C */ u32 mDLType; + /* 0x210 */ u32 mPrjType; + /* 0x214 */ s16 mClrKeyFrame; + /* 0x216 */ u8 mDrawCount; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAEmitterCallBack { +public: + virtual ~JPAEmitterCallBack() = 0; + /* 80050368 */ virtual void execute(JPABaseEmitter*) {} + /* 80050374 */ virtual void executeAfter(JPABaseEmitter*) {} + /* 8005036C */ virtual void draw(JPABaseEmitter*) {} + /* 80050370 */ virtual void drawAfter(JPABaseEmitter*) {} + + /* 8027E6A4 */ //~JPAEmitterCallBack(); +}; + +enum { + JPAEmtrStts_StopEmit = 0x01, + JPAEmtrStts_StopCalc = 0x02, + JPAEmtrStts_StopDraw = 0x04, + JPAEmtrStts_EnableDeleteEmitter = 0x08, + JPAEmtrStts_FirstEmit = 0x10, + JPAEmtrStts_RateStepEmit = 0x20, + JPAEmtrStts_Immortal = 0x40, + JPAEmtrStts_Delete = 0x100, +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPABaseEmitter { +public: + /* 8027E5EC */ ~JPABaseEmitter() {} + /* 8027E64C */ JPABaseEmitter() : mLink(this), mRndm(0) {} + /* 8027E6EC */ void init(JPAEmitterManager*, JPAResource*); + /* 8027EDD4 */ bool processTillStartFrame(); + /* 8027EE14 */ bool processTermination(); + /* 8027EEB0 */ void calcEmitterGlobalPosition(JGeometry::TVec3*) const; + /* 8027EC60 */ void deleteAllParticle(); + /* 8027EB60 */ JPABaseParticle* createChild(JPABaseParticle*); + /* 8027EA40 */ JPABaseParticle* createParticle(); + /* 8027EF30 */ u32 getCurrentCreateNumber() const; + /* 8027EF40 */ u8 getDrawCount() const; + /* 8027EF50 */ bool loadTexture(u8, GXTexMapID); + + void initStatus(u32 status) { mStatus = status; } + void setStatus(u32 status) { mStatus |= status; } + void clearStatus(u32 status) { mStatus &= ~status; } + u32 checkStatus(u32 status) const { return (mStatus & status); } + bool checkFlag(u32 flag) const { return !!(mpRes->getDyn()->getFlag() & flag); } + u8 getResourceManagerID() const { return mResMgrID; } + u8 getGroupID() const { return mGroupID; } + u8 getDrawTimes() const { return mDrawTimes; } + void setRate(f32 rate) { mRate = rate; } + void setDirectionalSpeed(f32 i_speed) { mDirSpeed = i_speed; } + void setRandomDirectionSpeed(f32 i_speed) { mRndmDirSpeed = i_speed; } + void setEmitterCallBackPtr(JPAEmitterCallBack* ptr) { mpEmtrCallBack = ptr; } + void setGlobalRTMatrix(const Mtx m) { JPASetRMtxTVecfromMtx(m, mGlobalRot, &mGlobalTrs); } + void setGlobalSRTMatrix(const Mtx m) { + JPASetRMtxSTVecfromMtx(m, mGlobalRot, &mGlobalScl, &mGlobalTrs); + + // set is actually used here in debug + mGlobalPScl.x = mGlobalScl.x; + mGlobalPScl.y = mGlobalScl.y; + } + void setGlobalTranslation(f32 x, f32 y, f32 z) { mGlobalTrs.set(x, y, z); } + void setGlobalTranslation(const JGeometry::TVec3& trs) { mGlobalTrs.set(trs); } + void getLocalTranslation(JGeometry::TVec3& vec) { vec.set(mLocalTrs); } + void setGlobalRotation(const JGeometry::TVec3& rot) { + JPAGetXYZRotateMtx(rot.x, rot.y, rot.z, mGlobalRot); + } + void getGlobalTranslation(JGeometry::TVec3* out) const { out->set(mGlobalTrs); } + void setGlobalDynamicsScale(const JGeometry::TVec3& i_scale) { mGlobalScl.set(i_scale); } + void setGlobalAlpha(u8 alpha) { mGlobalPrmClr.a = alpha; } + u8 getGlobalAlpha() { return mGlobalPrmClr.a; } + void getGlobalPrmColor(GXColor& color) { color = mGlobalPrmClr; } + void setGlobalPrmColor(u8 r, u8 g, u8 b) { mGlobalPrmClr.r = r; mGlobalPrmClr.g = g; mGlobalPrmClr.b = b; } + void setGlobalEnvColor(u8 r, u8 g, u8 b) { mGlobalEnvClr.r = r; mGlobalEnvClr.g = g; mGlobalEnvClr.b = b; } + void setVolumeSize(u16 size) { mVolumeSize = size; } + void setLifeTime(s16 lifetime) { mLifeTime = lifetime; } + void setAwayFromCenterSpeed(f32 i_speed) { mAwayFromCenterSpeed = i_speed; } + void setAwayFromAxisSpeed(f32 i_speed) { mAwayFromAxisSpeed = i_speed; } + void setSpread(f32 i_spread) { mSpread = i_spread; } + void setLocalTranslation(const JGeometry::TVec3& i_trans) { mLocalTrs.set(i_trans); } + void setLocalRotation(const JGeometry::TVec3& i_rot) { mLocalRot.set(i_rot.x * 0.005493248f, i_rot.y * 0.005493248f, i_rot.z * 0.005493248f); } + void setRateStep(u8 i_step) { mRateStep = i_step; } + + void setGlobalParticleHeightScale(f32 height) { + mGlobalPScl.y = height; + } + void setGlobalParticleScale(const JGeometry::TVec3& scale) { + mGlobalPScl.set(scale.x, scale.y); + } + void setGlobalParticleScale(f32 scaleX, f32 scaleY) { + mGlobalPScl.set(scaleX, scaleY); + } + void getGlobalParticleScale(JGeometry::TVec3& scale) { + scale.set(mGlobalPScl.x, mGlobalPScl.y, 1.0f); + } + void setGlobalScale(const JGeometry::TVec3& scale) { + mGlobalScl.set(scale); + mGlobalPScl.set(scale.x ,scale.y); + } + void setGlobalSRTMatrix(const MtxP matrix) { + JPASetRMtxSTVecfromMtx(matrix, mGlobalRot, &mGlobalScl, &mGlobalTrs); + mGlobalPScl.set(mGlobalScl.x, mGlobalScl.y); + } + void setDirection(const JGeometry::TVec3& direction) { + mLocalDir.set(direction); + } + + void setLocalScale(const JGeometry::TVec3& scale) { + mLocalScl.set(scale); + } + + f32 get_r_f() { return mRndm.get_rndm_f(); } + f32 get_r_zp() { return mRndm.get_rndm_zp(); } + f32 get_r_zh() { return mRndm.get_rndm_zh(); } + s16 get_r_ss() { return mRndm.get_rndm_ss(); } + + void stopCreateParticle() { setStatus(JPAEmtrStts_StopEmit); } + void playCreateParticle() { clearStatus(JPAEmtrStts_StopEmit); } + void becomeImmortalEmitter() { setStatus(JPAEmtrStts_Immortal); } + void becomeContinuousParticle() { mMaxFrame = 0; } + void becomeDeleteEmitter() { setStatus(JPAEmtrStts_Delete); } + void becomeInvalidEmitter() { + stopCreateParticle(); + mMaxFrame = 1; + } + + void quitImmortalEmitter() { clearStatus(JPAEmtrStts_Immortal); } + void stopCalcEmitter() { setStatus(JPAEmtrStts_StopCalc); } + void playCalcEmitter() { clearStatus(JPAEmtrStts_StopCalc); } + void stopDrawParticle() { setStatus(JPAEmtrStts_StopDraw); } + void playDrawParticle() { clearStatus(JPAEmtrStts_StopDraw); } + + u32 getUserWork() { return mpUserWork; } + void setUserWork(u32 userWork) { mpUserWork = userWork; } + u32 getParticleNumber() { + return mAlivePtclBase.getNum() + mAlivePtclChld.getNum(); + } + bool isEnableDeleteEmitter() { + return checkStatus(JPAEmtrStts_EnableDeleteEmitter) && getParticleNumber() == 0; + } + void setDrawTimes(u8 drawTimes) { mDrawTimes = drawTimes; } + void setParticleCallBackPtr(JPAParticleCallBack* cb) { mpPtclCallBack = cb; } + JPAParticleCallBack* getParticleCallBackPtr() { return mpPtclCallBack; } + JPAEmitterCallBack* getEmitterCallBackPtr() const { return mpEmtrCallBack; } + u32 getAge() const { return mTick; } + +public: + /* 0x00 */ JGeometry::TVec3 mLocalScl; + /* 0x0C */ JGeometry::TVec3 mLocalTrs; + /* 0x18 */ JGeometry::TVec3 mLocalDir; + /* 0x24 */ s32 mMaxFrame; + /* 0x28 */ f32 mRate; + /* 0x2C */ f32 mVolumeSweep; + /* 0x30 */ f32 mVolumeMinRad; + /* 0x34 */ f32 mAwayFromCenterSpeed; + /* 0x38 */ f32 mAwayFromAxisSpeed; + /* 0x3C */ f32 mDirSpeed; + /* 0x40 */ f32 mSpread; + /* 0x44 */ f32 mRndmDirSpeed; + /* 0x48 */ f32 mAirResist; + /* 0x4C */ JGeometry::TVec3 mLocalRot; + /* 0x52 */ s16 mLifeTime; + /* 0x54 */ u16 mVolumeSize; + /* 0x56 */ u8 mRateStep; + /* 0x58 */ JSULink mLink; + /* 0x68 */ Mtx mGlobalRot; + /* 0x98 */ JGeometry::TVec3 mGlobalScl; + /* 0xA4 */ JGeometry::TVec3 mGlobalTrs; + /* 0xB0 */ JGeometry::TVec2 mGlobalPScl; + /* 0xB8 */ GXColor mGlobalPrmClr; + /* 0xBC */ GXColor mGlobalEnvClr; + /* 0xC0 */ s32 mpUserWork; + /* 0xC4 */ JPARandom mRndm; + /* 0xC8 */ JPAList mAlivePtclBase; + /* 0xD4 */ JPAList mAlivePtclChld; + /* 0xE0 */ JPAList* mpPtclPool; + /* 0xE4 */ JPAEmitterManager* mpEmtrMgr; + /* 0xE8 */ JPAResource* mpRes; + /* 0xEC */ JPAEmitterCallBack* mpEmtrCallBack; + /* 0xF0 */ JPAParticleCallBack* mpPtclCallBack; + /* 0xF4 */ volatile u32 mStatus; + /* 0xF8 */ f32 mEmitCount; + /* 0xFC */ f32 mScaleOut; + /* 0x100 */ u32 mTick; + /* 0x104 */ s16 mWaitTime; + /* 0x106 */ s16 mRateStepTimer; + /* 0x108 */ GXColor mPrmClr; + /* 0x10C */ GXColor mEnvClr; + /* 0x110 */ u8 mDrawTimes; + /* 0x111 */ u8 mTexAnmIdx; + /* 0x112 */ u8 mGroupID; + /* 0x113 */ u8 mResMgrID; +}; + +enum { + JPAPtclStts_Invisible = 0x08, +}; + +#endif /* JPAEMITTER_H */ diff --git a/include/JSystem/JParticle/JPAEmitterManager.h b/include/JSystem/JParticle/JPAEmitterManager.h new file mode 100644 index 00000000..5cd69a28 --- /dev/null +++ b/include/JSystem/JParticle/JPAEmitterManager.h @@ -0,0 +1,49 @@ +#ifndef JPAEMITTERMANAGER_H +#define JPAEMITTERMANAGER_H + +#include "dolphin/types.h" +#include "JSystem/JParticle/JPAList.h" +#include "JSystem/JParticle/JPADrawInfo.h" +#include "JSystem/JSupport/JSUList.h" +#include "JSystem/JGeometry.h" + +class JPAEmitterCallBack; +class JPAParticleCallBack; +class JPABaseEmitter; +class JPAResourceManager; +class JPABaseParticle; +class JKRHeap; +struct JPAEmitterWorkData; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAEmitterManager { +public: + /* 8027DCA0 */ JPAEmitterManager(u32, u32, JKRHeap*, u8, u8); + /* 8027DEBC */ JPABaseEmitter* createSimpleEmitterID(JGeometry::TVec3 const&, u16, u8, u8, + JPAEmitterCallBack*, JPAParticleCallBack*); + /* 8027DFA0 */ void calc(u8); + /* 8027E028 */ void draw(JPADrawInfo const*, u8); + /* 8027E220 */ void forceDeleteAllEmitter(); + /* 8027E278 */ void forceDeleteGroupEmitter(u8); + /* 8027E2D8 */ void forceDeleteEmitter(JPABaseEmitter*); + /* 8027E344 */ void entryResourceManager(JPAResourceManager*, u8); + /* 8027E354 */ void clearResourceManager(u8); + /* 8027E3F4 */ void calcYBBCam(); + JPAResourceManager* getResourceManager(u16 idx) { return pResMgrAry[idx]; } + +public: + /* 0x00 */ JSUList* pEmtrUseList; + /* 0x04 */ JSUList mFreeEmtrList; + /* 0x10 */ JPAList mPtclPool; + /* 0x1C */ JPAResourceManager** pResMgrAry; + /* 0x20 */ JPAEmitterWorkData* pWd; + /* 0x24 */ u32 emtrNum; + /* 0x28 */ u32 ptclNum; + /* 0x2C */ u8 gidMax; + /* 0x2D */ u8 ridMax; +}; + +#endif /* JPAEMITTERMANAGER_H */ diff --git a/include/JSystem/JParticle/JPAExTexShape.h b/include/JSystem/JParticle/JPAExTexShape.h new file mode 100644 index 00000000..b202cc9d --- /dev/null +++ b/include/JSystem/JParticle/JPAExTexShape.h @@ -0,0 +1,45 @@ +#ifndef JPAEXTEXSHAPE_H +#define JPAEXTEXSHAPE_H + +#include "dolphin/types.h" + +class JPAEmitterWorkData; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPAExTexShapeData { + // Common header. + /* 0x00 */ u8 mMagic[4]; + /* 0x04 */ u32 mSize; + + /* 0x08 */ u32 mFlags; + /* 0x0C */ f32 mIndTexMtx[2][3]; + /* 0x24 */ s8 mExpScale; + /* 0x25 */ s8 mIndTexIdx; + /* 0x26 */ s8 mSecTexIdx; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAExTexShape { +public: + /* 8027B13C */ JPAExTexShape(u8 const*); + + const f32* getIndTexMtx() const { return &mpData->mIndTexMtx[0][0]; } + s8 getExpScale() const { return mpData->mExpScale; } + u8 getIndTexIdx() const { return mpData->mIndTexIdx; } + u8 getSecTexIdx() const { return mpData->mSecTexIdx; } + bool isUseIndirect() const { return !!(mpData->mFlags & 0x01); } + bool isUseSecTex() const { return !!(mpData->mFlags & 0x0100); } + +public: + const JPAExTexShapeData* mpData; +}; + +void JPALoadExTex(JPAEmitterWorkData*); + +#endif /* JPAEXTEXSHAPE_H */ diff --git a/include/JSystem/JParticle/JPAExtraShape.h b/include/JSystem/JParticle/JPAExtraShape.h new file mode 100644 index 00000000..dbf46363 --- /dev/null +++ b/include/JSystem/JParticle/JPAExtraShape.h @@ -0,0 +1,112 @@ +#ifndef JPAEXTRASHAPE_H +#define JPAEXTRASHAPE_H + +#include "dolphin/types.h" + +class JPAEmitterWorkData; +class JPABaseParticle; + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPAExtraShapeData { + // Common header. + /* 0x00 */ u8 mMagic[4]; + /* 0x04 */ u32 mSize; + + /* 0x08 */ u32 mFlags; + /* 0x0C */ f32 mScaleInTiming; + /* 0x10 */ f32 mScaleOutTiming; + /* 0x14 */ f32 mScaleInValueX; + /* 0x18 */ f32 mScaleOutValueX; + /* 0x1C */ f32 mScaleInValueY; + /* 0x20 */ f32 mScaleOutValueY; + /* 0x24 */ f32 mScaleOutRandom; + /* 0x28 */ s16 mScaleAnmCycleX; + /* 0x2A */ s16 mScaleAnmCycleY; + /* 0x2C */ f32 mAlphaInTiming; + /* 0x30 */ f32 mAlphaOutTiming; + /* 0x34 */ f32 mAlphaInValue; + /* 0x38 */ f32 mAlphaBaseValue; + /* 0x3C */ f32 mAlphaOutValue; + /* 0x40 */ f32 mAlphaWaveFrequency; + /* 0x44 */ f32 mAlphaWaveRandom; + /* 0x48 */ f32 mAlphaWaveAmplitude; + /* 0x4C */ f32 mRotateAngle; + /* 0x50 */ f32 mRotateAngleRandom; + /* 0x54 */ f32 mRotateSpeed; + /* 0x58 */ f32 mRotateSpeedRandom; + /* 0x5C */ f32 mRotateDirection; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAExtraShape { +public: + /* 8027AD88 */ JPAExtraShape(u8 const*); + /* 8027ADBC */ void init(); + + f32 getScaleInTiming() const { return mpData->mScaleInTiming; } + f32 getScaleOutTiming() const { return mpData->mScaleOutTiming; } + f32 getScaleInValueX() const { return mpData->mScaleInValueX; } + f32 getScaleInValueY() const { return mpData->mScaleInValueY; } + f32 getScaleOutValueX() const { return mpData->mScaleOutValueX; } + f32 getScaleOutValueY() const { return mpData->mScaleOutValueY; } + f32 getScaleRndm() const { return mpData->mScaleOutRandom; } + s16 getScaleAnmCycleX() const { return mpData->mScaleAnmCycleX; } + s16 getScaleAnmCycleY() const { return mpData->mScaleAnmCycleY; } + f32 getAlphaInTiming() const { return mpData->mAlphaInTiming; } + f32 getAlphaOutTiming() const { return mpData->mAlphaOutTiming; } + f32 getAlphaInValue() const { return mpData->mAlphaInValue; } + f32 getAlphaOutValue() const { return mpData->mAlphaOutValue; } + f32 getAlphaBaseValue() const { return mpData->mAlphaBaseValue; } + f32 getAlphaFreq() const { return mpData->mAlphaWaveFrequency; } + f32 getAlphaFreqRndm() const { return mpData->mAlphaWaveRandom; } + f32 getAlphaAmp() const { return mpData->mAlphaWaveAmplitude; } + f32 getRotateInitAngle() const { return mpData->mRotateAngle; } + f32 getRotateRndmAngle() const { return mpData->mRotateAngleRandom; } + f32 getRotateInitSpeed() const { return mpData->mRotateSpeed; } + f32 getRotateRndmSpeed() const { return mpData->mRotateSpeedRandom; } + f32 getRotateDirection() const { return mpData->mRotateDirection; } + f32 getScaleIncRateX() const { return mScaleIncRateX; } + f32 getScaleDecRateX() const { return mScaleDecRateX; } + f32 getScaleIncRateY() const { return mScaleIncRateY; } + f32 getScaleDecRateY() const { return mScaleDecRateY; } + f32 getAlphaIncRate() const { return mAlphaIncRate; } + f32 getAlphaDecRate() const { return mAlphaDecRate; } + + BOOL isEnableScaleAnm() const { return mpData->mFlags & 1; } + BOOL isScaleXYDiff() const { return mpData->mFlags & 2; } + u32 getScaleAnmTypeX() const { return (mpData->mFlags >> 8) & 3; } + u32 getScaleAnmTypeY() const { return (mpData->mFlags >> 10) & 3; } + u32 getScaleCenterX() const { return (mpData->mFlags >> 12) & 3; } + u32 getScaleCenterY() const { return (mpData->mFlags >> 14) & 3; } + BOOL isEnableAlphaAnm() const { return mpData->mFlags & 0x10000; } + BOOL isEnableAlphaFlick() const { return mpData->mFlags & 0x20000; } + BOOL isEnableRotateAnm() const { return mpData->mFlags & 0x1000000; } + +private: + /* 0x00 */ const JPAExtraShapeData* mpData; + /* 0x04 */ f32 mAlphaIncRate; + /* 0x08 */ f32 mAlphaDecRate; + /* 0x0C */ f32 mScaleIncRateX; + /* 0x10 */ f32 mScaleIncRateY; + /* 0x14 */ f32 mScaleDecRateX; + /* 0x18 */ f32 mScaleDecRateY; +}; + +void JPACalcAlphaFlickAnm(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcAlphaAnm(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleX(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleY(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleCopy(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleAnmNormal(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleAnmRepeatX(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleAnmReverseX(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleAnmRepeatY(JPAEmitterWorkData*, JPABaseParticle*); +void JPACalcScaleAnmReverseY(JPAEmitterWorkData*, JPABaseParticle*); + +#endif /* JPAEXTRASHAPE_H */ diff --git a/include/JSystem/JParticle/JPAFieldBlock.h b/include/JSystem/JParticle/JPAFieldBlock.h new file mode 100644 index 00000000..2031ba26 --- /dev/null +++ b/include/JSystem/JParticle/JPAFieldBlock.h @@ -0,0 +1,174 @@ +#ifndef JPAFIELDBLOCK_H +#define JPAFIELDBLOCK_H + +#include "JSystem/JGeometry.h" +#include "dolphin/types.h" + +class JKRHeap; +class JPAEmitterWorkData; +class JPABaseParticle; +class JPAFieldBlock; + +class JPAFieldBase { +public: + /* 8027BDEC */ void calcAffect(JPAFieldBlock*, JPABaseParticle*); + /* 8027BF18 */ f32 calcFadeAffect(JPAFieldBlock*, f32) const; + + /* 8027D3AC */ virtual ~JPAFieldBase() {} + /* 80276A8C */ virtual void prepare(JPAEmitterWorkData*, JPAFieldBlock*) {} + virtual void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*) = 0; + + /* 0x04 */ JGeometry::TVec3 mAccel; +}; + +class JPAFieldVortex : public JPAFieldBase { +public: + /* 8027C56C */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027C674 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D564 */ ~JPAFieldVortex() {} + + /* 0x10 */ JGeometry::TVec3 field_0x10; + /* 0x1C */ f32 field_0x1c; + /* 0x20 */ f32 field_0x20; +}; + +class JPAFieldSpin : public JPAFieldBase { +public: + /* 8027CE64 */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027CFA8 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D3F4 */ ~JPAFieldSpin() {} + + /* 0x10 */ JGeometry::TVec3 field_0x10; + /* 0x1C */ JGeometry::TVec3 field_0x1c; + /* 0x28 */ JGeometry::TVec3 field_0x28; +}; + +class JPAFieldRandom : public JPAFieldBase { +public: + /* 8027CCCC */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D4AC */ ~JPAFieldRandom() {} +}; + +class JPAFieldNewton : public JPAFieldBase { +public: + /* 8027C36C */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027C3E0 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D5C0 */ ~JPAFieldNewton() {} + + /* 0x10 */ JGeometry::TVec3 mDir; + /* 0x1C */ f32 mCutoff; +}; + +class JPAFieldMagnet : public JPAFieldBase { +public: + /* 8027C24C */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027C29C */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D61C */ ~JPAFieldMagnet() {} + + /* 0x10 */ JGeometry::TVec3 mDir; +}; + +class JPAFieldGravity : public JPAFieldBase { +public: + /* 8027BFB4 */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027C054 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D6D4 */ ~JPAFieldGravity() {} +}; + +class JPAFieldDrag : public JPAFieldBase { +public: + /* 8027CDE4 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D450 */ ~JPAFieldDrag() {} +}; + +class JPAFieldConvection : public JPAFieldBase { +public: + /* 8027C814 */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027CA94 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D508 */ ~JPAFieldConvection() {} + + /* 0x10 */ JGeometry::TVec3 field_0x10; + /* 0x1C */ JGeometry::TVec3 field_0x1c; + /* 0x28 */ JGeometry::TVec3 field_0x28; +}; + +class JPAFieldAir : public JPAFieldBase { +public: + /* 8027C07C */ void prepare(JPAEmitterWorkData*, JPAFieldBlock*); + /* 8027C1B8 */ void calc(JPAEmitterWorkData*, JPAFieldBlock*, JPABaseParticle*); + /* 8027D678 */ ~JPAFieldAir() {} +}; + +// unknown name +class JPAFieldBlockData { +public: + /* 0x00 */ u8 mMagic[4]; + /* 0x04 */ u32 mSize; + /* 0x08 */ u32 mFlags; + /* 0x0C */ JGeometry::TVec3 mPos; + /* 0x18 */ JGeometry::TVec3 mDir; + /* 0x24 */ f32 mMag; + /* 0x28 */ f32 mMagRndm; + /* 0x2C */ f32 mVal1; + /* 0x30 */ f32 mFadeInTime; + /* 0x34 */ f32 mFadeOutTime; + /* 0x38 */ f32 mEnTime; + /* 0x3C */ f32 mDisTime; + /* 0x40 */ u8 mCycle; +}; + +class JPAFieldBlock { +public: + /* 8027D088 */ JPAFieldBlock(u8 const*, JKRHeap*); + /* 8027D0C0 */ void init(JKRHeap*); + + u32 getType() { return mpData->mFlags & 0xF; } + u32 getAddType() { return (mpData->mFlags >> 8) & 3; } + u32 getSttFlag() { return mpData->mFlags >> 16; } + bool checkStatus(u16 flag) { return flag & getSttFlag(); } + f32 getMagRndm() const { return mpData->mMagRndm; } + f32 getVal1() const { return mpData->mVal1; } + f32 getFadeInTime() { return mpData->mFadeInTime; } + f32 getFadeOutTime() { return mpData->mFadeOutTime; } + f32 getEnTime() { return mpData->mEnTime; } + f32 getDisTime() { return mpData->mDisTime; } + u8 getCycle() { return mpData->mCycle; } + f32 getFadeInRate() { return mFadeInRate; } + f32 getFadeOutRate() { return mFadeOutRate; } + JGeometry::TVec3& getPos() { return mPos; } + JGeometry::TVec3& getDir() { return mDir; } + f32 getMag() const { return mMag; } + void getPosOrig(JGeometry::TVec3* pos) { pos->set(mpData->mPos); } + void getDirOrig(JGeometry::TVec3* dir) { dir->set(mpData->mDir); } + f32 getMagOrig() { return mpData->mMag; } + void initOpParam() { + getPosOrig(&mPos); + getDirOrig(&mDir); + mMag = getMagOrig(); + } + void prepare(JPAEmitterWorkData* work) { mpField->prepare(work, this); } + void calc(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { mpField->calc(work, this, ptcl); } + +private: + /* 0x00 */ const JPAFieldBlockData* mpData; + /* 0x04 */ JPAFieldBase* mpField; + /* 0x08 */ f32 mFadeInRate; + /* 0x0C */ f32 mFadeOutRate; + /* 0x10 */ JGeometry::TVec3 mPos; + /* 0x1C */ JGeometry::TVec3 mDir; + /* 0x28 */ f32 mMag; + + enum Type { + /* 0x0 */ FIELD_GRAVITY, + /* 0x1 */ FIELD_AIR, + /* 0x2 */ FIELD_MAGNET, + /* 0x3 */ FIELD_NEWTON, + /* 0x4 */ FIELD_VORTEX, + /* 0x5 */ FIELD_RANDOM, + /* 0x6 */ FIELD_DRAG, + /* 0x7 */ FIELD_CONVECTION, + /* 0x8 */ FIELD_SPIN, + }; +}; + +#endif /* JPAFIELDBLOCK_H */ diff --git a/include/JSystem/JParticle/JPAKeyBlock.h b/include/JSystem/JParticle/JPAKeyBlock.h new file mode 100644 index 00000000..3d79e854 --- /dev/null +++ b/include/JSystem/JParticle/JPAKeyBlock.h @@ -0,0 +1,21 @@ +#ifndef JPAKEYBLOCK_H +#define JPAKEYBLOCK_H + +#include "dolphin/types.h" + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPAKeyBlock { + /* 8027D730 */ JPAKeyBlock(u8 const*); + /* 8027D740 */ f32 calc(f32); + + u8 getID() { return mDataStart[8]; } + + const u8* mDataStart; + const f32* field_0x4; +}; + + +#endif /* JPAKEYBLOCK_H */ diff --git a/include/JSystem/JParticle/JPAList.h b/include/JSystem/JParticle/JPAList.h new file mode 100644 index 00000000..ab2e5a7f --- /dev/null +++ b/include/JSystem/JParticle/JPAList.h @@ -0,0 +1,131 @@ +#ifndef JPALIST_H +#define JPALIST_H + +#include "dolphin/types.h" + +/** + * @ingroup jsystem-jparticle + * + */ +template +struct JPANode { + JPANode() : mpPrev(NULL), mpNext(NULL) { + } + ~JPANode() {} + JPANode* getPrev() { return mpPrev; } + JPANode* getNext() { return mpNext; } + T* getObject() { return &mData; } + + /* 0x00 */ JPANode* mpPrev; + /* 0x04 */ JPANode* mpNext; + /* 0x08 */ T mData; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +template +struct JPAList { + /* 0x00 */ JPANode* mpFirst; + /* 0x04 */ JPANode* mpLast; + /* 0x08 */ u32 mNum; + + JPAList() : mpFirst(NULL), mpLast(NULL), mNum() {} + ~JPAList() {} + + JPANode* getEnd() { return NULL; } + JPANode* getFirst() const { return mpFirst; } + JPANode* getLast() const { return mpLast; } + u32 getNum() const { return mNum; } + + void push_front(JPANode* node) { + if (mpFirst != NULL) { + node->mpPrev = NULL; + node->mpNext = mpFirst; + mpFirst->mpPrev = node; + mpFirst = node; + } else { + mpLast = node; + mpFirst = node; + node->mpPrev = NULL; + node->mpNext = NULL; + } + + mNum++; + } + + void push_back(JPANode* node) { + if (mpLast != NULL) { + node->mpPrev = mpLast; + node->mpNext = NULL; + mpLast->mpNext = node; + mpLast = node; + } else { + mpFirst = node; + mpLast = node; + node->mpNext = node->mpPrev = NULL; + } + + mNum++; + } + + JPANode* pop_front() { + JPANode* ret = NULL; + + if (mNum == 1) { + ret = mpFirst; + mpLast = NULL; + mpFirst = NULL; + mNum--; + } else if (mNum) { + ret = mpFirst; + ret->mpNext->mpPrev = NULL; + mpFirst = ret->mpNext; + mNum--; + } + + return ret; + } + + JPANode* pop_back() { + JPANode* ret = NULL; + + if (mNum == 1) { + ret = mpLast; + mpLast = NULL; + mpFirst = NULL; + mNum--; + } else if (mNum) { + ret = mpLast; + ret->mpPrev->mpNext = NULL; + mpLast = ret->mpPrev; + mNum--; + } + + return ret; + } + + JPANode* erase(JPANode* node) { + if (node->mpNext != NULL && node->mpPrev != NULL) { + node->mpPrev->mpNext = node->mpNext; + node->mpNext->mpPrev = node->mpPrev; + mNum--; + } else if (node->mpNext != NULL) { + node->mpNext->mpPrev = NULL; + mpFirst = node->mpNext; + mNum--; + } else if (node->mpPrev != NULL) { + node->mpPrev->mpNext = NULL; + mpLast = node->mpPrev; + mNum--; + } else { + mpLast = NULL; + mpFirst = NULL; + mNum--; + } + return node; + } +}; + +#endif diff --git a/include/JSystem/JParticle/JPAMath.h b/include/JSystem/JParticle/JPAMath.h new file mode 100644 index 00000000..68701359 --- /dev/null +++ b/include/JSystem/JParticle/JPAMath.h @@ -0,0 +1,16 @@ +#ifndef JPAMATH_H +#define JPAMATH_H + +#include "dolphin/mtx.h" +#include "JSystem/JGeometry.h" + +void JPAGetDirMtx(JGeometry::TVec3 const& param_0, f32 (*param_1)[4]); +void JPAGetYZRotateMtx(s16 angleY, s16 angleZ, f32 (*param_2)[4]); +void JPAGetXYZRotateMtx(s16 x, s16 y, s16 z, Mtx dst); +void JPASetRMtxTVecfromMtx(f32 const (*param_0)[4], f32 (*param_1)[4], + JGeometry::TVec3* param_2); +f32 JPACalcKeyAnmValue(f32 param_0, u16 param_1, f32 const* param_2); +void JPASetRMtxSTVecfromMtx(f32 const (*param_0)[4], f32 (*param_1)[4], + JGeometry::TVec3* param_2, JGeometry::TVec3* param_3); + +#endif /* JPAMATH_H */ diff --git a/include/JSystem/JParticle/JPAParticle.h b/include/JSystem/JParticle/JPAParticle.h new file mode 100644 index 00000000..2e67f8e8 --- /dev/null +++ b/include/JSystem/JParticle/JPAParticle.h @@ -0,0 +1,93 @@ +#ifndef JPAPARTICLE_H +#define JPAPARTICLE_H + +#include +#include "JSystem/JGeometry.h" + +class JKRHeap; +class JPABaseEmitter; +class JPABaseParticle; +class JPAEmitterCallBack; +class JPAEmitterManager; +class JPAParticleCallBack; +class JPAResourceManager; +struct JPAEmitterWorkData; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPABaseParticle { +public: + ~JPABaseParticle() {} + /* 8027EFEC */ void init_p(JPAEmitterWorkData*); + /* 8027F8C8 */ void init_c(JPAEmitterWorkData*, JPABaseParticle*); + /* 8027FFD0 */ bool calc_p(JPAEmitterWorkData*); + /* 80280260 */ bool calc_c(JPAEmitterWorkData*); + /* 802804C8 */ bool canCreateChild(JPAEmitterWorkData*); + /* 80280548 */ f32 getWidth(JPABaseEmitter const*) const; + /* 80280568 */ f32 getHeight(JPABaseEmitter const*) const; + int getAge() { return mAge; } + void setOffsetPosition(const JGeometry::TVec3& pos) { mOffsetPosition.set(pos); } + void setOffsetPosition(f32 x, f32 y, f32 z) { mOffsetPosition.set(x, y, z); } + void getOffsetPosition(JGeometry::TVec3& pos) { pos.set(mOffsetPosition); } + u16 getRotateAngle() const { return mRotateAngle; } + void getGlobalPosition(JGeometry::TVec3& pos) const { pos.set(mPosition); } + f32 getParticleScaleX() const { return mParticleScaleX; } + f32 getParticleScaleY() const { return mParticleScaleY; } + void setStatus(u32 flag) { mStatus |= flag; } + u32 checkStatus(u32 flag) { return mStatus & flag; } + void initStatus(u32 status) { mStatus = status; } + void setInvisibleParticleFlag() { setStatus(8); } + void setDeleteParticleFlag() { setStatus(2); } + void getVelVec(JGeometry::TVec3& vec) const { vec.set(mVelocity); } + void getLocalPosition(JGeometry::TVec3& vec) const { vec.set(mLocalPosition); } + void getBaseAxis(JGeometry::TVec3& vec) const { vec.set(mBaseAxis); } + +public: + /* 0x00 */ JGeometry::TVec3 mPosition; + /* 0x0C */ JGeometry::TVec3 mLocalPosition; + /* 0x18 */ JGeometry::TVec3 mOffsetPosition; + /* 0x24 */ JGeometry::TVec3 mVelocity; + /* 0x30 */ JGeometry::TVec3 mVelType1; + /* 0x3C */ JGeometry::TVec3 mVelType0; + /* 0x48 */ JGeometry::TVec3 mVelType2; + /* 0x54 */ JGeometry::TVec3 mBaseAxis; + /* 0x60 */ f32 mParticleScaleX; + /* 0x64 */ f32 mParticleScaleY; + /* 0x68 */ f32 mScaleOut; + /* 0x6C */ f32 mAlphaWaveRandom; + /* 0x70 */ f32 mMoment; + /* 0x74 */ f32 mDrag; + /* 0x78 */ u32 field_0x78; + /* 0x7C */ u32 mStatus; + /* 0x80 */ s16 mAge; + /* 0x82 */ s16 mLifeTime; + /* 0x84 */ f32 mTime; + /* 0x88 */ u16 mRotateAngle; + /* 0x8A */ s16 mRotateSpeed; + /* 0x8C */ GXColor mPrmClr; + /* 0x90 */ GXColor mEnvClr; + /* 0x94 */ u8 mTexAnmIdx; + /* 0x95 */ u8 mAnmRandom; + /* 0x96 */ u8 mPrmColorAlphaAnm; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAParticleCallBack { +public: + JPAParticleCallBack() {} + virtual ~JPAParticleCallBack() = 0; + virtual void execute(JPABaseEmitter*, JPABaseParticle*) {} + virtual void draw(JPABaseEmitter*, JPABaseParticle*) {} +}; + +// not sure where this belongs +static inline u32 COLOR_MULTI(u32 a, u32 b) { + return ((a * (b + 1)) * 0x10000) >> 24; +} + +#endif /* JPAPARTICLE_H */ diff --git a/include/JSystem/JParticle/JPARandom.h b/include/JSystem/JParticle/JPARandom.h new file mode 100644 index 00000000..5ffb276d --- /dev/null +++ b/include/JSystem/JParticle/JPARandom.h @@ -0,0 +1,43 @@ +#ifndef JPARANDOM_H +#define JPARANDOM_H + +#include "dolphin/types.h" + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPARandom { +public: + JPARandom() { mSeed = 0; } + JPARandom(u32 seed) { mSeed = seed; } + ~JPARandom() {} + void set_seed(u32 seed) { mSeed = seed; } + + u32 get_rndm_u() { return mSeed = mSeed * 0x19660du + 0x3c6ef35fu; } + + f32 get_rndm_f() { + union { + u32 u; + f32 f; + } a; + a.u = ((get_rndm_u() >> 9) | 0x3f800000); + return a.f - 1.0f; + } + + f32 get_rndm_zp() { + f32 f = get_rndm_f(); + return (f + f) - 1.0f; + } + + f32 get_rndm_zh() { + return get_rndm_f() - 0.5f; + } + + s16 get_rndm_ss() { return (s16)(get_rndm_u() >> 16); } + +public: + u32 mSeed; +}; + +#endif diff --git a/include/JSystem/JParticle/JPAResource.h b/include/JSystem/JParticle/JPAResource.h new file mode 100644 index 00000000..4b953233 --- /dev/null +++ b/include/JSystem/JParticle/JPAResource.h @@ -0,0 +1,81 @@ +#ifndef JPARESOURCE_H +#define JPARESOURCE_H + +#include "dolphin/types.h" + +class JKRHeap; +class JPAEmitterWorkData; +class JPABaseEmitter; +class JPABaseParticle; + +class JPABaseShape; +class JPAExtraShape; +class JPAChildShape; +class JPAExTexShape; +class JPADynamicsBlock; +class JPAFieldBlock; +class JPAKeyBlock; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAResource { +public: + /* 80274010 */ JPAResource(); + /* 80274080 */ void init(JKRHeap*); + /* 802755E8 */ bool calc(JPAEmitterWorkData*, JPABaseEmitter*); + /* 80275A94 */ void draw(JPAEmitterWorkData*, JPABaseEmitter*); + /* 80275B74 */ void drawP(JPAEmitterWorkData*); + /* 80275EB0 */ void drawC(JPAEmitterWorkData*); + /* 802761A8 */ void setPTev(); + /* 8027642C */ void setCTev(JPAEmitterWorkData*); + /* 8027658C */ void calc_p(JPAEmitterWorkData*, JPABaseParticle*); + /* 80276608 */ void calc_c(JPAEmitterWorkData*, JPABaseParticle*); + /* 80276684 */ void calcField(JPAEmitterWorkData*, JPABaseParticle*); + /* 80276700 */ void calcKey(JPAEmitterWorkData*); + /* 80276840 */ void calcWorkData_c(JPAEmitterWorkData*); + /* 80276A0C */ void calcWorkData_d(JPAEmitterWorkData*); + + JPABaseShape* getBsp() const { return mpBaseShape; } + JPAExtraShape* getEsp() const { return mpExtraShape; } + JPAChildShape* getCsp() const { return mpChildShape; } + JPAExTexShape* getEts() const { return mpExTexShape; } + JPADynamicsBlock* getDyn() const { return mpDynamicsBlock; } + + u32 getTexIdx(u32 idx) const { return mpTDB1[idx]; } + u16 getUsrIdx() const { return mUsrIdx; } + +public: + typedef void (*EmitterFunc)(JPAEmitterWorkData*); + typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*); + /* 0x00 */ EmitterFunc* mpCalcEmitterFuncList; + /* 0x04 */ EmitterFunc* mpDrawEmitterFuncList; + /* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList; + /* 0x0C */ ParticleFunc* mpCalcParticleFuncList; + /* 0x10 */ ParticleFunc* mpDrawParticleFuncList; + /* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList; + /* 0x18 */ ParticleFunc* mpDrawParticleChildFuncList; + + /* 0x1C */ JPABaseShape* mpBaseShape; + /* 0x20 */ JPAExtraShape* mpExtraShape; + /* 0x24 */ JPAChildShape* mpChildShape; + /* 0x28 */ JPAExTexShape* mpExTexShape; + /* 0x2C */ JPADynamicsBlock* mpDynamicsBlock; + /* 0x30 */ JPAFieldBlock** mpFieldBlocks; + /* 0x34 */ JPAKeyBlock** mpKeyBlocks; + /* 0x38 */ u16 const* mpTDB1; + /* 0x3C */ u16 mUsrIdx; + /* 0x3E */ u8 mFieldBlockNum; + /* 0x3F */ u8 mKeyBlockNum; + /* 0x40 */ u8 mTDB1Num; + /* 0x41 */ u8 mpCalcEmitterFuncListNum; + /* 0x42 */ u8 mpDrawEmitterFuncListNum; + /* 0x43 */ u8 mpDrawEmitterChildFuncListNum; + /* 0x44 */ u8 mpCalcParticleFuncListNum; + /* 0x45 */ u8 mpDrawParticleFuncListNum; + /* 0x46 */ u8 mpCalcParticleChildFuncListNum; + /* 0x47 */ u8 mpDrawParticleChildFuncListNum; +}; + +#endif /* JPARESOURCE_H */ diff --git a/include/JSystem/JParticle/JPAResourceLoader.h b/include/JSystem/JParticle/JPAResourceLoader.h new file mode 100644 index 00000000..10ff1e38 --- /dev/null +++ b/include/JSystem/JParticle/JPAResourceLoader.h @@ -0,0 +1,14 @@ +#ifndef JPARESOURCELOADER_H +#define JPARESOURCELOADER_H + +#include "dolphin/types.h" + +class JPAResourceManager; + +class JPAResourceLoader { +public: + /* 8027D8A0 */ JPAResourceLoader(u8 const*, JPAResourceManager*); + /* 8027D8E0 */ void load_jpc(u8 const*, JPAResourceManager*); +}; + +#endif /* JPARESOURCELOADER_H */ diff --git a/include/JSystem/JParticle/JPAResourceManager.h b/include/JSystem/JParticle/JPAResourceManager.h new file mode 100644 index 00000000..2820c810 --- /dev/null +++ b/include/JSystem/JParticle/JPAResourceManager.h @@ -0,0 +1,36 @@ +#ifndef JPARESOURCEMANAGER_H +#define JPARESOURCEMANAGER_H + +#include "JSystem/JParticle/JPATexture.h" + +class JKRHeap; +class JPAResource; +struct ResTIMG; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPAResourceManager { +public: + /* 80273E10 */ JPAResourceManager(void const*, JKRHeap*); + /* 80273E68 */ JPAResource* getResource(u16) const; + /* 80273EA8 */ bool checkUserIndexDuplication(u16) const; + /* 80273EEC */ const ResTIMG* swapTexture(ResTIMG const*, char const*); + /* 80273F8C */ void registRes(JPAResource*); + /* 80273FAC */ void registTex(JPATexture*); + /* 80273FCC */ u32 getResUserWork(u16) const; + + void load(u16 idx, GXTexMapID texMapID) { mpTexArr[idx]->load(texMapID); } + +public: + /* 0x00 */ JKRHeap* mpHeap; + /* 0x04 */ JPAResource** mpResArr; + /* 0x08 */ JPATexture** mpTexArr; + /* 0x0C */ u16 mResMax; + /* 0x0E */ u16 mResNum; + /* 0x10 */ u16 mTexMax; + /* 0x12 */ u16 mTexNum; +}; + +#endif /* JPARESOURCEMANAGER_H */ diff --git a/include/JSystem/JParticle/JPATexture.h b/include/JSystem/JParticle/JPATexture.h new file mode 100644 index 00000000..19b3bed7 --- /dev/null +++ b/include/JSystem/JParticle/JPATexture.h @@ -0,0 +1,36 @@ +#ifndef JPATEXTURE_H +#define JPATEXTURE_H + +#include "JSystem/JUtility/JUTTexture.h" + +/** + * @ingroup jsystem-jparticle + * + */ +struct JPATextureData { + // Probably magic / size / flags up top here, but they're unused. + /* 0x00 */ char field_0x00[0x0C]; + /* 0x0C */ char mName[0x14]; + /* 0x20 */ ResTIMG mResTIMG; +}; + +/** + * @ingroup jsystem-jparticle + * + */ +class JPATexture { +public: + JPATexture(u8 const*); + virtual ~JPATexture(); + + void load(GXTexMapID texMapID) { mTexture.load(texMapID); } + + JUTTexture* getJUTTexture() { return &mTexture; } + const char* getName() const { return mpData->mName; } + +public: + JUTTexture mTexture; + const JPATextureData* mpData; +}; + +#endif /* JPATEXTURE_H */ diff --git a/include/JSystem/JSupport/JSUList.h b/include/JSystem/JSupport/JSUList.h new file mode 100644 index 00000000..884b8b9b --- /dev/null +++ b/include/JSystem/JSupport/JSUList.h @@ -0,0 +1,254 @@ +#ifndef JSULIST_H +#define JSULIST_H + +#include "dolphin/types.h" + +template +class JSUList; + +// +// Link +// + +class JSUPtrList; + +/** +* @ingroup jsystem-jsupport +* +*/ +class JSUPtrLink { +public: + JSUPtrLink(void* object); + ~JSUPtrLink(); + + void* getObjectPtr() const { return mObject; } + + JSUPtrList* getList() const { return mList; } + + JSUPtrLink* getNext() const { return mNext; } + + JSUPtrLink* getPrev() const { return mPrev; } + +public: + void* mObject; + JSUPtrList* mList; + JSUPtrLink* mPrev; + JSUPtrLink* mNext; +}; + +/** +* @ingroup jsystem-jsupport +* +*/ +template +class JSULink : public JSUPtrLink { +public: + JSULink(T* object) : JSUPtrLink((void*)object) {} + + T* getObject() const { return static_cast(mObject); } + + JSUList* getSupervisor() const { return static_cast*>(this->getList()); } + + JSULink* getNext() const { return static_cast(mNext); } + + JSULink* getPrev() const { return static_cast(mPrev); } +}; + +// +// List +// + +/** +* @ingroup jsystem-jsupport +* +*/ +class JSUPtrList { +public: + JSUPtrList() { this->initiate(); } + JSUPtrList(bool init); + ~JSUPtrList(); + + void initiate(); + void setFirst(JSUPtrLink* first); + bool append(JSUPtrLink* ptr); + bool prepend(JSUPtrLink* ptr); + bool insert(JSUPtrLink* before, JSUPtrLink* ptr); + bool remove(JSUPtrLink* ptr); + JSUPtrLink* getNthLink(u32 i) const; + + JSUPtrLink* getFirstLink() const { return mHead; } + + JSUPtrLink* getLastLink() const { return mTail; } + + u32 getNumLinks() const { return mLength; } + +private: + JSUPtrLink* mHead; + JSUPtrLink* mTail; + u32 mLength; +}; + +/** +* @ingroup jsystem-jsupport +* +*/ +template +class JSUList : public JSUPtrList { +public: + JSUList() : JSUPtrList() {} + JSUList(bool init) : JSUPtrList(init) {} + + ~JSUList() {} + + bool append(JSULink* link) { return this->JSUPtrList::append((JSUPtrLink*)link); } + + bool prepend(JSULink* link) { return this->JSUPtrList::prepend((JSUPtrLink*)link); } + + bool insert(JSULink* before, JSULink* link) { + return this->JSUPtrList::insert((JSUPtrLink*)before, (JSUPtrLink*)link); + } + + bool remove(JSULink* link) { return this->JSUPtrList::remove((JSUPtrLink*)link); } + + JSULink* getFirst() const { return (JSULink*)getFirstLink(); } + + JSULink* getLast() const { return (JSULink*)getLastLink(); } + + JSULink* getNth(int index) { return (JSULink*)getNthLink(index); } + + JSULink* getEnd() const { return NULL; } + + u32 getNumLinks() const { return this->JSUPtrList::getNumLinks(); } +}; + +/** +* @ingroup jsystem-jsupport +* +*/ +template +class JSUListIterator { +public: + JSUListIterator() : mLink(NULL) {} + JSUListIterator(JSULink* link) : mLink(link) {} + JSUListIterator(JSUList* list) : mLink(list->getFirst()) {} + + JSUListIterator& operator=(JSULink* link) { + this->mLink = link; + return *this; + } + + T* getObject() { return this->mLink->getObject(); } + + bool operator==(JSULink const* other) const { return this->mLink == other; } + bool operator!=(JSULink const* other) const { return this->mLink != other; } + bool operator==(JSUListIterator const& other) const { return this->mLink == other.mLink; } + bool operator!=(JSUListIterator const& other) const { return this->mLink != other.mLink; } + + JSUListIterator operator++(int) { + JSUListIterator prev = *this; + this->mLink = this->mLink->getNext(); + return prev; + } + + JSUListIterator& operator++() { + this->mLink = this->mLink->getNext(); + return *this; + } + + JSUListIterator operator--(int) { + JSUListIterator prev = *this; + this->mLink = this->mLink->getPrev(); + return prev; + } + + JSUListIterator& operator--() { + this->mLink = this->mLink->getPrev(); + return *this; + } + + T& operator*() { return *this->getObject(); } + + T* operator->() const { return mLink->getObject(); } + +// private: + JSULink* mLink; +}; + +// +// Tree +// + +/** +* @ingroup jsystem-jsupport +* +*/ +template +class JSUTree : public JSUList, public JSULink { +public: + JSUTree(T* owner) : JSUList(), JSULink(owner) {} + ~JSUTree() {} + + bool appendChild(JSUTree* child) { return this->append(child); } + + bool removeChild(JSUTree* child) { return this->remove(child); } + + bool insertChild(JSUTree* before, JSUTree* child) { return this->insert(before, child); } + + JSUTree* getEndChild() const { return NULL; } + + JSUTree* getFirstChild() const { return (JSUTree*)this->getFirst(); } + + JSUTree* getLastChild() const { return (JSUTree*)this->getLast(); } + + JSUTree* getNextChild() const { return (JSUTree*)this->getNext(); } + + JSUTree* getPrevChild() const { return (JSUTree*)this->getPrev(); } + + u32 getNumChildren() const { return this->getNumLinks(); } + + T* getObject() const { return (T*)this->getObjectPtr(); } + + JSUTree* getParent() const { return (JSUTree*)this->getList(); } +}; + +/** +* @ingroup jsystem-jsupport +* +*/ +template +class JSUTreeIterator { +public: + JSUTreeIterator() : mTree(NULL) {} + JSUTreeIterator(JSUTree* tree) : mTree(tree) {} + + JSUTreeIterator& operator=(JSUTree* tree) { + this->mTree = tree; + return *this; + } + + T* getObject() { return this->mTree->getObject(); } + + bool operator==(JSUTree* other) { return this->mTree == other; } + + bool operator!=(JSUTree* other) { return this->mTree != other; } + + JSUTreeIterator operator++(int) { + JSUTreeIterator prev = *this; + this->mTree = this->mTree->getNextChild(); + return prev; + } + + JSUTreeIterator& operator++() { + this->mTree = this->mTree->getNextChild(); + return *this; + } + + T* operator*() { return this->getObject(); } + + T* operator->() { return this->getObject(); } + +private: + JSUTree* mTree; +}; + +#endif /* JSULIST_H */ diff --git a/include/JSystem/JSupport/JSupport.h b/include/JSystem/JSupport/JSupport.h new file mode 100644 index 00000000..c4a47c61 --- /dev/null +++ b/include/JSystem/JSupport/JSupport.h @@ -0,0 +1,45 @@ +#ifndef JSUPPORT_H +#define JSUPPORT_H + +#include + +/** +* @ingroup jsystem-jsupport +* +*/ +template +T* JSUConvertOffsetToPtr(const void* ptr, u32 offset) { + if (offset == 0) { + return NULL; + } else { + return (T*)((s32)ptr + (s32)offset); + } +} + +/** +* @ingroup jsystem-jsupport +* +*/ +template +T* JSUConvertOffsetToPtr(const void* ptr, const void* offset) { + if (offset == NULL) { + return NULL; + } else { + return (T*)((s32)ptr + (s32)offset); + } +} + +inline u8 JSULoNibble(u8 param_0) { return param_0 & 0x0f; } +inline u8 JSUHiNibble(u8 param_0) {return param_0 >> 4; } + +inline u8 JSULoByte(u16 in) { + return in & 0xff; +} + +inline u8 JSUHiByte(u16 in) { + return in >> 8; +} + +inline u16 JSULoHalf(u32 param_0) {return param_0; } + +#endif diff --git a/include/JSystem/JUtility/JUTAssert.h b/include/JSystem/JUtility/JUTAssert.h new file mode 100644 index 00000000..5d469fb3 --- /dev/null +++ b/include/JSystem/JUtility/JUTAssert.h @@ -0,0 +1,64 @@ +#ifndef JUTASSERT_H +#define JUTASSERT_H + +#include "dolphin/os.h" + +#ifdef DEBUG +#define JUT_ASSERT(LINE, COND) \ + (COND) ? (void)0 : (JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, LINE, #COND), OSPanic(__FILE__, LINE, "Halt")); + +#define JUT_ASSERT_MSG(LINE, COND, MSG) \ + (COND) ? (void)0 : (JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, LINE, MSG), OSPanic(__FILE__, LINE, "Halt")); + +#define JUT_ASSERT_MSG_F(LINE, COND, MSG, ...) \ + (COND) ? (void)0 : (JUTAssertion::showAssert_f(JUTAssertion::getSDevice(), __FILE__, LINE, MSG, __VA_ARGS__), OSPanic(__FILE__, LINE, "Halt")); + +#define J3D_ASSERT(LINE, COND, MSG) JUT_ASSERT_MSG(LINE, (COND) != 0, MSG) + +#define JUT_PANIC(LINE, TEXT) \ + JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, LINE, TEXT); \ + OSPanic(__FILE__, LINE, "Halt"); + +#define JUT_WARN_DEVICE(LINE, DEVICE, ...) \ + JUTAssertion::setWarningMessage_f(DEVICE, __FILE__, LINE, __VA_ARGS__); \ + +#define JUT_WARN(LINE, ...) \ + JUT_WARN_DEVICE(LINE, JUTAssertion::getSDevice(), __VA_ARGS__) + +#define JUT_LOG(LINE, ...) \ + JUTAssertion::setLogMessage_f(JUTAssertion::getSDevice(), __FILE__, LINE, __VA_ARGS__) + +#define JUT_CONFIRM(LINE, COND) \ + JUTAssertion::setConfirmMessage(JUTAssertion::getSDevice(), __FILE__, LINE, COND, #COND) + +#else +#define JUT_ASSERT(...) (void)0; +#define JUT_ASSERT_MSG(...) (void)0; +#define JUT_ASSERT_MSG_F(...) (void)0; +#define J3D_ASSERT(...) (void)0; +#define JUT_PANIC(...) +#define JUT_WARN(...) +#define JUT_WARN_DEVICE(...) +#define JUT_LOG(...) +#define JUT_CONFIRM(...) +#endif + +namespace JUTAssertion { + /* 802E495C */ void create(); + /* 802E4960 */ u32 flush_subroutine(); + /* 802E499C */ void flushMessage(); + /* 802E4A54 */ void flushMessage_dbPrint(); + /* 802E4C34 */ void setVisible(bool); + /* 802E4C3C */ void setMessageCount(int); + + u32 getSDevice(); + void showAssert(u32 device, const char * file, int line, const char * assertion); + void showAssert_f(u32 device, const char* file, int line, const char* msg, ...); + void setWarningMessage_f(u32 device, char * file, int line, const char * fmt, ...); + void setLogMessage_f(u32 device, char* file, int line, const char* fmt, ...); + void setConfirmMessage(u32 param_1, char* file, int line, bool param_4, const char* msg); +}; + +extern bool sAssertVisible; + +#endif /* JUTASSERT_H */ diff --git a/include/JSystem/JUtility/JUTTexture.h b/include/JSystem/JUtility/JUTTexture.h new file mode 100644 index 00000000..606cd581 --- /dev/null +++ b/include/JSystem/JUtility/JUTTexture.h @@ -0,0 +1,113 @@ +#ifndef JUTTEXTURE_H +#define JUTTEXTURE_H + +#include + +class JUTPalette; + +/** +* @ingroup jsystem-jutility +* @brief Image data header. +* +* Acts as the header to image data. Usually texture data immediately follows it, +* so any pointer arithmetic to go past the end of this structure is so that a +* variable sized allocated buffer can be accessed. +* +*/ +struct ResTIMG { + /* 0x00 */ u8 format; + /* 0x01 */ u8 alphaEnabled; + /* 0x02 */ u16 width; + /* 0x04 */ u16 height; + /* 0x06 */ u8 wrapS; + /* 0x07 */ u8 wrapT; + /* 0x08 */ u8 indexTexture; + /* 0x09 */ u8 colorFormat; + /* 0x0A */ u16 numColors; + /* 0x0C */ u32 paletteOffset; + /* 0x10 */ u8 mipmapEnabled; + /* 0x11 */ u8 doEdgeLOD; + /* 0x12 */ u8 biasClamp; + /* 0x13 */ u8 maxAnisotropy; + /* 0x14 */ u8 minFilter; + /* 0x15 */ u8 magFilter; + /* 0x16 */ s8 minLOD; + /* 0x17 */ s8 maxLOD; + /* 0x18 */ u8 mipmapCount; + /* 0x19 */ u8 unknown; + /* 0x1A */ s16 LODBias; + /* 0x1C */ u32 imageOffset; +}; // Size: 0x20 + +/** +* @ingroup jsystem-jutility +* +*/ +class JUTTexture { +public: + JUTTexture() { + setCaptureFlag(false); + mEmbPalette = NULL; + mTexInfo = NULL; + } + + JUTTexture(const ResTIMG* p_timg, u8 param_1) { + mEmbPalette = NULL; + storeTIMG(p_timg, param_1); + setCaptureFlag(false); + } + + ~JUTTexture(); + void storeTIMG(ResTIMG const*, JUTPalette*, _GXTlut); + void storeTIMG(ResTIMG const*, u8); + void storeTIMG(ResTIMG const*, JUTPalette*); + void attachPalette(JUTPalette*); + void init(); + void initTexObj(_GXTlut); + void initTexObj(); + void load(_GXTexMapID); + + const ResTIMG* getTexInfo() const { return mTexInfo; } + s32 getFormat() const { return mTexInfo->format; } + s32 getTransparency() { return mTexInfo->alphaEnabled; } + s32 getWidth() const { return mTexInfo->width; } + s32 getHeight() const { return mTexInfo->height; } + void setCaptureFlag(bool flag) { mFlags &= 2 | flag; } + u8 getCaptureFlag() const { return mFlags & 1; } + u8 getEmbPaletteDelFlag() const { return mFlags & 2; } + void setEmbPaletteDelFlag(bool flag) { mFlags = (mFlags & 1) | (flag << 1);} + u8 getTlutName() const { return mTlutName; } + bool operator==(const JUTTexture& other) { + return mTexInfo == other.mTexInfo + && field_0x2c == other.field_0x2c + && mWrapS == other.mWrapS + && mWrapT == other.mWrapT + && mMinFilter == other.mMinFilter + && mMagFilter == other.mMagFilter + && mMinLOD == other.mMinLOD + && mMinLOD == other.mMinLOD + && mLODBias == other.mLODBias; + } + bool operator!=(const JUTTexture& other) { + return !operator==(other); + } + +private: + /* 0x00 */ GXTexObj mTexObj; + /* 0x20 */ const ResTIMG* mTexInfo; + /* 0x24 */ void* mTexData; + /* 0x28 */ JUTPalette* mEmbPalette; + /* 0x2C */ JUTPalette* field_0x2c; + /* 0x30 */ u8 mWrapS; + /* 0x31 */ u8 mWrapT; + /* 0x32 */ u8 mMinFilter; + /* 0x33 */ u8 mMagFilter; + /* 0x34 */ u16 mMinLOD; + /* 0x36 */ u16 mMaxLOD; + /* 0x38 */ s16 mLODBias; + /* 0x3A */ u8 mTlutName; + /* 0x3B */ u8 mFlags; + /* 0x3C */ void* field_0x3c; +}; + +#endif /* JUTTEXTURE_H */ diff --git a/include/JSystem/TPosition3.h b/include/JSystem/TPosition3.h new file mode 100644 index 00000000..807ce4fe --- /dev/null +++ b/include/JSystem/TPosition3.h @@ -0,0 +1,86 @@ +#ifndef TPOSITION3_H +#define TPOSITION3_H + +#include "dolphin/mtx.h" +#include "JSystem/JMath/JMath.h" +#include "JSystem/JGeometry.h" + +namespace JGeometry { + +template +struct SMatrix34C { + T data[3][4]; +}; + +template <> +struct SMatrix34C { + f32 data[3][4]; + + void identity() { MTXIdentity(data); } + + typedef f32 ArrType[4]; + void set(const ArrType* src) { + JMath::gekko_ps_copy12(data, src); + } + + operator ArrType*() { return data; } + operator const ArrType*() const { return data; } +}; + +template +struct SMatrix33C { + T data[3][3]; + + inline T& ref(int i, int j) { + return data[i][j]; + } + + inline T at(int i, int j) const { + return data[i][j]; + } + + inline void set(T param_1, T param_2, T param_3, T param_4, T param_5, + T param_6, T param_7, T param_8, T param_9) { + ref(0,0) = param_1; + ref(0,1) = param_2; + ref(0,2) = param_3; + ref(1,0) = param_4; + ref(1,1) = param_5; + ref(1,2) = param_6; + ref(2,0) = param_7; + ref(2,1) = param_8; + ref(2,2) = param_9; + } +}; + +template +struct TMatrix34 : public T {}; + +template +struct TRotation3 : public T {}; + +template +struct TRotation3 > : public SMatrix33C { + inline void getEulerXYZ(TVec3* param_1) const { + if (at(2, 0) - TUtil::one() >= -TUtil::epsilon()) { + param_1->set(TUtil::atan2(-at(0, 1), at(1, 1)), -TUtil::halfPI(), 0.0); + } else { + if (at(2, 0) + TUtil::one() <= TUtil::epsilon()) { + param_1->set(TUtil::atan2(at(0, 1), at(1, 1)), TUtil::halfPI(), 0.0); + } else { + param_1->x = TUtil::atan2(at(2, 1), at(2, 2)); + param_1->z = TUtil::atan2(at(1, 0), at(0, 0)); + param_1->y = TUtil::asin(-at(2, 0)); + } + } + } +}; + +template +struct TPosition3 : public T {}; + +typedef TPosition3 > > > TPosition3f32; + +} // namespace JGeometry + +#endif diff --git a/src/JSystem/JParticle/JPABaseShape.cpp b/src/JSystem/JParticle/JPABaseShape.cpp new file mode 100644 index 00000000..d869cd20 --- /dev/null +++ b/src/JSystem/JParticle/JPABaseShape.cpp @@ -0,0 +1,1449 @@ +// +// Generated By: dol2asm +// Translation Unit: JPABaseShape +// + +#include "JSystem/JParticle/JPABaseShape.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "JSystem/JMath/JMATrigonometric.h" +#include "dolphin/mtx.h" +#include "dolphin/gx.h" + +/* 80276A90-80276ACC 2713D0 003C+00 0/0 1/1 0/0 .text JPASetPointSize__FP18JPAEmitterWorkData */ +void JPASetPointSize(JPAEmitterWorkData* work) { + GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE); +} + +/* 80276ACC-80276B08 27140C 003C+00 0/0 1/1 0/0 .text JPASetLineWidth__FP18JPAEmitterWorkData */ +void JPASetLineWidth(JPAEmitterWorkData* work) { + GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE); +} + +/* 80276B08-80276B4C 271448 0044+00 0/0 1/1 0/0 .text + * JPASetPointSize__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE); +} + +/* 80276B4C-80276B90 27148C 0044+00 0/0 1/1 0/0 .text + * JPASetLineWidth__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE); +} + +/* 80276B90-80276C2C 2714D0 009C+00 0/0 1/1 0/0 .text JPARegistPrm__FP18JPAEmitterWorkData */ +void JPARegistPrm(JPAEmitterWorkData* work) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm = emtr->mPrmClr; + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + GXSetTevColor(GX_TEVREG0, prm); +} + +/* 80276C2C-80276CB0 27156C 0084+00 0/0 1/1 0/0 .text JPARegistEnv__FP18JPAEmitterWorkData */ +void JPARegistEnv(JPAEmitterWorkData* work) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor env = emtr->mEnvClr; + env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); + env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); + env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); + GXSetTevColor(GX_TEVREG1, env); +} + +/* 80276CB0-80276DB0 2715F0 0100+00 0/0 1/1 0/0 .text JPARegistPrmEnv__FP18JPAEmitterWorkData */ +void JPARegistPrmEnv(JPAEmitterWorkData* work) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm = emtr->mPrmClr; + GXColor env = emtr->mEnvClr; + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); + env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); + env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); + GXSetTevColor(GX_TEVREG0, prm); + GXSetTevColor(GX_TEVREG1, env); +} + +/* 80276DB0-80276E60 2716F0 00B0+00 0/0 1/1 0/0 .text + * JPARegistAlpha__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm = emtr->mPrmClr; + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm); + GXSetTevColor(GX_TEVREG0, prm); +} + +/* 80276E60-80276F10 2717A0 00B0+00 0/0 1/1 0/0 .text + * JPARegistPrmAlpha__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm = ptcl->mPrmClr; + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm); + GXSetTevColor(GX_TEVREG0, prm); +} + +/* 80276F10-80277024 271850 0114+00 0/0 1/1 0/0 .text + * JPARegistPrmAlphaEnv__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm = ptcl->mPrmClr; + GXColor env = ptcl->mEnvClr; + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm); + env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); + env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); + env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); + GXSetTevColor(GX_TEVREG0, prm); + GXSetTevColor(GX_TEVREG1, env); +} + +/* 80277024-80277138 271964 0114+00 0/0 1/1 0/0 .text + * JPARegistAlphaEnv__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm = emtr->mPrmClr; + GXColor env = ptcl->mEnvClr; + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm); + env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); + env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); + env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); + GXSetTevColor(GX_TEVREG0, prm); + GXSetTevColor(GX_TEVREG1, env); +} + +/* 80277138-802771BC 271A78 0084+00 0/0 1/1 0/0 .text + * JPARegistEnv__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPABaseEmitter* emtr = work->mpEmtr; + GXColor env = ptcl->mEnvClr; + env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); + env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); + env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); + GXSetTevColor(GX_TEVREG1, env); +} + +/* 802771BC-802771E8 271AFC 002C+00 0/0 1/1 0/0 .text JPACalcClrIdxNormal__FP18JPAEmitterWorkData + */ +void JPACalcClrIdxNormal(JPAEmitterWorkData* work) { + JPABaseShape* bsp = work->mpRes->getBsp(); + s16 keyFrame; + if (work->mpEmtr->mTick < bsp->getClrAnmMaxFrm()) { + keyFrame = work->mpEmtr->mTick; + } else { + keyFrame = bsp->getClrAnmMaxFrm(); + } + work->mClrKeyFrame = keyFrame; +} + +/* 802771E8-80277210 271B28 0028+00 0/0 1/1 0/0 .text + * JPACalcClrIdxNormal__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcClrIdxNormal(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s16 age = param_1->mAge; + s16 maxFrm = shape->getClrAnmMaxFrm(); + s16 keyFrame; + if (age < maxFrm) { + keyFrame = age; + } else { + keyFrame = maxFrm; + } + work->mClrKeyFrame = keyFrame; +} + +/* 80277210-80277240 271B50 0030+00 0/0 1/1 0/0 .text JPACalcClrIdxRepeat__FP18JPAEmitterWorkData + */ +void JPACalcClrIdxRepeat(JPAEmitterWorkData* work) { + JPABaseShape* shape = work->mpRes->getBsp(); + work->mClrKeyFrame = work->mpEmtr->mTick % (shape->getClrAnmMaxFrm() + 1); +} + +/* 80277240-8027727C 271B80 003C+00 0/0 1/1 0/0 .text + * JPACalcClrIdxRepeat__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcClrIdxRepeat(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s32 tick = shape->getClrLoopOfst(param_1->mAnmRandom); + tick = param_1->mAge + tick; + work->mClrKeyFrame = tick % (shape->getClrAnmMaxFrm() + 1); +} + +/* 8027727C-802772BC 271BBC 0040+00 0/0 1/1 0/0 .text JPACalcClrIdxReverse__FP18JPAEmitterWorkData + */ +void JPACalcClrIdxReverse(JPAEmitterWorkData* work) { + JPABaseShape* shape = work->mpRes->getBsp(); + int maxFrm = shape->getClrAnmMaxFrm(); + u32 tick = work->mpEmtr->mTick; + u32 uVar1 = tick / maxFrm; + tick = tick % maxFrm; + uVar1 &= 1; + work->mClrKeyFrame = tick + (uVar1) * (maxFrm - tick * 2); +} + +/* 802772BC-80277308 271BFC 004C+00 0/0 1/1 0/0 .text + * JPACalcClrIdxReverse__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcClrIdxReverse(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s32 tick = param_1->mAge + shape->getClrLoopOfst(param_1->mAnmRandom); + s32 maxFrm = shape->getClrAnmMaxFrm(); + s32 rem = tick % maxFrm; + work->mClrKeyFrame = rem + ((tick / maxFrm) & 1) * (maxFrm - rem * 2); +} + +/* 80277308-80277314 271C48 000C+00 0/0 1/1 0/0 .text JPACalcClrIdxMerge__FP18JPAEmitterWorkData + */ +void JPACalcClrIdxMerge(JPAEmitterWorkData* work) { + work->mClrKeyFrame = 0; +} + +/* 80277314-80277384 271C54 0070+00 0/0 1/1 0/0 .text + * JPACalcClrIdxMerge__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcClrIdxMerge(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s32 maxFrm = shape->getClrAnmMaxFrm() + 1; + s32 tick = (s32)(param_1->mTime * maxFrm) + shape->getClrLoopOfst(param_1->mAnmRandom); + work->mClrKeyFrame = tick % maxFrm; +} + +/* 80277384-80277390 271CC4 000C+00 0/0 1/1 0/0 .text JPACalcClrIdxRandom__FP18JPAEmitterWorkData + */ +void JPACalcClrIdxRandom(JPAEmitterWorkData* work) { + work->mClrKeyFrame = 0; +} + +/* 80277390-802773C4 271CD0 0034+00 0/0 1/1 0/0 .text + * JPACalcClrIdxRandom__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcClrIdxRandom(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s32 tick = shape->getClrLoopOfst(param_1->mAnmRandom); + s32 maxFrm = shape->getClrAnmMaxFrm() + 1; + work->mClrKeyFrame = tick % maxFrm; +} + +/* 802773C4-80277404 271D04 0040+00 0/0 1/1 0/0 .text JPACalcPrm__FP18JPAEmitterWorkData + */ +void JPACalcPrm(JPAEmitterWorkData* work) { + work->mpRes->getBsp()->getPrmClr(work->mClrKeyFrame, &work->mpEmtr->mPrmClr); +} + +/* 80277404-80277440 271D44 003C+00 0/0 1/1 0/0 .text + * JPACalcPrm__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcPrm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + work->mpRes->getBsp()->getPrmClr(work->mClrKeyFrame, &ptcl->mPrmClr); +} + +/* 80277440-80277480 271D80 0040+00 0/0 1/1 0/0 .text JPACalcEnv__FP18JPAEmitterWorkData + */ +void JPACalcEnv(JPAEmitterWorkData* work) { + work->mpRes->getBsp()->getEnvClr(work->mClrKeyFrame, &work->mpEmtr->mEnvClr); +} + +/* 80277480-802774BC 271DC0 003C+00 0/0 1/1 0/0 .text + * JPACalcEnv__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + work->mpRes->getBsp()->getEnvClr(work->mClrKeyFrame, &ptcl->mEnvClr); +} + +/* 802774BC-80277504 271DFC 0048+00 0/0 1/1 0/0 .text + * JPACalcColorCopy__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcColorCopy(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPABaseEmitter* emtr = work->mpEmtr; + ptcl->mPrmClr = emtr->mPrmClr; + ptcl->mEnvClr = emtr->mEnvClr; +} + +/* 80277504-8027753C 271E44 0038+00 0/0 1/1 0/0 .text JPAGenTexCrdMtxIdt__FP18JPAEmitterWorkData + */ +void JPAGenTexCrdMtxIdt(JPAEmitterWorkData* param_0) { + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); +} + +/* 8027753C-80277574 271E7C 0038+00 0/0 1/1 0/0 .text JPAGenTexCrdMtxAnm__FP18JPAEmitterWorkData + */ +void JPAGenTexCrdMtxAnm(JPAEmitterWorkData* param_0) { + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0, GX_FALSE, GX_PTIDENTITY); +} + +/* 80277574-802775AC 271EB4 0038+00 0/0 1/1 0/0 .text JPAGenTexCrdMtxPrj__FP18JPAEmitterWorkData + */ +void JPAGenTexCrdMtxPrj(JPAEmitterWorkData* param_0) { + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0, GX_FALSE, GX_PTIDENTITY); +} + +/* 802775AC-80277758 271EEC 01AC+00 0/0 1/1 0/0 .text + * JPAGenCalcTexCrdMtxAnm__FP18JPAEmitterWorkData */ +void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData* work) { + JPABaseShape* shape = work->mpRes->getBsp(); + f32 dVar16 = work->mpEmtr->mTick; + f32 dVar15 = 0.5f * (1.0f + shape->getTilingS()); + f32 dVar14 = 0.5f * (1.0f + shape->getTilingT()); + f32 dVar11 = (dVar16 * shape->getIncTransX()) + shape->getInitTransX(); + f32 dVar10 = (dVar16 * shape->getIncTransY()) + shape->getInitTransY(); + f32 dVar13 = (dVar16 * shape->getIncScaleX()) + shape->getInitScaleX(); + f32 dVar12 = (dVar16 * shape->getIncScaleY()) + shape->getInitScaleY(); + s32 local_c0 = (dVar16 * shape->getIncRot()) + shape->getInitRot(); + f32 dVar8 = JMASSin(local_c0); + f32 dVar9 = JMASCos(local_c0); + Mtx local_108; + local_108[0][0] = dVar13 * dVar9; + local_108[0][1] = -dVar13 * dVar8; + local_108[0][2] = 0.0f; + local_108[0][3] = + (dVar15 + (dVar13 * ((dVar8 * (dVar14 + dVar10)) - (dVar9 * (dVar15 + dVar11))))); + local_108[1][0] = dVar12 * dVar8; + local_108[1][1] = dVar12 * dVar9; + local_108[1][2] = 0.0f; + local_108[1][3] = + (dVar14 + (-dVar12 * ((dVar8 * (dVar15 + dVar11)) + (dVar9 * (dVar14 + dVar10))))); + local_108[2][0] = 0.0f; + local_108[2][1] = 0.0f; + local_108[2][2] = 1.0f; + local_108[2][3] = 0.0f; + GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x1e, false, 0x7d); +} + +/* 80277758-802778EC 272098 0194+00 0/0 1/1 0/0 .text + * JPALoadCalcTexCrdMtxAnm__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + f32 dVar16 = param_1->mAge; + f32 dVar15 = 0.5f * (1.0f + shape->getTilingS()); + f32 dVar14 = 0.5f * (1.0f + shape->getTilingT()); + f32 dVar11 = (dVar16 * shape->getIncTransX()) + shape->getInitTransX(); + f32 dVar10 = (dVar16 * shape->getIncTransY()) + shape->getInitTransY(); + f32 dVar13 = (dVar16 * shape->getIncScaleX()) + shape->getInitScaleX(); + f32 dVar12 = (dVar16 * shape->getIncScaleY()) + shape->getInitScaleY(); + s32 local_c0 = (dVar16 * shape->getIncRot()) + shape->getInitRot(); + f32 dVar8 = JMASSin(local_c0); + f32 dVar9 = JMASCos(local_c0); + Mtx local_108; + local_108[0][0] = dVar13 * dVar9; + local_108[0][1] = -dVar13 * dVar8; + local_108[0][2] = 0.0f; + local_108[0][3] = + (dVar15 + (dVar13 * ((dVar8 * (dVar14 + dVar10)) - (dVar9 * (dVar15 + dVar11))))); + local_108[1][0] = dVar12 * dVar8; + local_108[1][1] = dVar12 * dVar9; + local_108[1][2] = 0.0f; + local_108[1][3] = + (dVar14 + (-dVar12 * ((dVar8 * (dVar15 + dVar11)) + (dVar9 * (dVar14 + dVar10))))); + local_108[2][0] = 0.0f; + local_108[2][1] = 0.0f; + local_108[2][2] = 1.0f; + local_108[2][3] = 0.0f; + GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4); +} + +/* 802778EC-80277940 27222C 0054+00 0/0 1/1 0/0 .text JPALoadTex__FP18JPAEmitterWorkData + */ +void JPALoadTex(JPAEmitterWorkData* work) { + work->mpResMgr->load(work->mpRes->getTexIdx(work->mpRes->getBsp()->getTexIdx()), GX_TEXMAP0); +} + +/* 80277940-80277990 272280 0050+00 0/0 1/1 0/0 .text JPALoadTexAnm__FP18JPAEmitterWorkData */ +void JPALoadTexAnm(JPAEmitterWorkData* work) { + work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0); +} + +/* 80277990-802779DC 2722D0 004C+00 0/0 1/1 0/0 .text + * JPALoadTexAnm__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0); +} + +/* 802779DC-80277A18 27231C 003C+00 0/0 1/1 0/0 .text JPACalcTexIdxNormal__FP18JPAEmitterWorkData + */ +void JPACalcTexIdxNormal(JPAEmitterWorkData* work) { + JPABaseShape* shape = work->mpRes->getBsp(); + u8 tick = shape->getTexAnmKeyNum() - 1 < work->mpEmtr->mTick + ? shape->getTexAnmKeyNum() - 1 : work->mpEmtr->mTick; + work->mpEmtr->mTexAnmIdx = shape->getTexIdx(tick); +} + +/* 80277A18-80277A50 272358 0038+00 0/0 1/1 0/0 .text + * JPACalcTexIdxNormal__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcTexIdxNormal(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + u8 tick = shape->getTexAnmKeyNum() - 1 < param_1->mAge + ? shape->getTexAnmKeyNum() - 1 : param_1->mAge; + param_1->mTexAnmIdx = shape->getTexIdx(tick); +} + +/* 80277A50-80277A88 272390 0038+00 0/0 1/1 0/0 .text JPACalcTexIdxRepeat__FP18JPAEmitterWorkData + */ +void JPACalcTexIdxRepeat(JPAEmitterWorkData* work) { + JPABaseShape* shape = work->mpRes->getBsp(); + work->mpEmtr->mTexAnmIdx = shape->getTexIdx(work->mpEmtr->mTick % shape->getTexAnmKeyNum()); +} + +/* 80277A88-80277ACC 2723C8 0044+00 0/0 1/1 0/0 .text + * JPACalcTexIdxRepeat__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcTexIdxRepeat(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + param_1->mTexAnmIdx = shape->getTexIdx( + ((int)shape->getTexLoopOfst(param_1->mAnmRandom) + param_1->mAge) + % shape->getTexAnmKeyNum()); +} + +/* 80277ACC-80277B1C 27240C 0050+00 0/0 1/1 0/0 .text JPACalcTexIdxReverse__FP18JPAEmitterWorkData + */ +void JPACalcTexIdxReverse(JPAEmitterWorkData* work) { + JPABaseShape* shape = work->mpRes->getBsp(); + int tick = work->mpEmtr->mTick; + int keyNum = (int)shape->getTexAnmKeyNum() - 1; + int div = tick / keyNum; + int rem = tick % keyNum; + work->mpEmtr->mTexAnmIdx = shape->getTexIdx(rem + (div & 1) * (keyNum - rem * 2)); +} + +/* 80277B1C-80277B78 27245C 005C+00 0/0 1/1 0/0 .text + * JPACalcTexIdxReverse__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcTexIdxReverse(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s32 tick = shape->getTexLoopOfst(param_1->mAnmRandom) + param_1->mAge; + int keyNum = (int)shape->getTexAnmKeyNum() - 1; + int div = tick / keyNum; + int rem = tick % keyNum; + param_1->mTexAnmIdx = shape->getTexIdx(rem + (div & 1) * (keyNum - rem * 2)); +} + +/* 80277B78-80277B94 2724B8 001C+00 0/0 1/1 0/0 .text JPACalcTexIdxMerge__FP18JPAEmitterWorkData + */ +void JPACalcTexIdxMerge(JPAEmitterWorkData* work) { + work->mpEmtr->mTexAnmIdx = work->mpRes->getBsp()->getTexIdx(); +} + +/* 80277B94-80277C0C 2724D4 0078+00 0/0 1/1 0/0 .text + * JPACalcTexIdxMerge__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcTexIdxMerge(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + s32 maxFrm = shape->getTexAnmKeyNum(); + s32 tick = (s32)(maxFrm * param_1->mTime) + shape->getTexLoopOfst(param_1->mAnmRandom); + param_1->mTexAnmIdx = shape->getTexIdx(tick % maxFrm); +} + +/* 80277C0C-80277C28 27254C 001C+00 0/0 1/1 0/0 .text JPACalcTexIdxRandom__FP18JPAEmitterWorkData + */ +void JPACalcTexIdxRandom(JPAEmitterWorkData* work) { + work->mpEmtr->mTexAnmIdx = work->mpRes->getBsp()->getTexIdx(); +} + +/* 80277C28-80277C64 272568 003C+00 0/0 1/1 0/0 .text + * JPACalcTexIdxRandom__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcTexIdxRandom(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + JPABaseShape* shape = work->mpRes->getBsp(); + param_1->mTexAnmIdx = shape->getTexIdx(((int)shape->getTexLoopOfst(param_1->mAnmRandom)) + % shape->getTexAnmKeyNum()); +} + +/* 80277C64-80277C8C 2725A4 0028+00 0/0 1/1 0/0 .text JPALoadPosMtxCam__FP18JPAEmitterWorkData */ +void JPALoadPosMtxCam(JPAEmitterWorkData* work) { + GXLoadPosMtxImm(work->mPosCamMtx, GX_PNMTX0); +} + +/* 80277C8C-80277C90 2725CC 0004+00 1/0 0/0 0/0 .text noLoadPrj__FPC18JPAEmitterWorkDataPA4_Cf */ +static void noLoadPrj(JPAEmitterWorkData const* work, const Mtx srt) { + /* empty function */ +} + +/* 80277C90-80277CC8 2725D0 0038+00 1/0 0/0 0/0 .text loadPrj__FPC18JPAEmitterWorkDataPA4_Cf */ +void loadPrj(JPAEmitterWorkData const* work, const Mtx srt) { + Mtx mtx; + MTXConcat(work->mPrjMtx, srt, mtx); + GXLoadTexMtxImm(mtx, GX_TEXMTX0, GX_MTX3x4); +} + +/* 80277CC8-80277E88 272608 01C0+00 1/0 0/0 0/0 .text loadPrjAnm__FPC18JPAEmitterWorkDataPA4_Cf */ +static void loadPrjAnm(JPAEmitterWorkData const* work, const Mtx srt) { + JPABaseShape* shape = work->mpRes->getBsp(); + f32 dVar16 = work->mpEmtr->getAge(); + f32 dVar15 = 0.5f * (1.0f + shape->getTilingS()); + f32 dVar14 = 0.5f * (1.0f + shape->getTilingT()); + f32 dVar11 = (dVar16 * shape->getIncTransX()) + shape->getInitTransX(); + f32 dVar10 = (dVar16 * shape->getIncTransY()) + shape->getInitTransY(); + f32 dVar13 = (dVar16 * shape->getIncScaleX()) + shape->getInitScaleX(); + f32 dVar12 = (dVar16 * shape->getIncScaleY()) + shape->getInitScaleY(); + s32 local_c0 = (dVar16 * shape->getIncRot()) + shape->getInitRot(); + f32 dVar8 = JMASSin(local_c0); + f32 dVar9 = JMASCos(local_c0); + Mtx local_108; + local_108[0][0] = dVar13 * dVar9; + local_108[0][1] = -dVar13 * dVar8; + local_108[0][2] = + (dVar15 + (dVar13 * ((dVar8 * (dVar14 + dVar10)) - (dVar9 * (dVar15 + dVar11))))); + local_108[0][3] = 0.0f; + local_108[1][0] = dVar12 * dVar8; + local_108[1][1] = dVar12 * dVar9; + local_108[1][2] = + (dVar14 + (-dVar12 * ((dVar8 * (dVar15 + dVar11)) + (dVar9 * (dVar14 + dVar10))))); + local_108[1][3] = 0.0f; + local_108[2][0] = 0.0f; + local_108[2][1] = 0.0f; + local_108[2][2] = 1.0f; + local_108[2][3] = 0.0f; + MTXConcat(local_108, work->mPrjMtx, local_108); + MTXConcat(local_108, srt, local_108); + GXLoadTexMtxImm(local_108, 0x1e, GX_MTX3x4); +} + +/* 803C42E0-803C4300 021400 0020+00 10/9 0/0 0/0 .data jpa_dl */ +static u8 jpa_dl[32] = { + 0x80, 0x00, 0x04, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* 803C4300-803C4320 021420 0020+00 1/0 0/0 0/0 .data jpa_dl_x */ +static u8 jpa_dl_x[32] = { + 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x48, 0x00, 0x49, 0x01, 0x4A, + 0x02, 0x4B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +typedef void (*projectionFunc)(JPAEmitterWorkData const*, const Mtx); + +/* 803C4320-803C432C -00001 000C+00 6/10 0/0 0/0 .data p_prj */ +static projectionFunc p_prj[3] = { + noLoadPrj, + loadPrj, + loadPrjAnm, +}; + +/* 80277E88-80277F70 2727C8 00E8+00 0/0 1/1 0/0 .text + * JPADrawBillboard__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_48; + MTXMultVec(work->mPosCamMtx, param_1->mPosition, local_48); + Mtx local_38; + local_38[0][0] = work->mGlobalPtclScl.x * param_1->mParticleScaleX; + local_38[0][3] = local_48.x; + local_38[1][1] = work->mGlobalPtclScl.y * param_1->mParticleScaleY; + local_38[1][3] = local_48.y; + local_38[2][2] = 1.0f; + local_38[2][3] = local_48.z; + local_38[2][1] = 0.0f; + local_38[2][0] = 0.0f; + local_38[1][2] = 0.0f; + local_38[1][0] = 0.0f; + local_38[0][2] = 0.0f; + local_38[0][1] = 0.0f; + GXLoadPosMtxImm(local_38, 0); + p_prj[work->mPrjType](work, local_38); + GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); + } +} + +/* 80277F70-80278088 2728B0 0118+00 0/0 1/1 0/0 .text + * JPADrawRotBillboard__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_48; + MTXMultVec(work->mPosCamMtx, param_1->mPosition, local_48); + f32 sinRot = JMASSin(param_1->mRotateAngle); + f32 cosRot = JMASCos(param_1->mRotateAngle); + f32 particleX = work->mGlobalPtclScl.x * param_1->mParticleScaleX; + f32 particleY = work->mGlobalPtclScl.y * param_1->mParticleScaleY; + + Mtx local_38; + local_38[0][0] = cosRot * particleX; + local_38[0][1] = -sinRot * particleY; + local_38[0][3] = local_48.x; + local_38[1][0] = sinRot * particleX; + local_38[1][1] = cosRot * particleY; + local_38[1][3] = local_48.y; + local_38[2][2] = 1.0f; + local_38[2][3] = local_48.z; + local_38[2][1] = 0.0f; + local_38[2][0] = 0.0f; + local_38[1][2] = 0.0f; + local_38[0][2] = 0.0f; + GXLoadPosMtxImm(local_38, 0); + p_prj[work->mPrjType](work, local_38); + GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); + } +} + +/* 80278088-80278184 2729C8 00FC+00 0/0 1/1 0/0 .text + * JPADrawYBillboard__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_48; + MTXMultVec(work->mPosCamMtx, param_1->mPosition, local_48); + Mtx local_38; + f32 particleY = work->mGlobalPtclScl.y * param_1->mParticleScaleY; + local_38[0][0] = work->mGlobalPtclScl.x * param_1->mParticleScaleX; + local_38[0][3] = local_48.x; + local_38[1][1] = work->mYBBCamMtx[1][1] * particleY; + local_38[1][2] = work->mYBBCamMtx[1][2]; + local_38[1][3] = local_48.y; + local_38[2][1] = work->mYBBCamMtx[2][1] * particleY; + local_38[2][2] = work->mYBBCamMtx[2][2]; + local_38[2][3] = local_48.z; + local_38[2][0] = 0.0f; + local_38[1][0] = 0.0f; + local_38[0][2] = 0.0f; + local_38[0][1] = 0.0f; + GXLoadPosMtxImm(local_38, 0); + p_prj[work->mPrjType](work, local_38); + GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); + } +} + +/* 80278184-802782B4 272AC4 0130+00 0/0 1/1 0/0 .text + * JPADrawRotYBillboard__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_48; + MTXMultVec(work->mPosCamMtx, param_1->mPosition, local_48); + f32 sinRot = JMASSin(param_1->mRotateAngle); + f32 cosRot = JMASCos(param_1->mRotateAngle); + Mtx local_38; + f32 particleX = work->mGlobalPtclScl.x * param_1->mParticleScaleX; + f32 particleY = work->mGlobalPtclScl.y * param_1->mParticleScaleY; + f32 local_98 = (float)(sinRot * particleX); + f32 local_94 = (float)(cosRot * particleY); + f32 local_90 = work->mYBBCamMtx[1][1]; + f32 fVar1 = work->mYBBCamMtx[2][1]; + local_38[0][0] = (float)(cosRot * particleX); + local_38[0][1] = (float)(-sinRot * particleY); + local_38[0][2] = 0.0f; + local_38[0][3] = local_48.x; + local_38[1][0] = local_98 * local_90; + local_38[1][1] = local_94 * local_90; + local_38[1][2] = -fVar1; + local_38[1][3] = local_48.y; + local_38[2][0] = local_98 * fVar1; + local_38[2][1] = local_94 * fVar1; + local_38[2][2] = local_90; + local_38[2][3] = local_48.z; + GXLoadPosMtxImm(local_38, 0); + p_prj[work->mPrjType](work, local_38); + GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); + } +} + +/* 802782B4-802782D0 272BF4 001C+00 1/0 0/0 0/0 .text + * dirTypeVel__FPC18JPAEmitterWorkDataPC15JPABaseParticlePQ29JGeometry8TVec3 */ +void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1, + JGeometry::TVec3* param_2) { + param_1->getVelVec(*param_2); +} + +/* 802782D0-802782EC 272C10 001C+00 1/0 0/0 0/0 .text + * dirTypePos__FPC18JPAEmitterWorkDataPC15JPABaseParticlePQ29JGeometry8TVec3 */ +void dirTypePos(JPAEmitterWorkData const* work, JPABaseParticle const* param_1, + JGeometry::TVec3* param_2) { + param_1->getLocalPosition(*param_2); +} + +/* 802782EC-80278320 272C2C 0034+00 1/0 0/0 0/0 .text + * dirTypePosInv__FPC18JPAEmitterWorkDataPC15JPABaseParticlePQ29JGeometry8TVec3 */ +void dirTypePosInv(JPAEmitterWorkData const* work, JPABaseParticle const* param_1, + JGeometry::TVec3* param_2) { + param_1->getLocalPosition(*param_2); + param_2->negate(); +} + +/* 80278320-8027833C 272C60 001C+00 1/0 0/0 0/0 .text + * dirTypeEmtrDir__FPC18JPAEmitterWorkDataPC15JPABaseParticlePQ29JGeometry8TVec3 */ +void dirTypeEmtrDir(JPAEmitterWorkData const* work, JPABaseParticle const* param_1, + JGeometry::TVec3* param_2) { + param_2->set(work->mGlobalEmtrDir); +} + +/* 8027833C-802783D4 272C7C 0098+00 1/0 0/0 0/0 .text + * dirTypePrevPtcl__FPC18JPAEmitterWorkDataPC15JPABaseParticlePQ29JGeometry8TVec3 */ +void dirTypePrevPtcl(JPAEmitterWorkData const* work, JPABaseParticle const* param_1, + JGeometry::TVec3* param_2) { + JGeometry::TVec3 aTStack_24; + param_1->getGlobalPosition(aTStack_24); + JPANode* end = work->mpAlivePtcl->getEnd(); + JPANode* prev = work->mpCurNode->getPrev(); + + if (end != prev) { + JPABaseParticle* particle = work->mpCurNode->getPrev()->getObject(); + particle->getGlobalPosition(*param_2); + } else { + work->mpEmtr->calcEmitterGlobalPosition(param_2); + } + param_2->sub(aTStack_24); +} + +/* 802783D4-80278414 272D14 0040+00 1/0 0/0 0/0 .text rotTypeY__FffRA3_A4_f */ +static void rotTypeY(f32 param_0, f32 param_1, Mtx& param_2) { + param_2[0][0] = param_1; + param_2[0][1] = 0.0f; + param_2[0][2] = -param_0; + param_2[0][3] = 0.0f; + param_2[1][0] = 0.0f; + param_2[1][1] = 1.0f; + param_2[1][2] = 0.0f; + param_2[1][3] = 0.0f; + param_2[2][0] = param_0; + param_2[2][1] = 0.0f; + param_2[2][2] = param_1; + param_2[2][3] = 0.0f; +} + +/* 80278414-80278454 272D54 0040+00 1/0 0/0 0/0 .text rotTypeX__FffRA3_A4_f */ +static void rotTypeX(f32 param_0, f32 param_1, Mtx& param_2) { + param_2[0][0] = 1.0f; + param_2[0][1] = 0.0f; + param_2[0][2] = 0.0f; + param_2[0][3] = 0.0f; + param_2[1][0] = 0.0f; + param_2[1][1] = param_1; + param_2[1][2] = -param_0; + param_2[1][3] = 0.0f; + param_2[2][0] = 0.0f; + param_2[2][1] = param_0; + param_2[2][2] = param_1; + param_2[2][3] = 0.0f; +} + +/* 80278454-80278494 272D94 0040+00 1/0 0/0 0/0 .text rotTypeZ__FffRA3_A4_f */ +static void rotTypeZ(f32 param_0, f32 param_1, Mtx& param_2) { + param_2[0][0] = param_1; + param_2[0][1] = -param_0; + param_2[0][2] = 0.0f; + param_2[0][3] = 0.0f; + param_2[1][0] = param_0; + param_2[1][1] = param_1; + param_2[1][2] = 0.0f; + param_2[1][3] = 0.0f; + param_2[2][0] = 0.0f; + param_2[2][1] = 0.0f; + param_2[2][2] = 1.0f; + param_2[2][3] = 0.0f; +} + +/* 80278494-802784F0 272DD4 005C+00 1/0 0/0 0/0 .text rotTypeXYZ__FffRA3_A4_f */ +static void rotTypeXYZ(f32 param_0, f32 param_1, Mtx& param_2) { + f32 f3 = 0.33333298563957214f * (1.0f - param_1); + f32 fVar1; + f32 f4; + f4 = f3 + 0.5773500204086304f * param_0; + fVar1 = f3 - 0.5773500204086304f * param_0; + f3 += param_1; + param_2[0][0] = f3; + param_2[0][1] = fVar1; + param_2[0][2] = f4; + param_2[0][3] = 0.0f; + param_2[1][0] = f4; + param_2[1][1] = f3; + param_2[1][2] = fVar1; + param_2[1][3] = 0.0f; + param_2[2][0] = fVar1; + param_2[2][1] = f4; + param_2[2][2] = f3; + param_2[2][3] = 0.0f; +} + +/* 802784F0-8027853C 272E30 004C+00 1/0 0/0 0/0 .text basePlaneTypeXY__FPA4_fff */ +static void basePlaneTypeXY(MtxP param_0, f32 param_1, f32 param_2) { + param_0[0][0] *= param_1; + param_0[1][0] *= param_1; + param_0[2][0] *= param_1; + param_0[0][1] *= param_2; + param_0[1][1] *= param_2; + param_0[2][1] *= param_2; +} + +/* 8027853C-80278588 272E7C 004C+00 1/0 0/0 0/0 .text basePlaneTypeXZ__FPA4_fff */ +static void basePlaneTypeXZ(MtxP param_0, f32 param_1, f32 param_2) { + param_0[0][0] *= param_1; + param_0[1][0] *= param_1; + param_0[2][0] *= param_1; + param_0[0][2] *= param_2; + param_0[1][2] *= param_2; + param_0[2][2] *= param_2; +} + +/* 80278588-802785F8 272EC8 0070+00 1/0 0/0 0/0 .text basePlaneTypeX__FPA4_fff */ +static void basePlaneTypeX(MtxP param_0, f32 param_1, f32 param_2) { + param_0[0][0] *= param_1; + param_0[1][0] *= param_1; + param_0[2][0] *= param_1; + param_0[0][1] *= param_2; + param_0[1][1] *= param_2; + param_0[2][1] *= param_2; + param_0[0][2] *= param_1; + param_0[1][2] *= param_1; + param_0[2][2] *= param_1; +} + +/* 803C432C-803C4340 -00001 0014+00 2/5 0/0 0/0 .data p_direction */ +typedef void (*dirTypeFunc)(JPAEmitterWorkData const*, JPABaseParticle const*, + JGeometry::TVec3*); +static dirTypeFunc p_direction[5] = { + dirTypeVel, dirTypePos, dirTypePosInv, + dirTypeEmtrDir, dirTypePrevPtcl, +}; + +/* 803C4340-803C4354 -00001 0014+00 0/2 0/0 0/0 .data p_rot */ +typedef void (*rotTypeFunc)(f32, f32, Mtx&); +#pragma push +#pragma force_active on +static rotTypeFunc p_rot[5] = { + rotTypeY, rotTypeX, rotTypeZ, + rotTypeXYZ, rotTypeY, +}; +#pragma pop + +/* 803C4354-803C4360 -00001 000C+00 0/3 0/0 0/0 .data p_plane */ + +typedef void (*planeFunc)(MtxP, f32, f32); + +static planeFunc p_plane[3] = { + basePlaneTypeXY, + basePlaneTypeXZ, + basePlaneTypeX, +}; + +/* 804507A0-804507A8 -00001 0008+00 3/3 0/0 0/0 .sdata p_dl */ +static u8* p_dl[2] = { + jpa_dl, + jpa_dl_x, +}; + +/* 802785F8-80278994 272F38 039C+00 0/0 1/1 0/0 .text + * JPADrawDirection__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawDirection(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_6c; + JGeometry::TVec3 local_78; + p_direction[param_0->mDirType](param_0, param_1, &local_6c); + if (!local_6c.isZero()) { + local_6c.normalize(); + local_78.cross(param_1->mBaseAxis, local_6c); + if (!local_78.isZero()) { + local_78.normalize(); + param_1->mBaseAxis.cross(local_6c, local_78); + param_1->mBaseAxis.normalize(); + Mtx local_60; + f32 fVar1 = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX; + f32 fVar2 = param_0->mGlobalPtclScl.y * param_1->mParticleScaleY; + local_60[0][0] = param_1->mBaseAxis.x; + local_60[0][1] = local_6c.x; + local_60[0][2] = local_78.x; + local_60[0][3] = param_1->mPosition.x; + local_60[1][0] = param_1->mBaseAxis.y; + local_60[1][1] = local_6c.y; + local_60[1][2] = local_78.y; + local_60[1][3] = param_1->mPosition.y; + local_60[2][0] = param_1->mBaseAxis.z; + local_60[2][1] = local_6c.z; + local_60[2][2] = local_78.z; + local_60[2][3] = param_1->mPosition.z; + p_plane[param_0->mPlaneType](local_60, fVar1, fVar2); + MTXConcat(param_0->mPosCamMtx, local_60, local_60); + GXLoadPosMtxImm(local_60, 0); + p_prj[param_0->mPrjType](param_0, local_60); + GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl)); + } + } + } +} + +/* 80278994-80278DA8 2732D4 0414+00 0/0 1/1 0/0 .text + * JPADrawRotDirection__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawRotDirection(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + f32 sinRot = JMASSin(param_1->mRotateAngle); + f32 cosRot = JMASCos(param_1->mRotateAngle); + JGeometry::TVec3 local_6c; + JGeometry::TVec3 local_78; + p_direction[param_0->mDirType](param_0, param_1, &local_6c); + if (!local_6c.isZero()) { + local_6c.normalize(); + local_78.cross(param_1->mBaseAxis, local_6c); + if (!local_78.isZero()) { + local_78.normalize(); + param_1->mBaseAxis.cross(local_6c, local_78); + param_1->mBaseAxis.normalize(); + f32 particleX = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX; + f32 particleY = param_0->mGlobalPtclScl.y * param_1->mParticleScaleY; + Mtx auStack_80; + Mtx local_60; + p_rot[param_0->mRotType](sinRot, cosRot, auStack_80); + p_plane[param_0->mPlaneType](auStack_80, particleX, particleY); + local_60[0][0] = param_1->mBaseAxis.x; + local_60[0][1] = local_6c.x; + local_60[0][2] = local_78.x; + local_60[0][3] = param_1->mPosition.x; + local_60[1][0] = param_1->mBaseAxis.y; + local_60[1][1] = local_6c.y; + local_60[1][2] = local_78.y; + local_60[1][3] = param_1->mPosition.y; + local_60[2][0] = param_1->mBaseAxis.z; + local_60[2][1] = local_6c.z; + local_60[2][2] = local_78.z; + local_60[2][3] = param_1->mPosition.z; + MTXConcat(local_60, auStack_80, auStack_80); + MTXConcat(param_0->mPosCamMtx, auStack_80, local_60); + GXLoadPosMtxImm(local_60, 0); + p_prj[param_0->mPrjType](param_0, local_60); + GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl)); + } + } + } +} + +/* 80278DA8-80278FC8 2736E8 0220+00 0/0 1/1 0/0 .text + * JPADrawDBillboard__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_70; + p_direction[param_0->mDirType](param_0, param_1, &local_70); + JGeometry::TVec3 aTStack_7c; + aTStack_7c.set(param_0->mPosCamMtx[2][0], param_0->mPosCamMtx[2][1], + param_0->mPosCamMtx[2][2]); + local_70.cross(local_70, aTStack_7c); + if (!local_70.isZero()) { + local_70.normalize(); + MTXMultVecSR(param_0->mPosCamMtx, local_70, local_70); + JGeometry::TVec3 local_88; + MTXMultVec(param_0->mPosCamMtx, param_1->mPosition, local_88); + f32 particleX = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX; + f32 particleY = param_0->mGlobalPtclScl.y * param_1->mParticleScaleY; + Mtx local_60; + local_60[0][0] = local_70.x * particleX; + local_60[0][1] = -local_70.y * particleY; + local_60[0][3] = local_88.x; + local_60[1][0] = local_70.y * particleX; + local_60[1][1] = local_70.x * particleY; + local_60[1][3] = local_88.y; + local_60[2][2] = 1.0f; + local_60[2][3] = local_88.z; + local_60[2][1] = 0.0f; + local_60[2][0] = 0.0f; + local_60[1][2] = 0.0f; + local_60[0][2] = 0.0f; + GXLoadPosMtxImm(local_60, 0); + p_prj[param_0->mPrjType](param_0, local_60); + GXCallDisplayList(jpa_dl, sizeof(jpa_dl)); + } + } +} + +/* 80278FC8-80279110 273908 0148+00 0/0 1/1 0/0 .text + * JPADrawRotation__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + f32 sinRot = JMASSin(param_1->mRotateAngle); + f32 cosRot = JMASCos(param_1->mRotateAngle); + f32 particleX = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX; + f32 particleY = param_0->mGlobalPtclScl.y * param_1->mParticleScaleY; + Mtx auStack_88; + p_rot[param_0->mRotType](sinRot, cosRot, auStack_88); + p_plane[param_0->mPlaneType](auStack_88, particleX, particleY); + auStack_88[0][3] = param_1->mPosition.x; + auStack_88[1][3] = param_1->mPosition.y; + auStack_88[2][3] = param_1->mPosition.z; + MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88); + GXLoadPosMtxImm(auStack_88, 0); + p_prj[param_0->mPrjType](param_0, auStack_88); + GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl)); + } +} + +/* 80279110-802791B0 273A50 00A0+00 0/0 1/1 0/0 .text + * JPADrawPoint__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + if (!!(ptcl->mStatus & JPAPtclStts_Invisible)) + return; + + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXBegin(GX_POINTS, GX_VTXFMT1, 1); + GXPosition3f32(ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z); + GXTexCoord2f32(0.0f, 0.0f); + GXEnd(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX8); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); +} + +/* 802791B0-80279364 273AF0 01B4+00 0/0 1/1 0/0 .text + * JPADrawLine__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) { + if (param_1->checkStatus(8) == 0) { + JGeometry::TVec3 local_1c; + JGeometry::setTVec3f(¶m_1->mPosition.x, &local_1c.x); + JGeometry::TVec3 local_28; + param_1->getVelVec(local_28); + if (!local_28.isZero()) { + local_28.setLength(param_0->mGlobalPtclScl.y * (25.0f * param_1->mParticleScaleY)); + local_28.sub(local_1c, local_28); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXBegin(GX_LINES, GX_VTXFMT1, 2); + GXPosition3f32(local_1c.x, local_1c.y, local_1c.z); + GXTexCoord2f32(0.0f, 0.0f); + GXPosition3f32(local_28.x, local_28.y, local_28.z); + GXTexCoord2f32(0.0f, 1.0f); + GXEnd(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX8); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); + } + } +} + +/* 80279364-8027936C 273CA4 0008+00 2/2 0/0 0/0 .text getNext__FP26JPANode<15JPABaseParticle> */ +JPANode* getNext(JPANode* param_0) { + return param_0->getNext(); +} + +/* 8027936C-80279374 273CAC 0008+00 2/2 0/0 0/0 .text getPrev__FP26JPANode<15JPABaseParticle> */ +JPANode* getPrev(JPANode* param_0) { + return param_0->getPrev(); +} + +typedef JPANode* (*getNodeFunc)(JPANode*); + +/* 80279374-8027996C 273CB4 05F8+00 0/0 1/1 0/0 .text JPADrawStripe__FP18JPAEmitterWorkData */ +void JPADrawStripe(JPAEmitterWorkData* param_0) { + JPABaseShape* shape = param_0->mpRes->getBsp(); + u32 ptcl_num = param_0->mpAlivePtcl->getNum(); + if (ptcl_num < 2) { + return; + } + + f32 coord = 0.0f; + f32 step = 1.0f / (ptcl_num - 1.0f); + f32 dVar14 = (1.0f + param_0->mPivot.x) * (25.0f * param_0->mGlobalPtclScl.x); + f32 dVar13 = (1.0f - param_0->mPivot.x) * (25.0f * param_0->mGlobalPtclScl.x); + Mtx local_c8; + f32 dVar11; + f32 dVar12; + JGeometry::TVec3 local_ec; + JGeometry::TVec3 local_e0[2]; + JGeometry::TVec3 local_f8; + JGeometry::TVec3 local_104; + getNodeFunc node_func; + JPANode* startNode; + if (shape->isDrawFwdAhead()) { + startNode = param_0->mpAlivePtcl->getLast(); + node_func = getPrev; + coord = 1.0f; + step = -step; + } else { + startNode = param_0->mpAlivePtcl->getFirst(); + node_func = getNext; + } + + GXLoadPosMtxImm(param_0->mPosCamMtx, 0); + p_prj[param_0->mPrjType](param_0, param_0->mPosCamMtx); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1); + for (JPANode* node = startNode; node != param_0->mpAlivePtcl->getEnd(); + node = node_func(node), coord += step) { + param_0->mpCurNode = node; + JPABaseParticle* particle = node->getObject(); + local_ec.set(particle->mPosition); + dVar11 = JMASSin(particle->mRotateAngle); + dVar12 = JMASCos(particle->mRotateAngle); + local_e0[0].set(-particle->mParticleScaleX * dVar14, 0.0f, 0.0f); + local_e0[0].set(local_e0[0].x * dVar12, 0.0f, local_e0[0].x * dVar11); + local_e0[1].set(particle->mParticleScaleX * dVar13, 0.0f, 0.0f); + local_e0[1].set(local_e0[1].x * dVar12, 0.0f, local_e0[1].x * dVar11); + p_direction[param_0->mDirType](param_0, particle, &local_f8); + if (local_f8.isZero()) { + local_f8.set(0.0f, 1.0f, 0.0f); + } else { + local_f8.normalize(); + } + local_104.cross(particle->mBaseAxis, local_f8); + if (local_104.isZero()) { + local_104.set(1.0f, 0.0f, 0.0f); + } else { + local_104.normalize(); + } + particle->mBaseAxis.cross(local_f8, local_104); + particle->mBaseAxis.normalize(); + + local_c8[0][0] = local_104.x; + local_c8[0][1] = local_f8.x; + local_c8[0][2] = particle->mBaseAxis.x; + local_c8[0][3] = 0.0f; + local_c8[1][0] = local_104.y; + local_c8[1][1] = local_f8.y; + local_c8[1][2] = particle->mBaseAxis.y; + local_c8[1][3] = 0.0f; + local_c8[2][0] = local_104.z; + local_c8[2][1] = local_f8.z; + local_c8[2][2] = particle->mBaseAxis.z; + local_c8[2][3] = 0.0f; + MTXMultVecArraySR(local_c8, (Vec*)local_e0, (Vec*)local_e0, 2); + GXPosition3f32(local_e0[0].x + local_ec.x, local_e0[0].y + local_ec.y, + local_e0[0].z + local_ec.z); + GXTexCoord2f32(0.0f, coord); + GXPosition3f32(local_e0[1].x + local_ec.x, local_e0[1].y + local_ec.y, + local_e0[1].z + local_ec.z); + GXTexCoord2f32(1.0f, coord); + } + GXEnd(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX8); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); +} + +/* 8027996C-8027A3D8 2742AC 0A6C+00 0/0 1/1 0/0 .text JPADrawStripeX__FP18JPAEmitterWorkData */ +void JPADrawStripeX(JPAEmitterWorkData* param_0) { + JPABaseShape* shape = param_0->mpRes->getBsp(); + u32 ptcl_num = param_0->mpAlivePtcl->getNum(); + if (ptcl_num < 2) { + return; + } + + f32 start_coord = 0.0f; + f32 coord = 0.0f; + f32 step = 1.0f / (ptcl_num - 1.0f); + f32 local_154 = (1.0f + param_0->mPivot.x) * (25.0f * param_0->mGlobalPtclScl.x); + f32 local_158 = (1.0f - param_0->mPivot.x) * (25.0f * param_0->mGlobalPtclScl.x); + f32 local_15c = (1.0f + param_0->mPivot.y) * (25.0f * param_0->mGlobalPtclScl.y); + f32 local_160 = (1.0f - param_0->mPivot.y) * (25.0f * param_0->mGlobalPtclScl.y); + Mtx local_90; + f32 dVar11; + f32 dVar12; + JGeometry::TVec3 local_b4; + JGeometry::TVec3 local_a8[2]; + JGeometry::TVec3 local_c0; + JGeometry::TVec3 local_cc; + JPANode* startNode; + getNodeFunc node_func; + if (shape->isDrawFwdAhead()) { + startNode = param_0->mpAlivePtcl->getLast(); + node_func = getPrev; + start_coord = coord = 1.0f; + step = -step; + } else { + startNode = param_0->mpAlivePtcl->getFirst(); + node_func = getNext; + } + + GXLoadPosMtxImm(param_0->mPosCamMtx, 0); + p_prj[param_0->mPrjType](param_0, param_0->mPosCamMtx); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1); + for (JPANode* node = startNode; node != param_0->mpAlivePtcl->getEnd(); + node = node_func(node), coord += step) { + param_0->mpCurNode = node; + JPABaseParticle* particle = node->getObject(); + local_b4.set(particle->mPosition); + dVar11 = JMASSin(particle->mRotateAngle); + dVar12 = JMASCos(particle->mRotateAngle); + local_a8[0].set(-particle->mParticleScaleX * local_154, 0.0f, 0.0f); + local_a8[0].set(local_a8[0].x * dVar12, 0.0f, local_a8[0].x * dVar11); + local_a8[1].set(particle->mParticleScaleX * local_158, 0.0f, 0.0f); + local_a8[1].set(local_a8[1].x * dVar12, 0.0f, local_a8[1].x * dVar11); + p_direction[param_0->mDirType](param_0, particle, &local_c0); + if (local_c0.isZero()) { + local_c0.set(0.0f, 1.0f, 0.0f); + } else { + local_c0.normalize(); + } + local_cc.cross(particle->mBaseAxis, local_c0); + if (local_cc.isZero()) { + local_cc.set(1.0f, 0.0f, 0.0f); + } else { + local_cc.normalize(); + } + particle->mBaseAxis.cross(local_c0, local_cc); + particle->mBaseAxis.normalize(); + + local_90[0][0] = local_cc.x; + local_90[0][1] = local_c0.x; + local_90[0][2] = particle->mBaseAxis.x; + local_90[0][3] = 0.0f; + local_90[1][0] = local_cc.y; + local_90[1][1] = local_c0.y; + local_90[1][2] = particle->mBaseAxis.y; + local_90[1][3] = 0.0f; + local_90[2][0] = local_cc.z; + local_90[2][1] = local_c0.z; + local_90[2][2] = particle->mBaseAxis.z; + local_90[2][3] = 0.0f; + MTXMultVecArraySR(local_90, (Vec*)local_a8, (Vec*)local_a8, 2); + GXPosition3f32(local_a8[0].x + local_b4.x, local_a8[0].y + local_b4.y, + local_a8[0].z + local_b4.z); + GXTexCoord2f32(0.0f, coord); + GXPosition3f32(local_a8[1].x + local_b4.x, local_a8[1].y + local_b4.y, + local_a8[1].z + local_b4.z); + GXTexCoord2f32(1.0f, coord); + } + GXEnd(); + + coord = start_coord; + GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1); + for (JPANode* node = startNode; node != param_0->mpAlivePtcl->getEnd(); + node = node_func(node), coord += step) { + param_0->mpCurNode = node; + JPABaseParticle* particle = node->getObject(); + local_b4.set(particle->mPosition); + dVar11 = JMASCos(particle->mRotateAngle); + dVar12 = -JMASSin(particle->mRotateAngle); + local_a8[0].set(-particle->mParticleScaleY * local_15c, 0.0f, 0.0f); + local_a8[0].set(local_a8[0].x * dVar12, 0.0f, local_a8[0].x * dVar11); + local_a8[1].set(particle->mParticleScaleY * local_160, 0.0f, 0.0f); + local_a8[1].set(local_a8[1].x * dVar12, 0.0f, local_a8[1].x * dVar11); + p_direction[param_0->mDirType](param_0, particle, &local_c0); + if (local_c0.isZero()) { + local_c0.set(0.0f, 1.0f, 0.0f); + } else { + local_c0.normalize(); + } + local_cc.cross(particle->mBaseAxis, local_c0); + if (local_cc.isZero()) { + local_cc.set(1.0f, 0.0f, 0.0f); + } else { + local_cc.normalize(); + } + particle->mBaseAxis.cross(local_c0, local_cc); + particle->mBaseAxis.normalize(); + + local_90[0][0] = local_cc.x; + local_90[0][1] = local_c0.x; + local_90[0][2] = particle->mBaseAxis.x; + local_90[0][3] = 0.0f; + local_90[1][0] = local_cc.y; + local_90[1][1] = local_c0.y; + local_90[1][2] = particle->mBaseAxis.y; + local_90[1][3] = 0.0f; + local_90[2][0] = local_cc.z; + local_90[2][1] = local_c0.z; + local_90[2][2] = particle->mBaseAxis.z; + local_90[2][3] = 0.0f; + MTXMultVecArraySR(local_90, (Vec*)local_a8, (Vec*)local_a8, 2); + GXPosition3f32(local_a8[0].x + local_b4.x, local_a8[0].y + local_b4.y, + local_a8[0].z + local_b4.z); + GXTexCoord2f32(0.0f, coord); + GXPosition3f32(local_a8[1].x + local_b4.x, local_a8[1].y + local_b4.y, + local_a8[1].z + local_b4.z); + GXTexCoord2f32(1.0f, coord); + } + GXEnd(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX8); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); +} + +/* 8027A3D8-8027A414 274D18 003C+00 0/0 1/1 0/0 .text + * JPADrawEmitterCallBackB__FP18JPAEmitterWorkData */ +void JPADrawEmitterCallBackB(JPAEmitterWorkData* work) { + if (work->mpEmtr->mpEmtrCallBack == NULL) + return; + + work->mpEmtr->mpEmtrCallBack->draw(work->mpEmtr); +} + +/* 8027A414-8027A454 274D54 0040+00 0/0 1/1 0/0 .text + * JPADrawParticleCallBack__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + if (work->mpEmtr->mpPtclCallBack == NULL) + return; + + work->mpEmtr->mpPtclCallBack->draw(work->mpEmtr, ptcl); +} + +/* 8027A454-8027A6DC 274D94 0288+00 1/1 0/0 0/0 .text + * makeColorTable__FPP8_GXColorPC16JPAClrAnmKeyDataUcsP7JKRHeap */ +static void makeColorTable(GXColor** o_color_table, JPAClrAnmKeyData const* i_data, u8 param_2, + s16 i_size, JKRHeap* i_heap) { + GXColor* color_table = (GXColor*)JKRAllocFromHeap(i_heap, (i_size + 1) * 4, 4); + f32 r_step, g_step, b_step, a_step; + r_step = g_step = b_step = a_step = 0.0f; + f32 r = i_data[0].color.r; + f32 g = i_data[0].color.g; + f32 b = i_data[0].color.b; + f32 a = i_data[0].color.a; + int j = 0; + for (s16 i = 0; i < i_size + 1; i++) { + if (i == i_data[j].index) { + color_table[i] = i_data[j].color; + r = i_data[j].color.r; + g = i_data[j].color.g; + b = i_data[j].color.b; + a = i_data[j].color.a; + j++; + if (j < param_2) { + f32 base_step = 1.0f / (i_data[j].index - i_data[j - 1].index); + r_step = base_step * ((f32)i_data[j].color.r - r); + g_step = base_step * ((f32)i_data[j].color.g - g); + b_step = base_step * ((f32)i_data[j].color.b - b); + a_step = base_step * ((f32)i_data[j].color.a - a); + } else { + r_step = g_step = b_step = a_step = 0.0f; + } + } else { + r += r_step; + color_table[i].r = r; + g += g_step; + color_table[i].g = g; + b += b_step; + color_table[i].b = b; + a += a_step; + color_table[i].a = a; + } + } + *o_color_table = color_table; +} + +/* 8027A6DC-8027A7E8 27501C 010C+00 0/0 1/1 0/0 .text __ct__12JPABaseShapeFPCUcP7JKRHeap + */ +JPABaseShape::JPABaseShape(u8 const* pData, JKRHeap* pHeap) { + mpData = (const JPABaseShapeData*)pData; + + if (isTexCrdAnm()) { + mpTexCrdMtxAnmTbl = (const void*)(pData + sizeof(JPABaseShapeData)); + } else { + mpTexCrdMtxAnmTbl = NULL; + } + + if (isTexAnm()) { + u32 offs = sizeof(JPABaseShapeData); + if (isTexCrdAnm()) + offs = sizeof(JPABaseShapeData) + 0x28; + mpTexIdxAnimTbl = (const u8*)(pData + offs); + } else { + mpTexIdxAnimTbl = NULL; + } + + if (isPrmAnm()) { + makeColorTable(&mpPrmClrAnmTbl, (JPAClrAnmKeyData*)(pData + mpData->mClrPrmAnmOffset), + mpData->mClrPrmKeyNum, mpData->mClrAnmFrmMax, pHeap); + } else { + mpPrmClrAnmTbl = NULL; + } + + if (isEnvAnm()) { + makeColorTable(&mpEnvClrAnmTbl, (JPAClrAnmKeyData*)(pData + mpData->mClrEnvAnmOffset), + mpData->mClrEnvKeyNum, mpData->mClrAnmFrmMax, pHeap); + } else { + mpEnvClrAnmTbl = NULL; + } +} + +/* 803C4360-803C436C 021480 000C+00 0/1 0/0 0/0 .data st_bm__12JPABaseShape */ +GXBlendMode JPABaseShape::st_bm[3] = { + GX_BM_NONE, + GX_BM_BLEND, + GX_BM_LOGIC, +}; + +/* 803C436C-803C4394 02148C 0028+00 0/1 0/0 0/0 .data st_bf__12JPABaseShape */ +GXBlendFactor JPABaseShape::st_bf[10] = { + GX_BL_ZERO, GX_BL_ONE, GX_BL_SRCCLR, GX_BL_INVSRCCLR, + GX_BL_SRCCLR, GX_BL_INVSRCCLR, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, + GX_BL_DSTALPHA, GX_BL_INVDSTALPHA, +}; + +/* 803C4394-803C43D4 0214B4 0040+00 0/1 0/0 0/0 .data st_lo__12JPABaseShape */ +GXLogicOp JPABaseShape::st_lo[16] = { + GX_LO_CLEAR, GX_LO_SET, GX_LO_COPY, GX_LO_INVCOPY, GX_LO_NOOP, GX_LO_INV, + GX_LO_AND, GX_LO_NAND, GX_LO_OR, GX_LO_NOR, GX_LO_XOR, GX_LO_EQUIV, + GX_LO_REVAND, GX_LO_INVAND, GX_LO_REVOR, GX_LO_INVOR, +}; + +/* 803C43D4-803C43F4 0214F4 0020+00 0/1 0/0 0/0 .data st_c__12JPABaseShape */ +GXCompare JPABaseShape::st_c[8] = { + GX_NEVER, GX_LESS, GX_LEQUAL, GX_EQUAL, GX_NEQUAL, GX_GEQUAL, GX_GREATER, GX_ALWAYS, +}; + +/* 803C43F4-803C4404 021514 0010+00 0/1 0/0 0/0 .data st_ao__12JPABaseShape */ +GXAlphaOp JPABaseShape::st_ao[4] = { + GX_AOP_AND, + GX_AOP_OR, + GX_AOP_XOR, + GX_AOP_XNOR, +}; + +/* 803C4404-803C4464 021524 0060+00 0/1 0/0 0/0 .data st_ca__12JPABaseShape */ +GXTevColorArg JPABaseShape::st_ca[6][4] = { + { + GX_CC_ZERO, + GX_CC_TEXC, + GX_CC_ONE, + GX_CC_ZERO, + }, + { + GX_CC_ZERO, + GX_CC_C0, + GX_CC_TEXC, + GX_CC_ZERO, + }, + { + GX_CC_C0, + GX_CC_ONE, + GX_CC_TEXC, + GX_CC_ZERO, + }, + { + GX_CC_C1, + GX_CC_C0, + GX_CC_TEXC, + GX_CC_ZERO, + }, + { + GX_CC_ZERO, + GX_CC_TEXC, + GX_CC_C0, + GX_CC_C1, + }, + { + GX_CC_ZERO, + GX_CC_ZERO, + GX_CC_ZERO, + GX_CC_C0, + }, +}; + +/* 803C4464-803C4488 021584 0020+04 0/1 0/0 0/0 .data st_aa__12JPABaseShape */ +GXTevAlphaArg JPABaseShape::st_aa[2][4] = { + { + GX_CA_ZERO, + GX_CA_TEXA, + GX_CA_A0, + GX_CA_ZERO, + }, + { + GX_CA_ZERO, + GX_CA_ZERO, + GX_CA_ZERO, + GX_CA_A0, + }, +}; + +/* 8027A7E8-8027A918 275128 0130+00 0/0 1/1 0/0 .text setGX__12JPABaseShapeCFP18JPAEmitterWorkData + */ +void JPABaseShape::setGX(JPAEmitterWorkData* work) const { + const GXTevColorArg* colorArg = getTevColorArg(); + const GXTevAlphaArg* alphaArg = getTevAlphaArg(); + GXSetBlendMode(getBlendMode(), getBlendSrc(), getBlendDst(), getLogicOp()); + GXSetZMode(getZEnable(), getZCmp(), getZUpd()); + GXSetAlphaCompare(getAlphaCmp0(), getAlphaRef0(), getAlphaOp(), getAlphaCmp1(), getAlphaRef1()); + GXSetTevColorIn(GX_TEVSTAGE0, colorArg[0], colorArg[1], colorArg[2], colorArg[3]); + GXSetTevAlphaIn(GX_TEVSTAGE0, alphaArg[0], alphaArg[1], alphaArg[2], alphaArg[3]); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevDirect(GX_TEVSTAGE1); + GXSetZCompLoc(getZCompLoc()); +} diff --git a/src/JSystem/JParticle/JPAChildShape.cpp b/src/JSystem/JParticle/JPAChildShape.cpp new file mode 100644 index 00000000..cbc24cbb --- /dev/null +++ b/src/JSystem/JParticle/JPAChildShape.cpp @@ -0,0 +1,48 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAChildShape +// + +#include "JSystem/JParticle/JPAChildShape.h" +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "dolphin/gx.h" +#include "dolphin/os.h" + +/* 8027AEBC-8027AFDC 2757FC 0120+00 0/0 1/1 0/0 .text JPARegistChildPrmEnv__FP18JPAEmitterWorkData + */ +void JPARegistChildPrmEnv(JPAEmitterWorkData* work) { + JPAChildShape* csp = work->mpRes->getCsp(); + JPABaseEmitter* emtr = work->mpEmtr; + GXColor prm, env; + csp->getPrmClr(&prm); + csp->getEnvClr(&env); + prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r); + prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g); + prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b); + prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a); + env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r); + env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g); + env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b); + GXSetTevColor(GX_TEVREG0, prm); + GXSetTevColor(GX_TEVREG1, env); +} + +/* 8027AFDC-8027B008 27591C 002C+00 0/0 1/1 0/0 .text + * JPACalcChildAlphaOut__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcChildAlphaOut(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + f32 anm = (1.0f - ptcl->mTime) * 255.0f; + OSf32tou8(&anm, &ptcl->mPrmColorAlphaAnm); +} + +/* 8027B008-8027B038 275948 0030+00 0/0 1/1 0/0 .text + * JPACalcChildScaleOut__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcChildScaleOut(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + ptcl->mParticleScaleX = ptcl->mScaleOut * (1.0f - ptcl->mTime); + ptcl->mParticleScaleY = ptcl->mAlphaWaveRandom * (1.0f - ptcl->mTime); +} + +/* 8027B038-8027B040 -00001 0008+00 0/0 0/0 0/0 .text __ct__13JPAChildShapeFPCUc */ +JPAChildShape::JPAChildShape(u8 const* pData) { + mpData = (JPAChildShapeData*)pData; +} diff --git a/src/JSystem/JParticle/JPADynamicsBlock.cpp b/src/JSystem/JParticle/JPADynamicsBlock.cpp new file mode 100644 index 00000000..672c8413 --- /dev/null +++ b/src/JSystem/JParticle/JPADynamicsBlock.cpp @@ -0,0 +1,233 @@ +// +// Generated By: dol2asm +// Translation Unit: JPADynamicsBlock +// + +#include "JSystem/JParticle/JPADynamicsBlock.h" +#include "JSystem/JMath/JMATrigonometric.h" +#include "JSystem/JParticle/JPAEmitter.h" + +/* 8027B144-8027B220 275A84 00DC+00 1/1 0/0 0/0 .text JPAVolumePoint__FP18JPAEmitterWorkData */ +void JPAVolumePoint(JPAEmitterWorkData* work) { + work->mVolumeCalcData.mVolumePos.zero(); + work->mVolumeCalcData.mVelOmni.set(work->mpEmtr->get_r_zh(), work->mpEmtr->get_r_zh(), + work->mpEmtr->get_r_zh()); + work->mVolumeCalcData.mVelAxis.set(work->mVolumeCalcData.mVelOmni.x, 0.0f, + work->mVolumeCalcData.mVelOmni.z); +} + +/* 8027B220-8027B33C 275B60 011C+00 1/1 0/0 0/0 .text JPAVolumeLine */ +void JPAVolumeLine(JPAEmitterWorkData* work) { + if (work->mpEmtr->checkFlag(JPADynFlag_FixedInterval)) { + work->mVolumeCalcData.mVolumePos.set( + 0.0f, 0.0f, + work->mVolumeSize * ((work->mVolumeEmitIdx / (work->mEmitCount - 1.0f) - 0.5f))); + work->mVolumeEmitIdx++; + } else { + work->mVolumeCalcData.mVolumePos.set(0.0f, 0.0f, + work->mVolumeSize * work->mpEmtr->get_r_zh()); + } + + work->mVolumeCalcData.mVelOmni.set(0.0f, 0.0f, + work->mVolumeCalcData.mVolumePos.z * work->mGlobalScl.z); + work->mVolumeCalcData.mVelAxis.set(0.0f, 0.0f, work->mVolumeCalcData.mVolumePos.z); +} + +/* 8027B33C-8027B4E8 275C7C 01AC+00 1/1 0/0 0/0 .text JPAVolumeCircle */ +// NONMATCHING regalloc. Could be issue with mul asm implementations +void JPAVolumeCircle(JPAEmitterWorkData* work) { + s16 theta; + f32 distance; + + if (work->mpEmtr->checkFlag(JPADynFlag_FixedInterval)) { + theta = (s16)((work->mVolumeEmitIdx << 16) / work->mEmitCount); + theta = theta * work->mVolumeSweep; + work->mVolumeEmitIdx++; + } else { + theta = work->mVolumeSweep * work->mpEmtr->get_r_ss(); + } + + distance = work->mpEmtr->get_r_f(); + if (work->mpEmtr->checkFlag(JPADynFlag_FixedDensity)) { + distance = 1.0f - (distance * distance); + } + + distance = work->mVolumeSize * (work->mVolumeMinRad + distance * (1.0f - work->mVolumeMinRad)); + work->mVolumeCalcData.mVolumePos.set(distance * JMASSin(theta), 0.0f, + distance * JMASCos(theta)); + work->mVolumeCalcData.mVelOmni.mul(work->mVolumeCalcData.mVolumePos, work->mGlobalScl); + work->mVolumeCalcData.mVelAxis.set(work->mVolumeCalcData.mVolumePos.x, 0.0f, + work->mVolumeCalcData.mVolumePos.z); +} + +/* 8027B4E8-8027B5F0 275E28 0108+00 1/1 0/0 0/0 .text JPAVolumeCube */ +void JPAVolumeCube(JPAEmitterWorkData* work) { + work->mVolumeCalcData.mVolumePos.set(work->mpEmtr->get_r_zh() * work->mVolumeSize, + work->mpEmtr->get_r_zh() * work->mVolumeSize, + work->mpEmtr->get_r_zh() * work->mVolumeSize); + work->mVolumeCalcData.mVelOmni.mul(work->mVolumeCalcData.mVolumePos, work->mGlobalScl); + work->mVolumeCalcData.mVelAxis.set(work->mVolumeCalcData.mVolumePos.x, 0.0f, work->mVolumeCalcData.mVolumePos.z); +} + +/* 8027B5F0-8027B87C 275F30 028C+00 1/1 0/0 0/0 .text JPAVolumeSphere__FP18JPAEmitterWorkData */ +static void JPAVolumeSphere(JPAEmitterWorkData* work) { + s16 phi, theta; + if (work->mpEmtr->checkFlag(JPADynFlag_FixedInterval)) { + phi = (u16)(work->mVolumeX * 0x8000 / (work->mDivNumber - 1) + 0x4000); + f32 tmp = (u16)(work->mVolumeAngleNum * 0x10000 / (work->mVolumeAngleMax - 1)); + theta = tmp * work->mVolumeSweep + 0x8000; + work->mVolumeAngleNum++; + if (work->mVolumeAngleNum == work->mVolumeAngleMax) { + work->mVolumeAngleNum = 0; + work->mVolumeX++; + if (work->mVolumeX * 2 < work->mDivNumber) { + work->mVolumeAngleMax = work->mVolumeAngleMax != 1 ? + work->mVolumeAngleMax + 4 : work->mVolumeAngleMax + 3; + } else { + work->mVolumeAngleMax = work->mVolumeAngleMax != 4 ? work->mVolumeAngleMax - 4 : 1; + } + } + } else { + phi = work->mpEmtr->get_r_ss() >> 1; + theta = work->mVolumeSweep * work->mpEmtr->get_r_ss(); + } + + f32 rnd = work->mpEmtr->get_r_f(); + if (work->mpEmtr->checkFlag(JPADynFlag_FixedDensity)) { + rnd = 1.0f - rnd * rnd * rnd; + } + f32 rad = work->mVolumeSize * (work->mVolumeMinRad + rnd * (1.0f - work->mVolumeMinRad)); + work->mVolumeCalcData.mVolumePos.set(rad * JMASCos(phi) * JMASSin(theta), -rad * JMASSin(phi), + rad * JMASCos(phi) * JMASCos(theta)); + work->mVolumeCalcData.mVelOmni.mul(work->mVolumeCalcData.mVolumePos, work->mGlobalScl); + work->mVolumeCalcData.mVelAxis.set(work->mVolumeCalcData.mVolumePos.x, 0.0f, + work->mVolumeCalcData.mVolumePos.z); +} + +/* 8027B87C-8027B9F8 2761BC 017C+00 1/1 0/0 0/0 .text JPAVolumeCylinder__FP18JPAEmitterWorkData */ +static void JPAVolumeCylinder(JPAEmitterWorkData* work) { + s16 theta = work->mVolumeSweep * work->mpEmtr->get_r_ss(); + f32 rnd = work->mpEmtr->get_r_f(); + if (work->mpEmtr->checkFlag(JPADynFlag_FixedDensity)) { + rnd = 1.0f - rnd * rnd; + } + f32 rad = work->mVolumeSize * (work->mVolumeMinRad + rnd * (1.0f - work->mVolumeMinRad)); + work->mVolumeCalcData.mVolumePos.set( + rad * JMASSin(theta), work->mVolumeSize * work->mpEmtr->get_r_zp(), rad * JMASCos(theta)); + work->mVolumeCalcData.mVelOmni.mul(work->mVolumeCalcData.mVolumePos, work->mGlobalScl); + work->mVolumeCalcData.mVelAxis.set(work->mVolumeCalcData.mVolumePos.x, 0.0f, + work->mVolumeCalcData.mVolumePos.z); +} + +/* 8027B9F8-8027BB18 276338 0120+00 1/1 0/0 0/0 .text JPAVolumeTorus__FP18JPAEmitterWorkData */ +static void JPAVolumeTorus(JPAEmitterWorkData* work) { + s16 theta = work->mVolumeSweep * work->mpEmtr->get_r_ss(); + s16 phi = work->mpEmtr->get_r_ss(); + f32 rad = work->mVolumeSize * work->mVolumeMinRad; + work->mVolumeCalcData.mVelAxis.set(rad * JMASSin(theta) * JMASCos(phi), rad * JMASSin(phi), + rad * JMASCos(theta) * JMASCos(phi)); + work->mVolumeCalcData.mVolumePos.set( + work->mVolumeCalcData.mVelAxis.x + work->mVolumeSize * JMASSin(theta), + work->mVolumeCalcData.mVelAxis.y, + work->mVolumeCalcData.mVelAxis.z + work->mVolumeSize * JMASCos(theta)); + work->mVolumeCalcData.mVelOmni.mul(work->mVolumeCalcData.mVolumePos, work->mGlobalScl); +} + +/* 8027BB18-8027BB4C 276458 0034+00 0/0 1/1 0/0 .text __ct__16JPADynamicsBlockFPCUc */ +JPADynamicsBlock::JPADynamicsBlock(u8 const* data) { + mpData = (const JPADynamicsBlockData*)data; + init(); +} + +enum { + VOL_Cube = 0x00, + VOL_Sphere = 0x01, + VOL_Cylinder = 0x02, + VOL_Torus = 0x03, + VOL_Point = 0x04, + VOL_Circle = 0x05, + VOL_Line = 0x06, +}; + +/* 8027BB4C-8027BBE8 27648C 009C+00 2/1 0/0 0/0 .text init__16JPADynamicsBlockFv */ +void JPADynamicsBlock::init() { + switch (getVolumeType()) { + case VOL_Cube: + mpCalcVolumeFunc = &JPAVolumeCube; + break; + case VOL_Sphere: + mpCalcVolumeFunc = &JPAVolumeSphere; + break; + case VOL_Cylinder: + mpCalcVolumeFunc = &JPAVolumeCylinder; + break; + case VOL_Torus: + mpCalcVolumeFunc = &JPAVolumeTorus; + break; + case VOL_Point: + mpCalcVolumeFunc = &JPAVolumePoint; + break; + case VOL_Circle: + mpCalcVolumeFunc = &JPAVolumeCircle; + break; + case VOL_Line: + mpCalcVolumeFunc = &JPAVolumeLine; + break; + } +} + +/* 8027BBE8-8027BDEC 276528 0204+00 0/0 1/1 0/0 .text + * create__16JPADynamicsBlockFP18JPAEmitterWorkData */ +void JPADynamicsBlock::create(JPAEmitterWorkData* work) { + if (work->mpEmtr->checkStatus(JPAEmtrStts_RateStepEmit)) { + s32 emitCount; + s32 createCount; + + // Probably an inlined function. + if (work->mpEmtr->checkFlag(JPADynFlag_FixedInterval)) { + s32 count; + if (getVolumeType() == VOL_Sphere) { + count = 4 * getDivNumber() * getDivNumber() + 2; + } else { + count = getDivNumber(); + } + emitCount = count; + + work->mVolumeEmitIdx = 0; + } else { + f32 newPtclCount = + work->mpEmtr->mRate * (getRateRndm() * work->mpEmtr->get_r_zp() + 1.0f); + f32 newEmitCount = work->mpEmtr->mEmitCount + newPtclCount; + work->mpEmtr->mEmitCount = newEmitCount; + emitCount = (s32)newEmitCount; + work->mpEmtr->mEmitCount -= emitCount; + + if (work->mpEmtr->checkStatus(JPAEmtrStts_FirstEmit) && 0.0f < newPtclCount && + newPtclCount < 1.0f) + emitCount = 1; + } + + work->mEmitCount = emitCount; + if (work->mpEmtr->checkStatus(JPAEmtrStts_StopEmit)) { + emitCount = 0; + } + + // Probably an inlined function. + createCount = emitCount; + while (createCount > 0) { + JPABaseParticle* ptcl = work->mpEmtr->createParticle(); + if (ptcl == NULL) + break; + createCount--; + } + } + + if (++work->mpEmtr->mRateStepTimer >= (work->mpEmtr->mRateStep + 1)) { + work->mpEmtr->mRateStepTimer -= (work->mpEmtr->mRateStep + 1); + work->mpEmtr->setStatus(JPAEmtrStts_RateStepEmit); + } else { + work->mpEmtr->clearStatus(JPAEmtrStts_RateStepEmit); + } + + work->mpEmtr->clearStatus(JPAEmtrStts_FirstEmit); +} diff --git a/src/JSystem/JParticle/JPAEmitter.cpp b/src/JSystem/JParticle/JPAEmitter.cpp new file mode 100644 index 00000000..517421c8 --- /dev/null +++ b/src/JSystem/JParticle/JPAEmitter.cpp @@ -0,0 +1,183 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAEmitter +// + +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAEmitterManager.h" +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "JSystem/JParticle/JPABaseShape.h" +#include "dolphin/types.h" + +// +// Types: +// + +// +// Forward References: +// + +// +// External References: +// + +// +// Declarations: +// + +/* 8027E6A4-8027E6EC 278FE4 0048+00 0/0 14/14 16/16 .text __dt__18JPAEmitterCallBackFv */ +JPAEmitterCallBack::~JPAEmitterCallBack() { +} + +/* 8027E6EC-8027EA40 27902C 0354+00 0/0 1/1 0/0 .text + * init__14JPABaseEmitterFP17JPAEmitterManagerP11JPAResource */ +void JPABaseEmitter::init(JPAEmitterManager* param_0, JPAResource* param_1) { + mpEmtrMgr = param_0; + mpRes = param_1; + mpRes->getDyn()->getEmitterScl(&mLocalScl); + mpRes->getDyn()->getEmitterTrs(&mLocalTrs); + mpRes->getDyn()->getEmitterDir(&mLocalDir); + mLocalDir.normalize(); + mpRes->getDyn()->getEmitterRot(&mLocalRot); + mMaxFrame = mpRes->getDyn()->getMaxFrame(); + mLifeTime = mpRes->getDyn()->getLifetime(); + mVolumeSize = mpRes->getDyn()->getVolumeSize(); + mRate = mpRes->getDyn()->getRate(); + mRateStep = mpRes->getDyn()->getRateStep(); + mVolumeSweep = mpRes->getDyn()->getVolumeSweep(); + mVolumeMinRad = mpRes->getDyn()->getVolumeMinRad(); + mAwayFromCenterSpeed = mpRes->getDyn()->getInitVelOmni(); + mAwayFromAxisSpeed = mpRes->getDyn()->getInitVelAxis(); + mDirSpeed = mpRes->getDyn()->getInitVelDir(); + mSpread = mpRes->getDyn()->getInitVelDirSp(); + mRndmDirSpeed = mpRes->getDyn()->getInitVelRndm(); + mAirResist = mpRes->getDyn()->getAirRes(); + mRndm.set_seed(mpEmtrMgr->pWd->mRndm.get_rndm_u()); + MTXIdentity(mGlobalRot); + mGlobalScl.set(1.0f, 1.0f, 1.0f); + mGlobalTrs.zero(); + mGlobalPScl.set(1.0f, 1.0f); + mGlobalEnvClr.a = 0xff; + mGlobalEnvClr.b = 0xff; + mGlobalEnvClr.g = 0xff; + mGlobalEnvClr.r = 0xff; + mGlobalPrmClr.a = 0xff; + mGlobalPrmClr.b = 0xff; + mGlobalPrmClr.g = 0xff; + mGlobalPrmClr.r = 0xff; + param_1->getBsp()->getPrmClr(&mPrmClr); + param_1->getBsp()->getEnvClr(&mEnvClr); + mpUserWork = NULL; + mScaleOut = 1.0f; + mEmitCount = 0.0f; + initStatus(0x30); + mDrawTimes = 1; + mTick = 0; + mWaitTime = 0; + mRateStepTimer = 0; + mTexAnmIdx = 0; +} + +/* 8027EA40-8027EB60 279380 0120+00 0/0 3/3 0/0 .text createParticle__14JPABaseEmitterFv + */ +JPABaseParticle* JPABaseEmitter::createParticle() { + if (mpPtclPool->getNum() != 0) { + JPANode* node = mpPtclPool->pop_front(); + mAlivePtclBase.push_front(node); + mpRes->getDyn()->calc(mpEmtrMgr->pWd); + node->mData.init_p(mpEmtrMgr->pWd); + return &node->mData; + } + + return NULL; +} + +/* 8027EB60-8027EC60 2794A0 0100+00 0/0 1/1 0/0 .text + * createChild__14JPABaseEmitterFP15JPABaseParticle */ +JPABaseParticle* JPABaseEmitter::createChild(JPABaseParticle* parent) { + if (mpPtclPool->getNum() != 0) { + JPANode* node = mpPtclPool->pop_front(); + mAlivePtclChld.push_front(node); + node->mData.init_c(mpEmtrMgr->pWd, parent); + return &node->mData; + } + + return NULL; +} + +/* 8027EC60-8027EDD4 2795A0 0174+00 0/0 2/2 21/21 .text deleteAllParticle__14JPABaseEmitterFv */ +void JPABaseEmitter::deleteAllParticle() { + while (mAlivePtclBase.getNum()) + mpPtclPool->push_front(mAlivePtclBase.pop_back()); + while (mAlivePtclChld.getNum()) + mpPtclPool->push_front(mAlivePtclChld.pop_back()); +} + +/* 8027EDD4-8027EE14 279714 0040+00 0/0 1/1 0/0 .text processTillStartFrame__14JPABaseEmitterFv */ +bool JPABaseEmitter::processTillStartFrame() { + JPADynamicsBlock* dyn = mpRes->getDyn(); + s16 startFrame = dyn->getStartFrame(); + + if (mWaitTime >= startFrame) + return true; + + if (!(mStatus & 2)) + mWaitTime++; + + return false; +} + +/* 8027EE14-8027EEB0 279754 009C+00 0/0 1/1 0/0 .text processTermination__14JPABaseEmitterFv */ +bool JPABaseEmitter::processTermination() { + if (checkStatus(0x100)) { + return true; + } + + if (mMaxFrame == 0) { + return false; + } + if (mMaxFrame < 0) { + setStatus(8); + return getParticleNumber() == 0; + } + if (mTick >= mMaxFrame) { + setStatus(8); + if (checkStatus(0x40)) { + return 0; + } + return getParticleNumber() == 0; + } + return false; +} + +/* 8027EEB0-8027EF30 2797F0 0080+00 0/0 1/1 0/0 .text + * calcEmitterGlobalPosition__14JPABaseEmitterCFPQ29JGeometry8TVec3 */ +void JPABaseEmitter::calcEmitterGlobalPosition(JGeometry::TVec3* dst) const { + Mtx mtx; + MTXScale(mtx, mGlobalScl.x, mGlobalScl.y, mGlobalScl.z); + MTXConcat(mGlobalRot, mtx, mtx); + mtx[0][3] = mGlobalTrs.x; + mtx[1][3] = mGlobalTrs.y; + mtx[2][3] = mGlobalTrs.z; + MTXMultVec(mtx, mLocalTrs, *dst); +} + +/* 8027EF30-8027EF40 279870 0010+00 0/0 1/1 0/0 .text getCurrentCreateNumber__14JPABaseEmitterCFv + */ +u32 JPABaseEmitter::getCurrentCreateNumber() const { + return mpEmtrMgr->pWd->mEmitCount; +} + +/* 8027EF40-8027EF50 279880 0010+00 0/0 3/3 0/0 .text getDrawCount__14JPABaseEmitterCFv + */ +u8 JPABaseEmitter::getDrawCount() const { + return mpEmtrMgr->pWd->mDrawCount; +} + +/* 8027EF50-8027EFA4 279890 0054+00 0/0 1/1 0/0 .text + * loadTexture__14JPABaseEmitterFUc11_GXTexMapID */ +bool JPABaseEmitter::loadTexture(u8 idx, GXTexMapID texMapID) { + mpEmtrMgr->pWd->mpResMgr->load(mpRes->getTexIdx(idx), texMapID); + return true; +} diff --git a/src/JSystem/JParticle/JPAEmitterManager.cpp b/src/JSystem/JParticle/JPAEmitterManager.cpp new file mode 100644 index 00000000..649f4226 --- /dev/null +++ b/src/JSystem/JParticle/JPAEmitterManager.cpp @@ -0,0 +1,203 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAEmitterManager +// + +#include "JSystem/JParticle/JPAEmitterManager.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "dolphin/gx.h" + +/* 8027DCA0-8027DEBC 2785E0 021C+00 0/0 1/1 0/0 .text __ct__17JPAEmitterManagerFUlUlP7JKRHeapUcUc + */ +JPAEmitterManager::JPAEmitterManager(u32 i_ptclNum, u32 i_emtrNum, JKRHeap* pHeap, u8 i_gidMax, + u8 i_ridMax) { + emtrNum = i_emtrNum; + ptclNum = i_ptclNum; + gidMax = i_gidMax; + ridMax = i_ridMax; + + JUT_ASSERT(40, emtrNum && ptclNum && gidMax && ridMax); + + JPABaseEmitter* p_emtr_link = new (pHeap, 0) JPABaseEmitter[emtrNum]; + JUT_ASSERT(44, p_emtr_link); + for (u32 i = 0; i < emtrNum; i++) + mFreeEmtrList.prepend(&p_emtr_link[i].mLink); + + JPANode* p_ptcl_node = new (pHeap, 0) JPANode[ptclNum]; + JUT_ASSERT(51, p_ptcl_node); + for (u32 i = 0; i < ptclNum; i++) + mPtclPool.push_back(&p_ptcl_node[i]); + + pEmtrUseList = new (pHeap, 0) JSUList[gidMax]; + JUT_ASSERT(58, pEmtrUseList); + pResMgrAry = new (pHeap, 0) JPAResourceManager*[ridMax]; + JUT_ASSERT(62, pResMgrAry) + for (int i = 0; i < ridMax; i++) { + pResMgrAry[i] = NULL; + } + + pWd = new (pHeap, 0) JPAEmitterWorkData(); + JUT_ASSERT(67, pWd); +} + +/* 8027DEBC-8027DFA0 2787FC 00E4+00 0/0 3/3 0/0 .text + * createSimpleEmitterID__17JPAEmitterManagerFRCQ29JGeometry8TVec3UsUcUcP18JPAEmitterCallBackP19JPAParticleCallBack + */ +JPABaseEmitter* JPAEmitterManager::createSimpleEmitterID(JGeometry::TVec3 const& pos, + u16 resID, u8 group_id, u8 res_mgr_id, + JPAEmitterCallBack* emtrCB, + JPAParticleCallBack* ptclCB) { + JUT_ASSERT(88, group_id < gidMax); + JUT_ASSERT(89, res_mgr_id < ridMax); + JUT_ASSERT(90, pResMgrAry[res_mgr_id] != 0); + JPAResource* pRes = pResMgrAry[res_mgr_id]->getResource(resID); + + if (pRes == NULL) { + JUT_WARN_DEVICE(94, 3, "JPA : User Index %d is NOT exist\n", resID); + } else if (mFreeEmtrList.getNumLinks() == 0) { + JUT_WARN_DEVICE(97, 3, "JPA : Can NOT create emitter more\n"); + } else { + JSULink* pLink = mFreeEmtrList.getFirst(); + mFreeEmtrList.remove(pLink); + pEmtrUseList[group_id].append(pLink); + JPABaseEmitter* emtr = pLink->getObject(); + emtr->init(this, pRes); + emtr->mpPtclPool = &mPtclPool; + emtr->mpEmtrCallBack = emtrCB; + emtr->mpPtclCallBack = ptclCB; + emtr->mGroupID = group_id; + emtr->mResMgrID = res_mgr_id; + emtr->mGlobalTrs.set(pos); + return emtr; + } + + return NULL; +} + +/* 8027DFA0-8027E028 2788E0 0088+00 0/0 3/3 0/0 .text calc__17JPAEmitterManagerFUc */ +void JPAEmitterManager::calc(u8 group_id) { + JUT_ASSERT(154, group_id < gidMax); + JSULink* pNext = NULL; + for (JSULink* pLink = pEmtrUseList[group_id].getFirst(); + pLink != pEmtrUseList[group_id].getEnd(); pLink = pNext) { + pNext = pLink->getNext(); + + JPABaseEmitter* emtr = pLink->getObject(); + + if (emtr->mpRes->calc(pWd, emtr) && !emtr->checkStatus(0x200)) + forceDeleteEmitter(emtr); + } +} + +/* 8027E028-8027E220 278968 01F8+00 0/0 1/1 0/0 .text draw__17JPAEmitterManagerFPC11JPADrawInfoUc + */ +void JPAEmitterManager::draw(JPADrawInfo const* drawInfo, u8 group_id) { + JUT_ASSERT(192, group_id < gidMax); + drawInfo->getCamMtx(pWd->mPosCamMtx); + drawInfo->getPrjMtx(pWd->mPrjMtx); + calcYBBCam(); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXEnableTexOffsets(GX_TEXCOORD0, GX_TRUE, GX_TRUE); + GXEnableTexOffsets(GX_TEXCOORD1, GX_TRUE, GX_TRUE); + GXEnableTexOffsets(GX_TEXCOORD2, GX_TRUE, GX_TRUE); + GXSetCullMode(GX_CULL_NONE); + GXSetCoPlanar(GX_FALSE); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_INDEX8); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXSetCurrentMtx(GX_PNMTX0); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, + GX_AF_NONE); + GXSetChanCtrl(GX_COLOR1A1, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, + GX_AF_NONE); + GXSetNumChans(0); + + for (JSULink* pLink = pEmtrUseList[group_id].getFirst(); + pLink != pEmtrUseList[group_id].getEnd(); pLink = pLink->getNext()) { + JPABaseEmitter* emtr = pLink->getObject(); + if (!emtr->checkStatus(0x04)) { + pWd->mpResMgr = pResMgrAry[emtr->mResMgrID]; + emtr->mpRes->draw(pWd, emtr); + } + } +} + +/* 8027E220-8027E278 278B60 0058+00 0/0 1/1 0/0 .text forceDeleteAllEmitter__17JPAEmitterManagerFv + */ +void JPAEmitterManager::forceDeleteAllEmitter() { + for (u8 i = 0; i < gidMax; i++) + forceDeleteGroupEmitter(i); +} + +/* 8027E278-8027E2D8 278BB8 0060+00 1/1 0/0 0/0 .text + * forceDeleteGroupEmitter__17JPAEmitterManagerFUc */ +void JPAEmitterManager::forceDeleteGroupEmitter(u8 group_id) { + JUT_ASSERT(288, group_id < gidMax); + while (pEmtrUseList[group_id].getNumLinks()) + forceDeleteEmitter(pEmtrUseList[group_id].getLast()->getObject()); +} + +/* 8027E2D8-8027E344 278C18 006C+00 3/3 1/1 0/0 .text + * forceDeleteEmitter__17JPAEmitterManagerFP14JPABaseEmitter */ +void JPAEmitterManager::forceDeleteEmitter(JPABaseEmitter* emtr) { + emtr->deleteAllParticle(); + emtr->setStatus(0x300); + pEmtrUseList[emtr->getGroupID()].remove(&emtr->mLink); + mFreeEmtrList.prepend(&emtr->mLink); +} + +/* 8027E344-8027E354 278C84 0010+00 0/0 2/2 0/0 .text + * entryResourceManager__17JPAEmitterManagerFP18JPAResourceManagerUc */ +void JPAEmitterManager::entryResourceManager(JPAResourceManager* resMgr, u8 resMgrID) { + JUT_ASSERT_MSG_F(325, resMgrID < ridMax && (pResMgrAry[resMgrID]) == 0, + "res_id %d res_id_max %d array[%d] = %x", resMgrID, ridMax, resMgrID, + pResMgrAry[resMgrID]); + pResMgrAry[resMgrID] = resMgr; +} + +/* 8027E354-8027E3F4 278C94 00A0+00 0/0 1/1 0/0 .text clearResourceManager__17JPAEmitterManagerFUc + */ +void JPAEmitterManager::clearResourceManager(u8 res_mgr_id) { + JUT_ASSERT(339, res_mgr_id < ridMax); + for (u8 i = 0; i < gidMax; i++) { + JSULink* pNext = NULL; + for (JSULink* pLink = pEmtrUseList[i].getFirst(); + pLink != pEmtrUseList[i].getEnd(); pLink = pNext) { + pNext = pLink->getNext(); + + if (res_mgr_id == pLink->getObject()->getResourceManagerID()) + forceDeleteEmitter(pLink->getObject()); + } + } + + pResMgrAry[res_mgr_id] = NULL; +} + +/* 8027E3F4-8027E51C 278D34 0128+00 1/1 0/0 0/0 .text calcYBBCam__17JPAEmitterManagerFv + */ +void JPAEmitterManager::calcYBBCam() { + JGeometry::TVec3 v(0.0f, pWd->mPosCamMtx[1][1], pWd->mPosCamMtx[2][1]); + JUT_ASSERT(367, !v.isZero()); + v.normalize(); + pWd->mYBBCamMtx[0][0] = 1.0f; + pWd->mYBBCamMtx[0][1] = 0.0f; + pWd->mYBBCamMtx[0][2] = 0.0f; + pWd->mYBBCamMtx[0][3] = pWd->mPosCamMtx[0][3]; + pWd->mYBBCamMtx[1][0] = 0.0f; + pWd->mYBBCamMtx[1][1] = v.y; + pWd->mYBBCamMtx[1][2] = -v.z; + pWd->mYBBCamMtx[1][3] = pWd->mPosCamMtx[1][3]; + pWd->mYBBCamMtx[2][0] = 0.0f; + pWd->mYBBCamMtx[2][1] = v.z; + pWd->mYBBCamMtx[2][2] = v.y; + pWd->mYBBCamMtx[2][3] = pWd->mPosCamMtx[2][3]; +} diff --git a/src/JSystem/JParticle/JPAExTexShape.cpp b/src/JSystem/JParticle/JPAExTexShape.cpp new file mode 100644 index 00000000..4763459a --- /dev/null +++ b/src/JSystem/JParticle/JPAExTexShape.cpp @@ -0,0 +1,35 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAExTexShape +// + +#include "JSystem/JParticle/JPAExTexShape.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "dolphin/gx.h" + +/* 8027B040-8027B13C 275980 00FC+00 0/0 1/1 0/0 .text JPALoadExTex__FP18JPAEmitterWorkData */ +void JPALoadExTex(JPAEmitterWorkData* work) { + JPAExTexShape* ets = work->mpRes->getEts(); + + GXTexCoordID secTexCoordID = GX_TEXCOORD1; + if (ets->isUseIndirect()) { + GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, + GX_PTIDENTITY); + u8 texIdx = ets->getIndTexIdx(); + work->mpResMgr->load(work->mpRes->getTexIdx(texIdx), GX_TEXMAP2); + secTexCoordID = GX_TEXCOORD2; + } + + if (ets->isUseSecTex()) { + GXSetTexCoordGen2(secTexCoordID, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, + GX_PTIDENTITY); + u8 texIdx = ets->getSecTexIdx(); + work->mpResMgr->load(work->mpRes->getTexIdx(texIdx), GX_TEXMAP3); + } +} + +/* 8027B13C-8027B144 -00001 0008+00 0/0 0/0 0/0 .text __ct__13JPAExTexShapeFPCUc */ +JPAExTexShape::JPAExTexShape(u8 const* data) { + mpData = (const JPAExTexShapeData*)data; +} \ No newline at end of file diff --git a/src/JSystem/JParticle/JPAExtraShape.cpp b/src/JSystem/JParticle/JPAExtraShape.cpp new file mode 100644 index 00000000..2c269a31 --- /dev/null +++ b/src/JSystem/JParticle/JPAExtraShape.cpp @@ -0,0 +1,152 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAExtraShape +// + +#include "JSystem/JParticle/JPAExtraShape.h" +#include "JSystem/JMath/JMATrigonometric.h" +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "dolphin/os.h" + +/* 8027A918-8027A990 275258 0078+00 0/0 1/1 0/0 .text + * JPACalcScaleX__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleX(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + if (work->mScaleAnm < esp->getScaleInTiming()) { + ptcl->mParticleScaleX = + ptcl->mScaleOut * (esp->getScaleIncRateX() * work->mScaleAnm + esp->getScaleInValueX()); + } else if (work->mScaleAnm > esp->getScaleOutTiming()) { + ptcl->mParticleScaleX = + ptcl->mScaleOut * + (esp->getScaleDecRateX() * (work->mScaleAnm - esp->getScaleOutTiming()) + 1.0f); + } else { + ptcl->mParticleScaleX = ptcl->mScaleOut; + } +} + +/* 8027A990-8027AA08 2752D0 0078+00 0/0 1/1 0/0 .text + * JPACalcScaleY__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleY(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + if (work->mScaleAnm < esp->getScaleInTiming()) { + ptcl->mParticleScaleY = + ptcl->mScaleOut * (esp->getScaleIncRateY() * work->mScaleAnm + esp->getScaleInValueY()); + } else if (work->mScaleAnm > esp->getScaleOutTiming()) { + ptcl->mParticleScaleY = + ptcl->mScaleOut * + (esp->getScaleDecRateY() * (work->mScaleAnm - esp->getScaleOutTiming()) + 1.0f); + } else { + ptcl->mParticleScaleY = ptcl->mScaleOut; + } +} + +/* 8027AA08-8027AA14 275348 000C+00 0/0 1/1 0/0 .text + * JPACalcScaleCopy__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleCopy(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + ptcl->mParticleScaleY = ptcl->mParticleScaleX; +} + +/* 8027AA14-8027AA20 275354 000C+00 0/0 1/1 0/0 .text + * JPACalcScaleAnmNormal__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleAnmNormal(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + work->mScaleAnm = ptcl->mTime; +} + +/* 8027AA20-8027AA84 275360 0064+00 0/0 1/1 0/0 .text + * JPACalcScaleAnmRepeatX__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleAnmRepeatX(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + work->mScaleAnm = (ptcl->mAge % esp->getScaleAnmCycleX()) / (f32)esp->getScaleAnmCycleX(); +} + +/* 8027AA84-8027AAE8 2753C4 0064+00 0/0 1/1 0/0 .text + * JPACalcScaleAnmRepeatY__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleAnmRepeatY(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + work->mScaleAnm = (ptcl->mAge % esp->getScaleAnmCycleY()) / (f32)esp->getScaleAnmCycleY(); +} + +/* 8027AAE8-8027AB7C 275428 0094+00 0/0 1/1 0/0 .text + * JPACalcScaleAnmReverseX__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleAnmReverseX(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + s32 cycle = ptcl->mAge / esp->getScaleAnmCycleX(); + f32 base = (ptcl->mAge % esp->getScaleAnmCycleX()) / (f32)esp->getScaleAnmCycleX(); + work->mScaleAnm = base + ((cycle & 1) * (1.0f - base * 2.0f)); +} + +/* 8027AB7C-8027AC10 2754BC 0094+00 0/0 1/1 0/0 .text + * JPACalcScaleAnmReverseY__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcScaleAnmReverseY(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + s32 cycle = ptcl->mAge / esp->getScaleAnmCycleY(); + f32 base = (ptcl->mAge % esp->getScaleAnmCycleY()) / (f32)esp->getScaleAnmCycleY(); + work->mScaleAnm = base + ((cycle & 1) * (1.0f - base * 2.0f)); +} + +/* 8027AC10-8027AC98 275550 0088+00 0/0 1/1 0/0 .text + * JPACalcAlphaAnm__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcAlphaAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + f32 alpha; + if (ptcl->mTime < esp->getAlphaInTiming()) { + alpha = 255.0f * (esp->getAlphaInValue() + esp->getAlphaIncRate() * ptcl->mTime); + } else if (ptcl->mTime > esp->getAlphaOutTiming()) { + alpha = 255.0f * ((ptcl->mTime - esp->getAlphaOutTiming()) * esp->getAlphaDecRate() + + esp->getAlphaBaseValue()); + } else { + alpha = 255.0f * esp->getAlphaBaseValue(); + } + OSf32tou8(&alpha, &ptcl->mPrmColorAlphaAnm); +} + +/* 8027AC98-8027AD88 2755D8 00F0+00 0/0 1/1 0/0 .text + * JPACalcAlphaFlickAnm__FP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPACalcAlphaFlickAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + JPAExtraShape* esp = work->mpRes->getEsp(); + f32 alpha; + if (ptcl->mTime < esp->getAlphaInTiming()) { + alpha = (esp->getAlphaInValue() + esp->getAlphaIncRate() * ptcl->mTime); + } else if (ptcl->mTime > esp->getAlphaOutTiming()) { + alpha = ((ptcl->mTime - esp->getAlphaOutTiming()) * esp->getAlphaDecRate() + + esp->getAlphaBaseValue()); + } else { + alpha = esp->getAlphaBaseValue(); + } + s32 theta = ptcl->mAlphaWaveRandom * ptcl->mAge * 16384.0f * (1.0f - esp->getAlphaFreq()); + f32 wave = JMASSin(theta); + alpha *= (1.0f + esp->getAlphaAmp() * (wave - 1.0f) * 0.5f) * 255.0f; + OSf32tou8(&alpha, &ptcl->mPrmColorAlphaAnm); +} + +/* 8027AD88-8027ADBC 2756C8 0034+00 0/0 1/1 0/0 .text __ct__13JPAExtraShapeFPCUc */ +JPAExtraShape::JPAExtraShape(u8 const* data) { + mpData = (const JPAExtraShapeData*)data; + init(); +} + +/* 8027ADBC-8027AEBC 2756FC 0100+00 1/1 0/0 0/0 .text init__13JPAExtraShapeFv */ +void JPAExtraShape::init() { + mAlphaIncRate = (getAlphaInTiming() != 0.0f) ? + (getAlphaBaseValue() - getAlphaInValue()) / getAlphaInTiming() : + 1.0f; + mAlphaDecRate = (getAlphaOutTiming() != 1.0f) ? + (getAlphaOutValue() - getAlphaBaseValue()) / (1.0f - getAlphaOutTiming()) : + 1.0f; + + if (getScaleInTiming() != 0.0f) { + mScaleIncRateX = (1.0f - getScaleInValueX()) / getScaleInTiming(); + mScaleIncRateY = (1.0f - getScaleInValueY()) / getScaleInTiming(); + } else { + mScaleIncRateX = mScaleIncRateY = 1.0f; + } + + if (getScaleOutTiming() != 1.0f) { + mScaleDecRateX = (getScaleOutValueX() - 1.0f) / (1.0f - getScaleOutTiming()); + mScaleDecRateY = (getScaleOutValueY() - 1.0f) / (1.0f - getScaleOutTiming()); + } else { + mScaleDecRateX = mScaleDecRateY = 1.0f; + } +} diff --git a/src/JSystem/JParticle/JPAFieldBlock.cpp b/src/JSystem/JParticle/JPAFieldBlock.cpp new file mode 100644 index 00000000..c9a4c038 --- /dev/null +++ b/src/JSystem/JParticle/JPAFieldBlock.cpp @@ -0,0 +1,299 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAFieldBlock +// + +#include "JSystem/JParticle/JPAFieldBlock.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAParticle.h" + +/* 8027BDEC-8027BF18 27672C 012C+00 8/8 0/0 0/0 .text + * calcAffect__12JPAFieldBaseFP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldBase::calcAffect(JPAFieldBlock* block, JPABaseParticle* ptcl) { + JGeometry::TVec3 vec = mAccel; + if (!ptcl->checkStatus(4) && block->checkStatus(0x78)) { + vec.scale(calcFadeAffect(block, ptcl->mTime)); + } + + switch (block->getAddType()) { + case 0: + ptcl->mVelType0.add(vec); + break; + case 1: + ptcl->mVelType1.add(vec); + break; + case 2: + ptcl->mVelType2.add(vec); + break; + } +} + +/* 8027BF18-8027BFB4 276858 009C+00 2/2 0/0 0/0 .text + * calcFadeAffect__12JPAFieldBaseCFP13JPAFieldBlockf */ +f32 JPAFieldBase::calcFadeAffect(JPAFieldBlock* block, f32 time) const { + f32 fade = 1.0f; + if ((block->checkStatus(8) && time < block->getEnTime()) + || (block->checkStatus(0x10) && time >= block->getDisTime())) + { + fade = 0.0f; + } else if (block->checkStatus(0x40) && time >= block->getFadeOutTime()) { + fade = (block->getDisTime() - time) * block->getFadeOutRate(); + } else if (block->checkStatus(0x20) && time < block->getFadeInTime()) { + fade = (time - block->getEnTime()) * block->getFadeInRate(); + } + return fade; +} + +/* 8027BFB4-8027C054 2768F4 00A0+00 1/0 0/0 0/0 .text + * prepare__15JPAFieldGravityFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldGravity::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + if (block->checkStatus(2)) { + mAccel.scale(block->getMag(), block->getDir()); + } else { + MTXMultVecSR(work->mRotationMtx, &block->getDir(), &mAccel); + mAccel.scale(block->getMag()); + } +} + +/* 8027C054-8027C07C 276994 0028+00 1/0 0/0 0/0 .text + * calc__15JPAFieldGravityFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldGravity::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + calcAffect(block, ptcl); +} + +/* 8027C07C-8027C1B8 2769BC 013C+00 1/0 0/0 0/0 .text + * prepare__11JPAFieldAirFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldAir::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + JGeometry::TVec3 vec; + vec.normalize(block->getDir()); + if (block->checkStatus(2)) { + mAccel.scale(block->getMag(), vec); + } else { + MTXMultVecSR(work->mRotationMtx, vec, mAccel); + mAccel.scale(block->getMag()); + } +} + +/* 8027C1B8-8027C24C 276AF8 0094+00 1/0 0/0 0/0 .text + * calc__11JPAFieldAirFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldAir::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + calcAffect(block, ptcl); + if (block->checkStatus(4)) { + f32 len = ptcl->mVelType1.length(); + if (len > block->getMagRndm()) { + ptcl->mVelType1.scale(block->getMagRndm() / len); + } + } +} + +/* 8027C24C-8027C29C 276B8C 0050+00 1/0 0/0 0/0 .text + * prepare__14JPAFieldMagnetFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldMagnet::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + mDir.sub(block->getPos(), work->mEmitterPos); + MTXMultVecSR(work->mRotationMtx, &mDir, &mDir); +} + +/* 8027C29C-8027C36C 276BDC 00D0+00 1/0 0/0 0/0 .text + * calc__14JPAFieldMagnetFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldMagnet::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + mAccel.sub(mDir, ptcl->mLocalPosition); + mAccel.setLength(block->getMag()); + calcAffect(block, ptcl); +} + +/* 8027C36C-8027C3E0 276CAC 0074+00 1/0 0/0 0/0 .text + * prepare__14JPAFieldNewtonFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldNewton::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + mDir.sub(block->getPos(), work->mEmitterPos); + MTXMultVecSR(work->mRotationMtx, &mDir, &mDir); + mCutoff = block->getVal1() * block->getVal1(); +} + +/* 8027C3E0-8027C56C 276D20 018C+00 1/0 0/0 0/0 .text + * calc__14JPAFieldNewtonFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldNewton::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + mAccel.sub(mDir, ptcl->mLocalPosition); + f32 len_sq = mAccel.squared(); + if (len_sq > mCutoff) { + mAccel.setLength(mCutoff * (block->getMag() * 10.0f) / len_sq); + } else { + mAccel.setLength(block->getMag() * 10.0f); + } + calcAffect(block, ptcl); +} + +/* 8027C56C-8027C674 276EAC 0108+00 1/0 0/0 0/0 .text + * prepare__14JPAFieldVortexFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldVortex::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + MTXMultVecSR(work->mGlobalRot, &block->getDir(), &field_0x10); + field_0x10.normalize(); + field_0x1c = block->getPos().z * block->getPos().z; + field_0x20 = 1.0f / field_0x1c; +} + +/* 8027C674-8027C814 276FB4 01A0+00 1/0 0/0 0/0 .text + * calc__14JPAFieldVortexFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldVortex::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + JGeometry::TVec3 vec; + vec.scale(field_0x10.dot(ptcl->mLocalPosition), field_0x10); + vec.sub(ptcl->mLocalPosition, vec); + f32 mag = vec.squared(); + if (mag > field_0x1c) { + mag = block->getMagRndm(); + } else { + mag *= field_0x20; + mag = (1.0f - mag) * block->getMag() + mag * block->getMagRndm(); + } + vec.normalize(); + mAccel.cross(vec, field_0x10); + mAccel.scale(mag); + calcAffect(block, ptcl); +} + +/* 8027C814-8027CA94 277154 0280+00 1/0 0/0 0/0 .text + * prepare__18JPAFieldConvectionFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldConvection::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + JGeometry::TVec3 vec1, vec2; + vec2.cross(block->getPos(), block->getDir()); + vec1.cross(block->getDir(), vec2); + MTXMultVecSR(work->mGlobalRot, &vec1, &field_0x10); + MTXMultVecSR(work->mGlobalRot, &block->getDir(), field_0x1c); + MTXMultVecSR(work->mGlobalRot, &vec2, &field_0x28); + field_0x10.normalize(); + field_0x1c.normalize(); + field_0x28.normalize(); +} + +/* 8027CA94-8027CCCC 2773D4 0238+00 1/0 0/0 0/0 .text + * calc__18JPAFieldConvectionFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldConvection::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, + JPABaseParticle* ptcl) { + JGeometry::TVec3 vec1, vec2, vec3; + vec1.scale(field_0x10.dot(ptcl->mLocalPosition), field_0x10); + vec3.scale(field_0x28.dot(ptcl->mLocalPosition), field_0x28); + vec1.add(vec3); + vec1.setLength(vec1, block->getVal1()); + vec2.sub(ptcl->mLocalPosition, vec1); + vec3.cross(field_0x1c, vec1); + mAccel.cross(vec3, vec2); + mAccel.setLength(block->getMag()); + calcAffect(block, ptcl); +} + +/* 8027CCCC-8027CDE4 27760C 0118+00 1/0 0/0 0/0 .text + * calc__14JPAFieldRandomFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldRandom::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + if (ptcl->mAge == 0 || (block->getCycle() != 0 && ptcl->mAge % block->getCycle() == 0)) { + JPABaseEmitter* emtr = work->mpEmtr; + mAccel.set(emtr->get_r_zh(), emtr->get_r_zh(), emtr->get_r_zh()); + mAccel.scale(block->getMag()); + calcAffect(block, ptcl); + } +} + +/* 8027CDE4-8027CE64 277724 0080+00 1/0 0/0 0/0 .text + * calc__12JPAFieldDragFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldDrag::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + if (!ptcl->checkStatus(4)) { + f32 fade = calcFadeAffect(block, ptcl->mTime); + ptcl->mDrag *= 1.0f - fade * (1.0f - block->getMag()); + } else { + ptcl->mDrag *= block->getMag(); + } +} + +/* 8027CE64-8027CFA8 2777A4 0144+00 1/0 0/0 0/0 .text + * prepare__12JPAFieldSpinFP18JPAEmitterWorkDataP13JPAFieldBlock */ +void JPAFieldSpin::prepare(JPAEmitterWorkData* work, JPAFieldBlock* block) { + JGeometry::TVec3 axis; + MTXMultVecSR(work->mGlobalRot, &block->getDir(), &axis); + axis.normalize(); + Mtx mtx; + MTXRotAxisRad(mtx, &axis, block->getMag()); + field_0x10.set(mtx[0][0], mtx[1][0], mtx[2][0]); + field_0x1c.set(mtx[0][1], mtx[1][1], mtx[2][1]); + field_0x28.set(mtx[0][2], mtx[1][2], mtx[2][2]); +} + +/* 8027CFA8-8027D088 2778E8 00E0+00 1/0 0/0 0/0 .text + * calc__12JPAFieldSpinFP18JPAEmitterWorkDataP13JPAFieldBlockP15JPABaseParticle */ +void JPAFieldSpin::calc(JPAEmitterWorkData* work, JPAFieldBlock* block, JPABaseParticle* ptcl) { + Mtx mtx; + mtx[0][0] = field_0x10.x; + mtx[1][0] = field_0x10.y; + mtx[2][0] = field_0x10.z; + mtx[0][1] = field_0x1c.x; + mtx[1][1] = field_0x1c.y; + mtx[2][1] = field_0x1c.z; + mtx[0][2] = field_0x28.x; + mtx[1][2] = field_0x28.y; + mtx[2][2] = field_0x28.z; + mtx[0][3] = mtx[1][3] = mtx[2][3] = 0.0f; + Vec vec; + MTXMultVecSR(mtx, &ptcl->mLocalPosition, &vec); + mAccel.set(vec.x - ptcl->mLocalPosition.x, vec.y - ptcl->mLocalPosition.y, + vec.z - ptcl->mLocalPosition.z); + calcAffect(block, ptcl); +} + +/* 8027D088-8027D0C0 2779C8 0038+00 0/0 1/1 0/0 .text __ct__13JPAFieldBlockFPCUcP7JKRHeap + */ +JPAFieldBlock::JPAFieldBlock(u8 const* data, JKRHeap* heap) + : mpData((const JPAFieldBlockData*)data) { + init(heap); +} + +/* 8027D0C0-8027D3AC 277A00 02EC+00 2/1 0/0 0/0 .text init__13JPAFieldBlockFP7JKRHeap */ +void JPAFieldBlock::init(JKRHeap* heap) { + mFadeInRate = getFadeInTime() - getEnTime(); + if (mFadeInRate == 0.0f) { + mFadeInRate = 1.0f; + } else { + mFadeInRate = 1.0f / mFadeInRate; + } + + mFadeOutRate = getDisTime() - getFadeOutTime(); + if (mFadeOutRate == 0.0f) { + mFadeOutRate = 1.0f; + } else { + mFadeOutRate = 1.0f / mFadeOutRate; + } + + getPosOrig(&mPos); + getDirOrig(&mDir); + mMag = getMagOrig(); + + switch (getType()) { + case FIELD_GRAVITY: + mpField = new (heap, 0) JPAFieldGravity(); + break; + case FIELD_AIR: + mpField = new (heap, 0) JPAFieldAir(); + break; + case FIELD_MAGNET: + mpField = new (heap, 0) JPAFieldMagnet(); + break; + case FIELD_NEWTON: + mpField = new (heap, 0) JPAFieldNewton(); + break; + case FIELD_VORTEX: + mpField = new (heap, 0) JPAFieldVortex(); + break; + case FIELD_RANDOM: + mpField = new (heap, 0) JPAFieldRandom(); + break; + case FIELD_DRAG: + mpField = new (heap, 0) JPAFieldDrag(); + break; + case FIELD_CONVECTION: + mpField = new (heap, 0) JPAFieldConvection(); + break; + case FIELD_SPIN: + mpField = new (heap, 0) JPAFieldSpin(); + break; + default: + mpField = NULL; + break; + } +} diff --git a/src/JSystem/JParticle/JPAKeyBlock.cpp b/src/JSystem/JParticle/JPAKeyBlock.cpp new file mode 100644 index 00000000..fdb1e8e6 --- /dev/null +++ b/src/JSystem/JParticle/JPAKeyBlock.cpp @@ -0,0 +1,25 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAKeyBlock +// + +#include "JSystem/JParticle/JPAKeyBlock.h" +#include "JSystem/JParticle/JPAMath.h" + +/* 8027D730-8027D740 278070 0010+00 0/0 1/1 0/0 .text __ct__11JPAKeyBlockFPCUc */ +JPAKeyBlock::JPAKeyBlock(const u8* data) + : mDataStart(data) + , field_0x4(reinterpret_cast(&data[0xC])) +{ +} + +/* 8027D740-8027D7D4 278080 0094+00 0/0 1/1 0/0 .text calc__11JPAKeyBlockFf */ +f32 JPAKeyBlock::calc(float p1) { + if (mDataStart[0xB] != '\0') { + int v1 = (int)field_0x4[(mDataStart[9] - 1) * 4] + 1; + // p1 -= (v1 * ((int)p1 / v1)); + int v2 = ((int)p1 / v1); + p1 = p1 - (v2 * v1); + } + return JPACalcKeyAnmValue(p1, mDataStart[9], field_0x4); +} diff --git a/src/JSystem/JParticle/JPAMath.cpp b/src/JSystem/JParticle/JPAMath.cpp new file mode 100644 index 00000000..c8686038 --- /dev/null +++ b/src/JSystem/JParticle/JPAMath.cpp @@ -0,0 +1,182 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAMath +// + +#include "JSystem/JParticle/JPAMath.h" +#include "JSystem/JMath/JMATrigonometric.h" +#include "JSystem/J2DGraph/J2DAnimation.h" + +// +// Types: +// + +// +// Forward References: +// + +extern "C" void func_80280588(); +extern "C" void JPAGetYZRotateMtx__FssPA4_f(); +extern "C" void JPAGetXYZRotateMtx__FsssPA4_f(); +extern "C" void func_802807E0(); +extern "C" void func_80280808(); +extern "C" void JPACalcKeyAnmValue__FfUsPCf(); + +// +// External References: +// + +extern "C" void _savegpr_28(); +extern "C" void _restgpr_28(); +extern "C" u8 sincosTable___5JMath[65536]; + +// +// Declarations: +// + +/* ############################################################################################## */ +// Probably some local function needed to change float literal order +static f32 floatDummyFunc() { + return 1.0f; +} + +/* 80280588-802806C0 27AEC8 0138+00 0/0 1/1 0/0 .text JPAGetDirMtx__FRCQ29JGeometry8TVec3PA4_f + */ +void JPAGetDirMtx(JGeometry::TVec3 const& param_0, f32 (*param_1)[4]) { + JGeometry::TVec3 local_78(param_0.y, -param_0.x, 0.0f); + f32 len = local_78.length(); + + if (len <= JGeometry::TUtil::epsilon()) { + local_78.zero(); + } else { + local_78.scale(1.0f / len); + } + f32 xsquared = local_78.x * local_78.x; + f32 ysquared = local_78.y * local_78.y; + f32 xlen = local_78.x * len; + f32 ylen = local_78.y * len; + f32 fVar5 = (1.0f - param_0.z) * (local_78.x * local_78.y); + param_1[0][0] = xsquared + param_0.z * (1.0f - xsquared); + param_1[0][1] = fVar5; + param_1[0][2] = -ylen; + param_1[0][3] = 0.0f; + param_1[1][0] = fVar5; + param_1[1][1] = ysquared + param_0.z * (1.0f - ysquared); + param_1[1][2] = xlen; + param_1[1][3] = 0.0f; + param_1[2][0] = ylen; + param_1[2][1] = -xlen; + param_1[2][2] = param_0.z; + param_1[2][3] = 0.0f; +} + +/* 802806C0-80280734 27B000 0074+00 0/0 1/1 0/0 .text JPAGetYZRotateMtx__FssPA4_f */ +void JPAGetYZRotateMtx(s16 angleY, s16 angleZ, f32 (*param_2)[4]) { + f32 cosy = JMASCos(angleY); + f32 cosz = JMASCos(angleZ); + f32 siny = JMASSin(angleY); + f32 sinz = JMASSin(angleZ); + param_2[0][0] = (cosy * cosz); + param_2[0][1] = -sinz; + param_2[0][2] = (siny * cosz); + param_2[1][0] = (cosy * sinz); + param_2[1][1] = cosz; + param_2[1][2] = (siny * sinz); + param_2[2][0] = -siny; + param_2[2][2] = cosy; + param_2[2][3] = 0.0f; + param_2[2][1] = 0.0f; + param_2[1][3] = 0.0f; + param_2[0][3] = 0.0f; +} + +/* 80280734-802807E0 27B074 00AC+00 0/0 6/6 11/11 .text JPAGetXYZRotateMtx__FsssPA4_f */ +void JPAGetXYZRotateMtx(s16 x, s16 y, s16 z, Mtx mtx) { + f32 cosx = JMASCos(x); + f32 cosy = JMASCos(y); + f32 cosz = JMASCos(z); + f32 sinx = JMASSin(x); + f32 siny = JMASSin(y); + f32 sinz = JMASSin(z); + mtx[0][0] = cosy * cosz; + mtx[1][0] = cosy * sinz; + mtx[2][0] = -siny; + mtx[2][1] = sinx * cosy; + mtx[2][2] = cosx * cosy; + f32 cosxsinz = cosx * sinz; + f32 sinxcosz = sinx * cosz; + mtx[0][1] = sinxcosz * siny - cosxsinz; + mtx[1][2] = cosxsinz * siny - sinxcosz; + f32 sinxsinz = sinx * sinz; + f32 cosxcosz = cosx * cosz; + mtx[0][2] = sinxsinz + cosxcosz * siny; + mtx[1][1] = cosxcosz + sinxsinz * siny; + mtx[2][3] = 0.0f; + mtx[1][3] = 0.0f; + mtx[0][3] = 0.0f; +} + +/* 802807E0-80280808 27B120 0028+00 0/0 11/11 71/71 .text + * JPASetRMtxTVecfromMtx__FPA4_CfPA4_fPQ29JGeometry8TVec3 */ +void JPASetRMtxTVecfromMtx(f32 const (*param_0)[4], f32 (*param_1)[4], + JGeometry::TVec3* param_2) { + JGeometry::TVec3 dummy; + JPASetRMtxSTVecfromMtx(param_0, param_1, &dummy, param_2); +} + +/* 80280808-80280984 27B148 017C+00 1/1 1/1 53/53 .text + * JPASetRMtxSTVecfromMtx__FPA4_CfPA4_fPQ29JGeometry8TVec3PQ29JGeometry8TVec3 */ +void JPASetRMtxSTVecfromMtx(f32 const (*param_0)[4], f32 (*param_1)[4], + JGeometry::TVec3* param_2, JGeometry::TVec3* param_3) { + JGeometry::TVec3 aTStack_54; + aTStack_54.set(param_0[0][0], param_0[1][0], param_0[2][0]); + param_2->x = aTStack_54.length(); + aTStack_54.set(param_0[0][1], param_0[1][1], param_0[2][1]); + param_2->y = aTStack_54.length(); + aTStack_54.set(param_0[0][2], param_0[1][2], param_0[2][2]); + param_2->z = aTStack_54.length(); + MTXIdentity(param_1); + if (param_2->x != 0.0f) { + f32 fVar5 = 1.0f / param_2->x; + param_1[0][0] = param_0[0][0] * fVar5; + param_1[1][0] = param_0[1][0] * fVar5; + param_1[2][0] = param_0[2][0] * fVar5; + } + if (param_2->y != 0.0f) { + f32 fVar5 = 1.0f / param_2->y; + param_1[0][1] = param_0[0][1] * fVar5; + param_1[1][1] = param_0[1][1] * fVar5; + param_1[2][1] = param_0[2][1] * fVar5; + } + if (param_2->z != 0.0f) { + f32 fVar5 = 1.0f / param_2->z; + param_1[0][2] = param_0[0][2] * fVar5; + param_1[1][2] = param_0[1][2] * fVar5; + param_1[2][2] = param_0[2][2] * fVar5; + } + param_3->set(param_0[0][3], param_0[1][3], param_0[2][3]); +} + +/* 80280984-80280A48 27B2C4 00C4+00 0/0 2/1 0/0 .text JPACalcKeyAnmValue__FfUsPCf */ +f32 JPACalcKeyAnmValue(f32 param_0, u16 param_1, f32 const* param_2) { + if (param_0 < param_2[0]) { + return param_2[1]; + } + int ind = param_1 - 1; + if (param_2[ind * 4] <= param_0) { + return param_2[ind * 4 + 1]; + } + int x = param_1; + while (x > 1) { + u32 uVar3 = x / 2; + if (param_0 >= param_2[uVar3 * 4]) { + param_2 += uVar3 * 4; + x -= uVar3; + } else { + x = uVar3; + } + } + return JMAHermiteInterpolation(param_0, param_2[0], param_2[1], + param_2[3], param_2[4], + param_2[5], param_2[6]); +} diff --git a/src/JSystem/JParticle/JPAParticle.cpp b/src/JSystem/JParticle/JPAParticle.cpp new file mode 100644 index 00000000..c06c62b9 --- /dev/null +++ b/src/JSystem/JParticle/JPAParticle.cpp @@ -0,0 +1,331 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAParticle +// + +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPABaseShape.h" +#include "JSystem/JParticle/JPAChildShape.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAEmitterManager.h" +#include "JSystem/JParticle/JPAExtraShape.h" + +/* 8027EFA4-8027EFEC 2798E4 0048+00 0/0 11/11 1/1 .text __dt__19JPAParticleCallBackFv */ +JPAParticleCallBack::~JPAParticleCallBack() { + /* empty function */ +} + +/* 8027EFEC-8027F8C8 27992C 08DC+00 0/0 1/1 0/0 .text + * init_p__15JPABaseParticleFP18JPAEmitterWorkData */ +void JPABaseParticle::init_p(JPAEmitterWorkData* work) { + JPABaseEmitter* emtr = work->mpEmtr; + JPAExtraShape* esp = work->mpRes->getEsp(); + JPABaseShape* bsp = work->mpRes->getBsp(); + JPADynamicsBlock* dyn = work->mpRes->getDyn(); + + mAge = -1; + mLifeTime = (1.0f - dyn->getLifetimeRndm() * emtr->get_r_f()) * emtr->mLifeTime; + mTime = 0.0f; + + initStatus(0); + MTXMultVecSR(work->mGlobalSR, &work->mVolumeCalcData.mVolumePos, &mLocalPosition); + if (emtr->checkFlag(8)) { + setStatus(0x20); + } + + mOffsetPosition.set(work->mGlobalPos); + mPosition.set(mOffsetPosition.x + mLocalPosition.x * work->mPublicScale.x, + mOffsetPosition.y + mLocalPosition.y * work->mPublicScale.y, + mOffsetPosition.z + mLocalPosition.z * work->mPublicScale.z); + + JGeometry::TVec3 velOmni; + if (emtr->mAwayFromCenterSpeed) { + velOmni.setLength(work->mVolumeCalcData.mVelOmni, emtr->mAwayFromCenterSpeed); + } else { + velOmni.zero(); + } + + JGeometry::TVec3 velAxis; + if (emtr->mAwayFromAxisSpeed) { + velAxis.setLength(work->mVolumeCalcData.mVelAxis, emtr->mAwayFromAxisSpeed); + } else { + velAxis.zero(); + } + + JGeometry::TVec3 velDir; + if (emtr->mDirSpeed) { + Mtx mtx; + JPAGetYZRotateMtx(emtr->get_r_zp() * 0x8000 * emtr->mSpread, emtr->get_r_ss(), mtx); + MTXConcat(work->mDirectionMtx, mtx, mtx); + velDir.set(emtr->mDirSpeed * mtx[0][2], + emtr->mDirSpeed * mtx[1][2], + emtr->mDirSpeed * mtx[2][2]); + } else { + velDir.zero(); + } + + JGeometry::TVec3 velRndm; + if (emtr->mRndmDirSpeed) { + velRndm.set(emtr->mRndmDirSpeed * emtr->get_r_zh(), + emtr->mRndmDirSpeed * emtr->get_r_zh(), + emtr->mRndmDirSpeed * emtr->get_r_zh()); + } else { + velRndm.zero(); + } + + f32 ratio = emtr->get_r_zp() * dyn->getInitVelRatio() + 1.0f; + mVelType1.set(ratio * (velOmni.x + velAxis.x + velDir.x + velRndm.x), + ratio * (velOmni.y + velAxis.y + velDir.y + velRndm.y), + ratio * (velOmni.z + velAxis.z + velDir.z + velRndm.z)); + + if (emtr->checkFlag(4)) { + mVelType1.mul(emtr->mLocalScl); + } + MTXMultVecSR(work->mGlobalRot, &mVelType1, &mVelType1); + + mVelType0.zero(); + + mMoment = 1.0f - dyn->getMomentRndm() * emtr->get_r_f(); + mDrag = 1.0f; + field_0x78 = 0; + + mBaseAxis.set(work->mGlobalRot[0][1], work->mGlobalRot[1][1], work->mGlobalRot[2][1]); + + mPrmClr = emtr->mPrmClr; + mEnvClr = emtr->mEnvClr; + + mAnmRandom = emtr->get_r_f() * bsp->getLoopOfstValue(); + + if (esp != NULL && esp->isEnableScaleAnm()) { + mParticleScaleX = mParticleScaleY = mScaleOut = emtr->mScaleOut * (emtr->get_r_zp() * esp->getScaleRndm() + 1.0f); + } else { + mParticleScaleX = mParticleScaleY = mScaleOut = emtr->mScaleOut; + } + + mPrmColorAlphaAnm = 0xff; + + if (esp != NULL && esp->isEnableAlphaFlick()) { + mAlphaWaveRandom = emtr->get_r_zp() * esp->getAlphaFreqRndm() + 1.0f; + } else { + mAlphaWaveRandom = 1.0f; + } + + if (esp != NULL) { + if (esp->isEnableRotateAnm()) { + mRotateAngle = esp->getRotateInitAngle() + esp->getRotateRndmAngle() * emtr->get_r_zh(); + mRotateSpeed = esp->getRotateInitSpeed() * + (esp->getRotateRndmSpeed() * emtr->get_r_zp() + 1.0f); + mRotateSpeed = emtr->get_r_zp() < esp->getRotateDirection() ? + mRotateSpeed : (s16)-mRotateSpeed; + } else { + mRotateAngle = 0; + mRotateSpeed = 0; + } + } else { + mRotateAngle = 0; + mRotateSpeed = 0; + } +} + +/* 8027F8C8-8027FFD0 27A208 0708+00 0/0 1/1 0/0 .text + * init_c__15JPABaseParticleFP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent) { + JPABaseEmitter* emtr = work->mpEmtr; + JPAChildShape* csp = work->mpRes->getCsp(); + + mAge = -1; + mLifeTime = csp->getLife(); + mTime = 0.0f; + initStatus(4); + mLocalPosition.set(parent->mLocalPosition); + + f32 pos_rndm = csp->getPosRndm(); + if (pos_rndm != 0.0f) { + JGeometry::TVec3 rnd(emtr->get_r_zh(), emtr->get_r_zh(), emtr->get_r_zh()); + rnd.setLength(pos_rndm * emtr->get_r_f()); + mLocalPosition.add(rnd); + } + + if (emtr->checkFlag(0x10)) { + setStatus(0x20); + } + + mOffsetPosition.set(parent->mOffsetPosition); + + f32 base_speed = csp->getBaseVel() * (csp->getBaseVelRndm() * emtr->get_r_zp() + 1.0f); + JGeometry::TVec3 base_vel(emtr->get_r_zp(), emtr->get_r_zp(), emtr->get_r_zp()); + base_vel.setLength(base_speed); + mVelType1.scaleAdd(csp->getVelInhRate(), parent->mVelType1, base_vel); + mVelType0.scale(csp->getVelInhRate(), parent->mVelType2); + + mMoment = parent->mMoment; + if (csp->isFieldAffected()) { + mDrag = parent->mDrag; + } else { + setStatus(0x40); + mDrag = 1.0f; + } + field_0x78 = parent->field_0x78; + + mVelType2.set(mVelType0); + f32 ratio = mMoment * mDrag; + mVelocity.set(ratio * (mVelType1.x + mVelType2.x), + ratio * (mVelType1.y + mVelType2.y), + ratio * (mVelType1.z + mVelType2.z)); + + mBaseAxis.set(parent->mBaseAxis); + + if (csp->isScaleInherited()) { + mParticleScaleX = mScaleOut = parent->mParticleScaleX * csp->getScaleInhRate(); + mParticleScaleY = mAlphaWaveRandom = parent->mParticleScaleY * csp->getScaleInhRate(); + } else { + mParticleScaleX = mScaleOut = mParticleScaleY = mAlphaWaveRandom = 1.0f; + } + + if (csp->isColorInherited()) { + mPrmClr.r = parent->mPrmClr.r * csp->getColorInhRate(); + mPrmClr.g = parent->mPrmClr.g * csp->getColorInhRate(); + mPrmClr.b = parent->mPrmClr.b * csp->getColorInhRate(); + mEnvClr.r = parent->mEnvClr.r * csp->getColorInhRate(); + mEnvClr.g = parent->mEnvClr.g * csp->getColorInhRate(); + mEnvClr.b = parent->mEnvClr.b * csp->getColorInhRate(); + } else { + csp->getPrmClr(&mPrmClr); + csp->getEnvClr(&mEnvClr); + } + + mPrmColorAlphaAnm = 0xff; + if (csp->isAlphaInherited()) { + mPrmClr.a = COLOR_MULTI(parent->mPrmClr.a, parent->mPrmColorAlphaAnm) + * csp->getAlphaInhRate(); + } else { + mPrmClr.a = csp->getPrmAlpha(); + } + + mRotateAngle = parent->mRotateAngle; + if (csp->isRotateOn()) { + mRotateSpeed = csp->getRotInitSpeed(); + } else { + mRotateSpeed = 0; + } + + mTexAnmIdx = 0; +} + +/* 8027FFD0-80280260 27A910 0290+00 0/0 1/1 0/0 .text + * calc_p__15JPABaseParticleFP18JPAEmitterWorkData */ +bool JPABaseParticle::calc_p(JPAEmitterWorkData* work) { + if (++mAge >= mLifeTime) { + return true; + } + mTime = (f32)mAge / (f32)mLifeTime; + + if (checkStatus(0x20)) { + mOffsetPosition.set(work->mGlobalPos); + } + + mVelType2.zero(); + if (!checkStatus(0x40)) { + work->mpRes->calcField(work, this); + } + mVelType2.add(mVelType0); + mVelType1.scale(work->mpEmtr->mAirResist); + f32 ratio = mMoment * mDrag; + mVelocity.set(ratio * (mVelType1.x + mVelType2.x), + ratio * (mVelType1.y + mVelType2.y), + ratio * (mVelType1.z + mVelType2.z)); + + if (work->mpEmtr->mpPtclCallBack != NULL) { + work->mpEmtr->mpPtclCallBack->execute(work->mpEmtr, this); + } + + if (checkStatus(2)) { + return true; + } + + work->mpRes->calc_p(work, this); + mRotateAngle += mRotateSpeed; + + if (work->mpRes->getCsp() != NULL && canCreateChild(work)) { + for (int i = work->mpRes->getCsp()->getRate(); i > 0; i--) { + work->mpEmtr->createChild(this); + } + } + + mLocalPosition.add(mVelocity); + mPosition.set(mOffsetPosition.x + mLocalPosition.x * work->mPublicScale.x, + mOffsetPosition.y + mLocalPosition.y * work->mPublicScale.y, + mOffsetPosition.z + mLocalPosition.z * work->mPublicScale.z); + + return false; +} + +/* 80280260-802804C8 27ABA0 0268+00 0/0 1/1 0/0 .text + * calc_c__15JPABaseParticleFP18JPAEmitterWorkData */ +bool JPABaseParticle::calc_c(JPAEmitterWorkData* work) { + if (++mAge >= mLifeTime) { + return true; + } + mTime = (f32)mAge / (f32)mLifeTime; + + if (mAge != 0) { + if (checkStatus(0x20)) { + mOffsetPosition.set(work->mGlobalPos); + } + + mVelType1.y -= work->mpRes->getCsp()->getGravity(); + mVelType2.zero(); + if (!checkStatus(0x40)) { + work->mpRes->calcField(work, this); + } + mVelType2.add(mVelType0); + mVelType1.scale(work->mpEmtr->mAirResist); + f32 ratio = mMoment * mDrag; + mVelocity.set(ratio * (mVelType1.x + mVelType2.x), + ratio * (mVelType1.y + mVelType2.y), + ratio * (mVelType1.z + mVelType2.z)); + } + + if (work->mpEmtr->mpPtclCallBack != NULL) { + work->mpEmtr->mpPtclCallBack->execute(work->mpEmtr, this); + } + + if (checkStatus(2)) { + return true; + } + + work->mpRes->calc_c(work, this); + mRotateAngle += mRotateSpeed; + mLocalPosition.add(mVelocity); + mPosition.set(mOffsetPosition.x + mLocalPosition.x * work->mPublicScale.x, + mOffsetPosition.y + mLocalPosition.y * work->mPublicScale.y, + mOffsetPosition.z + mLocalPosition.z * work->mPublicScale.z); + + return false; +} + +/* 802804C8-80280548 27AE08 0080+00 1/1 0/0 0/0 .text + * canCreateChild__15JPABaseParticleFP18JPAEmitterWorkData */ +bool JPABaseParticle::canCreateChild(JPAEmitterWorkData* work) { + JPAChildShape* csp = work->mpRes->getCsp(); + bool ret = false; + int time = mAge - (int)((mLifeTime - 1) * csp->getTiming()); + if (time >= 0 && time % (csp->getStep() + 1) == 0) { + ret = true; + } + return ret; +} + +/* 80280548-80280568 27AE88 0020+00 0/0 3/3 0/0 .text + * getWidth__15JPABaseParticleCFPC14JPABaseEmitter */ +f32 JPABaseParticle::getWidth(JPABaseEmitter const* emtr) const { + f32 scale = 2.0f * mParticleScaleX; + return scale * emtr->mpEmtrMgr->pWd->mGlobalPtclScl.x; +} + +/* 80280568-80280588 27AEA8 0020+00 0/0 3/3 0/0 .text + * getHeight__15JPABaseParticleCFPC14JPABaseEmitter */ +f32 JPABaseParticle::getHeight(JPABaseEmitter const* emtr) const { + f32 scale = 2.0f * mParticleScaleY; + return scale * emtr->mpEmtrMgr->pWd->mGlobalPtclScl.y; +} diff --git a/src/JSystem/JParticle/JPAResource.cpp b/src/JSystem/JParticle/JPAResource.cpp new file mode 100644 index 00000000..01bba7d2 --- /dev/null +++ b/src/JSystem/JParticle/JPAResource.cpp @@ -0,0 +1,1124 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAResource +// + +#include "JSystem/JParticle/JPAResource.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JParticle/JPABaseShape.h" +#include "JSystem/JParticle/JPAChildShape.h" +#include "JSystem/JParticle/JPAEmitter.h" +#include "JSystem/JParticle/JPAExTexShape.h" +#include "JSystem/JParticle/JPAExtraShape.h" +#include "JSystem/JParticle/JPAFieldBlock.h" +#include "JSystem/JParticle/JPAKeyBlock.h" +#include "JSystem/JParticle/JPAParticle.h" +#include "JSystem/JParticle/JPAResourceManager.h" +#include "dolphin/gx.h" +#include "global.h" + +/* 80274010-80274080 26E950 0070+00 0/0 1/1 0/0 .text __ct__11JPAResourceFv */ +JPAResource::JPAResource() { + mpDrawEmitterChildFuncList = NULL; + mpDrawEmitterFuncList = NULL; + mpCalcEmitterFuncList = NULL; + mpDrawParticleChildFuncList = NULL; + mpCalcParticleChildFuncList = NULL; + mpDrawParticleFuncList = NULL; + mpCalcParticleFuncList = NULL; + mpBaseShape = NULL; + mpExtraShape = NULL; + mpChildShape = NULL; + mpExTexShape = NULL; + mpDynamicsBlock = NULL; + mpFieldBlocks = NULL; + mpKeyBlocks = NULL; + mpTDB1 = NULL; + mpDrawParticleChildFuncListNum = 0; + mpCalcParticleChildFuncListNum = 0; + mpDrawParticleFuncListNum = 0; + mpCalcParticleFuncListNum = 0; + mpDrawEmitterChildFuncListNum = 0; + mpDrawEmitterFuncListNum = 0; + mpCalcEmitterFuncListNum = 0; + mTDB1Num = 0; + mKeyBlockNum = 0; + mFieldBlockNum = 0; + mUsrIdx = 0; +} + +/* 803C40C0-803C4220 0211E0 0144+1C 2/2 0/0 0/0 .data jpa_pos */ +static u8 jpa_pos[324] ALIGN_DECL(32) = { + 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0xCE, 0x00, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x19, 0xCE, 0x00, 0xE7, 0xCE, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, + 0x00, 0xCE, 0xCE, 0x00, 0x00, 0x19, 0x00, 0x32, 0x19, 0x00, 0x32, 0xE7, 0x00, 0x00, 0xE7, 0x00, + 0xE7, 0x19, 0x00, 0x19, 0x19, 0x00, 0x19, 0xE7, 0x00, 0xE7, 0xE7, 0x00, 0xCE, 0x19, 0x00, 0x00, + 0x19, 0x00, 0x00, 0xE7, 0x00, 0xCE, 0xE7, 0x00, 0x00, 0x32, 0x00, 0x32, 0x32, 0x00, 0x32, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE7, 0x32, 0x00, 0x19, 0x32, 0x00, 0x19, 0x00, 0x00, 0xE7, 0x00, 0x00, + 0xCE, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x32, 0x00, 0x32, 0x00, 0x00, 0x32, 0xE7, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, + 0x32, 0xE7, 0x00, 0x32, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xCE, 0x00, 0x32, + 0x00, 0x00, 0xE7, 0x32, 0x00, 0xE7, 0x32, 0x00, 0x19, 0x00, 0x00, 0x19, 0xE7, 0x00, 0xE7, 0x19, + 0x00, 0xE7, 0x19, 0x00, 0x19, 0xE7, 0x00, 0x19, 0xCE, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, + 0x19, 0xCE, 0x00, 0x19, 0x00, 0x00, 0xCE, 0x32, 0x00, 0xCE, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE7, 0x00, 0xCE, 0x19, 0x00, 0xCE, 0x19, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xCE, 0x00, 0xCE, 0x00, + 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0xCE, + 0x32, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x19, 0x00, 0xCE, 0x19, 0x00, 0xCE, 0xE7, + 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0xCE, 0xCE, 0x00, 0x19, 0x00, 0x00, + 0x19, 0x32, 0x00, 0xE7, 0x32, 0x00, 0xE7, 0x00, 0x00, 0x19, 0xE7, 0x00, 0x19, 0x19, 0x00, 0xE7, + 0x19, 0x00, 0xE7, 0xE7, 0x00, 0x19, 0xCE, 0x00, 0x19, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0xCE, + 0x00, 0x32, 0x00, 0x00, 0x32, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x32, 0xE7, 0x00, + 0x32, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0xE7, 0x00, 0x32, 0xCE, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xCE, +}; + +/* 803C4220-803C4240 021340 0020+00 2/2 0/0 0/0 .data jpa_crd */ +static u8 jpa_crd[32] ALIGN_DECL(32) = { + 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, +}; + +/* 80274080-802755E8 26E9C0 1568+00 2/0 1/1 0/0 .text init__11JPAResourceFP7JKRHeap */ +void JPAResource::init(JKRHeap* heap) { + BOOL is_glbl_clr_anm = mpBaseShape->isGlblClrAnm(); + BOOL is_glbl_tex_anm = mpBaseShape->isGlblTexAnm(); + BOOL is_prm_anm = mpBaseShape->isPrmAnm(); + BOOL is_env_anm = mpBaseShape->isEnvAnm(); + BOOL is_tex_anm = mpBaseShape->isTexAnm(); + BOOL is_tex_crd_anm = mpBaseShape->isTexCrdAnm(); + BOOL is_prj_tex = mpBaseShape->isPrjTex(); + BOOL is_enable_scale_anm = mpExtraShape != NULL && mpExtraShape->isEnableScaleAnm(); + BOOL is_enable_alpha_anm = mpExtraShape != NULL && mpExtraShape->isEnableAlphaAnm(); + BOOL is_enable_alpha_flick = mpExtraShape != NULL && mpExtraShape->isEnableAlphaAnm() + && mpExtraShape->isEnableAlphaFlick(); + BOOL is_enable_rotate_anm = mpExtraShape != NULL && mpExtraShape->isEnableRotateAnm(); + BOOL is_rotate_on = is_enable_rotate_anm + || (mpChildShape != NULL && mpChildShape->isRotateOn()); + BOOL base_type_5_6 = mpBaseShape->getType() == 5 || mpBaseShape->getType() == 6; + BOOL base_type_0 = mpBaseShape->getType() == 0; + BOOL base_type_0_1 = mpBaseShape->getType() == 0 || mpBaseShape->getType() == 1; + BOOL child_type_5_6 = mpChildShape != NULL + && (mpChildShape->getType() == 5 || mpChildShape->getType() == 6); + BOOL child_type_0 = mpChildShape != NULL && mpChildShape->getType() == 0; + BOOL child_type_0_1 = mpChildShape != NULL + && (mpChildShape->getType() == 0 || mpChildShape->getType() == 1); + BOOL is_draw_parent = !mpBaseShape->isNoDrawParent(); + BOOL is_draw_child = !mpBaseShape->isNoDrawChild(); + + if (is_glbl_tex_anm && is_tex_anm) { + mpCalcEmitterFuncListNum++; + } + + if (is_glbl_clr_anm) { + if (is_prm_anm) { + mpCalcEmitterFuncListNum++; + } + if (is_env_anm) { + mpCalcEmitterFuncListNum++; + } + if (is_prm_anm || is_env_anm) { + mpCalcEmitterFuncListNum++; + } + } + + if (mpCalcEmitterFuncListNum != 0) { + mpCalcEmitterFuncList = + (EmitterFunc*)JKRAllocFromHeap(heap, mpCalcEmitterFuncListNum * 4, 4); + } + + int func_no = 0; + + if (is_glbl_tex_anm && is_tex_anm) { + switch (mpBaseShape->getTexAnmType()) { + case 0: + mpCalcEmitterFuncList[func_no] = &JPACalcTexIdxNormal; + break; + case 1: + mpCalcEmitterFuncList[func_no] = &JPACalcTexIdxRepeat; + break; + case 2: + mpCalcEmitterFuncList[func_no] = &JPACalcTexIdxReverse; + break; + case 3: + mpCalcEmitterFuncList[func_no] = &JPACalcTexIdxMerge; + break; + case 4: + mpCalcEmitterFuncList[func_no] = &JPACalcTexIdxRandom; + break; + } + func_no++; + } + + if (is_glbl_clr_anm) { + if (is_prm_anm) { + mpCalcEmitterFuncList[func_no] = &JPACalcPrm; + func_no++; + } + if (is_env_anm) { + mpCalcEmitterFuncList[func_no] = &JPACalcEnv; + func_no++; + } + if (is_prm_anm || is_env_anm) { + switch (mpBaseShape->getClrAnmType()) { + case 0: + mpCalcEmitterFuncList[func_no] = &JPACalcClrIdxNormal; + break; + case 1: + mpCalcEmitterFuncList[func_no] = &JPACalcClrIdxRepeat; + break; + case 2: + mpCalcEmitterFuncList[func_no] = &JPACalcClrIdxReverse; + break; + case 3: + mpCalcEmitterFuncList[func_no] = &JPACalcClrIdxMerge; + break; + case 4: + mpCalcEmitterFuncList[func_no] = &JPACalcClrIdxRandom; + break; + } + } + } + + if (!is_glbl_tex_anm && is_tex_anm) { + mpCalcParticleFuncListNum++; + } + + if (!base_type_5_6 && (is_enable_alpha_anm || is_enable_alpha_flick)) { + mpCalcParticleFuncListNum++; + } + + if (!is_glbl_clr_anm) { + if (is_prm_anm) { + mpCalcParticleFuncListNum++; + } + if (is_env_anm) { + mpCalcParticleFuncListNum++; + } + if (is_prm_anm || is_env_anm) { + mpCalcParticleFuncListNum++; + } + } else { + mpCalcParticleFuncListNum++; + } + + if (is_enable_scale_anm) { + if (mpBaseShape->getType() != 0) { + if (mpExtraShape->isScaleXYDiff()) { + if (mpExtraShape->getScaleAnmTypeX() == 0 && mpExtraShape->getScaleAnmTypeY() == 0) { + mpCalcParticleFuncListNum++; + } else { + mpCalcParticleFuncListNum++; + mpCalcParticleFuncListNum++; + } + } else { + mpCalcParticleFuncListNum++; + } + } + mpCalcParticleFuncListNum++; + mpCalcParticleFuncListNum++; + } + + if (mpCalcParticleFuncListNum != 0) { + mpCalcParticleFuncList = + (ParticleFunc*)JKRAllocFromHeap(heap, mpCalcParticleFuncListNum * 4, 4); + } + + func_no = 0; + + if (!is_glbl_tex_anm && is_tex_anm) { + switch (mpBaseShape->getTexAnmType()) { + case 0: + mpCalcParticleFuncList[func_no] = &JPACalcTexIdxNormal; + break; + case 1: + mpCalcParticleFuncList[func_no] = &JPACalcTexIdxRepeat; + break; + case 2: + mpCalcParticleFuncList[func_no] = &JPACalcTexIdxReverse; + break; + case 3: + mpCalcParticleFuncList[func_no] = &JPACalcTexIdxMerge; + break; + case 4: + mpCalcParticleFuncList[func_no] = &JPACalcTexIdxRandom; + break; + } + func_no++; + } + + if (!base_type_5_6 && (is_enable_alpha_anm || is_enable_alpha_flick)) { + if (is_enable_alpha_flick) { + mpCalcParticleFuncList[func_no] = &JPACalcAlphaFlickAnm; + func_no++; + } else { + mpCalcParticleFuncList[func_no] = &JPACalcAlphaAnm; + func_no++; + } + } + + if (!is_glbl_clr_anm) { + if (is_prm_anm) { + mpCalcParticleFuncList[func_no] = &JPACalcPrm; + func_no++; + } + if (is_env_anm) { + mpCalcParticleFuncList[func_no] = &JPACalcEnv; + func_no++; + } + if (is_prm_anm || is_env_anm) { + switch (mpBaseShape->getClrAnmType()) { + case 0: + mpCalcParticleFuncList[func_no] = &JPACalcClrIdxNormal; + break; + case 1: + mpCalcParticleFuncList[func_no] = &JPACalcClrIdxRepeat; + break; + case 2: + mpCalcParticleFuncList[func_no] = &JPACalcClrIdxReverse; + break; + case 3: + mpCalcParticleFuncList[func_no] = &JPACalcClrIdxMerge; + break; + case 4: + mpCalcParticleFuncList[func_no] = &JPACalcClrIdxRandom; + break; + } + func_no++; + } + } else { + mpCalcParticleFuncList[func_no] = &JPACalcColorCopy; + func_no++; + } + + if (is_enable_scale_anm) { + if (mpBaseShape->getType() != 0) { + if (mpExtraShape->isScaleXYDiff()) { + mpCalcParticleFuncList[func_no] = &JPACalcScaleY; + func_no++; + if (mpExtraShape->getScaleAnmTypeY() != 0 || mpExtraShape->getScaleAnmTypeX() != 0) { + switch (mpExtraShape->getScaleAnmTypeY()) { + case 0: + mpCalcParticleFuncList[func_no] = &JPACalcScaleAnmNormal; + break; + case 1: + mpCalcParticleFuncList[func_no] = &JPACalcScaleAnmRepeatY; + break; + case 2: + mpCalcParticleFuncList[func_no] = &JPACalcScaleAnmReverseY; + break; + } + func_no++; + } + } else { + mpCalcParticleFuncList[func_no] = &JPACalcScaleCopy; + func_no++; + } + } + mpCalcParticleFuncList[func_no] = &JPACalcScaleX; + func_no++; + switch (mpExtraShape->getScaleAnmTypeX()) { + case 0: + mpCalcParticleFuncList[func_no] = &JPACalcScaleAnmNormal; + break; + case 1: + mpCalcParticleFuncList[func_no] = &JPACalcScaleAnmRepeatX; + break; + case 2: + mpCalcParticleFuncList[func_no] = &JPACalcScaleAnmReverseX; + break; + } + } + + if (mpChildShape != NULL && mpChildShape->isScaleOutOn()) { + mpCalcParticleChildFuncListNum++; + } + + if (mpChildShape != NULL && mpChildShape->isAlphaOutOn()) { + mpCalcParticleChildFuncListNum++; + } + + if (mpCalcParticleChildFuncListNum != 0) { + mpCalcParticleChildFuncList = + (ParticleFunc*)JKRAllocFromHeap(heap, mpCalcParticleChildFuncListNum * 4, 4); + } + + func_no = 0; + + if (mpChildShape != NULL && mpChildShape->isScaleOutOn()) { + mpCalcParticleChildFuncList[func_no] = &JPACalcChildScaleOut; + func_no++; + } + + if (mpChildShape != NULL && mpChildShape->isAlphaOutOn()) { + mpCalcParticleChildFuncList[func_no] = &JPACalcChildAlphaOut; + } + + if (is_draw_parent && base_type_5_6) { + mpDrawEmitterFuncListNum++; + } + + mpDrawEmitterFuncListNum++; + + if (mpExTexShape != NULL) { + mpDrawEmitterFuncListNum++; + } + + if (is_glbl_tex_anm || !is_tex_anm) { + mpDrawEmitterFuncListNum++; + } + + mpDrawEmitterFuncListNum++; + + if (base_type_0_1) { + mpDrawEmitterFuncListNum++; + } + + if (base_type_0_1 && !is_enable_scale_anm) { + mpDrawEmitterFuncListNum++; + } + + if (is_glbl_clr_anm || (!is_prm_anm && !is_enable_alpha_anm) || !is_env_anm) { + mpDrawEmitterFuncListNum++; + } + + if (mpDrawEmitterFuncListNum != 0) { + mpDrawEmitterFuncList = + (EmitterFunc*)JKRAllocFromHeap(heap, mpDrawEmitterFuncListNum * 4, 4); + } + + func_no = 0; + + if (is_draw_parent && base_type_5_6) { + if (mpBaseShape->getType() == 5) { + mpDrawEmitterFuncList[func_no] = &JPADrawStripe; + func_no++; + } else { + mpDrawEmitterFuncList[func_no] = &JPADrawStripeX; + func_no++; + } + } + + mpDrawEmitterFuncList[func_no] = &JPADrawEmitterCallBackB; + func_no++; + + if (mpExTexShape != NULL) { + mpDrawEmitterFuncList[func_no] = &JPALoadExTex; + func_no++; + } + + if (!is_tex_anm) { + mpDrawEmitterFuncList[func_no] = &JPALoadTex; + func_no++; + } else if (is_glbl_tex_anm) { + mpDrawEmitterFuncList[func_no] = &JPALoadTexAnm; + func_no++; + } + + if (base_type_0_1) { + mpDrawEmitterFuncList[func_no] = &JPAGenTexCrdMtxIdt; + func_no++; + } else if (is_prj_tex) { + mpDrawEmitterFuncList[func_no] = &JPAGenTexCrdMtxPrj; + func_no++; + } else if (is_tex_crd_anm) { + if (base_type_5_6) { + mpDrawEmitterFuncList[func_no] = &JPAGenCalcTexCrdMtxAnm; + func_no++; + } else { + mpDrawEmitterFuncList[func_no] = &JPAGenTexCrdMtxAnm; + func_no++; + } + } else { + mpDrawEmitterFuncList[func_no] = &JPAGenTexCrdMtxIdt; + func_no++; + } + + if (base_type_0_1) { + mpDrawEmitterFuncList[func_no] = &JPALoadPosMtxCam; + func_no++; + } + + if (base_type_0_1 && !is_enable_scale_anm) { + if (base_type_0) { + mpDrawEmitterFuncList[func_no] = &JPASetPointSize; + func_no++; + } else { + mpDrawEmitterFuncList[func_no] = &JPASetLineWidth; + func_no++; + } + } + + if (is_glbl_clr_anm) { + if (base_type_5_6 || !is_enable_alpha_anm) { + mpDrawEmitterFuncList[func_no] = &JPARegistPrmEnv; + } else if (is_enable_alpha_anm) { + mpDrawEmitterFuncList[func_no] = &JPARegistEnv; + } + } else if (!is_prm_anm && !is_enable_alpha_anm) { + if (!is_env_anm) { + mpDrawEmitterFuncList[func_no] = &JPARegistPrmEnv; + } else { + mpDrawEmitterFuncList[func_no] = &JPARegistPrm; + } + } else if (!is_env_anm) { + mpDrawEmitterFuncList[func_no] = &JPARegistEnv; + } + + if (is_draw_child && child_type_5_6) { + mpDrawEmitterChildFuncListNum++; + } + + mpDrawEmitterChildFuncListNum++; + + if (child_type_0_1) { + mpDrawEmitterChildFuncListNum++; + } + + if (mpChildShape != NULL && !mpChildShape->isAlphaOutOn() && !mpChildShape->isAlphaInherited() + && !mpChildShape->isColorInherited()) { + mpDrawEmitterChildFuncListNum++; + } + + if (mpDrawEmitterChildFuncListNum != 0) { + mpDrawEmitterChildFuncList = + (EmitterFunc*)JKRAllocFromHeap(heap, mpDrawEmitterChildFuncListNum * 4, 4); + } + + func_no = 0; + + if (is_draw_child && child_type_5_6) { + if (mpChildShape->getType() == 5) { + mpDrawEmitterChildFuncList[func_no] = &JPADrawStripe; + func_no++; + } else { + mpDrawEmitterChildFuncList[func_no] = &JPADrawStripeX; + func_no++; + } + } + + mpDrawEmitterChildFuncList[func_no] = &JPADrawEmitterCallBackB; + func_no++; + + if (child_type_0_1) { + mpDrawEmitterChildFuncList[func_no] = &JPALoadPosMtxCam; + func_no++; + } + + if (mpChildShape != NULL && !mpChildShape->isAlphaOutOn() && !mpChildShape->isAlphaInherited() + && !mpChildShape->isColorInherited()) { + mpDrawEmitterChildFuncList[func_no] = &JPARegistChildPrmEnv; + } + + if (is_draw_parent && !base_type_5_6) { + mpDrawParticleFuncListNum++; + } + + mpDrawParticleFuncListNum++; + + if (!is_glbl_tex_anm && is_tex_anm) { + mpDrawParticleFuncListNum++; + } + + if ((base_type_0_1 && is_enable_scale_anm) || (is_tex_crd_anm && !is_prj_tex)) { + mpDrawParticleFuncListNum++; + } + + if ((!is_glbl_clr_anm && (is_prm_anm || is_env_anm || is_enable_alpha_anm)) + || (is_glbl_clr_anm && is_enable_alpha_anm && !base_type_5_6)) { + mpDrawParticleFuncListNum++; + } + + if (mpDrawParticleFuncListNum != 0) { + mpDrawParticleFuncList = + (ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleFuncListNum * 4, 4); + } + + func_no = 0; + + if (is_draw_parent && !base_type_5_6) { + switch (mpBaseShape->getType()) { + case 2: + if (is_enable_rotate_anm) { + mpDrawParticleFuncList[func_no] = &JPADrawRotBillboard; + } else { + mpDrawParticleFuncList[func_no] = &JPADrawBillboard; + } + break; + case 10: + if (is_enable_rotate_anm) { + mpDrawParticleFuncList[func_no] = &JPADrawRotYBillboard; + } else { + mpDrawParticleFuncList[func_no] = &JPADrawYBillboard; + } + break; + case 3: + case 4: + if (is_enable_rotate_anm) { + mpDrawParticleFuncList[func_no] = &JPADrawRotDirection; + } else { + mpDrawParticleFuncList[func_no] = &JPADrawDirection; + } + break; + case 9: + mpDrawParticleFuncList[func_no] = &JPADrawDBillboard; + break; + case 7: + case 8: + mpDrawParticleFuncList[func_no] = &JPADrawRotation; + break; + case 0: + mpDrawParticleFuncList[func_no] = &JPADrawPoint; + break; + case 1: + mpDrawParticleFuncList[func_no] = &JPADrawLine; + break; + } + func_no++; + } + + mpDrawParticleFuncList[func_no] = &JPADrawParticleCallBack; + func_no++; + + if (!is_glbl_tex_anm && is_tex_anm) { + mpDrawParticleFuncList[func_no] = &JPALoadTexAnm; + func_no++; + } + + if (base_type_0_1 && is_enable_scale_anm) { + if (base_type_0) { + mpDrawParticleFuncList[func_no] = &JPASetPointSize; + func_no++; + } else { + mpDrawParticleFuncList[func_no] = &JPASetLineWidth; + func_no++; + } + } else if (is_tex_crd_anm && !is_prj_tex) { + mpDrawParticleFuncList[func_no] = &JPALoadCalcTexCrdMtxAnm; + func_no++; + } + + if (!is_glbl_clr_anm) { + if (is_prm_anm) { + if (is_env_anm) { + mpDrawParticleFuncList[func_no] = &JPARegistPrmAlphaEnv; + } else { + mpDrawParticleFuncList[func_no] = &JPARegistPrmAlpha; + } + } else if (is_enable_alpha_anm) { + if (is_env_anm) { + mpDrawParticleFuncList[func_no] = &JPARegistAlphaEnv; + } else { + mpDrawParticleFuncList[func_no] = &JPARegistAlpha; + } + } else if (is_env_anm) { + mpDrawParticleFuncList[func_no] = &JPARegistEnv; + } + } else if (is_enable_alpha_anm && !base_type_5_6) { + mpDrawParticleFuncList[func_no] = &JPARegistAlpha; + } + + if (is_draw_child && mpChildShape != NULL && !child_type_5_6) { + mpDrawParticleChildFuncListNum++; + } + + mpDrawParticleChildFuncListNum++; + + if (child_type_0_1) { + mpDrawParticleChildFuncListNum++; + } + + if (mpChildShape != NULL && (mpChildShape->isAlphaOutOn() || mpChildShape->isAlphaInherited() + || mpChildShape->isColorInherited())) { + mpDrawParticleChildFuncListNum++; + } + + if (mpDrawParticleChildFuncListNum != 0) { + mpDrawParticleChildFuncList = + (ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleChildFuncListNum * 4, 4); + } + + func_no = 0; + + if (is_draw_child && mpChildShape != NULL && !child_type_5_6) { + switch (mpChildShape->getType()) { + case 2: + if (is_rotate_on) { + mpDrawParticleChildFuncList[func_no] = &JPADrawRotBillboard; + } else { + mpDrawParticleChildFuncList[func_no] = &JPADrawBillboard; + } + break; + case 10: + if (is_rotate_on) { + mpDrawParticleChildFuncList[func_no] = &JPADrawRotYBillboard; + } else { + mpDrawParticleChildFuncList[func_no] = &JPADrawYBillboard; + } + break; + case 3: + case 4: + if (is_rotate_on) { + mpDrawParticleChildFuncList[func_no] = &JPADrawRotDirection; + } else { + mpDrawParticleChildFuncList[func_no] = &JPADrawDirection; + } + break; + case 9: + mpDrawParticleChildFuncList[func_no] = &JPADrawDBillboard; + break; + case 7: + case 8: + mpDrawParticleChildFuncList[func_no] = &JPADrawRotation; + break; + case 0: + mpDrawParticleChildFuncList[func_no] = &JPADrawPoint; + break; + case 1: + mpDrawParticleChildFuncList[func_no] = &JPADrawLine; + break; + } + func_no++; + } + + mpDrawParticleChildFuncList[func_no] = &JPADrawParticleCallBack; + func_no++; + + if (child_type_0_1) { + if (child_type_0) { + mpDrawParticleChildFuncList[func_no] = &JPASetPointSize; + func_no++; + } else { + mpDrawParticleChildFuncList[func_no] = &JPASetLineWidth; + func_no++; + } + } + + if (mpChildShape != NULL && (mpChildShape->isAlphaOutOn() || mpChildShape->isAlphaInherited() + || mpChildShape->isColorInherited())) { + mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv; + } +} + +/* 802755E8-80275A94 26FF28 04AC+00 0/0 1/1 0/0 .text + * calc__11JPAResourceFP18JPAEmitterWorkDataP14JPABaseEmitter */ +bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) { + work->mpEmtr = emtr; + work->mpRes = this; + work->mEmitCount = 0; + + if (!emtr->processTillStartFrame()) { + return false; + } + + if (emtr->processTermination()) { + return true; + } + + if (emtr->checkStatus(2)) { + if (emtr->mpEmtrCallBack != NULL) { + emtr->mpEmtrCallBack->execute(emtr); + if (emtr->checkStatus(0x100)) { + return true; + } + emtr->mpEmtrCallBack->executeAfter(emtr); + if (emtr->checkStatus(0x100)) { + return true; + } + } + + } else { + calcKey(work); + + for (int i = mFieldBlockNum - 1; i >= 0; i--) { + mpFieldBlocks[i]->initOpParam(); + } + + if (emtr->mpEmtrCallBack != NULL) { + emtr->mpEmtrCallBack->execute(emtr); + if (emtr->checkStatus(0x100)) { + return true; + } + } + + calcWorkData_c(work); + + for (int i = mpCalcEmitterFuncListNum - 1; i >= 0; i--) { + (*mpCalcEmitterFuncList[i])(work); + } + + for (int i = mFieldBlockNum - 1; i >= 0; i--) { + mpFieldBlocks[i]->prepare(work); + } + + if (!emtr->checkStatus(8)) { + mpDynamicsBlock->create(work); + } + + if (emtr->mpEmtrCallBack != NULL) { + emtr->mpEmtrCallBack->executeAfter(emtr); + if (emtr->checkStatus(0x100)) { + return true; + } + } + + JPANode* node = emtr->mAlivePtclBase.getFirst(); + JPANode* next; + while (node != emtr->mAlivePtclBase.getEnd()) { + next = node->getNext(); + if (node->getObject()->calc_p(work)) { + emtr->mpPtclPool->push_front(emtr->mAlivePtclBase.erase(node)); + } + node = next; + } + + node = emtr->mAlivePtclChld.getFirst(); + while (node != emtr->mAlivePtclChld.getEnd()) { + next = node->getNext(); + if (node->getObject()->calc_c(work)) { + emtr->mpPtclPool->push_front(emtr->mAlivePtclChld.erase(node)); + } + node = next; + } + + emtr->mTick++; + } + + return false; +} + +/* 80275A94-80275B74 2703D4 00E0+00 0/0 1/1 0/0 .text + * draw__11JPAResourceFP18JPAEmitterWorkDataP14JPABaseEmitter */ +void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) { + work->mpEmtr = emtr; + work->mpRes = this; + work->mDrawCount = 0; + calcWorkData_d(work); + mpBaseShape->setGX(work); + for (s32 i = 1; i <= emtr->getDrawTimes(); i++) { + work->mDrawCount++; + if (mpBaseShape->isDrawPrntAhead() && mpChildShape != NULL) + drawC(work); + drawP(work); + if (!mpBaseShape->isDrawPrntAhead() && mpChildShape != NULL) + drawC(work); + } +} + +/* 80275B74-80275EB0 2704B4 033C+00 1/1 0/0 0/0 .text drawP__11JPAResourceFP18JPAEmitterWorkData + */ +void JPAResource::drawP(JPAEmitterWorkData* work) { + work->mpEmtr->clearStatus(0x80); + + work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * mpBaseShape->getBaseSizeX(); + work->mGlobalPtclScl.y = work->mpEmtr->mGlobalPScl.y * mpBaseShape->getBaseSizeY(); + + if (mpBaseShape->getType() == 0) { + work->mGlobalPtclScl.x *= 1.02f; + } else if (mpBaseShape->getType() == 1) { + work->mGlobalPtclScl.x *= 1.02f; + work->mGlobalPtclScl.y *= 0.4f; + } + + if (mpExtraShape != NULL && mpExtraShape->isEnableScaleAnm()) { + work->mPivot.x = mpExtraShape->getScaleCenterX() - 1.0f; + work->mPivot.y = mpExtraShape->getScaleCenterY() - 1.0f; + } else { + work->mPivot.x = work->mPivot.y = 0.0f; + } + + work->mDirType = mpBaseShape->getDirType(); + work->mRotType = mpBaseShape->getRotType(); + work->mDLType = mpBaseShape->getType() == 4 || mpBaseShape->getType() == 8; + work->mPlaneType = work->mDLType ? 2 : mpBaseShape->getBasePlaneType(); + work->mPrjType = mpBaseShape->isPrjTex() ? (mpBaseShape->isTexCrdAnm() ? 2 : 1) : 0; + + work->mpAlivePtcl = &work->mpEmtr->mAlivePtclBase; + setPTev(); + + for (int i = mpDrawEmitterFuncListNum - 1; i >= 0; i--) { + (*mpDrawEmitterFuncList[i])(work); + } + + if (mpBaseShape->isDrawFwdAhead()) { + JPANode* node = work->mpEmtr->mAlivePtclBase.getLast(); + for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) { + work->mpCurNode = node; + if (mpDrawParticleFuncList != NULL) { + for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) { + (*mpDrawParticleFuncList[i])(work, node->getObject()); + } + } + } + } else { + JPANode* node = work->mpEmtr->mAlivePtclBase.getFirst(); + for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getNext()) { + work->mpCurNode = node; + if (mpDrawParticleFuncList != NULL) { + for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) { + (*mpDrawParticleFuncList[i])(work, node->getObject()); + } + } + } + } + + GXSetMisc(GX_MT_XF_FLUSH, 0); + + if (work->mpEmtr->mpEmtrCallBack != NULL) { + work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr); + } +} + +/* 80275EB0-802761A8 2707F0 02F8+00 1/1 0/0 0/0 .text drawC__11JPAResourceFP18JPAEmitterWorkData + */ +void JPAResource::drawC(JPAEmitterWorkData* work) { + work->mpEmtr->setStatus(0x80); + + if (mpChildShape->isScaleInherited()) { + work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * mpBaseShape->getBaseSizeX(); + work->mGlobalPtclScl.y = work->mpEmtr->mGlobalPScl.y * mpBaseShape->getBaseSizeY(); + } else { + work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * mpChildShape->getScaleX(); + work->mGlobalPtclScl.y = work->mpEmtr->mGlobalPScl.y * mpChildShape->getScaleY(); + } + + if (mpChildShape->getType() == 0) { + work->mGlobalPtclScl.x *= 1.02f; + } else if (mpChildShape->getType() == 1) { + work->mGlobalPtclScl.x *= 1.02f; + work->mGlobalPtclScl.y *= 0.4f; + } + + work->mPivot.x = work->mPivot.y = 0.0f; + + work->mDirType = mpChildShape->getDirType(); + work->mRotType = mpChildShape->getRotType(); + work->mDLType = mpChildShape->getType() == 4 || mpChildShape->getType() == 8; + work->mPlaneType = work->mDLType ? 2 : mpChildShape->getBasePlaneType(); + work->mPrjType = 0; + + work->mpAlivePtcl = &work->mpEmtr->mAlivePtclChld; + setCTev(work); + + for (int i = mpDrawEmitterChildFuncListNum - 1; i >= 0; i--) { + (*mpDrawEmitterChildFuncList[i])(work); + } + + if (mpBaseShape->isDrawFwdAhead()) { + JPANode* node = work->mpEmtr->mAlivePtclChld.getLast(); + for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) { + work->mpCurNode = node; + if (mpDrawParticleChildFuncList != NULL) { + for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) { + (*mpDrawParticleChildFuncList[i])(work, node->getObject()); + } + } + } + } else { + JPANode* node = work->mpEmtr->mAlivePtclChld.getFirst(); + for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getNext()) { + work->mpCurNode = node; + if (mpDrawParticleChildFuncList != NULL) { + for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) { + (*mpDrawParticleChildFuncList[i])(work, node->getObject()); + } + } + } + } + + GXSetMisc(GX_MT_XF_FLUSH, 0); + + if (work->mpEmtr->mpEmtrCallBack != NULL) { + work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr); + } +} + +/* 802761A8-8027642C 270AE8 0284+00 1/1 0/0 0/0 .text setPTev__11JPAResourceFv */ +void JPAResource::setPTev() { + GXTexCoordID tex_coord = GX_TEXCOORD1; + u8 tev_stages = 1; + u8 tex_gens = 1; + u8 ind_stages = 0; + + int base_plane_type = (mpBaseShape->getType() == 3 || mpBaseShape->getType() == 7) ? + mpBaseShape->getBasePlaneType() : 0; + int center_offset; + if (mpExtraShape != NULL) { + center_offset = + (mpExtraShape->getScaleCenterX() + 3 * mpExtraShape->getScaleCenterY()) * 0xC; + } else { + center_offset = 0x30; + } + int pos_offset = center_offset + base_plane_type * 0x6C; + int crd_offset = (mpBaseShape->getTilingS() + 2 * mpBaseShape->getTilingT()) * 8; + GXSetArray(GX_VA_POS, jpa_pos + pos_offset, 3); + GXSetArray(GX_VA_TEX0, jpa_crd + crd_offset, 2); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + + if (mpExTexShape != NULL) { + if (mpExTexShape->isUseIndirect()) { + GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD1, GX_TEXMAP2); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1); + GXSetIndTexMtx(GX_ITM_0, (f32(*)[3])mpExTexShape->getIndTexMtx(), mpExTexShape->getExpScale()); + GXSetTevIndirect(GX_TEVSTAGE0, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_STU, GX_ITM_0, + GX_ITW_OFF, GX_ITW_OFF, 0, 0, GX_ITBA_OFF); + ind_stages++; + tex_gens++; + tex_coord = GX_TEXCOORD2; + } + if (mpExTexShape->isUseSecTex()) { + GXSetTevOrder(GX_TEVSTAGE1, tex_coord, GX_TEXMAP3, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, + GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, + GX_TEVPREV); + tev_stages++; + tex_gens++; + } + } + + GXSetNumTevStages(tev_stages); + GXSetNumIndStages(ind_stages); + if (mpBaseShape->isClipOn()) { + GXSetMisc(GX_MT_XF_FLUSH, 8); + GXSetClipMode(GX_CLIP_ENABLE); + } else { + GXSetClipMode(GX_CLIP_DISABLE); + } + GXSetNumTexGens(tex_gens); +} + +/* 8027642C-8027658C 270D6C 0160+00 1/1 0/0 0/0 .text setCTev__11JPAResourceFP18JPAEmitterWorkData + */ +void JPAResource::setCTev(JPAEmitterWorkData* work) { + int base_plane_type = (mpChildShape->getType() == 3 || mpChildShape->getType() == 7) ? + mpChildShape->getBasePlaneType() : 0; + int pos_offset = 0x30 + base_plane_type * 0x6C; + GXSetArray(GX_VA_POS, jpa_pos + pos_offset, 3); + GXSetArray(GX_VA_TEX0, jpa_crd, 2); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3C); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetNumTevStages(1); + GXSetNumIndStages(0); + if (mpChildShape->isClipOn()) { + GXSetMisc(GX_MT_XF_FLUSH, 8); + GXSetClipMode(GX_CLIP_ENABLE); + } else { + GXSetClipMode(GX_CLIP_DISABLE); + } + GXSetNumTexGens(1); + work->mpResMgr->load(work->mpRes->getTexIdx(mpChildShape->getTexIdx()), GX_TEXMAP1); +} + +/* 8027658C-80276608 270ECC 007C+00 0/0 1/1 0/0 .text + * calc_p__11JPAResourceFP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPAResource::calc_p(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + if (mpCalcParticleFuncList != NULL) { + for (int i = mpCalcParticleFuncListNum - 1; i >= 0; i--) { + (*mpCalcParticleFuncList[i])(work, ptcl); + } + } +} + +/* 80276608-80276684 270F48 007C+00 0/0 1/1 0/0 .text + * calc_c__11JPAResourceFP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPAResource::calc_c(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + if (mpCalcParticleChildFuncList != NULL) { + for (int i = mpCalcParticleChildFuncListNum - 1; i >= 0; i--) { + (*mpCalcParticleChildFuncList[i])(work, ptcl); + } + } +} + +/* 80276684-80276700 270FC4 007C+00 0/0 2/2 0/0 .text + * calcField__11JPAResourceFP18JPAEmitterWorkDataP15JPABaseParticle */ +void JPAResource::calcField(JPAEmitterWorkData* work, JPABaseParticle* ptcl) { + for (int i = mFieldBlockNum - 1; i >= 0; i--) { + mpFieldBlocks[i]->calc(work, ptcl); + } +} + +/* 80276700-80276840 271040 0140+00 2/1 0/0 0/0 .text calcKey__11JPAResourceFP18JPAEmitterWorkData + */ +void JPAResource::calcKey(JPAEmitterWorkData* work) { + for (int i = mKeyBlockNum - 1; i >= 0; i--) { + f32 val = mpKeyBlocks[i]->calc(work->mpEmtr->mTick); + switch (mpKeyBlocks[i]->getID()) { + case 0: + work->mpEmtr->mRate = val; + break; + case 1: + work->mpEmtr->mVolumeSize = val; + break; + case 3: + work->mpEmtr->mVolumeMinRad = val; + break; + case 4: + work->mpEmtr->mLifeTime = val; + break; + case 6: + work->mpEmtr->mAwayFromCenterSpeed = val; + break; + case 7: + work->mpEmtr->mAwayFromAxisSpeed = val; + break; + case 8: + work->mpEmtr->mDirSpeed = val; + break; + case 9: + work->mpEmtr->mSpread = val; + break; + case 10: + work->mpEmtr->mScaleOut = val; + break; + } + } +} + +/* 80276840-80276A0C 271180 01CC+00 1/1 0/0 0/0 .text + * calcWorkData_c__11JPAResourceFP18JPAEmitterWorkData */ +void JPAResource::calcWorkData_c(JPAEmitterWorkData* work) { + work->mVolumeSize = work->mpEmtr->mVolumeSize; + work->mVolumeMinRad = work->mpEmtr->mVolumeMinRad; + work->mVolumeSweep = work->mpEmtr->mVolumeSweep; + work->mVolumeX = 0; + work->mVolumeAngleNum = 0; + work->mVolumeAngleMax = 1; + work->mDivNumber = mpDynamicsBlock->getDivNumber() * 2 + 1; + Mtx local_scl_mtx, local_rot_mtx, global_mtx; + MTXScale(local_scl_mtx, work->mpEmtr->mLocalScl.x, work->mpEmtr->mLocalScl.y, + work->mpEmtr->mLocalScl.z); + JPAGetXYZRotateMtx(work->mpEmtr->mLocalRot.x * 182, work->mpEmtr->mLocalRot.y * 182, + work->mpEmtr->mLocalRot.z * 182, local_rot_mtx); + MTXScale(global_mtx, work->mpEmtr->mGlobalScl.x, work->mpEmtr->mGlobalScl.y, + work->mpEmtr->mGlobalScl.z); + MTXConcat(work->mpEmtr->mGlobalRot, global_mtx, global_mtx); + global_mtx[0][3] = work->mpEmtr->mGlobalTrs.x; + global_mtx[1][3] = work->mpEmtr->mGlobalTrs.y; + global_mtx[2][3] = work->mpEmtr->mGlobalTrs.z; + MTXCopy(work->mpEmtr->mGlobalRot, work->mRotationMtx); + MTXConcat(work->mRotationMtx, local_rot_mtx, work->mGlobalRot); + MTXConcat(work->mGlobalRot, local_scl_mtx, work->mGlobalSR); + work->mEmitterPos.set(work->mpEmtr->mLocalTrs); + work->mGlobalScl.mul(work->mpEmtr->mGlobalScl, work->mpEmtr->mLocalScl); + JPAGetDirMtx(work->mpEmtr->mLocalDir, work->mDirectionMtx); + work->mPublicScale.set(work->mpEmtr->mGlobalScl); + MTXMultVec(global_mtx, &work->mpEmtr->mLocalTrs, &work->mGlobalPos); +} + +/* 80276A0C-80276A8C 27134C 0080+00 1/1 0/0 0/0 .text + * calcWorkData_d__11JPAResourceFP18JPAEmitterWorkData */ +void JPAResource::calcWorkData_d(JPAEmitterWorkData* work) { + Mtx mtx; + JPAGetXYZRotateMtx(work->mpEmtr->mLocalRot.x * 0xB6, work->mpEmtr->mLocalRot.y * 0xB6, + work->mpEmtr->mLocalRot.z * 0xB6, mtx); + MTXConcat(work->mpEmtr->mGlobalRot, mtx, work->mGlobalRot); + MTXMultVecSR(work->mGlobalRot, &work->mpEmtr->mLocalDir, &work->mGlobalEmtrDir); +} + +#pragma push +#pragma force_active on +static u8 jpa_resource_padding[28] = {0}; +#pragma pop diff --git a/src/JSystem/JParticle/JPAResourceLoader.cpp b/src/JSystem/JParticle/JPAResourceLoader.cpp new file mode 100644 index 00000000..580e913a --- /dev/null +++ b/src/JSystem/JParticle/JPAResourceLoader.cpp @@ -0,0 +1,106 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAResourceLoader +// + +#include "JSystem/JParticle/JPAResourceLoader.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JParticle/JPABaseShape.h" +#include "JSystem/JParticle/JPAChildShape.h" +#include "JSystem/JParticle/JPADynamicsBlock.h" +#include "JSystem/JParticle/JPAExTexShape.h" +#include "JSystem/JParticle/JPAExtraShape.h" +#include "JSystem/JParticle/JPAFieldBlock.h" +#include "JSystem/JParticle/JPAKeyBlock.h" +#include "JSystem/JParticle/JPAResource.h" +#include "JSystem/JParticle/JPAResourceManager.h" + +/* 8027D8A0-8027D8E0 2781E0 0040+00 0/0 1/1 0/0 .text + * __ct__17JPAResourceLoaderFPCUcP18JPAResourceManager */ +JPAResourceLoader::JPAResourceLoader(u8 const* data, JPAResourceManager* mgr) { + if (*(u32*)(data + 4) == '2-10') { + load_jpc(data, mgr); + } +} + +struct JPAResourceHeader { + /* 0x0 */ u16 mUsrIdx; + /* 0x2 */ u16 mBlockNum; + /* 0x4 */ u8 mFieldBlockNum; + /* 0x5 */ u8 mKeyBlockNum; + /* 0x6 */ u8 mTDB1Num; +}; + +/* 8027D8E0-8027DCA0 278220 03C0+00 1/1 0/0 0/0 .text + * load_jpc__17JPAResourceLoaderFPCUcP18JPAResourceManager */ +void JPAResourceLoader::load_jpc(u8 const* data, JPAResourceManager* mgr) { + JKRHeap* heap = mgr->mpHeap; + mgr->mResMax = *(u16*)(data + 8); + mgr->mTexMax = *(u16*)(data + 0xA); + mgr->mpResArr = new (heap, 0) JPAResource*[mgr->mResMax]; + mgr->mpTexArr = new (heap, 0) JPATexture*[mgr->mTexMax]; + + u32 offset = 0x10; + for (int i = 0; i < *(u16*)(data + 8); i++) { + JPAResourceHeader* header = (JPAResourceHeader*)(data + offset); + JPAResource* res = new (heap, 0) JPAResource(); + res->mFieldBlockNum = header->mFieldBlockNum; + res->mpFieldBlocks = res->mFieldBlockNum != 0 ? + new (heap, 0) JPAFieldBlock*[res->mFieldBlockNum] : NULL; + res->mKeyBlockNum = header->mKeyBlockNum; + res->mpKeyBlocks = res->mKeyBlockNum != 0 ? + new (heap, 0) JPAKeyBlock*[res->mKeyBlockNum] : NULL; + res->mTDB1Num = header->mTDB1Num; + res->mpTDB1 = NULL; + res->mUsrIdx = header->mUsrIdx; + + offset += 8; + u32 field_idx = 0; + u32 key_idx = 0; + + for (int j = 0; j < header->mBlockNum; j++) { + u32 magic = *(u32*)(data + offset); + u32 size = *(u32*)(data + offset + 4); + switch (magic) { + case 'FLD1': + res->mpFieldBlocks[field_idx] = new (heap, 0) JPAFieldBlock(data + offset, heap); + field_idx++; + break; + case 'KFA1': + res->mpKeyBlocks[key_idx] = new (heap, 0) JPAKeyBlock(data + offset); + key_idx++; + break; + case 'BEM1': + res->mpDynamicsBlock = new (heap, 0) JPADynamicsBlock(data + offset); + break; + case 'BSP1': + res->mpBaseShape = new (heap, 0) JPABaseShape(data + offset, heap); + break; + case 'ESP1': + res->mpExtraShape = new (heap, 0) JPAExtraShape(data + offset); + break; + case 'SSP1': + res->mpChildShape = new (heap, 0) JPAChildShape(data + offset); + break; + case 'ETX1': + res->mpExTexShape = new (heap, 0) JPAExTexShape(data + offset); + break; + case 'TDB1': + res->mpTDB1 = (const u16*)(data + offset + 8); + break; + } + offset += size; + } + + res->init(heap); + mgr->registRes(res); + } + + offset = *(u32*)(data + 0xC); + for (int i = 0; i < *(u16*)(data + 0xA); i++) { + u32 size = *(u32*)(data + offset + 4); + JPATexture* tex = new (heap, 0) JPATexture(data + offset); + mgr->registTex(tex); + offset += size; + } +} diff --git a/src/JSystem/JParticle/JPAResourceManager.cpp b/src/JSystem/JParticle/JPAResourceManager.cpp new file mode 100644 index 00000000..e06be753 --- /dev/null +++ b/src/JSystem/JParticle/JPAResourceManager.cpp @@ -0,0 +1,84 @@ +// +// Generated By: dol2asm +// Translation Unit: JPAResourceManager +// + +#include "JSystem/JParticle/JPAResourceManager.h" +#include "JSystem/JParticle/JPADynamicsBlock.h" +#include "JSystem/JParticle/JPAResource.h" +#include "string.h" + +struct JPAResourceLoader { + /* 8027D8A0 */ JPAResourceLoader(u8 const*, JPAResourceManager*); +}; + +/* 80273E10-80273E68 26E750 0058+00 0/0 2/2 0/0 .text __ct__18JPAResourceManagerFPCvP7JKRHeap */ +JPAResourceManager::JPAResourceManager(void const* pData, JKRHeap* pHeap) { + mpResArr = NULL; + mpTexArr = NULL; + mResMax = 0; + mResNum = 0; + mTexMax = 0; + mTexNum = 0; + mpHeap = pHeap; + JPAResourceLoader loader((u8 const*)pData, this); +} + +/* 80273E68-80273EA8 26E7A8 0040+00 1/1 1/1 0/0 .text getResource__18JPAResourceManagerCFUs */ +JPAResource* JPAResourceManager::getResource(u16 usrIdx) const { + for (u16 i = 0; i < mResNum; i++) + if (mpResArr[i]->getUsrIdx() == usrIdx) + return mpResArr[i]; + return NULL; +} + +/* 80273EA8-80273EEC 26E7E8 0044+00 0/0 2/2 0/0 .text + * checkUserIndexDuplication__18JPAResourceManagerCFUs */ +bool JPAResourceManager::checkUserIndexDuplication(u16 usrIdx) const { + for (s32 i = 0; i < mResNum; i++) + if (mpResArr[i]->getUsrIdx() == usrIdx) + return true; + return false; +} + +/* 80273EEC-80273F8C 26E82C 00A0+00 0/0 2/2 0/0 .text + * swapTexture__18JPAResourceManagerFPC7ResTIMGPCc */ +const ResTIMG* JPAResourceManager::swapTexture(ResTIMG const* img, char const* swapName) { + const ResTIMG* ret = NULL; + + for (s32 i = 0; i < mTexNum; i++) { + if (strcmp(swapName, mpTexArr[i]->getName()) == 0) { + JUTTexture* tex = mpTexArr[i]->getJUTTexture(); + ret = tex->getTexInfo(); + tex->storeTIMG(img, (u8)0); + break; + } + } + + return ret; +} + +/* 80273F8C-80273FAC 26E8CC 0020+00 0/0 1/1 0/0 .text + * registRes__18JPAResourceManagerFP11JPAResource */ +void JPAResourceManager::registRes(JPAResource* res) { + mpResArr[mResNum] = res; + mResNum++; +} + +/* 80273FAC-80273FCC 26E8EC 0020+00 0/0 1/1 0/0 .text + * registTex__18JPAResourceManagerFP10JPATexture */ +void JPAResourceManager::registTex(JPATexture* tex) { + mpTexArr[mTexNum] = tex; + mTexNum++; +} + +/* 80273FCC-80274010 26E90C 0044+00 0/0 6/6 0/0 .text getResUserWork__18JPAResourceManagerCFUs */ +u32 JPAResourceManager::getResUserWork(u16 usrIdx) const { + u32 ret = 0; + + JPAResource* res = getResource(usrIdx); + if (res != NULL) + ret = res->getDyn()->getResUserWork(); + + return ret; +} \ No newline at end of file diff --git a/src/JSystem/JParticle/JPATexture.cpp b/src/JSystem/JParticle/JPATexture.cpp new file mode 100644 index 00000000..17aac802 --- /dev/null +++ b/src/JSystem/JParticle/JPATexture.cpp @@ -0,0 +1,15 @@ +// +// Generated By: dol2asm +// Translation Unit: JPATexture +// + +#include "JSystem/JParticle/JPATexture.h" + +/* 8027D7D4-8027D83C 278114 0068+00 0/0 1/1 0/0 .text __ct__10JPATextureFPCUc */ +JPATexture::JPATexture(u8 const* pData) { + mpData = (const JPATextureData*)pData; + mTexture.storeTIMG(&mpData->mResTIMG, (u8)0); +} + +/* 8027D83C-8027D8A0 27817C 0064+00 1/0 0/0 0/0 .text __dt__10JPATextureFv */ +JPATexture::~JPATexture() {} \ No newline at end of file diff --git a/src/JSystem/JSupport/JSUList.cpp b/src/JSystem/JSupport/JSUList.cpp new file mode 100644 index 00000000..eb906508 --- /dev/null +++ b/src/JSystem/JSupport/JSUList.cpp @@ -0,0 +1,162 @@ +// +// Generated By: dol2asm +// Translation Unit: JSUList +// + +#include "JSystem/JSupport/JSUList.h" + +JSUPtrLink::JSUPtrLink(void* object) { + mList = NULL; + mObject = object; + mPrev = NULL; + mNext = NULL; +} + +JSUPtrLink::~JSUPtrLink() { + if (mList != NULL) { + mList->remove(this); + } +} + +JSUPtrList::JSUPtrList(bool init) { + if (init) { + initiate(); + } +} + +JSUPtrList::~JSUPtrList() { + JSUPtrLink* node = mHead; + s32 removed = 0; + while (mLength > removed) { + node->mList = NULL; + node = node->getNext(); + removed += 1; + } +} + +void JSUPtrList::initiate() { + mHead = NULL; + mTail = NULL; + mLength = 0; +} + +void JSUPtrList::setFirst(JSUPtrLink* first) { + first->mList = this; + first->mPrev = NULL; + first->mNext = NULL; + mTail = first; + mHead = first; + mLength = 1; +} + +bool JSUPtrList::append(JSUPtrLink* ptr) { + JSUPtrList* list = ptr->mList; + bool result = (NULL == list); + if (!result) { + result = list->remove(ptr); + } + + if (result) { + if (mLength == 0) { + setFirst(ptr); + } else { + ptr->mList = this; + ptr->mPrev = mTail; + ptr->mNext = NULL; + mTail->mNext = ptr; + mTail = ptr; + mLength++; + } + } + + return result; +} + +bool JSUPtrList::prepend(JSUPtrLink* ptr) { + JSUPtrList* list = ptr->mList; + bool result = (NULL == list); + if (!result) { + result = list->remove(ptr); + } + + if (result) { + if (mLength == 0) { + setFirst(ptr); + } else { + ptr->mList = this; + ptr->mPrev = NULL; + ptr->mNext = mHead; + mHead->mPrev = ptr; + mHead = ptr; + mLength++; + } + } + + return result; +} + +bool JSUPtrList::insert(JSUPtrLink* before, JSUPtrLink* ptr) { + if (before == mHead) { + return prepend(ptr); + } else if (before == NULL) { + return append(ptr); + } + + if (before->mList != this) { + return false; + } + + bool result = (NULL == ptr->mList); + if (!result) { + result = ptr->mList->remove(ptr); + } + + if (result) { + JSUPtrLink* prev = before->mPrev; + ptr->mList = this; + ptr->mPrev = prev; + ptr->mNext = before; + prev->mNext = ptr; + before->mPrev = ptr; + mLength++; + } + + return result; +} + +bool JSUPtrList::remove(JSUPtrLink* ptr) { + bool is_parent = (ptr->mList == this); + if (is_parent) { + if (mLength == 1) { + mHead = NULL; + mTail = NULL; + } else if (ptr == mHead) { + ptr->mNext->mPrev = NULL; + mHead = ptr->mNext; + } else if (ptr == mTail) { + ptr->mPrev->mNext = NULL; + mTail = ptr->mPrev; + } else { + ptr->mPrev->mNext = ptr->mNext; + ptr->mNext->mPrev = ptr->mPrev; + } + + ptr->mList = NULL; + mLength--; + } + + return is_parent; +} + +JSUPtrLink* JSUPtrList::getNthLink(u32 index) const { + if (index >= mLength) { + return NULL; + } + + JSUPtrLink* node = mHead; + for (u32 i = 0; i < index; i++) { + node = node->getNext(); + } + + return node; +} \ No newline at end of file