From 1ac6df8de7956a790b7782e74a1503568f922904 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Thu, 30 Apr 2026 07:52:44 -0700 Subject: [PATCH 1/6] mirror clip fix closes #581 --- src/d/actor/d_a_obj_mirror_chain.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/d/actor/d_a_obj_mirror_chain.cpp b/src/d/actor/d_a_obj_mirror_chain.cpp index 92c062f7c8..da4a09e1c5 100644 --- a/src/d/actor/d_a_obj_mirror_chain.cpp +++ b/src/d/actor/d_a_obj_mirror_chain.cpp @@ -59,7 +59,8 @@ void dScissorBegin_packet_c::draw() { } if (sp50 >= 4) { - GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0); + IF_DUSK(GXSetColorUpdate(GX_FALSE)); + IF_NOT_DUSK(GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0)); return; } @@ -170,7 +171,8 @@ void dScissorBegin_packet_c::draw() { } if (spBC.z < 0.0f || var_f31 > sp6C || sp7C < sp70 || var_f30 > sp64 || sp78 < sp68) { - GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0); + IF_DUSK(GXSetColorUpdate(GX_FALSE)); + IF_NOT_DUSK(GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0)); } else { var_f31 = cLib_minLimit(var_f31, sp70); sp7C = cLib_maxLimit(sp7C, sp6C); @@ -187,6 +189,7 @@ void dScissorEnd_packet_c::draw() { #endif GXSetScissor(l_scissor[0], l_scissor[1], l_scissor[2], l_scissor[3]); + IF_DUSK(GXSetColorUpdate(GX_TRUE)); } static int createSolidHeap(fopAc_ac_c* i_this) { From 9b6b344ecf4e80389918ee7bae981b178bede215 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 30 Apr 2026 12:09:18 -0600 Subject: [PATCH 2/6] Revert "mirror clip fix" This reverts commit 1ac6df8de7956a790b7782e74a1503568f922904. --- src/d/actor/d_a_obj_mirror_chain.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/d/actor/d_a_obj_mirror_chain.cpp b/src/d/actor/d_a_obj_mirror_chain.cpp index da4a09e1c5..92c062f7c8 100644 --- a/src/d/actor/d_a_obj_mirror_chain.cpp +++ b/src/d/actor/d_a_obj_mirror_chain.cpp @@ -59,8 +59,7 @@ void dScissorBegin_packet_c::draw() { } if (sp50 >= 4) { - IF_DUSK(GXSetColorUpdate(GX_FALSE)); - IF_NOT_DUSK(GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0)); + GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0); return; } @@ -171,8 +170,7 @@ void dScissorBegin_packet_c::draw() { } if (spBC.z < 0.0f || var_f31 > sp6C || sp7C < sp70 || var_f30 > sp64 || sp78 < sp68) { - IF_DUSK(GXSetColorUpdate(GX_FALSE)); - IF_NOT_DUSK(GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0)); + GXSetScissor(FB_WIDTH + 1, FB_HEIGHT + 1, 0, 0); } else { var_f31 = cLib_minLimit(var_f31, sp70); sp7C = cLib_maxLimit(sp7C, sp6C); @@ -189,7 +187,6 @@ void dScissorEnd_packet_c::draw() { #endif GXSetScissor(l_scissor[0], l_scissor[1], l_scissor[2], l_scissor[3]); - IF_DUSK(GXSetColorUpdate(GX_TRUE)); } static int createSolidHeap(fopAc_ac_c* i_this) { From 89649de7c3aa19cafa3d07d43e5fcefc922fddb1 Mon Sep 17 00:00:00 2001 From: doop <56421834+dooplecks@users.noreply.github.com> Date: Thu, 30 Apr 2026 19:39:02 +0000 Subject: [PATCH 3/6] Correct trim height for arbitrary aspect ratios Fixes #543. --- src/d/d_camera.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/d/d_camera.cpp b/src/d/d_camera.cpp index 471c93bb19..b610c3f492 100644 --- a/src/d/d_camera.cpp +++ b/src/d/d_camera.cpp @@ -1481,7 +1481,7 @@ void dCamera_c::CalcTrimSize() { mTrimHeight += -mTrimHeight * 0.25f; break; case 2: -#if WIDESCREEN_SUPPORT +#if 0 && WIDESCREEN_SUPPORT if (mDoGph_gInf_c::isWide() && mDoGph_gInf_c::isWideZoom()) { mTrimHeight += (16.0f - mTrimHeight) * 0.25f; break; @@ -11161,12 +11161,25 @@ static int camera_draw(camera_process_class* i_this) { } #endif - int trim_height = body->TrimHeight(); - #if TARGET_PC + auto trim_height = body->TrimHeight(); + + if (mDoGph_gInf_c::isWideZoom()) { + const auto target_ar = FB_WIDTH / (FB_HEIGHT - trim_height * 2.0f); + const auto current_ar = mDoGph_gInf_c::m_safeWidthF / mDoGph_gInf_c::m_safeHeightF; + + if (current_ar < target_ar) { + trim_height = FB_HEIGHT / 2.0f * (1.0f - current_ar / target_ar); + } else { + trim_height = 0.0f; + } + } + trim_height *= viewport->height / FB_HEIGHT; window->setScissor(0.0f, trim_height, viewport->width, viewport->height - trim_height * 2.0f); #else + int trim_height = body->TrimHeight(); + window->setScissor(0.0f, trim_height, FB_WIDTH, FB_HEIGHT - trim_height * 2.0f); #endif From 88c7ff63ff8a7581797b326c866f7a72d0ac2a2d Mon Sep 17 00:00:00 2001 From: doop <56421834+dooplecks@users.noreply.github.com> Date: Thu, 30 Apr 2026 19:48:03 +0000 Subject: [PATCH 4/6] Fix preprocessor conditional --- src/d/d_camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d/d_camera.cpp b/src/d/d_camera.cpp index b610c3f492..983a5d53e4 100644 --- a/src/d/d_camera.cpp +++ b/src/d/d_camera.cpp @@ -1481,7 +1481,7 @@ void dCamera_c::CalcTrimSize() { mTrimHeight += -mTrimHeight * 0.25f; break; case 2: -#if 0 && WIDESCREEN_SUPPORT +#if !TARGET_PC && WIDESCREEN_SUPPORT if (mDoGph_gInf_c::isWide() && mDoGph_gInf_c::isWideZoom()) { mTrimHeight += (16.0f - mTrimHeight) * 0.25f; break; From 2e8415b9509fa5af97584b85cec04cd861bb0b12 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 30 Apr 2026 14:43:44 -0600 Subject: [PATCH 5/6] Update aurora --- extern/aurora | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/aurora b/extern/aurora index d3f34bfea8..1bd972429e 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit d3f34bfea84b8b70bd1c8b13d78a3d67a3e4d332 +Subproject commit 1bd972429ebba4e486012b1acd08d4d7580eb917 From 9629c000bdd49987613ce5a1652d7a142149b5db Mon Sep 17 00:00:00 2001 From: doop <56421834+dooplecks@users.noreply.github.com> Date: Fri, 1 May 2026 03:25:07 +0000 Subject: [PATCH 6/6] Interpolate shadow camera Fixes #454. --- src/d/d_drawlist.cpp | 54 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/src/d/d_drawlist.cpp b/src/d/d_drawlist.cpp index 373791f994..1f16b2f655 100644 --- a/src/d/d_drawlist.cpp +++ b/src/d/d_drawlist.cpp @@ -22,6 +22,10 @@ #include "dusk/frame_interpolation.h" #include "dusk/gx_helper.h" #include "dusk/logging.h" + +static const void* getInterpKey(const void* base, int idx) { + return reinterpret_cast(reinterpret_cast(base) ^ idx); +} #endif class dDlst_2Dm_c { @@ -1062,7 +1066,15 @@ void dDlst_shadowReal_c::reset() { } void dDlst_shadowReal_c::imageDraw(Mtx param_0) { - GXSetProjection(mRenderProjMtx, GX_ORTHOGRAPHIC); +#ifdef TARGET_PC + Mtx render_proj_mtx; + if (dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 2), render_proj_mtx)) { + GXSetProjection(render_proj_mtx, GX_ORTHOGRAPHIC); + } else +#endif + { + GXSetProjection(mRenderProjMtx, GX_ORTHOGRAPHIC); + } JUT_ASSERT(1916, mModelNum); J3DModelData* model_data; J3DModel** models = mpModels; @@ -1075,7 +1087,15 @@ void dDlst_shadowReal_c::imageDraw(Mtx param_0) { for (u16 j = 0; j < model_data->getShapeNum(); j++) { if (!model_data->getShapeNodePointer(j)->checkFlag(1)) { shape_pkt = (*models)->getShapePacket(j); - shape_pkt->setBaseMtxPtr(&mViewMtx); +#ifdef TARGET_PC + Mtx view_mtx; + if (dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 1), view_mtx)) { + shape_pkt->setBaseMtxPtr(&view_mtx); + } else +#endif + { + shape_pkt->setBaseMtxPtr(&mViewMtx); + } shape_pkt->drawFast(); shape_pkt->setBaseMtxPtr((Mtx*)param_0); } @@ -1096,7 +1116,18 @@ void dDlst_shadowReal_c::draw() { GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetCurrentMtx(GX_PNMTX0); - GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4); +#ifdef TARGET_PC + Mtx view_mtx, recv_proj_mtx; + const auto have_view_mtx = dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 1), view_mtx); + const auto have_recv_proj_mtx = dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 3), recv_proj_mtx); + if (have_view_mtx && have_recv_proj_mtx) { + cMtx_concat(recv_proj_mtx, view_mtx, recv_proj_mtx); + GXLoadTexMtxImm(recv_proj_mtx, GX_TEXMTX0, GX_MTX3x4); + } else +#endif + { + GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4); + } mShadowRealPoly.draw(); } @@ -1253,6 +1284,13 @@ u8 dDlst_shadowReal_c::setShadowRealMtx(cXyz* param_0, cXyz* param_1, f32 param_ cMtx_lookAt(mViewMtx, &local_64, param_1, 0); C_MTXOrtho(mRenderProjMtx, param_2, -param_2, -param_2, param_2, 1.0f, 10000.0f); C_MTXLightOrtho(mReceiverProjMtx, param_2, -param_2, -param_2, param_2, 0.5f, -0.5f, 0.5f, 0.5f); + +#ifdef TARGET_PC + const auto keybase = mpModels[0]; + dusk::frame_interp::record_final_mtx(mViewMtx, getInterpKey(keybase, 1)); + dusk::frame_interp::record_final_mtx(mRenderProjMtx, getInterpKey(keybase, 2)); + dusk::frame_interp::record_final_mtx(mReceiverProjMtx, getInterpKey(keybase, 3)); +#endif cMtx_concat(mReceiverProjMtx, mViewMtx, mReceiverProjMtx); return r29; } @@ -1277,6 +1315,10 @@ u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 par } } +#ifdef TARGET_PC + // provide a stable key for interpolation + mpModels[0] = i_model; +#endif field_0x1 = setShadowRealMtx(&sp60, param_2, param_3, param_4, param_7, param_5); if (!field_0x1) { @@ -1370,12 +1412,6 @@ void dDlst_shadowSimple_c::draw() { GXCallDisplayList(l_shadowVolumeDL, 0x40); } -#if TARGET_PC -static const void* getInterpKey(const void* base, int idx) { - return reinterpret_cast(reinterpret_cast(base) ^ idx); -} -#endif - void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* param_3, s16 param_4, f32 param_5, TGXTexObj* param_6) { if (param_5 < 0.0f) {