From 4698a889ebd3134ba9feaaaf37328d26c65241f1 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 11 Apr 2026 20:37:32 +0200 Subject: [PATCH 01/13] Fix daBaseNpc_c field_0x744 array size (#3154) --- include/d/actor/d_a_npc2.h | 3 +-- src/d/actor/d_a_obj_gra2.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/d/actor/d_a_npc2.h b/include/d/actor/d_a_npc2.h index d1d06d7764..c940d14a87 100644 --- a/include/d/actor/d_a_npc2.h +++ b/include/d/actor/d_a_npc2.h @@ -119,8 +119,7 @@ public: public: /* 0x56C */ dBgS_ObjAcch mAcch; - /* 0x744 */ char field_0x744; - /* 0x745 */ u8 field_0x745[0x74c - 0x745]; + /* 0x744 */ char field_0x744[8]; /* 0x74C */ request_of_phase_process_class mPhase; /* 0x754 */ mDoExt_McaMorfSO* mpModelMorf; /* 0x758 */ Z2Creature mSound; diff --git a/src/d/actor/d_a_obj_gra2.cpp b/src/d/actor/d_a_obj_gra2.cpp index 58802a63ea..c57c9b372e 100644 --- a/src/d/actor/d_a_obj_gra2.cpp +++ b/src/d/actor/d_a_obj_gra2.cpp @@ -539,7 +539,7 @@ const char* daObj_GrA_c::getResName() { u8 daObj_GrA_c::getMode() { u32 uVar1 = fopAcM_GetParam(this) >> 28 & 3; - strcpy(&field_0x744, "Obj_grA"); + strcpy(field_0x744, "Obj_grA"); switch (uVar1) { case 1: From d0fa5f267574bf1e402a5b7fe4c497dcbe95ae1b Mon Sep 17 00:00:00 2001 From: Howard Luck Date: Sat, 11 Apr 2026 13:50:50 -0600 Subject: [PATCH 02/13] Fix daNpcCoach_Attr_c::field_0x28 array size (#3148) --- include/d/actor/d_a_npc_coach.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/d/actor/d_a_npc_coach.h b/include/d/actor/d_a_npc_coach.h index d5ee60e2cf..3917d6f11c 100644 --- a/include/d/actor/d_a_npc_coach.h +++ b/include/d/actor/d_a_npc_coach.h @@ -25,10 +25,7 @@ public: /* 0x1C */ f32 max_speed; // 最大速度 - Maximum Speed /* 0x20 */ f32 spring_constant; // バネ係数 - Spring Constant /* 0x24 */ f32 damp_coeff[1]; // 減衰係数 - Damp Coefficient - /* 0x28 */ f32 field_0x28[1]; - /* 0x2C */ f32 field_0x2c; - /* 0x30 */ f32 field_0x30; - /* 0x34 */ f32 field_0x34; + /* 0x28 */ f32 field_0x28[4]; /* 0x38 */ f32 vert_swing_width; // 縦揺れ幅 - Vertical Swing Width /* 0x3C */ f32 shake_dist; // 揺れ距離 - Shake Distance /* 0x40 */ f32 jump_dist; // 跳ね距離 - Jump Distance From ef23a2294c5426b3c3ef82519b36249bbbf08231 Mon Sep 17 00:00:00 2001 From: Howard Luck Date: Sat, 11 Apr 2026 13:51:20 -0600 Subject: [PATCH 03/13] Fix obj_maki_class::field_0x6f8 array size (#3149) --- include/d/actor/d_a_obj_maki.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/d/actor/d_a_obj_maki.h b/include/d/actor/d_a_obj_maki.h index c15b0b9ac1..aad8028e9c 100644 --- a/include/d/actor/d_a_obj_maki.h +++ b/include/d/actor/d_a_obj_maki.h @@ -28,11 +28,9 @@ public: /* 0x580 */ s16 field_0x580[2]; /* 0x584*/ dCcD_Stts mStts; /* 0x5c0 */ dCcD_Sph mSph; - /* 0x6f8 */ u32 field_0x6f8[4]; - /* 0x6fc */ u8 field_0x6fc[0x70c - 0x708]; // Undefined + /* 0x6f8 */ u32 field_0x6f8[5]; /* 0x70c */ LIGHT_INFLUENCE mLightObj; /* 0x72c */ u8 field_0x72c; - /* 0x72d */ u8 field_0x72d[0x730 - 0x72d]; //Undefined }; STATIC_ASSERT(sizeof(obj_maki_class) == 0x730); From 501f1c11d66ae94877f54d7dd49afab9fdc07a05 Mon Sep 17 00:00:00 2001 From: Howard Luck Date: Sat, 11 Apr 2026 13:52:48 -0600 Subject: [PATCH 04/13] Fix daE_FB_c::mKeys array size on PC (#3151) --- include/d/actor/d_a_e_fb.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/d/actor/d_a_e_fb.h b/include/d/actor/d_a_e_fb.h index 3e8734b8b6..a4494c5e7a 100644 --- a/include/d/actor/d_a_e_fb.h +++ b/include/d/actor/d_a_e_fb.h @@ -71,10 +71,16 @@ private: /* 0xA30 */ dCcD_Sph mSphere2; /* 0xB68 */ dCcD_Sph mAtSph; /* 0xCA0 */ dCcU_AtInfo mAtInfo; +#if AVOID_UB + /* 0xCC4 */ u32 mKeys[8]; + /* 0xCE4 */ u8 mHIOInit; + /* 0xCE5 */ u8 field_0xce5[0xCE8 - 0xCE5]; +#else // !@bug Seems that the orig developers didn't size mKeys correctly, as ideally it should be len=8, not len=7: /* 0xCC4 */ u32 mKeys[7]; /* 0xCE0 */ u8 mHIOInit; /* 0xCE1 */ u8 field_0xce1[0xCE8 - 0xCE1]; +#endif }; STATIC_ASSERT(sizeof(daE_FB_c) == 0xce8); From 83c6032c15194a75a9efffaa4a56e5c369d955c6 Mon Sep 17 00:00:00 2001 From: Howard Luck Date: Sat, 11 Apr 2026 13:53:51 -0600 Subject: [PATCH 05/13] Fix daE_VA_c::mRopeCutStatus and va_tag_* array sizes (#3152) --- include/d/actor/d_a_e_vt.h | 3 +-- src/d/actor/d_a_e_vt.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/include/d/actor/d_a_e_vt.h b/include/d/actor/d_a_e_vt.h index 5d6bf3dfd2..4b6082adae 100644 --- a/include/d/actor/d_a_e_vt.h +++ b/include/d/actor/d_a_e_vt.h @@ -159,8 +159,7 @@ private: /* 0x00958 */ mDoExt_3DlineMat1_c mRope; /* 0x00994 */ cXyz field_0x994[100]; /* 0x00E44 */ csXyz field_0xe44[100]; - /* 0x0109C */ u8 mRopeCutStatus[10]; - /* 0x010A6 */ u8 field_0x10A6[0x01100 - 0x010A6]; + /* 0x0109C */ u8 mRopeCutStatus[100]; /* 0x01100 */ u8 mDrawRopes; /* 0x01101 */ u8 field_0x1101[0x01104 - 0x01101]; /* 0x01104 */ f32 field_0x1104[10]; diff --git a/src/d/actor/d_a_e_vt.cpp b/src/d/actor/d_a_e_vt.cpp index a52b02e598..b0b7d42ab0 100644 --- a/src/d/actor/d_a_e_vt.cpp +++ b/src/d/actor/d_a_e_vt.cpp @@ -167,6 +167,30 @@ static dCcD_SrcSph cc_vt_magic_src = { } // mSphAttr }; +// !@bug The i<40 loops that index these arrays read one element past the end; on +// GC/Wii the OOB reads land on adjacent rodata instead of a defined value. +#if AVOID_UB +static u8 va_tag_set_size[40] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x00, +}; + +static u8 va_tag_set_num[40] = { + 0x01, 0x0C, 0x16, 0x1F, 0x21, 0x2A, 0x2B, 0x02, 0x04, 0x0D, 0x0F, 0x15, 0x18, + 0x20, 0x2C, 0x03, 0x05, 0x06, 0x0B, 0x10, 0x17, 0x19, 0x1A, 0x22, 0x24, 0x29, + 0x2D, 0x34, 0x49, 0x52, 0x36, 0x3E, 0x54, 0x5C, 0x39, 0x41, 0x4C, 0x56, 0x5E, + 0x00, +}; + +static f32 va_tag_offset[40] = { + 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 0.0f, 40.0f, 0.0f, 30.0f, 10.0f, 0.0f, 0.0f, 20.0f, + 0.0f, 10.0f, 20.0f, 40.0f, 0.0f, 20.0f, 0.0f, 0.0f, 20.0f, 0.0f, 10.0f, 0.0f, 0.0f, + 20.0f, 10.0f, 20.0f, 30.0f, 0.0f, 10.0f, 20.0f, 0.0f, 0.0f, 10.0f, 20.0f, 30.0f, 0.0f, + 0.0f, +}; +#else static u8 va_tag_set_size[39] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, @@ -184,6 +208,7 @@ static f32 va_tag_offset[39] = { 0.0f, 10.0f, 20.0f, 40.0f, 0.0f, 20.0f, 0.0f, 0.0f, 20.0f, 0.0f, 10.0f, 0.0f, 0.0f, 20.0f, 10.0f, 20.0f, 30.0f, 0.0f, 10.0f, 20.0f, 0.0f, 0.0f, 10.0f, 20.0f, 30.0f, 0.0f, }; +#endif } // namespace From 55122561b3ca6c521648783006ae16f9a7a3ef51 Mon Sep 17 00:00:00 2001 From: Howard Luck Date: Sat, 11 Apr 2026 13:54:25 -0600 Subject: [PATCH 06/13] Fix dMsgFlow_c::event027 aParam8 buffer size (#3153) --- src/d/d_msg_flow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/d/d_msg_flow.cpp b/src/d/d_msg_flow.cpp index 4648f81dc9..47ef21063e 100644 --- a/src/d/d_msg_flow.cpp +++ b/src/d/d_msg_flow.cpp @@ -2229,7 +2229,13 @@ int dMsgFlow_c::event027(mesg_flow_node_event* i_flowNode_p, fopAc_ac_c* i_speak u16 prm0; getParam(&prm0, &prm1, i_flowNode_p->params); + // !@bug aParam8 is undersized; getParam always writes 4 bytes, stomping the + // 2 bytes past the buffer. Harmless on GC/Wii (MWCC stack layout absorbs it). +#if AVOID_UB + u8 aParam8[4]; +#else u8 aParam8[2]; +#endif getParam(aParam8, i_flowNode_p->params); JUT_ASSERT(4509, (aParam8[0] >= 0 && aParam8[0] <= dSv_player_item_c::BOMB_BAG_MAX) || (aParam8[0] == 4)); From 8b0e6c877be4e28e671cb03f0b3800f0ecb0aabe Mon Sep 17 00:00:00 2001 From: SuperDude88 <82904174+SuperDude88@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:36:30 -0400 Subject: [PATCH 07/13] Per-Axis Sensitivity - Allow changing the sensitivity of the gyro on each axis independently --- include/dusk/settings.h | 3 ++- src/dusk/gyro_aim.cpp | 5 ++--- src/dusk/imgui/ImGuiMenuEnhancements.cpp | 3 ++- src/dusk/settings.cpp | 6 ++++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/dusk/settings.h b/include/dusk/settings.h index 2ab587d3ce..68ea49c752 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -64,7 +64,8 @@ struct UserSettings { // Input ConfigVar enableGyroAim; - ConfigVar gyroAimSensitivity; + ConfigVar gyroAimSensitivityX; + ConfigVar gyroAimSensitivityY; ConfigVar gyroAimInvertPitch; ConfigVar gyroAimInvertYaw; diff --git a/src/dusk/gyro_aim.cpp b/src/dusk/gyro_aim.cpp index 3558b804d1..48edd640b3 100644 --- a/src/dusk/gyro_aim.cpp +++ b/src/dusk/gyro_aim.cpp @@ -61,9 +61,8 @@ void read(float dt, bool context_active) { float yaw_rate = apply_deadband(s_smooth_gy); float pitch_rate = apply_deadband(s_smooth_gx); - const float sens = dusk::getSettings().game.gyroAimSensitivity; - s_pending_yaw_rad += yaw_rate * dt * sens; - s_pending_pitch_rad += pitch_rate * dt * sens; + s_pending_yaw_rad += yaw_rate * dt * dusk::getSettings().game.gyroAimSensitivityX; + s_pending_pitch_rad += pitch_rate * dt * dusk::getSettings().game.gyroAimSensitivityY; } void consumeAimDeltas(float& out_yaw_rad, float& out_pitch_rad) { diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.cpp b/src/dusk/imgui/ImGuiMenuEnhancements.cpp index 50e44f5c60..a50ec1ee4c 100644 --- a/src/dusk/imgui/ImGuiMenuEnhancements.cpp +++ b/src/dusk/imgui/ImGuiMenuEnhancements.cpp @@ -119,7 +119,8 @@ namespace dusk { "Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod."); } - config::ImGuiSliderFloat("Gyro Sensitivity", getSettings().game.gyroAimSensitivity, 0.25f, 4.0f, "%.2f"); + config::ImGuiSliderFloat("Gyro Pitch Sensitivity", getSettings().game.gyroAimSensitivityY, 0.25f, 4.0f, "%.2f"); + config::ImGuiSliderFloat("Gyro Yaw Sensitivity", getSettings().game.gyroAimSensitivityX, 0.25f, 4.0f, "%.2f"); config::ImGuiCheckbox("Invert Gyro Pitch", getSettings().game.gyroAimInvertPitch); config::ImGuiCheckbox("Invert Gyro Yaw", getSettings().game.gyroAimInvertYaw); diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index 0e39e55854..9d3d873acc 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -52,7 +52,8 @@ UserSettings g_userSettings = { // Input .enableGyroAim {"game.enableGyroAim", false}, - .gyroAimSensitivity {"game.gyroAimSensitivity", 1.0f}, + .gyroAimSensitivityX {"game.gyroAimSensitivityX", 1.0f}, + .gyroAimSensitivityY {"game.gyroAimSensitivityY", 1.0f}, .gyroAimInvertPitch {"game.gyroAimInvertPitch", false}, .gyroAimInvertYaw {"game.gyroAimInvertYaw", false}, @@ -126,7 +127,8 @@ void registerSettings() { Register(g_userSettings.game.fastSpinner); Register(g_userSettings.game.enableFrameInterpolation); Register(g_userSettings.game.enableGyroAim); - Register(g_userSettings.game.gyroAimSensitivity); + Register(g_userSettings.game.gyroAimSensitivityX); + Register(g_userSettings.game.gyroAimSensitivityY); Register(g_userSettings.game.gyroAimInvertPitch); Register(g_userSettings.game.gyroAimInvertYaw); From 42a4e787b664e169ef42b65f11cf8a5e968c724c Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 12 Apr 2026 22:26:19 -0700 Subject: [PATCH 08/13] bloom cleanup start start working on a better bloom --- src/m_Do/m_Do_graphic.cpp | 213 +++++++++++++++++++++++++++++++++++--- 1 file changed, 196 insertions(+), 17 deletions(-) diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index f9d5750d71..dc6f80b63f 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -1232,12 +1232,12 @@ void mDoGph_drawFilterQuad(s8 param_0, s8 param_1) { void mDoGph_gInf_c::bloom_c::create() { if (m_buffer == NULL) { #ifdef TARGET_PC - u32 size = 0x20; // No need to allocate memory for texture + m_buffer = (void*)1; #else u32 size = GXGetTexBufferSize(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGBA8, GX_FALSE, 0); -#endif m_buffer = mDoExt_getArchiveHeap()->alloc(size, -32); JUT_ASSERT(1621, m_buffer != NULL); +#endif mEnable = false; mMode = 0; @@ -1249,20 +1249,202 @@ void mDoGph_gInf_c::bloom_c::create() { } void mDoGph_gInf_c::bloom_c::remove() { +#if !TARGET_PC if (m_buffer != NULL) { mDoExt_getArchiveHeap()->free(m_buffer); m_buffer = NULL; } +#endif mMonoColor.a = 0; } -void mDoGph_gInf_c::bloom_c::draw() { + #if TARGET_PC +static void CopyToTexObj(GXTexObj* pDst, uintptr_t texID, int dstWidth, int dstHeight, GXTexFmt dstFmt = GX_TF_RGBA8) { + GXSetTexCopyDst(dstWidth, dstHeight, dstFmt, FALSE); + GXCopyTex((void*)texID, false); + GXInitTexObj(pDst, (void*)texID, dstWidth, dstHeight, dstFmt, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObjLOD(pDst, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); +} + +void mDoGph_gInf_c::bloom_c::draw() { ZoneScoped; if (!dusk::getSettings().game.enableBloom) { return; } -#endif + + bool enabled = mEnable; + if (mMonoColor.a == 0 && !enabled) + return; + + f32 width = mDoGph_gInf_c::getWidth(); + f32 height = mDoGph_gInf_c::getHeight(); + GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f); + GXSetScissor(0, 0, width, height); + + GXLoadTexObj(getFrameBufferTexObj(), GX_TEXMAP0); + GXSetNumChans(0); + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_GREEN); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); + GXSetZCompLoc(1); + GXSetZMode(0, GX_ALWAYS, 0); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + GXSetFog(GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, g_clearColor); + GXSetFogRangeAdj(0, 0, 0); + GXSetCullMode(GX_CULL_NONE); + GXSetDither(1); + Mtx44 ortho; + C_MTXOrtho(ortho, 0.0f, height, 0.0f, width, 0.0f, 10.0f); + GXLoadPosMtxImm(cMtx_getIdentity(), 0); + GXSetProjection(ortho, GX_ORTHOGRAPHIC); + GXSetCurrentMtx(0); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0); + + auto filterQuad = [&](int div) { + f32 x = width / div, y = height / div; + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + GXPosition3f32(0, 0, -5); + GXTexCoord2s8(0, 0); + GXPosition3f32(x, 0, -5); + GXTexCoord2s8(1, 0); + GXPosition3f32(x, y, -5); + GXTexCoord2s8(1, 1); + GXPosition3f32(0, y, -5); + GXTexCoord2s8(0, 1); + GXEnd(); + }; + + if (mMonoColor.a != 0) { + GXSetNumTevStages(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C2, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A2); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP1, GX_TEV_SWAP1); + GXSetTevColor(GX_TEVREG2, mMonoColor); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR); + filterQuad(1); + } + + if (enabled) { + enum PassID { Pass0, Pass1, Pass2 }; + + GXCreateFrameBuffer(width, height); + + GXSetNumTevStages(3); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_TEXA, GX_CC_HALF, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP1, GX_TEV_SWAP1); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_TEXC, GX_CC_CPREV, GX_CC_HALF, GX_CC_C0); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP3, GX_TEV_SWAP3); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_OR); + GXColorS10 tevColor0 = {(s16)-mPoint, (s16)-mPoint, (s16)-mPoint, 0x40}; + GXSetTevColorS10(GX_TEVREG0, tevColor0); + GXColor tevColor1 = {mBlureRatio, mBlureRatio, mBlureRatio, mBlureRatio}; + GXSetTevColor(GX_TEVREG1, tevColor1); + GXPixModeSync(); + filterQuad(2); + + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); + + // Downsample and filter from 1/2 EFB into 1/4. + TGXTexObj tmpTex[3]; + GXSetTexCopySrc(0, 0, width / 2, height / 2); + CopyToTexObj(&tmpTex[0], Pass0, width / 4, height / 4); + GXLoadTexObj(&tmpTex[0], GX_TEXMAP0); + + GXSetNumTexGens(8); + u32 texMtxID = GX_TEXMTX0; + int angle = 0; + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { + GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); + + f32 dVar15 = mBlureSize * ((448.0f / getHeight()) / 6400.0f); + + mDoMtx_stack_c::transS((dVar15 * cM_scos(angle)) * getInvScale(), + dVar15 * cM_ssin(angle), 0.0f); + GXLoadTexMtxImm(mDoMtx_stack_c::get(), texMtxID, GX_MTX2x4); + + texMtxID += 3; + angle += 0x2492; + } + + GXSetNumTevStages(8); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + for (int tevStage = (int)GX_TEVSTAGE1; tevStage < 8; tevStage++) { + GXSetTevOrder((GXTevStageID)tevStage, (GXTexCoordID)tevStage, GX_TEXMAP0, + GX_COLOR_NULL); + GXSetTevColorIn((GXTevStageID)tevStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_CPREV); + GXSetTevColorOp((GXTevStageID)tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, + GX_TEVPREV); + GXSetTevAlphaIn((GXTevStageID)tevStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp((GXTevStageID)tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, + GX_TEVPREV); + } + GXPixModeSync(); + + // Blur filter from tmp_tex1 1/4 to EFB 1/4. + filterQuad(4); + + GXSetTexCopySrc(0, 0, width / 4, height / 4); + CopyToTexObj(&tmpTex[1], Pass1, width / 8, height / 8); + GXLoadTexObj(&tmpTex[1], GX_TEXMAP0); + + // Upsample 1/8 buffer back up to 1/4 buffer. + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR); + GXPixModeSync(); + GXInvalidateTexAll(); + filterQuad(4); + + // Now that we've upsampled and filtered our final bloom, copy 1/4 buffer. + GXSetTexCopySrc(0, 0, width / 4, height / 4); + CopyToTexObj(&tmpTex[2], Pass2, width / 4, height / 4); + GXLoadTexObj(&tmpTex[2], GX_TEXMAP0); + + GXRestoreFrameBuffer(); + + // Now blend our bloom into the real FB. + GXSetTevColor(GX_TEVREG0, mBlendColor); + GXSetNumTevStages(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetBlendMode(GX_BM_BLEND, mMode == 1 ? GX_BL_INVDSTCLR : GX_BL_ONE, GX_BL_SRCALPHA, GX_LO_OR); + GXPixModeSync(); + GXInvalidateTexAll(); + filterQuad(1); + } +} +#else +void mDoGph_gInf_c::bloom_c::draw() { bool enabled = mEnable && m_buffer != NULL; if (mMonoColor.a != 0 || enabled) { #if TARGET_PC @@ -1376,24 +1558,20 @@ void mDoGph_gInf_c::bloom_c::draw() { GXLoadTexObj(&tmp_tex1, GX_TEXMAP0); GXSetNumTexGens(8); - u32 iVar11 = 0x1e; - int sVar10 = 0; - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + u32 texMtxID = GX_TEXMTX0; + int angle = 0; + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { - GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, iVar11); + GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); - #if TARGET_PC - f32 dVar15 = mBlureSize * ((448.0f / getHeight()) / 6400.0f); - #else f32 dVar15 = mBlureSize * (1.0f / 6400.0f); - #endif - mDoMtx_stack_c::transS((dVar15 * cM_scos(sVar10)) * getInvScale(), - dVar15 * cM_ssin(sVar10), 0.0f); - GXLoadTexMtxImm(mDoMtx_stack_c::get(), iVar11, GX_MTX2x4); + mDoMtx_stack_c::transS((dVar15 * cM_scos(angle)) * getInvScale(), + dVar15 * cM_ssin(angle), 0.0f); + GXLoadTexMtxImm(mDoMtx_stack_c::get(), texMtxID, GX_MTX2x4); - iVar11 += 3; - sVar10 += 0x2492; + texMtxID += 3; + angle += 0x2492; } GXSetNumTevStages(8); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); @@ -1495,6 +1673,7 @@ void mDoGph_gInf_c::bloom_c::draw() { } } } +#endif static void retry_captue_frame(view_class* param_0, view_port_class* param_1, int param_2) { UNUSED(param_0); From 0f15b279d866689173ce62d225b5893ad77cbb71 Mon Sep 17 00:00:00 2001 From: Lurs <2795933+Lurs@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:33:04 +0200 Subject: [PATCH 09/13] Update README.md (libxss-dev libxtst-dev missing for Ubuntu) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 754d3ff1dc..c41985d394 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ build-essential curl git ninja-build clang lld zlib1g-dev libcurl4-openssl-dev \ libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev libpulse-dev \ libudev-dev libpng-dev libncurses5-dev cmake libx11-xcb-dev python3 python-is-python3 \ - libclang-dev libfreetype-dev libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev + libclang-dev libfreetype-dev libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev \ + libxss-dev libxtst-dev ``` * Arch Linux packages ``` From 16241b45a6ac186b143fe6988052eaa0f1bec5c5 Mon Sep 17 00:00:00 2001 From: YunataSavior Date: Mon, 13 Apr 2026 00:44:18 -0700 Subject: [PATCH 10/13] Fix MDH cat door opening * Needs to be upstreamed Fixes #182 --- include/d/actor/d_a_obj_catdoor.h | 2 +- src/d/actor/d_a_obj_catdoor.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/d/actor/d_a_obj_catdoor.h b/include/d/actor/d_a_obj_catdoor.h index 78f5525d8c..77d285dc07 100644 --- a/include/d/actor/d_a_obj_catdoor.h +++ b/include/d/actor/d_a_obj_catdoor.h @@ -67,7 +67,7 @@ private: /* 0x790 */ s16 mRotSpeed; public: - static u32 const M_attr; + static s16 const M_attr[2]; }; #endif /* D_A_OBJ_CATDOOR_H */ diff --git a/src/d/actor/d_a_obj_catdoor.cpp b/src/d/actor/d_a_obj_catdoor.cpp index e1f3373e87..a2438515f2 100644 --- a/src/d/actor/d_a_obj_catdoor.cpp +++ b/src/d/actor/d_a_obj_catdoor.cpp @@ -10,7 +10,7 @@ static const char* l_arcName = "CatDoor"; -u32 const daObjCatDoor_c::M_attr = 0x001E0578; +s16 const daObjCatDoor_c::M_attr[2] = {0x001E, 0x0578}; daObjCatDoor_c::~daObjCatDoor_c() { if (mDoor1.bgw.ChkUsed()) { @@ -71,7 +71,7 @@ int daObjCatDoor_c::execute() { } const s16* daObjCatDoor_c::attr() const { - return (const s16*)&daObjCatDoor_c::M_attr; + return daObjCatDoor_c::M_attr; } static int createSolidHeap(fopAc_ac_c* i_this) { From a14fe187b9571c3c08eb6a5b280ea93d0d592f54 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Mon, 13 Apr 2026 01:29:12 -0700 Subject: [PATCH 11/13] bloom2 wip --- include/m_Do/m_Do_graphic.h | 3 + src/m_Do/m_Do_graphic.cpp | 214 ++++++++++++++++++++++++------------ 2 files changed, 144 insertions(+), 73 deletions(-) diff --git a/include/m_Do/m_Do_graphic.h b/include/m_Do/m_Do_graphic.h index 5a97f4a326..c6b22654fa 100644 --- a/include/m_Do/m_Do_graphic.h +++ b/include/m_Do/m_Do_graphic.h @@ -31,6 +31,9 @@ public: void create(); void remove(); void draw(); +#if TARGET_PC + void draw2(); +#endif u8 getEnable() { return mEnable; } void setEnable(u8 i_enable) { mEnable = i_enable; } diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index dc6f80b63f..8c6b5e7c45 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -1258,7 +1258,6 @@ void mDoGph_gInf_c::bloom_c::remove() { mMonoColor.a = 0; } - #if TARGET_PC static void CopyToTexObj(GXTexObj* pDst, uintptr_t texID, int dstWidth, int dstHeight, GXTexFmt dstFmt = GX_TF_RGBA8) { GXSetTexCopyDst(dstWidth, dstHeight, dstFmt, FALSE); @@ -1267,11 +1266,11 @@ static void CopyToTexObj(GXTexObj* pDst, uintptr_t texID, int dstWidth, int dstH GXInitTexObjLOD(pDst, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); } -void mDoGph_gInf_c::bloom_c::draw() { +void mDoGph_gInf_c::bloom_c::draw2() { ZoneScoped; - if (!dusk::getSettings().game.enableBloom) { - return; - } + // if (!dusk::getSettings().game.enableBloom) { + // return; + // } bool enabled = mEnable; if (mMonoColor.a == 0 && !enabled) @@ -1279,13 +1278,11 @@ void mDoGph_gInf_c::bloom_c::draw() { f32 width = mDoGph_gInf_c::getWidth(); f32 height = mDoGph_gInf_c::getHeight(); - GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f); - GXSetScissor(0, 0, width, height); GXLoadTexObj(getFrameBufferTexObj(), GX_TEXMAP0); GXSetNumChans(0); GXSetNumTexGens(1); - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_GREEN); GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); GXSetZCompLoc(1); @@ -1296,7 +1293,7 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetCullMode(GX_CULL_NONE); GXSetDither(1); Mtx44 ortho; - C_MTXOrtho(ortho, 0.0f, height, 0.0f, width, 0.0f, 10.0f); + C_MTXOrtho(ortho, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 10.0f); GXLoadPosMtxImm(cMtx_getIdentity(), 0); GXSetProjection(ortho, GX_ORTHOGRAPHIC); GXSetCurrentMtx(0); @@ -1306,16 +1303,51 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0); - auto filterQuad = [&](int div) { - f32 x = width / div, y = height / div; + // Set up viewports for our pyramid. + enum { MaxDivNum = 10 }; + enum { + Pass0, + FinalPass, + BlurPass0, BlurPassN = BlurPass0 + MaxDivNum, + MaxTexNum, + }; + scissor_class divPorts[MaxDivNum]; + divPorts[0] = {0.0f, 0.0f, 1.0f, 1.0f}; // full-size texture + divPorts[1] = {0.0f, 0.0f, 0.5f, 0.5f}; // bloom texture (wide enough, half-tall) + divPorts[2] = {0.5f, 0.0f, 0.25f, 0.25f}; + for (int i = 3; i < ARRAY_SIZE(divPorts); i++) { + auto& port = divPorts[i]; + auto const& prev = divPorts[i - 1]; + port.x_orig = prev.x_orig; + port.y_orig = prev.y_orig + prev.height; + port.width = prev.width * 0.5f; + port.height = prev.height * 0.5f; + } + + auto divCopySrc = [&](int divNo) { + auto const& port = divPorts[divNo]; + GXSetTexCopySrc(port.x_orig * width, port.y_orig * height, port.width * width, port.height * height); + }; + + TGXTexObj tmpTex[MaxTexNum]; + auto divCopyTex = [&](uintptr_t texNo, int divNo) -> GXTexObj * { + auto const& port = divPorts[divNo]; + CopyToTexObj(&tmpTex[texNo], texNo, port.width * width, port.height * height); + return &tmpTex[texNo]; + }; + + auto divQuad = [&](int divNo) { + auto const& port = divPorts[divNo]; + f32 x0 = port.x_orig, y0 = port.y_orig; + f32 x1 = x0 + port.width, y1 = y0 + port.height; GXBegin(GX_QUADS, GX_VTXFMT0, 4); - GXPosition3f32(0, 0, -5); + GXPosition3f32(x0, y0, -5); GXTexCoord2s8(0, 0); - GXPosition3f32(x, 0, -5); + GXPosition3f32(x1, y0, -5); GXTexCoord2s8(1, 0); - GXPosition3f32(x, y, -5); + GXPosition3f32(x1, y1, -5); GXTexCoord2s8(1, 1); - GXPosition3f32(0, y, -5); + GXPosition3f32(x0, y1, -5); GXTexCoord2s8(0, 1); GXEnd(); }; @@ -1330,13 +1362,12 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP1, GX_TEV_SWAP1); GXSetTevColor(GX_TEVREG2, mMonoColor); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR); - filterQuad(1); + divQuad(0); } if (enabled) { - enum PassID { Pass0, Pass1, Pass2 }; - - GXCreateFrameBuffer(width, height); + GXCreateFrameBuffer(width * 0.75f, height * 0.5f); + GXSetViewport(0.0f, 0.0f, width, height, 0.1f, 1.0f); // use oversized viewport to make the math easier GXSetNumTevStages(3); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); @@ -1359,75 +1390,96 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_OR); GXColorS10 tevColor0 = {(s16)-mPoint, (s16)-mPoint, (s16)-mPoint, 0x40}; GXSetTevColorS10(GX_TEVREG0, tevColor0); - GXColor tevColor1 = {mBlureRatio, mBlureRatio, mBlureRatio, mBlureRatio}; - GXSetTevColor(GX_TEVREG1, tevColor1); GXPixModeSync(); - filterQuad(2); + + // Create thresholded 1/2 image. + divQuad(1); GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); // Downsample and filter from 1/2 EFB into 1/4. - TGXTexObj tmpTex[3]; - GXSetTexCopySrc(0, 0, width / 2, height / 2); - CopyToTexObj(&tmpTex[0], Pass0, width / 4, height / 4); - GXLoadTexObj(&tmpTex[0], GX_TEXMAP0); + divCopySrc(1); + GXTexObj* texPass0 = divCopyTex(Pass0, 2); + GXLoadTexObj(texPass0, GX_TEXMAP0); + f32 blurScale = mBlureSize * ((448.0f / getHeight()) / 6400.0f); + + // Setup blur filter TEV. GXSetNumTexGens(8); - u32 texMtxID = GX_TEXMTX0; - int angle = 0; - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); - for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { - GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); - f32 dVar15 = mBlureSize * ((448.0f / getHeight()) / 6400.0f); - - mDoMtx_stack_c::transS((dVar15 * cM_scos(angle)) * getInvScale(), - dVar15 * cM_ssin(angle), 0.0f); - GXLoadTexMtxImm(mDoMtx_stack_c::get(), texMtxID, GX_MTX2x4); - - texMtxID += 3; - angle += 0x2492; - } + auto SetupBlurMtx = [](float scale) { + u32 texMtxID = GX_TEXMTX0; + int angle = 0; + for (int texCoord = (int)GX_TEXCOORD0; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { + GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); + mDoMtx_stack_c::transS((scale * cM_scos(angle)) * getInvScale(), + scale * cM_ssin(angle), 0.0f); + GXLoadTexMtxImm(mDoMtx_stack_c::get(), texMtxID, GX_MTX2x4); + texMtxID += 3; + angle += 0x2000; + } + }; GXSetNumTevStages(8); - GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); - GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_ZERO); - GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); - GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); - GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); - for (int tevStage = (int)GX_TEVSTAGE1; tevStage < 8; tevStage++) { - GXSetTevOrder((GXTevStageID)tevStage, (GXTexCoordID)tevStage, GX_TEXMAP0, - GX_COLOR_NULL); - GXSetTevColorIn((GXTevStageID)tevStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_CPREV); - GXSetTevColorOp((GXTevStageID)tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, - GX_TEVPREV); - GXSetTevAlphaIn((GXTevStageID)tevStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); - GXSetTevAlphaOp((GXTevStageID)tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, - GX_TEVPREV); + for (int stage = 0; stage < 8; stage++) { + GXTevStageID tevStage = (GXTevStageID)stage; + GXSetTevOrder(tevStage, (GXTexCoordID)stage, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(tevStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, stage == 0 ? GX_CC_ZERO : GX_CC_CPREV); + GXSetTevColorOp(tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(tevStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp(tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); } - GXPixModeSync(); - // Blur filter from tmp_tex1 1/4 to EFB 1/4. - filterQuad(4); + // Successively downsample and apply blurs. + int divStart = 2; + int divNum = 6; - GXSetTexCopySrc(0, 0, width / 4, height / 4); - CopyToTexObj(&tmpTex[1], Pass1, width / 8, height / 8); - GXLoadTexObj(&tmpTex[1], GX_TEXMAP0); + // Distribute the brightness through each pass. + int totalNumPasses = (divNum - divStart) * 2; // down, up + float brightnessF32 = (mBlureRatio / 255.0f); + float brightnessPerPass = 255.0f * powf(brightnessF32, 1.0f / totalNumPasses); + GXSetTevColorS10(GX_TEVREG1, {0, 0, 0, s16(brightnessPerPass / 8)}); - // Upsample 1/8 buffer back up to 1/4 buffer. - GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR); - GXPixModeSync(); - GXInvalidateTexAll(); - filterQuad(4); + for (int i = divStart; i < divNum; i++) { + float blurStrength = 1.0f + (i - divStart) * 5.0f; + SetupBlurMtx(blurScale * blurStrength); + + // Apply blur filter. + divQuad(i); + + // Copy to next layer. + divCopySrc(i); + + // Set up for the next pass down. + GXTexObj * blurTex = divCopyTex(BlurPass0 + i, i + 1); + GXLoadTexObj(blurTex, GX_TEXMAP0); + } + + // All the way down at the bottom. Instead of blurring the bottom layer by itself, we blur when going up to the next layer. + // The remaining upscales are all just normal alpha blending. + divQuad(divNum); + + // Now successively alpha blend back up, don't blur anymore. + GXSetNumTevStages(1); + GXSetTevColorS10(GX_TEVREG1, {0, 0, 0, s16(brightnessPerPass)}); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_OR); + for (int i = divNum; i > divStart; i--) { + divCopySrc(i); + GXTexObj* upTex = divCopyTex(BlurPass0 + i, i); + GXLoadTexObj(upTex, GX_TEXMAP0); + divQuad(i - 1); + } // Now that we've upsampled and filtered our final bloom, copy 1/4 buffer. - GXSetTexCopySrc(0, 0, width / 4, height / 4); - CopyToTexObj(&tmpTex[2], Pass2, width / 4, height / 4); - GXLoadTexObj(&tmpTex[2], GX_TEXMAP0); + divCopySrc(2); + GXTexObj* texFinal = divCopyTex(FinalPass, 2); + GXLoadTexObj(texFinal, GX_TEXMAP0); GXRestoreFrameBuffer(); + GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f); // Now blend our bloom into the real FB. GXSetTevColor(GX_TEVREG0, mBlendColor); @@ -1437,14 +1489,27 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); - GXSetBlendMode(GX_BM_BLEND, mMode == 1 ? GX_BL_INVDSTCLR : GX_BL_ONE, GX_BL_SRCALPHA, GX_LO_OR); + GXSetBlendMode(GX_BM_BLEND, mMode == 1 ? GX_BL_INVDSTCLR : GX_BL_ONE, GX_BL_SRCALPHA, + GX_LO_OR); GXPixModeSync(); GXInvalidateTexAll(); - filterQuad(1); + divQuad(0); } } -#else +#endif + void mDoGph_gInf_c::bloom_c::draw() { + ZoneScoped; + if (!dusk::getSettings().game.enableBloom) { + return; + } + + static bool s_bloom2 = false; + if (s_bloom2) { + draw2(); + return; + } + bool enabled = mEnable && m_buffer != NULL; if (mMonoColor.a != 0 || enabled) { #if TARGET_PC @@ -1563,8 +1628,12 @@ void mDoGph_gInf_c::bloom_c::draw() { GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); - + + #if TARGET_PC + f32 dVar15 = mBlureSize * ((448.0f / height) / 6400.0f); + #else f32 dVar15 = mBlureSize * (1.0f / 6400.0f); + #endif mDoMtx_stack_c::transS((dVar15 * cM_scos(angle)) * getInvScale(), dVar15 * cM_ssin(angle), 0.0f); @@ -1673,7 +1742,6 @@ void mDoGph_gInf_c::bloom_c::draw() { } } } -#endif static void retry_captue_frame(view_class* param_0, view_port_class* param_1, int param_2) { UNUSED(param_0); From b4ca7304a0349e1d3267d39cac603e87286cd3e7 Mon Sep 17 00:00:00 2001 From: TakaRikka <38417346+TakaRikka@users.noreply.github.com> Date: Mon, 13 Apr 2026 01:42:10 -0700 Subject: [PATCH 12/13] cat door cleanup (#3155) --- include/d/actor/d_a_obj_catdoor.h | 27 +++++++++-- src/d/actor/d_a_obj_catdoor.cpp | 75 +++++++++++++++++-------------- 2 files changed, 65 insertions(+), 37 deletions(-) diff --git a/include/d/actor/d_a_obj_catdoor.h b/include/d/actor/d_a_obj_catdoor.h index 78f5525d8c..dd7141d920 100644 --- a/include/d/actor/d_a_obj_catdoor.h +++ b/include/d/actor/d_a_obj_catdoor.h @@ -12,6 +12,27 @@ public: /* 0xf4 */ s16 angle; }; +class daObjCatDoor_Attr_c { +public: + /* 0x0 */ s16 speed; + /* 0x2 */ s16 decay_rate; +}; + +class daObjCatDoor_Hio_c : public mDoHIO_entry_c { +public: + daObjCatDoor_Hio_c(); + ~daObjCatDoor_Hio_c(); + + void genMessage(JORMContext*); + + void ct(); + void dt(); + void default_set(); + + /* 0x8 */ int field_0x8; + /* 0xC */ daObjCatDoor_Attr_c m_attr; +}; + /** * @ingroup actors-objects * @class daObjCatDoor_c @@ -24,7 +45,7 @@ class daObjCatDoor_c : public fopAc_ac_c { public: inline ~daObjCatDoor_c(); - const s16* attr() const; + const daObjCatDoor_Attr_c* attr() const; void initBaseMtx(); void setBaseMtx(); void calcOpen(); @@ -45,7 +66,7 @@ public: } void setDoorOpen() { - mRotSpeed = attr()[1]; + mRotSpeed = attr()->decay_rate; dBgW* bgw1 = &mDoor1.bgw; if (bgw1->ChkUsed()) { dComIfG_Bgsp().Release(bgw1); @@ -67,7 +88,7 @@ private: /* 0x790 */ s16 mRotSpeed; public: - static u32 const M_attr; + static const daObjCatDoor_Attr_c M_attr; }; #endif /* D_A_OBJ_CATDOOR_H */ diff --git a/src/d/actor/d_a_obj_catdoor.cpp b/src/d/actor/d_a_obj_catdoor.cpp index b513e70050..1be955b6c9 100644 --- a/src/d/actor/d_a_obj_catdoor.cpp +++ b/src/d/actor/d_a_obj_catdoor.cpp @@ -10,35 +10,38 @@ static const char* l_arcName = "CatDoor"; -u32 const daObjCatDoor_c::M_attr = 0x001E0578; +const daObjCatDoor_Attr_c daObjCatDoor_c::M_attr = { + 30, + 1400, +}; daObjCatDoor_c::~daObjCatDoor_c() { if (mDoor1.bgw.ChkUsed()) { dComIfG_Bgsp().Release(&mDoor1.bgw); } + if (mDoor2.bgw.ChkUsed()) { dComIfG_Bgsp().Release(&mDoor2.bgw); } + dComIfG_resDelete(&mPhaseReq, l_arcName); } int daObjCatDoor_c::createHeap() { J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes(l_arcName, 4); + JUT_ASSERT(174, modelData != NULL); - ASSERT(modelData != NULL); mDoor1.pmodel = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000084); mDoor2.pmodel = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000084); if (mDoor1.pmodel == NULL || mDoor2.pmodel == NULL) { return 0; } - cBgD_t* cbgd = (cBgD_t*)dComIfG_getObjectRes(l_arcName, 7); - if (mDoor1.bgw.Set(cbgd, 1, &mDoor1.mtx)) { + if (mDoor1.bgw.Set((cBgD_t*)dComIfG_getObjectRes(l_arcName, 7), 1, &mDoor1.mtx)) { return 0; } - cBgD_t* cbgd2 = (cBgD_t*)dComIfG_getObjectRes(l_arcName, 7); - if (mDoor2.bgw.Set(cbgd2, 1, &mDoor2.mtx)) { + if (mDoor2.bgw.Set((cBgD_t*)dComIfG_getObjectRes(l_arcName, 7), 1, &mDoor2.mtx)) { return 0; } @@ -48,9 +51,9 @@ int daObjCatDoor_c::createHeap() { int daObjCatDoor_c::draw() { g_env_light.settingTevStruct(0x10, ¤t.pos, &tevStr); - fopAc_ac_c* p1 = static_cast(this); - g_env_light.setLightTevColorType_MAJI(mDoor1.pmodel, &p1->tevStr); - g_env_light.setLightTevColorType_MAJI(mDoor2.pmodel, &p1->tevStr); + fopAc_ac_c* actor = (fopAc_ac_c*)this; + g_env_light.setLightTevColorType_MAJI(mDoor1.pmodel, &actor->tevStr); + g_env_light.setLightTevColorType_MAJI(mDoor2.pmodel, &actor->tevStr); dComIfGd_setListBG(); mDoExt_modelUpdateDL(mDoor1.pmodel); @@ -60,22 +63,22 @@ int daObjCatDoor_c::draw() { } int daObjCatDoor_c::execute() { - if (dComIfGs_isSwitch(fopAcM_GetParam(this) & 0xFF, fopAcM_GetHomeRoomNo(this)) || - mRotSpeed == 0) - { + if (fopAcM_isSwitch(this, getSwitchNo()) || mRotSpeed == 0) { return 1; } + calcOpen(); setBaseMtx(); return 1; } -const s16* daObjCatDoor_c::attr() const { - return (const s16*)&daObjCatDoor_c::M_attr; +const daObjCatDoor_Attr_c* daObjCatDoor_c::attr() const { + return &daObjCatDoor_c::M_attr; } -static int createSolidHeap(fopAc_ac_c* i_this) { - return static_cast(i_this)->createHeap(); +static int createSolidHeap(fopAc_ac_c* actor) { + daObjCatDoor_c* i_this = (daObjCatDoor_c*)actor; + return i_this->createHeap(); } int daObjCatDoor_c::create() { @@ -84,7 +87,7 @@ int daObjCatDoor_c::create() { int phase_state = dComIfG_resLoad(&mPhaseReq, l_arcName); if (phase_state == cPhs_COMPLEATE_e) { if (!fopAcM_entrySolidHeap(this, createSolidHeap, 0x2520)) { - phase_state = cPhs_ERROR_e; + return cPhs_ERROR_e; } else { create_init(); } @@ -93,7 +96,8 @@ int daObjCatDoor_c::create() { } void daObjCatDoor_c::create_init() { - ASSERT(getSwitchNo() != 0xff); + JUT_ASSERT(295, getSwitchNo() != 0xff); + fopAcM_setCullSizeBox(this, -200.0f, 0.0f, -20.0f, 200.0f, 260.0f, 100.0f); if (fopAcM_isSwitch(this, getSwitchNo())) { mDoor1.angle = 0x8800; @@ -106,37 +110,40 @@ void daObjCatDoor_c::create_init() { mDoor2.bgw.SetRoomId(fopAcM_GetRoomNo(this)); dComIfG_Bgsp().Regist(&mDoor2.bgw, this); } + initBaseMtx(); } void daObjCatDoor_c::initBaseMtx() { - cullMtx = mMtx; + fopAcM_SetMtx(this, mMtx); mDoMtx_stack_c::transS(current.pos); - mDoMtx_YrotM(mDoMtx_stack_c::get(), shape_angle.y); - mDoMtx_copy(mDoMtx_stack_c::get(), mMtx); + mDoMtx_stack_c::YrotM(shape_angle.y); + cMtx_copy(mDoMtx_stack_c::get(), mMtx); setBaseMtx(); } void daObjCatDoor_c::setBaseMtx() { mDoMtx_stack_c::transS(current.pos); - mDoMtx_YrotM(mDoMtx_stack_c::get(), shape_angle.y); + mDoMtx_stack_c::YrotM(shape_angle.y); + for (int i = 0; i < 2; i++) { daObjCatDoor_Door_c* door = i == 0 ? &mDoor1 : &mDoor2; f32 xOff = i == 0 ? -97.0f : 97.0f; s16 rot = i == 0 ? door->angle : s16(door->angle + 0x8000); + mDoMtx_stack_c::push(); mDoMtx_stack_c::transM(xOff, 0.0, 0.0); - mDoMtx_YrotM(mDoMtx_stack_c::get(), (s16)rot); - mDoMtx_copy(mDoMtx_stack_c::get(), door->pmodel->mBaseTransformMtx); - mDoMtx_copy(mDoMtx_stack_c::get(), door->mtx); + mDoMtx_stack_c::YrotM((s16)rot); + door->pmodel->setBaseTRMtx(mDoMtx_stack_c::get()); + cMtx_copy(mDoMtx_stack_c::get(), door->mtx); door->bgw.Move(); mDoMtx_stack_c::pop(); } } void daObjCatDoor_c::calcOpen() { - s16 prev = mRotSpeed; - int res = cLib_chaseS(&mRotSpeed, 0, *attr()); + s16 prev = (s16)mRotSpeed; + int res = cLib_chaseS(&mRotSpeed, 0, attr()->speed); for (int i = 0; i < 2; i++) { daObjCatDoor_Door_c* door = i == 0 ? &mDoor1 : &mDoor2; if (i == 0) { @@ -159,20 +166,20 @@ static int daObjCatDoor_Execute(daObjCatDoor_c* i_this) { return static_cast(i_this)->execute(); } -static bool daObjCatDoor_IsDelete(daObjCatDoor_c* i_this) { - return true; +static int daObjCatDoor_IsDelete(daObjCatDoor_c* i_this) { + return 1; } static int daObjCatDoor_Delete(daObjCatDoor_c* i_this) { - fopAcM_GetID(i_this); + fpc_ProcID id = fopAcM_GetID(i_this); i_this->~daObjCatDoor_c(); return 1; } -static int daObjCatDoor_Create(fopAc_ac_c* i_this) { - fopAcM_GetID(i_this); - daObjCatDoor_c* a_this = static_cast(i_this); - return a_this->create(); +static int daObjCatDoor_Create(fopAc_ac_c* actor) { + daObjCatDoor_c* i_this = (daObjCatDoor_c*)actor; + fpc_ProcID id = fopAcM_GetID(actor); + return i_this->create(); } static actor_method_class l_daObjCatDoor_Method = { From 299503a5aa3a7598bed7dfea8ef54176547a756d Mon Sep 17 00:00:00 2001 From: Lurs <2795933+Lurs@users.noreply.github.com> Date: Mon, 13 Apr 2026 12:29:40 +0200 Subject: [PATCH 13/13] Fix GCC compiler error under wsl ubuntu --- src/dusk/imgui/ImGuiEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dusk/imgui/ImGuiEngine.cpp b/src/dusk/imgui/ImGuiEngine.cpp index eb7bf4c6bc..f8dc048c0f 100644 --- a/src/dusk/imgui/ImGuiEngine.cpp +++ b/src/dusk/imgui/ImGuiEngine.cpp @@ -60,7 +60,7 @@ inline ImFont* CreateFont(float size, const std::string& fontPath, std::string_v void ImGuiEngine_Initialize(float scale) { // Round font scale to nearest integer - scale = std::ceilf(scale); + scale = std::ceil(scale); ImGui::GetCurrentContext(); ImGuiIO& io = ImGui::GetIO();