From 9d5fa671c62bc45ef5603a982b112542a6644216 Mon Sep 17 00:00:00 2001 From: Alex Micharski Date: Thu, 30 Apr 2026 18:25:36 -0400 Subject: [PATCH 1/7] add DrawYBillboard() --- .../drawstrategy/ef_drawbillboardstrategy.cpp | 77 ++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp index 5830bc94..593ed818 100644 --- a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp +++ b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp @@ -174,7 +174,82 @@ inline void DrawBillboardStrategy::DispParticle_Normal( } void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, - ParticleManager* pManager); + ParticleManager* pManager) { + InitGraphics(rInfo, pManager); + + const EmitterDrawSetting& rSetting = + *pManager->mResource->GetEmitterDrawSetting(); + + int flags = mNumTexmap > 0 ? 1 : 0; + const math::MTX34& rInfoMtx = *rInfo.GetViewMtx(); + + math::VEC2 pivot; + pivot.x = rSetting.pivotX / 100.0f; + pivot.y = rSetting.pivotY / 100.0f; + + math::MTX34 viewMtx; + pManager->CalcGlobalMtx(&viewMtx); + math::MTX34Mult(&viewMtx, &rInfoMtx, &viewMtx); + + if (rSetting.zOffset != 0.0f) { + CalcZOffset(&viewMtx, pManager, rInfo, rSetting.zOffset); + } + + f32 rc, rs; + f32 mag; + + mag = math::FSqrt(rInfoMtx._02 * rInfoMtx._02 + + rInfoMtx._22 * rInfoMtx._22); + + if (mag < std::numeric_limits::epsilon()) { + rs = 0.0f; + rc = 1.0f; + } else { + f32 invMag = 1.0f / mag; + + // Project camera forward onto XZ plane and normalize. + // This yields yaw; rs/rc match sin/cos of that yaw. + rs = -rInfoMtx._02 * invMag; // sin(yaw) + rc = rInfoMtx._22 * invMag; // cos(yaw) + } + + f32 vx = math::FSqrt(viewMtx._00 * viewMtx._00 + + viewMtx._10 * viewMtx._10 + + viewMtx._20 * viewMtx._20); + + f32 vy = math::FSqrt(viewMtx._01 * viewMtx._01 + + viewMtx._11 * viewMtx._11 + + viewMtx._21 * viewMtx._21); + f32 vz = 0.0f; + + GetFirstDrawParticleFunc pGetFirstFunc = GetGetFirstDrawParticleFunc( + rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); + + GetNextDrawParticleFunc pGetNextFunc = GetGetNextDrawParticleFunc( + rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); + + bool first = true; + + for (Particle* pIt = pGetFirstFunc(pManager); pIt != NULL; + pIt = pGetNextFunc(pManager, pIt)) { + + f32 sx = pIt->Draw_GetSizeX(); + if (sx < std::numeric_limits::epsilon()) { + continue; + } + + f32 sy = pIt->Draw_GetSizeY(); + if (sy < std::numeric_limits::epsilon()) { + continue; + } + + SetupGP(pIt, rSetting, rInfo, first, false); + first = false; + + // Pass rc/rs instead of explicit right/up vectors + DispParticle_YBillboard(pIt, viewMtx, vx, vy, vz, rc, rs, sx, sy, pivot, flags); + } +} inline void DrawBillboardStrategy::DispParticle_YBillboard( Particle* pParticle, const math::MTX34& rViewMtx, f32 vx, f32 vy, f32 vz, From 6006e08c5b906329b696ac35dfc2f6a090febbd5 Mon Sep 17 00:00:00 2001 From: Alex Micharski Date: Sat, 9 May 2026 14:31:45 -0400 Subject: [PATCH 2/7] start DrawDirectionalBillboard --- Wii Sports.gpr | 0 Wii Sports.rep/idata/~index.bak | 4 + Wii Sports.rep/idata/~index.dat | 4 + Wii Sports.rep/project.prp | 6 + Wii Sports.rep/projectState | 11 + Wii Sports.rep/user/~index.dat | 4 + Wii Sports.rep/versioned/~index.bak | 4 + Wii Sports.rep/versioned/~index.dat | 4 + ogws.gpr | 0 ogws.lock | 9 + ogws.lock~ | 0 ogws.rep/idata/~index.bak | 4 + ogws.rep/idata/~index.dat | 4 + ogws.rep/project.prp | 9 + ogws.rep/projectState | 629 ++++++++++++++++++ ogws.rep/user/~index.dat | 4 + .../drawstrategy/ef_drawbillboardstrategy.cpp | 321 +++++++-- 17 files changed, 946 insertions(+), 71 deletions(-) create mode 100644 Wii Sports.gpr create mode 100644 Wii Sports.rep/idata/~index.bak create mode 100644 Wii Sports.rep/idata/~index.dat create mode 100644 Wii Sports.rep/project.prp create mode 100644 Wii Sports.rep/projectState create mode 100644 Wii Sports.rep/user/~index.dat create mode 100644 Wii Sports.rep/versioned/~index.bak create mode 100644 Wii Sports.rep/versioned/~index.dat create mode 100644 ogws.gpr create mode 100644 ogws.lock create mode 100644 ogws.lock~ create mode 100644 ogws.rep/idata/~index.bak create mode 100644 ogws.rep/idata/~index.dat create mode 100644 ogws.rep/project.prp create mode 100644 ogws.rep/projectState create mode 100644 ogws.rep/user/~index.dat diff --git a/Wii Sports.gpr b/Wii Sports.gpr new file mode 100644 index 00000000..e69de29b diff --git a/Wii Sports.rep/idata/~index.bak b/Wii Sports.rep/idata/~index.bak new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/Wii Sports.rep/idata/~index.bak @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/idata/~index.dat b/Wii Sports.rep/idata/~index.dat new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/Wii Sports.rep/idata/~index.dat @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/project.prp b/Wii Sports.rep/project.prp new file mode 100644 index 00000000..7c1381a6 --- /dev/null +++ b/Wii Sports.rep/project.prp @@ -0,0 +1,6 @@ + + + + + + diff --git a/Wii Sports.rep/projectState b/Wii Sports.rep/projectState new file mode 100644 index 00000000..6b12bd35 --- /dev/null +++ b/Wii Sports.rep/projectState @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Wii Sports.rep/user/~index.dat b/Wii Sports.rep/user/~index.dat new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/Wii Sports.rep/user/~index.dat @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/versioned/~index.bak b/Wii Sports.rep/versioned/~index.bak new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/Wii Sports.rep/versioned/~index.bak @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/versioned/~index.dat b/Wii Sports.rep/versioned/~index.dat new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/Wii Sports.rep/versioned/~index.dat @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/ogws.gpr b/ogws.gpr new file mode 100644 index 00000000..e69de29b diff --git a/ogws.lock b/ogws.lock new file mode 100644 index 00000000..a59f998d --- /dev/null +++ b/ogws.lock @@ -0,0 +1,9 @@ +#Ghidra Lock File +#Sat May 09 14:01:02 EDT 2026 +\ Supports\ File\ Channel\ Locking=Channel Lock +Hostname=SHAW +OS\ Architecture=amd64 +OS\ Name=Windows 11 +OS\ Version=10.0 +Timestamp=5/9/26, 2\:01\u202FPM +Username=alex diff --git a/ogws.lock~ b/ogws.lock~ new file mode 100644 index 00000000..e69de29b diff --git a/ogws.rep/idata/~index.bak b/ogws.rep/idata/~index.bak new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/ogws.rep/idata/~index.bak @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/ogws.rep/idata/~index.dat b/ogws.rep/idata/~index.dat new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/ogws.rep/idata/~index.dat @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/ogws.rep/project.prp b/ogws.rep/project.prp new file mode 100644 index 00000000..e7de89b5 --- /dev/null +++ b/ogws.rep/project.prp @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/ogws.rep/projectState b/ogws.rep/projectState new file mode 100644 index 00000000..f75b084b --- /dev/null +++ b/ogws.rep/projectState @@ -0,0 +1,629 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ogws.rep/user/~index.dat b/ogws.rep/user/~index.dat new file mode 100644 index 00000000..b1e697ff --- /dev/null +++ b/ogws.rep/user/~index.dat @@ -0,0 +1,4 @@ +VERSION=1 +/ +NEXT-ID:0 +MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp index 593ed818..5844d428 100644 --- a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp +++ b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp @@ -15,20 +15,20 @@ void DrawBillboardStrategy::Draw(const DrawInfo& rInfo, *pManager->mResource->GetEmitterDrawSetting(); switch (rSetting.typeOption) { - case EmitterDrawSetting::ASSIST_BB_NORMAL: { - DrawNormalBillboard(rInfo, pManager); - break; - } + case EmitterDrawSetting::ASSIST_BB_NORMAL: { + DrawNormalBillboard(rInfo, pManager); + break; + } - case EmitterDrawSetting::ASSIST_BB_Y: { - DrawYBillboard(rInfo, pManager); - break; - } + case EmitterDrawSetting::ASSIST_BB_Y: { + DrawYBillboard(rInfo, pManager); + break; + } - case EmitterDrawSetting::ASSIST_BB_DIRECTIONAL: { - DrawDirectionalBillboard(rInfo, pManager); - break; - } + case EmitterDrawSetting::ASSIST_BB_DIRECTIONAL: { + DrawDirectionalBillboard(rInfo, pManager); + break; + } } } @@ -86,7 +86,7 @@ void DrawBillboardStrategy::DrawNormalBillboard(const DrawInfo& rInfo, bool first = true; for (Particle* pIt = pGetFirstFunc(pManager); pIt != NULL; - pIt = pGetNextFunc(pManager, pIt)) { + pIt = pGetNextFunc(pManager, pIt)) { f32 sx = pIt->Draw_GetSizeX(); if (sx < std::numeric_limits::epsilon()) { @@ -132,7 +132,8 @@ inline void DrawBillboardStrategy::DispParticle_Normal( if (rot.z != 0.0f) { f32 cr, sr; - math::SinCosRad(&sr, &cr, -rot.z); + //math::SinCosRad(&sr, &cr, -rot.z); + math::SinCosFIdx(&sr, &cr, -rot.z); f32 cr_sx = cr * sx; f32 sr_sx = sr * sx; @@ -167,61 +168,194 @@ inline void DrawBillboardStrategy::DispParticle_Normal( d1.y = vx_rs_cr_sx + vx_rs_sr_sy + vy_rc_sr_sx - vy_rc_cr_sy; d1.z = 0.0f; } else { - // todo + f32 dx0 = sx * px; + f32 dy0 = sy * py; + + float exp0 = px - dx0; + float exp1 = py - dy0; + + p0.x = vy_rc * exp0 + vy_rs * exp1 + pos.x; + p0.y = vy * exp1 + pos.y; + p0.z = (-vy * rs) * exp0 + (vy * rc) * exp1 + pos.z; + + d0.x = vy_rc * sx; + d0.y = 0.0f; + d0.z = (-vy * rs) * sx; + + d1.x = vy_rs * sy; + d1.y = vy * sy; + d1.z = (vy * rc) * sy; } DispPolygon(p0, d0, d1, flags); } void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, - ParticleManager* pManager) { + ParticleManager* pManager) +{ InitGraphics(rInfo, pManager); const EmitterDrawSetting& rSetting = *pManager->mResource->GetEmitterDrawSetting(); - int flags = mNumTexmap > 0 ? 1 : 0; - const math::MTX34& rInfoMtx = *rInfo.GetViewMtx(); + int flags = mNumTexmap != 0; math::VEC2 pivot; - pivot.x = rSetting.pivotX / 100.0f; - pivot.y = rSetting.pivotY / 100.0f; + pivot.x = rSetting.pivotY / 100.0f; + pivot.y = rSetting.pivotX / 100.0f; math::MTX34 viewMtx; pManager->CalcGlobalMtx(&viewMtx); - math::MTX34Mult(&viewMtx, &rInfoMtx, &viewMtx); + math::MTX34Mult(&viewMtx, rInfo.GetViewMtx(), &viewMtx); if (rSetting.zOffset != 0.0f) { CalcZOffset(&viewMtx, pManager, rInfo, rSetting.zOffset); } + f32 vx = math::FSqrt(viewMtx._00 * viewMtx._00 + + viewMtx._10 * viewMtx._10 + + viewMtx._20 * viewMtx._20); + + f32 vy = math::FSqrt(viewMtx._01 * viewMtx._01 + + viewMtx._11 * viewMtx._11 + + viewMtx._21 * viewMtx._21); + f32 rc, rs; - f32 mag; + { + const math::MTX34* pView = rInfo.GetViewMtx(); + f32 mag = math::FSqrt(pView->_01 * pView->_01 + + pView->_21 * pView->_21); + if (mag == 0.0f) { + rc = 1.0f; + rs = 0.0f; + } else { + f32 invMag = math::FInv(mag); + rc = pView->_21 * invMag; + rs = pView->_01 * invMag; + } + } - mag = math::FSqrt(rInfoMtx._02 * rInfoMtx._02 + - rInfoMtx._22 * rInfoMtx._22); + GetFirstDrawParticleFunc pGetFirstFunc = + GetGetFirstDrawParticleFunc( + rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); + GetNextDrawParticleFunc pGetNextFunc = + GetGetNextDrawParticleFunc( + rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); - if (mag < std::numeric_limits::epsilon()) { - rs = 0.0f; - rc = 1.0f; + bool first = true; + + for (Particle* pIt = pGetFirstFunc(pManager); pIt != NULL; + pIt = pGetNextFunc(pManager, pIt)) { + + if (pIt->GetLifeStatus() != 1) continue; + + f32 sx = pIt->Draw_GetSizeX(); + if (sx < std::numeric_limits::epsilon()) continue; + + f32 sy = pIt->Draw_GetSizeY(); + if (sy < std::numeric_limits::epsilon()) continue; + + SetupGP(pIt, rSetting, rInfo, first, false); + first = false; + + DispParticle_YBillboard( + pIt, viewMtx, vx, vy, 0.0f, rc, rs, sx, sy, pivot, flags); + } +} + +inline void DrawBillboardStrategy::DispParticle_YBillboard( + Particle* pParticle, const math::MTX34& rViewMtx, f32 vx, f32 vy, f32 vz, + f32 rs, f32 rc, f32 sx, f32 sy, const math::VEC2& rPivot, int flags) { + +#pragma unused(vz) + + math::VEC3 rot; + pParticle->Draw_GetRotate(&rot); + + math::VEC3 p0; + math::VEC3 d0; + math::VEC3 d1; + math::VEC3 pos; + + math::VEC3Transform(&pos, &rViewMtx, &pParticle->mParameter.mPosition); + + f32 px = rPivot.x; + f32 py = rPivot.y; + + f32 vx_rc = vx * rc; + f32 vx_invrs = vx * -rs; + f32 upY = vy; + f32 vx_rs = vx * rs; + + f32 cr = 1.0f; + f32 sr = 0.0f; + if (rot.z != 0.0f) { + math::SinCosRad(&sr, &cr, -rot.z); + + f32 cr_sx = cr * sx; + f32 sr_sx = sr * sx; + f32 cr_sy = cr * sy; + f32 sr_sy = sr * sy; + + f32 exp0 = (px - cr_sx * px) - sr_sy * py; + f32 exp1 = (py + sr_sx * px) - cr_sy * py; + + p0.x = vx_rc * exp0 + vx_rs * exp1 + pos.x; + p0.y = upY * exp1 + pos.y; + p0.z = vx_invrs * exp0 + vx_rc * exp1 + pos.z; + + f32 dxLocalX = cr_sx; + f32 dyLocalX = sr_sx; + f32 dxLocalY = -sr_sy; + f32 dyLocalY = cr_sy; + + d0.x = vx_rc * dxLocalX + vx_rs * dyLocalX; + d0.y = upY * dyLocalX; + d0.z = vx_invrs * dxLocalX + vx_rc * dyLocalX; + + d1.x = vx_rc * dxLocalY + vx_rs * dyLocalY; + d1.y = upY * dyLocalY; + d1.z = vx_invrs * dxLocalY + vx_rc * dyLocalY; } else { - f32 invMag = 1.0f / mag; + // todo + } + + DispPolygon(p0, d0, d1, flags); +} + +void DrawBillboardStrategy::DrawDirectionalBillboard(const DrawInfo& rInfo, + ParticleManager* pManager) { + InitGraphics(rInfo, pManager); + + const EmitterDrawSetting& rSetting = + *pManager->mResource->GetEmitterDrawSetting(); + + int flags = mNumTexmap > 0 ? 1 : 0; + const math::MTX34& rInfoMtx = *rInfo.GetViewMtx(); + + math::VEC2 pivot; + pivot.x = rSetting.pivotX / 100.0f; + pivot.y = rSetting.pivotY / 100.0f; + + math::MTX34 viewMtx; + pManager->CalcGlobalMtx(&viewMtx); + math::MTX34Mult(&viewMtx, &rInfoMtx, &viewMtx); - // Project camera forward onto XZ plane and normalize. - // This yields yaw; rs/rc match sin/cos of that yaw. - rs = -rInfoMtx._02 * invMag; // sin(yaw) - rc = rInfoMtx._22 * invMag; // cos(yaw) + if (rSetting.zOffset != 0.0f) { + CalcZOffset(&viewMtx, pManager, rInfo, rSetting.zOffset); } - f32 vx = math::FSqrt(viewMtx._00 * viewMtx._00 + - viewMtx._10 * viewMtx._10 + + f32 vx = math::FSqrt(viewMtx._00 * viewMtx._00 + viewMtx._10 * viewMtx._10 + viewMtx._20 * viewMtx._20); - f32 vy = math::FSqrt(viewMtx._01 * viewMtx._01 + - viewMtx._11 * viewMtx._11 + + f32 vy = math::FSqrt(viewMtx._01 * viewMtx._01 + viewMtx._11 * viewMtx._11 + viewMtx._21 * viewMtx._21); + f32 vz = 0.0f; + DrawStrategyImpl::AheadContext ahead(viewMtx, pManager); + CalcAheadFunc pCalcAheadFunc = GetCalcAheadFunc(pManager); + GetFirstDrawParticleFunc pGetFirstFunc = GetGetFirstDrawParticleFunc( rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); @@ -232,7 +366,6 @@ void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, for (Particle* pIt = pGetFirstFunc(pManager); pIt != NULL; pIt = pGetNextFunc(pManager, pIt)) { - f32 sx = pIt->Draw_GetSizeX(); if (sx < std::numeric_limits::epsilon()) { continue; @@ -246,21 +379,67 @@ void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, SetupGP(pIt, rSetting, rInfo, first, false); first = false; - // Pass rc/rs instead of explicit right/up vectors - DispParticle_YBillboard(pIt, viewMtx, vx, vy, vz, rc, rs, sx, sy, pivot, flags); + math::VEC3 aheadVec; + pCalcAheadFunc(&aheadVec, &ahead, pIt); + math::VEC3TransformNormal(&aheadVec, &viewMtx, &aheadVec); + + f32 mag = math::FSqrt(aheadVec.x * aheadVec.x + aheadVec.y * aheadVec.y); + + f32 rc, rs; + if (mag == 0.0f) { + rs = 0.0f; + rc = 1.0f; + } else { + f32 denom = 1.0f / mag; + rs = -aheadVec.x * denom; + rc = aheadVec.y * denom; + } + + DispParticle_Directional(pIt, viewMtx, vx, vy, vz, rc, rs, sx, sy, pivot, + flags); } } -inline void DrawBillboardStrategy::DispParticle_YBillboard( +inline void DrawBillboardStrategy::DispParticle_Directional( Particle* pParticle, const math::MTX34& rViewMtx, f32 vx, f32 vy, f32 vz, - f32 rc, f32 rs, f32 sx, f32 sy, const math::VEC2& rPivot, int flags); + f32 rc, f32 rs, f32 sx, f32 sy, const math::VEC2& rPivot, int flags) { +#pragma unused(vz) -void DrawBillboardStrategy::DrawDirectionalBillboard(const DrawInfo& rInfo, - ParticleManager* pManager); + math::VEC3 p0; + math::VEC3 d0; + math::VEC3 d1; + math::VEC3 pos; -inline void DrawBillboardStrategy::DispParticle_Directional( - Particle* pParticle, const math::MTX34& rViewMtx, f32 vx, f32 vy, f32 vz, - f32 rc, f32 rs, f32 sx, f32 sy, const math::VEC2& rPivot, int flags); + math::VEC3Transform(&pos, &rViewMtx, &pParticle->mParameter.mPosition); + + f32 px = rPivot.x; + f32 py = rPivot.y; + + f32 vx_rc = vx * rc; + f32 vx_rs = vx * rs; + f32 vy_rc = vy * rc; + f32 vy_rs = vy * rs; + + f32 dx0 = sx * px; + f32 dy0 = sy * py; + + f32 exp0 = px - dx0; + f32 exp1 = py - dy0; + + p0.x = vx_rc * exp0 + vy_rs * exp1 + pos.x; + p0.y = vx_rs * exp0 - vy_rc * exp1 + pos.y; + p0.z = pos.z; + + d0.x = vx_rc * sx; + d0.y = vx_rs * sx; + d0.z = 0.0f; + + d1.x = vy_rs * sy; + d1.y = -vy_rc * sy; + d1.z = 0.0f; + + DispPolygon(p0, d0, d1, flags); +} void DrawBillboardStrategy::DispPolygon(const math::VEC3& rP, const math::VEC3& rD1, @@ -299,35 +478,35 @@ void DrawBillboardStrategy::CalcZOffset(math::MTX34* pMtx, GXGetProjectionv(proj); switch (static_cast(proj[0])) { - case GX_PERSPECTIVE: { - math::MTX34 glbMtx; - pManager->mManagerEM->CalcGlobalMtx(&glbMtx); - - math::VEC3 pos(glbMtx._03, glbMtx._13, glbMtx._23); - math::VEC3TransformCoord(&pos, rInfo.GetViewMtx(), &pos); - - if (Normalize(&pos)) { - if (pos.z >= 0.0f) { - pMtx->_03 += pos.x * offsetZ; - pMtx->_13 += pos.y * offsetZ; - pMtx->_23 += pos.z * offsetZ; - } else { - pMtx->_03 -= pos.x * offsetZ; - pMtx->_13 -= pos.y * offsetZ; - pMtx->_23 -= pos.z * offsetZ; + case GX_PERSPECTIVE: { + math::MTX34 glbMtx; + pManager->mManagerEM->CalcGlobalMtx(&glbMtx); + + math::VEC3 pos(glbMtx._03, glbMtx._13, glbMtx._23); + math::VEC3TransformCoord(&pos, rInfo.GetViewMtx(), &pos); + + if (Normalize(&pos)) { + if (pos.z >= 0.0f) { + pMtx->_03 += pos.x * offsetZ; + pMtx->_13 += pos.y * offsetZ; + pMtx->_23 += pos.z * offsetZ; + } else { + pMtx->_03 -= pos.x * offsetZ; + pMtx->_13 -= pos.y * offsetZ; + pMtx->_23 -= pos.z * offsetZ; + } } + break; } - break; - } - case GX_ORTHOGRAPHIC: { - pMtx->_23 += offsetZ; - break; - } + case GX_ORTHOGRAPHIC: { + pMtx->_23 += offsetZ; + break; + } - default: { - break; - } + default: { + break; + } } } From e2355b6d96d4d7e358d96eaf2537e77bb7aeb9bd Mon Sep 17 00:00:00 2001 From: Alex Micharski Date: Sat, 9 May 2026 14:34:54 -0400 Subject: [PATCH 3/7] update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 49db154d..0aa37949 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ orig/*/* *.o *.map *.MAP +*.rep +*.gpr +*.lock* # Build files build/ From 7529fa6316fd4eb5c25d7310c4e1699a2aea199a Mon Sep 17 00:00:00 2001 From: Alex Micharski Date: Sat, 9 May 2026 14:36:14 -0400 Subject: [PATCH 4/7] clean ignored files --- Wii Sports.gpr | 0 Wii Sports.rep/idata/~index.bak | 4 - Wii Sports.rep/idata/~index.dat | 4 - Wii Sports.rep/project.prp | 6 - Wii Sports.rep/projectState | 11 - Wii Sports.rep/user/~index.dat | 4 - Wii Sports.rep/versioned/~index.bak | 4 - Wii Sports.rep/versioned/~index.dat | 4 - configure.py | 0 ogws.gpr | 0 ogws.lock | 9 - ogws.lock~ | 0 ogws.rep/idata/~index.bak | 4 - ogws.rep/idata/~index.dat | 4 - ogws.rep/project.prp | 9 - ogws.rep/projectState | 629 ---------------------------- ogws.rep/user/~index.dat | 4 - tools/transform_dep.py | 0 tools/upload_progress.py | 0 19 files changed, 696 deletions(-) delete mode 100644 Wii Sports.gpr delete mode 100644 Wii Sports.rep/idata/~index.bak delete mode 100644 Wii Sports.rep/idata/~index.dat delete mode 100644 Wii Sports.rep/project.prp delete mode 100644 Wii Sports.rep/projectState delete mode 100644 Wii Sports.rep/user/~index.dat delete mode 100644 Wii Sports.rep/versioned/~index.bak delete mode 100644 Wii Sports.rep/versioned/~index.dat mode change 100755 => 100644 configure.py delete mode 100644 ogws.gpr delete mode 100644 ogws.lock delete mode 100644 ogws.lock~ delete mode 100644 ogws.rep/idata/~index.bak delete mode 100644 ogws.rep/idata/~index.dat delete mode 100644 ogws.rep/project.prp delete mode 100644 ogws.rep/projectState delete mode 100644 ogws.rep/user/~index.dat mode change 100755 => 100644 tools/transform_dep.py mode change 100755 => 100644 tools/upload_progress.py diff --git a/Wii Sports.gpr b/Wii Sports.gpr deleted file mode 100644 index e69de29b..00000000 diff --git a/Wii Sports.rep/idata/~index.bak b/Wii Sports.rep/idata/~index.bak deleted file mode 100644 index b1e697ff..00000000 --- a/Wii Sports.rep/idata/~index.bak +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/idata/~index.dat b/Wii Sports.rep/idata/~index.dat deleted file mode 100644 index b1e697ff..00000000 --- a/Wii Sports.rep/idata/~index.dat +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/project.prp b/Wii Sports.rep/project.prp deleted file mode 100644 index 7c1381a6..00000000 --- a/Wii Sports.rep/project.prp +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/Wii Sports.rep/projectState b/Wii Sports.rep/projectState deleted file mode 100644 index 6b12bd35..00000000 --- a/Wii Sports.rep/projectState +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Wii Sports.rep/user/~index.dat b/Wii Sports.rep/user/~index.dat deleted file mode 100644 index b1e697ff..00000000 --- a/Wii Sports.rep/user/~index.dat +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/versioned/~index.bak b/Wii Sports.rep/versioned/~index.bak deleted file mode 100644 index b1e697ff..00000000 --- a/Wii Sports.rep/versioned/~index.bak +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/Wii Sports.rep/versioned/~index.dat b/Wii Sports.rep/versioned/~index.dat deleted file mode 100644 index b1e697ff..00000000 --- a/Wii Sports.rep/versioned/~index.dat +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/configure.py b/configure.py old mode 100755 new mode 100644 diff --git a/ogws.gpr b/ogws.gpr deleted file mode 100644 index e69de29b..00000000 diff --git a/ogws.lock b/ogws.lock deleted file mode 100644 index a59f998d..00000000 --- a/ogws.lock +++ /dev/null @@ -1,9 +0,0 @@ -#Ghidra Lock File -#Sat May 09 14:01:02 EDT 2026 -\ Supports\ File\ Channel\ Locking=Channel Lock -Hostname=SHAW -OS\ Architecture=amd64 -OS\ Name=Windows 11 -OS\ Version=10.0 -Timestamp=5/9/26, 2\:01\u202FPM -Username=alex diff --git a/ogws.lock~ b/ogws.lock~ deleted file mode 100644 index e69de29b..00000000 diff --git a/ogws.rep/idata/~index.bak b/ogws.rep/idata/~index.bak deleted file mode 100644 index b1e697ff..00000000 --- a/ogws.rep/idata/~index.bak +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/ogws.rep/idata/~index.dat b/ogws.rep/idata/~index.dat deleted file mode 100644 index b1e697ff..00000000 --- a/ogws.rep/idata/~index.dat +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/ogws.rep/project.prp b/ogws.rep/project.prp deleted file mode 100644 index e7de89b5..00000000 --- a/ogws.rep/project.prp +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/ogws.rep/projectState b/ogws.rep/projectState deleted file mode 100644 index f75b084b..00000000 --- a/ogws.rep/projectState +++ /dev/null @@ -1,629 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ogws.rep/user/~index.dat b/ogws.rep/user/~index.dat deleted file mode 100644 index b1e697ff..00000000 --- a/ogws.rep/user/~index.dat +++ /dev/null @@ -1,4 +0,0 @@ -VERSION=1 -/ -NEXT-ID:0 -MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/tools/transform_dep.py b/tools/transform_dep.py old mode 100755 new mode 100644 diff --git a/tools/upload_progress.py b/tools/upload_progress.py old mode 100755 new mode 100644 From 6644d7acacd6b6fef27e6f4c582dd08c980494c1 Mon Sep 17 00:00:00 2001 From: Alex Micharski Date: Thu, 14 May 2026 09:39:32 -0400 Subject: [PATCH 5/7] clang formatted --- .../drawstrategy/ef_drawbillboardstrategy.cpp | 158 ++++++++++-------- 1 file changed, 87 insertions(+), 71 deletions(-) diff --git a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp index 5844d428..fb543b51 100644 --- a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp +++ b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp @@ -15,20 +15,20 @@ void DrawBillboardStrategy::Draw(const DrawInfo& rInfo, *pManager->mResource->GetEmitterDrawSetting(); switch (rSetting.typeOption) { - case EmitterDrawSetting::ASSIST_BB_NORMAL: { - DrawNormalBillboard(rInfo, pManager); - break; - } + case EmitterDrawSetting::ASSIST_BB_NORMAL: { + DrawNormalBillboard(rInfo, pManager); + break; + } - case EmitterDrawSetting::ASSIST_BB_Y: { - DrawYBillboard(rInfo, pManager); - break; - } + case EmitterDrawSetting::ASSIST_BB_Y: { + DrawYBillboard(rInfo, pManager); + break; + } - case EmitterDrawSetting::ASSIST_BB_DIRECTIONAL: { - DrawDirectionalBillboard(rInfo, pManager); - break; - } + case EmitterDrawSetting::ASSIST_BB_DIRECTIONAL: { + DrawDirectionalBillboard(rInfo, pManager); + break; + } } } @@ -86,7 +86,7 @@ void DrawBillboardStrategy::DrawNormalBillboard(const DrawInfo& rInfo, bool first = true; for (Particle* pIt = pGetFirstFunc(pManager); pIt != NULL; - pIt = pGetNextFunc(pManager, pIt)) { + pIt = pGetNextFunc(pManager, pIt)) { f32 sx = pIt->Draw_GetSizeX(); if (sx < std::numeric_limits::epsilon()) { @@ -132,7 +132,7 @@ inline void DrawBillboardStrategy::DispParticle_Normal( if (rot.z != 0.0f) { f32 cr, sr; - //math::SinCosRad(&sr, &cr, -rot.z); + // math::SinCosRad(&sr, &cr, -rot.z); math::SinCosFIdx(&sr, &cr, -rot.z); f32 cr_sx = cr * sx; @@ -191,8 +191,7 @@ inline void DrawBillboardStrategy::DispParticle_Normal( } void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, - ParticleManager* pManager) -{ + ParticleManager* pManager) { InitGraphics(rInfo, pManager); const EmitterDrawSetting& rSetting = @@ -212,19 +211,17 @@ void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, CalcZOffset(&viewMtx, pManager, rInfo, rSetting.zOffset); } - f32 vx = math::FSqrt(viewMtx._00 * viewMtx._00 + - viewMtx._10 * viewMtx._10 + + f32 vx = math::FSqrt(viewMtx._00 * viewMtx._00 + viewMtx._10 * viewMtx._10 + viewMtx._20 * viewMtx._20); - f32 vy = math::FSqrt(viewMtx._01 * viewMtx._01 + - viewMtx._11 * viewMtx._11 + + f32 vy = math::FSqrt(viewMtx._01 * viewMtx._01 + viewMtx._11 * viewMtx._11 + viewMtx._21 * viewMtx._21); f32 rc, rs; { const math::MTX34* pView = rInfo.GetViewMtx(); - f32 mag = math::FSqrt(pView->_01 * pView->_01 + - pView->_21 * pView->_21); + f32 mag = + math::FSqrt(pView->_01 * pView->_01 + pView->_21 * pView->_21); if (mag == 0.0f) { rc = 1.0f; rs = 0.0f; @@ -235,31 +232,32 @@ void DrawBillboardStrategy::DrawYBillboard(const DrawInfo& rInfo, } } - GetFirstDrawParticleFunc pGetFirstFunc = - GetGetFirstDrawParticleFunc( - rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); - GetNextDrawParticleFunc pGetNextFunc = - GetGetNextDrawParticleFunc( - rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); + GetFirstDrawParticleFunc pGetFirstFunc = GetGetFirstDrawParticleFunc( + rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); + GetNextDrawParticleFunc pGetNextFunc = GetGetNextDrawParticleFunc( + rSetting.mFlags & EmitterDrawSetting::FLAG_DRAW_ORDER); bool first = true; for (Particle* pIt = pGetFirstFunc(pManager); pIt != NULL; pIt = pGetNextFunc(pManager, pIt)) { - if (pIt->GetLifeStatus() != 1) continue; + if (pIt->GetLifeStatus() != 1) + continue; f32 sx = pIt->Draw_GetSizeX(); - if (sx < std::numeric_limits::epsilon()) continue; + if (sx < std::numeric_limits::epsilon()) + continue; f32 sy = pIt->Draw_GetSizeY(); - if (sy < std::numeric_limits::epsilon()) continue; + if (sy < std::numeric_limits::epsilon()) + continue; SetupGP(pIt, rSetting, rInfo, first, false); first = false; - DispParticle_YBillboard( - pIt, viewMtx, vx, vy, 0.0f, rc, rs, sx, sy, pivot, flags); + DispParticle_YBillboard(pIt, viewMtx, vx, vy, 0.0f, rc, rs, sx, sy, + pivot, flags); } } @@ -282,9 +280,9 @@ inline void DrawBillboardStrategy::DispParticle_YBillboard( f32 px = rPivot.x; f32 py = rPivot.y; - f32 vx_rc = vx * rc; - f32 vx_invrs = vx * -rs; - f32 upY = vy; + f32 vx_rc = vx * rc; + f32 vx_invrs = vx * -rs; + f32 upY = vy; f32 vx_rs = vx * rs; f32 cr = 1.0f; @@ -304,17 +302,17 @@ inline void DrawBillboardStrategy::DispParticle_YBillboard( p0.y = upY * exp1 + pos.y; p0.z = vx_invrs * exp0 + vx_rc * exp1 + pos.z; - f32 dxLocalX = cr_sx; - f32 dyLocalX = sr_sx; + f32 dxLocalX = cr_sx; + f32 dyLocalX = sr_sx; f32 dxLocalY = -sr_sy; - f32 dyLocalY = cr_sy; + f32 dyLocalY = cr_sy; d0.x = vx_rc * dxLocalX + vx_rs * dyLocalX; - d0.y = upY * dyLocalX; + d0.y = upY * dyLocalX; d0.z = vx_invrs * dxLocalX + vx_rc * dyLocalX; d1.x = vx_rc * dxLocalY + vx_rs * dyLocalY; - d1.y = upY * dyLocalY; + d1.y = upY * dyLocalY; d1.z = vx_invrs * dxLocalY + vx_rc * dyLocalY; } else { // todo @@ -323,8 +321,8 @@ inline void DrawBillboardStrategy::DispParticle_YBillboard( DispPolygon(p0, d0, d1, flags); } -void DrawBillboardStrategy::DrawDirectionalBillboard(const DrawInfo& rInfo, - ParticleManager* pManager) { +void DrawBillboardStrategy::DrawDirectionalBillboard( + const DrawInfo& rInfo, ParticleManager* pManager) { InitGraphics(rInfo, pManager); const EmitterDrawSetting& rSetting = @@ -383,7 +381,8 @@ void DrawBillboardStrategy::DrawDirectionalBillboard(const DrawInfo& rInfo, pCalcAheadFunc(&aheadVec, &ahead, pIt); math::VEC3TransformNormal(&aheadVec, &viewMtx, &aheadVec); - f32 mag = math::FSqrt(aheadVec.x * aheadVec.x + aheadVec.y * aheadVec.y); + f32 mag = + math::FSqrt(aheadVec.x * aheadVec.x + aheadVec.y * aheadVec.y); f32 rc, rs; if (mag == 0.0f) { @@ -395,8 +394,25 @@ void DrawBillboardStrategy::DrawDirectionalBillboard(const DrawInfo& rInfo, rc = aheadVec.y * denom; } - DispParticle_Directional(pIt, viewMtx, vx, vy, vz, rc, rs, sx, sy, pivot, - flags); + f32 dirScale = 1.0f; + if (rSetting.typeDir != 0) { + const math::VEC3& v0 = *reinterpret_cast( + reinterpret_cast(pIt) + 0xAC); + const math::VEC3& v1 = *reinterpret_cast( + reinterpret_cast(pIt) + 0xB8); + math::VEC3 diff; + + diff.x = v0.x - v1.x; + diff.y = v0.y - v1.y; + diff.z = v0.z - v1.z; + + f32 len = math::FSqrt(diff.x * diff.x + diff.y * diff.y + + diff.z * diff.z); + dirScale += 0.5f * len / sy; + } + + DispParticle_Directional(pIt, viewMtx, vx, vy, vz, rc, rs, sx, sy, + pivot, flags); } } @@ -478,35 +494,35 @@ void DrawBillboardStrategy::CalcZOffset(math::MTX34* pMtx, GXGetProjectionv(proj); switch (static_cast(proj[0])) { - case GX_PERSPECTIVE: { - math::MTX34 glbMtx; - pManager->mManagerEM->CalcGlobalMtx(&glbMtx); - - math::VEC3 pos(glbMtx._03, glbMtx._13, glbMtx._23); - math::VEC3TransformCoord(&pos, rInfo.GetViewMtx(), &pos); - - if (Normalize(&pos)) { - if (pos.z >= 0.0f) { - pMtx->_03 += pos.x * offsetZ; - pMtx->_13 += pos.y * offsetZ; - pMtx->_23 += pos.z * offsetZ; - } else { - pMtx->_03 -= pos.x * offsetZ; - pMtx->_13 -= pos.y * offsetZ; - pMtx->_23 -= pos.z * offsetZ; - } + case GX_PERSPECTIVE: { + math::MTX34 glbMtx; + pManager->mManagerEM->CalcGlobalMtx(&glbMtx); + + math::VEC3 pos(glbMtx._03, glbMtx._13, glbMtx._23); + math::VEC3TransformCoord(&pos, rInfo.GetViewMtx(), &pos); + + if (Normalize(&pos)) { + if (pos.z >= 0.0f) { + pMtx->_03 += pos.x * offsetZ; + pMtx->_13 += pos.y * offsetZ; + pMtx->_23 += pos.z * offsetZ; + } else { + pMtx->_03 -= pos.x * offsetZ; + pMtx->_13 -= pos.y * offsetZ; + pMtx->_23 -= pos.z * offsetZ; } - break; } + break; + } - case GX_ORTHOGRAPHIC: { - pMtx->_23 += offsetZ; - break; - } + case GX_ORTHOGRAPHIC: { + pMtx->_23 += offsetZ; + break; + } - default: { - break; - } + default: { + break; + } } } From 2815bf0881d8a7a7c04db1324a60df0bd54a5ed3 Mon Sep 17 00:00:00 2001 From: Alex <58712923+codewriter3000@users.noreply.github.com> Date: Tue, 26 May 2026 08:27:28 -0400 Subject: [PATCH 6/7] Update src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp Co-authored-by: Kiwi <49212064+kiwi515@users.noreply.github.com> --- src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp index fb543b51..1a4a4a62 100644 --- a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp +++ b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp @@ -171,7 +171,7 @@ inline void DrawBillboardStrategy::DispParticle_Normal( f32 dx0 = sx * px; f32 dy0 = sy * py; - float exp0 = px - dx0; + f32 exp0 = px - dx0; float exp1 = py - dy0; p0.x = vy_rc * exp0 + vy_rs * exp1 + pos.x; From 095d3dffade9a46750b483e6321fff032d0c5314 Mon Sep 17 00:00:00 2001 From: Alex <58712923+codewriter3000@users.noreply.github.com> Date: Tue, 26 May 2026 08:27:35 -0400 Subject: [PATCH 7/7] Update src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp Co-authored-by: Kiwi <49212064+kiwi515@users.noreply.github.com> --- src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp index 1a4a4a62..f3b0f76f 100644 --- a/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp +++ b/src/nw4r/ef/drawstrategy/ef_drawbillboardstrategy.cpp @@ -172,7 +172,7 @@ inline void DrawBillboardStrategy::DispParticle_Normal( f32 dy0 = sy * py; f32 exp0 = px - dx0; - float exp1 = py - dy0; + f32 exp1 = py - dy0; p0.x = vy_rc * exp0 + vy_rs * exp1 + pos.x; p0.y = vy * exp1 + pos.y;