From 315f23b9307a1d2101982d9ef0b770541729dedb Mon Sep 17 00:00:00 2001 From: CraftyBoss Date: Thu, 19 Mar 2026 23:54:00 -0400 Subject: [PATCH 01/18] fix StaffWork being too big for work buffer, increase mpTalkHeap size --- include/d/d_event_data.h | 11 +++++++++++ src/d/d_event_data.cpp | 16 ++++++++++++++++ src/d/d_menu_fmap.cpp | 21 +++++++++++---------- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/d/d_event_data.h b/include/d/d_event_data.h index f42e16b7a7..ee9b868af4 100644 --- a/include/d/d_event_data.h +++ b/include/d/d_event_data.h @@ -136,6 +136,17 @@ public: } msgs; }; +#if TARGET_PC + struct StaffWorkPtrHolder { + StaffWork* m_ptr = nullptr; + + StaffWork* operator->() const { return m_ptr; } + + void createPtr(); + void deletePtr(); + }; +#endif + struct MessageData { BE(s16) unk; }; diff --git a/src/d/d_event_data.cpp b/src/d/d_event_data.cpp index 3b099e891c..a339c835c7 100644 --- a/src/d/d_event_data.cpp +++ b/src/d/d_event_data.cpp @@ -318,6 +318,17 @@ static int dEvDt_Next_Stage(int i_staffId, int i_wipe) { return 1; } +#if TARGET_PC +void dEvDtStaff_c::StaffWorkPtrHolder::createPtr() { + if (m_ptr == nullptr) + m_ptr = (StaffWork*)JKRAllocFromHeap(mDoExt_getGameHeap(), sizeof(StaffWork), 8); +} +void dEvDtStaff_c::StaffWorkPtrHolder::deletePtr() { + delete m_ptr; + m_ptr = nullptr; +} +#endif + BOOL dEvDtFlag_c::flagCheck(int flag) { if (flagMaxCheck(flag)) { return FALSE; @@ -527,7 +538,12 @@ void dEvDtStaff_c::specialProcLight() { void dEvDtStaff_c::specialProcMessage() { MessageData* data = (MessageData*)&mData; +#if TARGET_PC + StaffWorkPtrHolder& wk = *(StaffWorkPtrHolder*)&mWork; + wk.createPtr(); +#else StaffWork* wk = (StaffWork*)&mWork; +#endif int staffId = dComIfGp_evmng_getMyStaffId("MESSAGE", NULL, 0); if (staffId == -1) { diff --git a/src/d/d_menu_fmap.cpp b/src/d/d_menu_fmap.cpp index 58c839d666..cd370a56d7 100644 --- a/src/d/d_menu_fmap.cpp +++ b/src/d/d_menu_fmap.cpp @@ -1,27 +1,28 @@ #include "d/dolzel.h" // IWYU pragma: keep -#include "d/d_menu_fmap.h" -#include "SSystem/SComponent/c_math.h" +#include +#include #include "JSystem/JKernel/JKRAramArchive.h" #include "JSystem/JKernel/JKRExpHeap.h" #include "JSystem/JKernel/JKRMemArchive.h" -#include -#include -#include "f_op/f_op_msg_mng.h" +#include "SSystem/SComponent/c_math.h" +#include "d/actor/d_a_midna.h" +#include "d/actor/d_a_player.h" #include "d/d_com_inf_game.h" #include "d/d_lib.h" +#include "d/d_menu_fmap.h" #include "d/d_menu_fmap2D.h" #include "d/d_menu_fmap_map.h" #include "d/d_menu_window.h" -#include "d/d_meter_HIO.h" -#include "d/d_meter_map.h" #include "d/d_meter2_draw.h" #include "d/d_meter2_info.h" +#include "d/d_meter_HIO.h" +#include "d/d_meter_map.h" #include "d/d_msg_object.h" #include "d/d_msg_scrn_explain.h" #include "d/d_stage.h" -#include "d/actor/d_a_player.h" -#include "d/actor/d_a_midna.h" +#include "dusk/memory.h" +#include "f_op/f_op_msg_mng.h" static dMf_HIO_c g_fmHIO; @@ -189,7 +190,7 @@ dMenu_Fmap_c::dMenu_Fmap_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i field_0x148[i] = 0.0f; } - mpTalkHeap = JKRCreateExpHeap(0x32000, mpHeap, false); + mpTalkHeap = JKRCreateExpHeap(HEAP_SIZE(0x32000, 0x40000), mpHeap, false); JUT_ASSERT(359, mpTalkHeap != NULL); field_0x200 = 0; mIsWarpMap = false; From 91d8e422ac2edf1bbc7bdc40d844dca807269f04 Mon Sep 17 00:00:00 2001 From: CraftyBoss Date: Thu, 19 Mar 2026 23:59:37 -0400 Subject: [PATCH 02/18] oops forgot to include something --- src/d/d_event_data.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/d/d_event_data.cpp b/src/d/d_event_data.cpp index a339c835c7..6e8a57b57a 100644 --- a/src/d/d_event_data.cpp +++ b/src/d/d_event_data.cpp @@ -15,6 +15,8 @@ #include "SSystem/SComponent/c_counter.h" #include +#include "JSystem/JKernel/JKRExpHeap.h" + inline BOOL dEvDtFlagCheck(int i_flag) { return dComIfGp_getEventManager().getFlags().flagCheck(i_flag); } From 7ae18f3a9d7842647bc809dbd6f84de284410393 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Fri, 20 Mar 2026 02:51:29 -0400 Subject: [PATCH 03/18] Fix last argument in calls to dCamera_c::startEventCamera The last argument is used as a char*, so we need to explicitly pass nullptr instead of 0 to ensure it has the correct type. This was causing crashes due to va_arg reading 8 bytes when only 4 were provided by the caller - if the out-of-bounds bytes are non-zero, the null check fails and it continues pulling args from beyond the argument buffer potentially triggering a segfault. --- src/d/actor/d_a_alink_bottle.inc | 6 +++--- src/d/actor/d_a_alink_canoe.inc | 2 +- src/d/actor/d_a_alink_damage.inc | 4 ++-- src/d/actor/d_a_alink_demo.inc | 6 +++--- src/d/actor/d_a_alink_horse.inc | 2 +- src/d/actor/d_a_alink_kandelaar.inc | 2 +- src/d/actor/d_a_alink_whistle.inc | 2 +- src/d/actor/d_a_alink_wolf.inc | 6 +++--- src/d/actor/d_a_npc_tkc.cpp | 2 +- src/d/actor/d_a_obj_tks.cpp | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/d/actor/d_a_alink_bottle.inc b/src/d/actor/d_a_alink_bottle.inc index 65670e0fd2..8af270df7a 100644 --- a/src/d/actor/d_a_alink_bottle.inc +++ b/src/d/actor/d_a_alink_bottle.inc @@ -379,7 +379,7 @@ int daAlink_c::procBottleDrinkInit(u16 i_itemNo) { mProcVar0.field_0x3008 = 0; u32 id = fopAcM_GetID(this); - dCam_getBody()->StartEventCamera(0x12, id, "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(0x12, id, "Type", 1, &field_0x3194, nullptr); mProcVar2.field_0x300c = 0; mProcVar3.field_0x300e = 0; return 1; @@ -429,7 +429,7 @@ int daAlink_c::procBottleOpenInit(u16 i_itemNo) { mProcVar3.field_0x300e = 0; - dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x3194, nullptr); mProcVar2.field_0x300c = 0; field_0x27c8.initialize(current.pos.y + mHeight); @@ -738,7 +738,7 @@ int daAlink_c::procBottleGetInit(BOOL param_0) { } u32 id = fopAcM_GetID(this); - dCam_getBody()->StartEventCamera(0x12, id, "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(0x12, id, "Type", 1, &field_0x3194, nullptr); if (mEquipItem == dItemNo_FAIRY_DROP_e || mEquipItem == dItemNo_CHUCHU_RARE_e || mEquipItem == dItemNo_WORM_e) { setFaceBasicTexture(FTANM_I_BINGET); diff --git a/src/d/actor/d_a_alink_canoe.inc b/src/d/actor/d_a_alink_canoe.inc index efe6f4551a..fdf1ca0f6a 100644 --- a/src/d/actor/d_a_alink_canoe.inc +++ b/src/d/actor/d_a_alink_canoe.inc @@ -1575,7 +1575,7 @@ int daAlink_c::procCanoeBottleDrinkInit(u16 i_itemNo) { dComIfGp_setPlayerStatus1(0, 0x2000); field_0x319c = 1; - dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x319c, 0); + dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x319c, nullptr); mProcVar2.field_0x300c = 0; return 1; } diff --git a/src/d/actor/d_a_alink_damage.inc b/src/d/actor/d_a_alink_damage.inc index 3863551c62..122bf8f248 100644 --- a/src/d/actor/d_a_alink_damage.inc +++ b/src/d/actor/d_a_alink_damage.inc @@ -1982,7 +1982,7 @@ int daAlink_c::procCoLavaReturnInit(BOOL i_isSandReturn) { mNormalSpeed = 0.0f; field_0x3194 = 1; - dCam_getBody()->StartEventCamera(9, fopAcM_GetID(this), "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(9, fopAcM_GetID(this), "Type", 1, &field_0x3194, nullptr); return 1; } @@ -2040,7 +2040,7 @@ int daAlink_c::procCoSwimFreezeReturnInit() { field_0x3194 = 1; u32 id = fopAcM_GetID(this); - dCam_getBody()->StartEventCamera(9, id, "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(9, id, "Type", 1, &field_0x3194, nullptr); mProcVar2.field_0x300c = 0x2D; return 1; } diff --git a/src/d/actor/d_a_alink_demo.inc b/src/d/actor/d_a_alink_demo.inc index dbea0add91..462c35d4e8 100644 --- a/src/d/actor/d_a_alink_demo.inc +++ b/src/d/actor/d_a_alink_demo.inc @@ -3019,7 +3019,7 @@ int daAlink_c::procCoDead() { if (!checkNoResetFlg2(FLG2_FORCE_GAMEOVER)) { mProcVar3.field_0x300e++; if (mProcVar3.field_0x300e == 2) { - dCam_getBody()->StartEventCamera(9, fopAcM_GetID(this), 0); + dCam_getBody()->StartEventCamera(9, fopAcM_GetID(this), nullptr); } else if (mProcVar3.field_0x300e > 10) { mProcVar3.field_0x300e = 10; } @@ -3330,7 +3330,7 @@ int daAlink_c::procCoFogDeadInit() { field_0x3194 = 0; - dCam_getBody()->StartEventCamera(0x13, fopAcM_GetID(this), "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(0x13, fopAcM_GetID(this), "Type", 1, &field_0x3194, nullptr); mProcVar0.field_0x3008 = 60; mProcVar2.field_0x300c = 0; return 1; @@ -3849,7 +3849,7 @@ int daAlink_c::procNotUseItemInit(int i_itemNo) { current.angle.y = shape_angle.y; field_0x3194 = 3; - dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x3194, nullptr); keepItemData(); dComIfGp_setPlayerStatus1(0, 0x4000800); diff --git a/src/d/actor/d_a_alink_horse.inc b/src/d/actor/d_a_alink_horse.inc index 6d56929288..ac7ce73e50 100644 --- a/src/d/actor/d_a_alink_horse.inc +++ b/src/d/actor/d_a_alink_horse.inc @@ -2570,7 +2570,7 @@ int daAlink_c::procHorseBottleDrinkInit(u16 i_itemNo) { dComIfGp_setPlayerStatus1(0, 0x2000); field_0x319c = 1; - dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x319c, 0); + dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x319c, nullptr); mProcVar2.field_0x300c = 0; return 1; } diff --git a/src/d/actor/d_a_alink_kandelaar.inc b/src/d/actor/d_a_alink_kandelaar.inc index cd25a66d7e..339ff90ce6 100644 --- a/src/d/actor/d_a_alink_kandelaar.inc +++ b/src/d/actor/d_a_alink_kandelaar.inc @@ -256,7 +256,7 @@ void daAlink_c::commonKandelaarPourInit() { mProcVar2.field_0x300c = 0; dComIfGp_setPlayerStatus1(0, 0x2000); field_0x3194 = 10; - dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x3194, 0); + dCam_getBody()->StartEventCamera(0x12, fopAcM_GetID(this), "Type", 1, &field_0x3194, nullptr); } int daAlink_c::commonKandelaarPour(int param_0) { diff --git a/src/d/actor/d_a_alink_whistle.inc b/src/d/actor/d_a_alink_whistle.inc index eabff6d408..5c16d3bf52 100644 --- a/src/d/actor/d_a_alink_whistle.inc +++ b/src/d/actor/d_a_alink_whistle.inc @@ -145,7 +145,7 @@ int daAlink_c::procGrassWhistleWaitInit(int param_0, int param_1, int param_2, s mProcVar2.field_0x300c = param_0; mProcVar3.field_0x300e = param_1; - dCam_getBody()->StartEventCamera(12, fopAcM_GetID(this), 0); + dCam_getBody()->StartEventCamera(12, fopAcM_GetID(this), nullptr); mProcVar0.field_0x3008 = 0; mProcVar4.field_0x3010 = 0; mProcVar5.field_0x3012 = 0; diff --git a/src/d/actor/d_a_alink_wolf.inc b/src/d/actor/d_a_alink_wolf.inc index 6f40a55cdb..2bf1129f17 100644 --- a/src/d/actor/d_a_alink_wolf.inc +++ b/src/d/actor/d_a_alink_wolf.inc @@ -3967,7 +3967,7 @@ int daAlink_c::procWolfHowlDemoInit() { } } - dCam_getBody()->StartEventCamera(12, fopAcM_GetID(this), 0); + dCam_getBody()->StartEventCamera(12, fopAcM_GetID(this), nullptr); mProcVar1.field_0x300a = 0; mMsgClassID = fpcM_ERROR_PROCESS_ID_e; field_0x32cc = 0x5DD; @@ -9206,7 +9206,7 @@ int daAlink_c::procWolfDigThroughInit(int param_0) { field_0x3198 = 3; } - dCam_getBody()->StartEventCamera(0x1E, fopAcM_GetID(this), "Type", 1, &field_0x3198, 0); + dCam_getBody()->StartEventCamera(0x1E, fopAcM_GetID(this), "Type", 1, &field_0x3198, nullptr); cXyz sp8(current.pos.x, 30.0f + field_0x27f4->current.pos.y, current.pos.z); if (fopAcM_gc_c::gndCheck(&sp8)) { @@ -9413,7 +9413,7 @@ int daAlink_c::procWolfGetSmell() { mProcVar4.field_0x3010 = 1; - dCam_getBody()->StartEventCamera(8, fopAcM_GetID(this), 0); + dCam_getBody()->StartEventCamera(8, fopAcM_GetID(this), nullptr); field_0x2f99 = 12; if (field_0x3198 == 0xBBC) { diff --git a/src/d/actor/d_a_npc_tkc.cpp b/src/d/actor/d_a_npc_tkc.cpp index 441beb1a5b..bcd5afedb8 100644 --- a/src/d/actor/d_a_npc_tkc.cpp +++ b/src/d/actor/d_a_npc_tkc.cpp @@ -577,7 +577,7 @@ void daNpcTkc_c::reset() { setAngle(fopAcM_searchPlayerAngleY(this)); static int const m_cameraItemNum = 1; - dCam_getBody()->StartEventCamera(18, fopAcM_GetID(this), "Type", 1, &m_cameraItemNum, 0); + dCam_getBody()->StartEventCamera(18, fopAcM_GetID(this), "Type", 1, &m_cameraItemNum, nullptr); } else if (parentActorID == fpcM_ERROR_PROCESS_ID_e) { home.pos.y += mpHIO->m.target_height; } else { diff --git a/src/d/actor/d_a_obj_tks.cpp b/src/d/actor/d_a_obj_tks.cpp index 7add35570e..7c87356c85 100644 --- a/src/d/actor/d_a_obj_tks.cpp +++ b/src/d/actor/d_a_obj_tks.cpp @@ -164,7 +164,7 @@ int daObjTks_c::Create() { field_0xde1 = 1; static const int m_cameraItemNum = 1; - dCam_getBody()->StartEventCamera(18, fopAcM_GetID(this), "Type", 1, &m_cameraItemNum, 0); + dCam_getBody()->StartEventCamera(18, fopAcM_GetID(this), "Type", 1, &m_cameraItemNum, nullptr); } return phase_state; From 0474db2fdf8022c275a3e1f248a9890f0e0728a4 Mon Sep 17 00:00:00 2001 From: Lurs <2795933+Lurs@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:50:57 +0100 Subject: [PATCH 04/18] remove double swapping --- include/d/d_bg_w_kcol.h | 11 ++- src/d/d_bg_w_kcol.cpp | 207 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 208 insertions(+), 10 deletions(-) diff --git a/include/d/d_bg_w_kcol.h b/include/d/d_bg_w_kcol.h index 1fc812dd98..463f414080 100644 --- a/include/d/d_bg_w_kcol.h +++ b/include/d/d_bg_w_kcol.h @@ -115,7 +115,16 @@ public: return pd; } - void getTri1Pos(KC_PrismData* pd, Vec** nrm) const { *nrm = &m_pkc_head->m_pos_data[pd->pos_i]; } + void getTri1Pos(KC_PrismData* pd, Vec** nrm) const { +#if TARGET_PC + static Vec pos_v; + pos_v = m_pkc_head->m_pos_data[pd->pos_i]; + be_swap(pos_v); + *nrm = &pos_v; +#else + *nrm = &m_pkc_head->m_pos_data[pd->pos_i]; +#endif + } private: /* 0x18 */ KC_Header* m_pkc_head; diff --git a/src/d/d_bg_w_kcol.cpp b/src/d/d_bg_w_kcol.cpp index 46e5e5dd21..f6d4c0f585 100644 --- a/src/d/d_bg_w_kcol.cpp +++ b/src/d/d_bg_w_kcol.cpp @@ -36,15 +36,6 @@ void* dBgWKCol::initKCollision(void* i_kclData) { be_swap(kcl->m_area_x_blocks_shift); be_swap(kcl->m_area_xy_blocks_shift); - Vec* p_pos = kcl->m_pos_data; - Vec* p_nrm = kcl->m_nrm_data; - KC_PrismData* p_prism = kcl->m_prism_data; - BE(u32)* p_block = kcl->m_block_data; - int np = 0, nn = 0; - for (Vec* pw = p_pos; pw < p_nrm; pw++, np++) - be_swap(*pw); - for (Vec* pw = p_nrm; (uintptr_t)pw < (uintptr_t)p_prism; pw++, nn++) - be_swap(*pw); // for (KC_PrismData* pw = p_prism; (uintptr_t)pw < (uintptr_t)p_block; pw++) // be_swap(*pw); @@ -73,8 +64,15 @@ void dBgWKCol::create(void* pprism, void* plc) { } void dBgWKCol::getTriNrm(KC_PrismData* pkc, Vec** nrm) const { +#if TARGET_PC + static Vec var_r31_v; + var_r31_v = m_pkc_head->m_nrm_data[pkc->fnrm_i]; + be_swap(var_r31_v); + *nrm = &var_r31_v; +#else Vec* var_r31 = &m_pkc_head->m_nrm_data[pkc->fnrm_i]; *nrm = var_r31; +#endif } bool dBgWKCol::ChkNotReady() const { @@ -127,12 +125,29 @@ bool dBgWKCol::GetTriPnt(int poly_index, Vec* ppos, Vec* param_2, Vec* param_3) bool dBgWKCol::GetTriPnt(KC_PrismData const* pd, Vec* ppos, Vec* param_3, Vec* param_4) const { +#if TARGET_PC + *ppos = m_pkc_head->m_pos_data[pd->pos_i]; + be_swap(*ppos); + Vec face_nrm_v = m_pkc_head->m_nrm_data[pd->fnrm_i]; + be_swap(face_nrm_v); + Vec* face_nrm = &face_nrm_v; + Vec edge_nrm1_v = m_pkc_head->m_nrm_data[pd->enrm1_i]; + be_swap(edge_nrm1_v); + Vec* edge_nrm1 = &edge_nrm1_v; + Vec edge_nrm2_v = m_pkc_head->m_nrm_data[pd->enrm2_i]; + be_swap(edge_nrm2_v); + Vec* edge_nrm2 = &edge_nrm2_v; + Vec edge_nrm3_v = m_pkc_head->m_nrm_data[pd->enrm3_i]; + be_swap(edge_nrm3_v); + Vec* edge_nrm3 = &edge_nrm3_v; +#else *ppos = m_pkc_head->m_pos_data[pd->pos_i]; Vec* face_nrm = &m_pkc_head->m_nrm_data[pd->fnrm_i]; Vec* edge_nrm1 = &m_pkc_head->m_nrm_data[pd->enrm1_i]; Vec* edge_nrm2 = &m_pkc_head->m_nrm_data[pd->enrm2_i]; Vec* edge_nrm3 = &m_pkc_head->m_nrm_data[pd->enrm3_i]; +#endif Vec sp64; PSVECCrossProduct(face_nrm, edge_nrm1, &sp64); @@ -443,8 +458,17 @@ bool dBgWKCol::LineCheck(cBgS_LinChk* plinchk) { } else { while (*(++sp28) != 0) { KC_PrismData* sp20 = getPrismData(sp28[0]); + #if TARGET_PC + Vec sp1C_v = m_pkc_head->m_nrm_data[sp20->fnrm_i]; + be_swap(sp1C_v); + Vec* sp1C = &sp1C_v; + Vec sp18_v = m_pkc_head->m_pos_data[sp20->pos_i]; + be_swap(sp18_v); + Vec* sp18 = &sp18_v; + #else Vec* sp1C = &m_pkc_head->m_nrm_data[sp20->fnrm_i]; Vec* sp18 = &m_pkc_head->m_pos_data[sp20->pos_i]; + #endif cXyz spE4; PSVECSubtract(&sp138, sp18, &spE4); @@ -472,13 +496,32 @@ bool dBgWKCol::LineCheck(cBgS_LinChk* plinchk) { cXyz spB4; PSVECAdd(&spE4, &spC0, &spB4); +#if TARGET_PC + Vec sp14_v = m_pkc_head->m_nrm_data[sp20->enrm1_i]; + be_swap(sp14_v); + Vec* sp14 = &sp14_v; +#else Vec* sp14 = &m_pkc_head->m_nrm_data[sp20->enrm1_i]; +#endif if (PSVECDotProduct(&spB4, sp14) <= 0.0075f) { +#if TARGET_PC + Vec sp10_v = m_pkc_head->m_nrm_data[sp20->enrm2_i]; + be_swap(sp10_v); + Vec* sp10 = &sp10_v; +#else Vec* sp10 = &m_pkc_head->m_nrm_data[sp20->enrm2_i]; +#endif if (PSVECDotProduct(&spB4, sp10) <= 0.0075f) { +#if TARGET_PC + Vec spC_v = + m_pkc_head->m_nrm_data[sp20->enrm3_i]; + be_swap(spC_v); + Vec* spC = &spC_v; +#else Vec* spC = &m_pkc_head->m_nrm_data[sp20->enrm3_i]; +#endif f32 var_f26 = PSVECDotProduct(&spB4, spC); if (var_f26 >= -0.0075f && var_f26 <= sp20->height + 0.0075f) @@ -596,18 +639,43 @@ bool dBgWKCol::GroundCross(cBgS_GndChk* i_chk) { while (*++sp1C != 0) { KC_PrismData* sp18 = getPrismData(sp1C[0]); +#if TARGET_PC + Vec sp14_v = m_pkc_head->m_nrm_data[sp18->fnrm_i]; + be_swap(sp14_v); + Vec* sp14 = &sp14_v; +#else Vec* sp14 = &m_pkc_head->m_nrm_data[sp18->fnrm_i]; +#endif if (!(sp14->y < 0.014f) && !cM3d_IsZero(sp14->y) && (!cBgW_CheckBWall(sp14->y) || i_chk->GetWallPrecheck())) { +#if TARGET_PC + Vec sp10_v = m_pkc_head->m_pos_data[sp18->pos_i]; + be_swap(sp10_v); + Vec* sp10 = &sp10_v; +#else Vec* sp10 = &m_pkc_head->m_pos_data[sp18->pos_i]; +#endif sp4C.x = point_p->x - sp10->x; sp4C.z = point_p->z - sp10->z; sp4C.y = -(sp4C.x * sp14->x + sp4C.z * sp14->z) / sp14->y; +#if TARGET_PC + Vec enrm1_v = m_pkc_head->m_nrm_data[sp18->enrm1_i]; + be_swap(enrm1_v); + Vec enrm2_v = m_pkc_head->m_nrm_data[sp18->enrm2_i]; + be_swap(enrm2_v); + if (!(PSVECDotProduct(&sp4C, &enrm1_v) > 0.0075f) && + !(PSVECDotProduct(&sp4C, &enrm2_v) > 0.0075f)) + { + Vec enrm3_v = m_pkc_head->m_nrm_data[sp18->enrm3_i]; + be_swap(enrm3_v); + f32 var_f30 = PSVECDotProduct(&sp4C, &enrm3_v); +#else if (!(PSVECDotProduct(&sp4C, &m_pkc_head->m_nrm_data[sp18->enrm1_i]) > 0.0075f) && !(PSVECDotProduct(&sp4C, &m_pkc_head->m_nrm_data[sp18->enrm2_i]) > 0.0075f)) { f32 var_f30 = PSVECDotProduct(&sp4C, &m_pkc_head->m_nrm_data[sp18->enrm3_i]); +#endif if (!(var_f30 > 0.0075f + sp18->height) && !(var_f30 < -0.0075f)) { dBgPc sp64; getPolyCode(sp1C[0], &sp64); @@ -819,6 +887,22 @@ void dBgWKCol::ShdwDraw(cBgS_ShdwDraw* param_0) { if (!ChkShdwDrawThrough(&polyCode_sp108)) { prismData_sp20 = getPrismData(p_prismList[0]); +#if TARGET_PC + sp11C[0] = + m_pkc_head->m_pos_data[prismData_sp20->pos_i]; + be_swap(sp11C[0]); + + Vec nrm1_sp1C_v = m_pkc_head->m_nrm_data[prismData_sp20->fnrm_i]; + be_swap(nrm1_sp1C_v); + nrm1_sp1C = &nrm1_sp1C_v; + Vec nrm2_sp18_v = m_pkc_head->m_nrm_data[prismData_sp20->enrm1_i]; + be_swap(nrm2_sp18_v); + nrm2_sp18 = &nrm2_sp18_v; + + Vec unk_sp14_v = m_pkc_head->m_nrm_data[prismData_sp20->enrm3_i]; + be_swap(unk_sp14_v); + unk_sp14 = &unk_sp14_v; +#else sp11C[0] = m_pkc_head->m_pos_data[prismData_sp20->pos_i]; @@ -829,6 +913,7 @@ void dBgWKCol::ShdwDraw(cBgS_ShdwDraw* param_0) { unk_sp14 = m_pkc_head->m_nrm_data + prismData_sp20->enrm3_i; +#endif PSVECCrossProduct(nrm1_sp1C, nrm2_sp18, &cross1_spBC); f32 dot = PSVECDotProduct(&cross1_spBC, unk_sp14); @@ -839,8 +924,14 @@ void dBgWKCol::ShdwDraw(cBgS_ShdwDraw* param_0) { &sp11C[2]); // Second edge direction +#if TARGET_PC + Vec temp_sp10_v = m_pkc_head->m_nrm_data[prismData_sp20->enrm2_i]; + be_swap(temp_sp10_v); + temp_sp10 = &temp_sp10_v; +#else temp_sp10 = m_pkc_head->m_nrm_data + prismData_sp20->enrm2_i; +#endif PSVECCrossProduct(temp_sp10, nrm1_sp1C, &cross2_spB0); f32 dot2 = @@ -990,7 +1081,13 @@ void dBgWKCol::CaptPoly(dBgS_CaptPoly& i_captpoly) { if (r28 != sp28) { while (*++r28 != 0) { KC_PrismData* spC = getPrismData(r28[0]); +#if TARGET_PC + Vec sp8_v = m_pkc_head->m_nrm_data[spC->fnrm_i]; + be_swap(sp8_v); + Vec* sp8 = &sp8_v; +#else Vec* sp8 = &m_pkc_head->m_nrm_data[spC->fnrm_i]; +#endif dBgPc spD8; getPolyCode(r28[0], &spD8); @@ -1174,7 +1271,13 @@ bool dBgWKCol::WallCorrectSort(dBgS_Acch* pwi) { } else { while (*++sp_c8 != 0) { KC_PrismData* sp_c0 = (KC_PrismData*)getPrismData(*sp_c8); +#if TARGET_PC + Vec sp_bc_v = m_pkc_head->m_nrm_data[sp_c0->fnrm_i]; + be_swap(sp_bc_v); + Vec* sp_bc = &sp_bc_v; +#else Vec* sp_bc = m_pkc_head->m_nrm_data + sp_c0->fnrm_i; +#endif if (!cBgW_CheckBGround(sp_bc->y)) { f32 sp_b8 = JMAFastSqrt(sp_bc->x * sp_bc->x + sp_bc->z * sp_bc->z); if (!cM3d_IsZero(sp_b8)) { @@ -1277,7 +1380,13 @@ bool dBgWKCol::WallCorrectSort(dBgS_Acch* pwi) { } int sp_a0 = sp_a4->_4; KC_PrismData* sp_9c = (KC_PrismData*)getPrismData(sp_a0); +#if TARGET_PC + Vec sp_98_v = m_pkc_head->m_nrm_data[sp_9c->fnrm_i]; + be_swap(sp_98_v); + Vec* sp_98 = &sp_98_v; +#else Vec* sp_98 = m_pkc_head->m_nrm_data + sp_9c->fnrm_i; +#endif f32 sp_94 = JMAFastSqrt(sp_98->x * sp_98->x + sp_98->z * sp_98->z); cXyz sp_168; cXyz sp_15c; @@ -1635,7 +1744,13 @@ bool dBgWKCol::WallCorrect(dBgS_Acch* pwi) { while (*++p_prismlist != 0) { KC_PrismData* sp9C = (KC_PrismData*)getPrismData(*p_prismlist); +#if TARGET_PC + Vec sp98_v = m_pkc_head->m_nrm_data[sp9C->fnrm_i]; + be_swap(sp98_v); + Vec* sp98 = &sp98_v; +#else Vec* sp98 = m_pkc_head->m_nrm_data + sp9C->fnrm_i; +#endif if (cBgW_CheckBGround(sp98->y)) { continue; } @@ -1932,15 +2047,48 @@ bool dBgWKCol::RoofChk(dBgS_RoofChk* param_0) { while (*++p_prismlist != 0) { sp1C = getPrismData(p_prismlist[0]); +#if TARGET_PC + Vec sp18_v = m_pkc_head->m_nrm_data[sp1C->fnrm_i]; + be_swap(sp18_v); + sp18 = &sp18_v; +#else sp18 = m_pkc_head->m_nrm_data + sp1C->fnrm_i; +#endif if (cBgW_CheckBRoof(sp18->y)) { +#if TARGET_PC + Vec sp14_v = m_pkc_head->m_pos_data[sp1C->pos_i]; + be_swap(sp14_v); + sp14 = &sp14_v; +#else sp14 = m_pkc_head->m_pos_data + sp1C->pos_i; +#endif cXyz sp5C; sp5C.x = sp40->x - sp14->x; sp5C.z = sp40->z - sp14->z; sp5C.y = -(sp5C.x * sp18->x + sp5C.z * sp18->z) / sp18->y; +#if TARGET_PC + Vec enrm1_v = m_pkc_head->m_nrm_data[sp1C->enrm1_i]; + be_swap(enrm1_v); + if (PSVECDotProduct(&sp5C, &enrm1_v) > + 0.0075f) + { + continue; + } + + Vec enrm2_v = m_pkc_head->m_nrm_data[sp1C->enrm2_i]; + be_swap(enrm2_v); + if (PSVECDotProduct(&sp5C, + &enrm2_v) > 0.0075f) + { + continue; + } + + Vec enrm3_v = m_pkc_head->m_nrm_data[sp1C->enrm3_i]; + be_swap(enrm3_v); + f32 dot_f30 = PSVECDotProduct(&sp5C, &enrm3_v); +#else if (PSVECDotProduct(&sp5C, &m_pkc_head->m_nrm_data[sp1C->enrm1_i]) > 0.0075f) { @@ -1954,6 +2102,7 @@ bool dBgWKCol::RoofChk(dBgS_RoofChk* param_0) { } f32 dot_f30 = PSVECDotProduct(&sp5C, &m_pkc_head->m_nrm_data[sp1C->enrm3_i]); +#endif if (dot_f30 < -0.0075f || dot_f30 > sp1C->height + 0.0075f) { continue; } @@ -2050,7 +2199,13 @@ bool dBgWKCol::SplGrpChk(dBgS_SplGrpChk* param_0) { BE(u16)* p_prismlist = (BE(u16)*)(block + (idx & 0x7fffffff)); while (*++p_prismlist != 0) { KC_PrismData* sp18 = getPrismData(*p_prismlist); +#if TARGET_PC + Vec sp14_v = m_pkc_head->m_nrm_data[sp18->fnrm_i]; + be_swap(sp14_v); + Vec* sp14 = &sp14_v; +#else Vec* sp14 = m_pkc_head->m_nrm_data + sp18->fnrm_i; +#endif if (!(sp14->y <= 0.0f) && !cM3d_IsZero(sp14->y)) { dBgPc sp64; getPolyCode(*p_prismlist, &sp64); @@ -2058,11 +2213,38 @@ bool dBgWKCol::SplGrpChk(dBgS_SplGrpChk* param_0) { if (!chkPolyThrough(&sp64, param_0->GetPolyPassChk(), param_0->GetGrpPassChk(), sp4C)) { +#if TARGET_PC + Vec sp10_v = m_pkc_head->m_pos_data[sp18->pos_i]; + be_swap(sp10_v); + Vec* sp10 = &sp10_v; +#else Vec* sp10 = m_pkc_head->m_pos_data + sp18->pos_i; +#endif cXyz sp40; sp40.x = sp3C->x - sp10->x; sp40.z = sp3C->z - sp10->z; sp40.y = -(sp40.x * sp14->x + sp40.z * sp14->z) / sp14->y; +#if TARGET_PC + Vec enrm1_v = m_pkc_head->m_nrm_data[sp18->enrm1_i]; + be_swap(enrm1_v); + if (PSVECDotProduct(&sp40, &enrm1_v) > + 0.0075f) + { + continue; + } + + Vec enrm2_v = m_pkc_head->m_nrm_data[sp18->enrm2_i]; + be_swap(enrm2_v); + if (PSVECDotProduct(&sp40, &enrm2_v) > + 0.0075f) + { + continue; + } + + Vec enrm3_v = m_pkc_head->m_nrm_data[sp18->enrm3_i]; + be_swap(enrm3_v); + f32 var_f30 = PSVECDotProduct(&sp40, &enrm3_v); +#else if (PSVECDotProduct(&sp40, &m_pkc_head->m_nrm_data[sp18->enrm1_i]) > 0.0075f) { @@ -2076,6 +2258,7 @@ bool dBgWKCol::SplGrpChk(dBgS_SplGrpChk* param_0) { } f32 var_f30 = PSVECDotProduct(&sp40, &m_pkc_head->m_nrm_data[sp18->enrm3_i]); +#endif if (var_f30 < -0.0075f || var_f30 > sp18->height + 0.0075f) { continue; } @@ -2225,7 +2408,13 @@ bool dBgWKCol::SphChk(dBgS_SphChk* param_0, void* param_1) { if (var_r28 != sp30) { while (*++var_r28 != 0) { KC_PrismData* sp14 = getPrismData(*var_r28); +#if TARGET_PC + Vec sp10_v = m_pkc_head->m_nrm_data[sp14->fnrm_i]; + be_swap(sp10_v); + Vec* sp10 = &sp10_v; +#else Vec* sp10 = &m_pkc_head->m_nrm_data[sp14->fnrm_i]; +#endif getPolyCode(*var_r28, &spD4); cXyz sp90 = *sp10; if (!chkPolyThrough(&spD4, param_0->GetPolyPassChk(), From 3fe39464f12f3ad2d6f7dae298829380b5a265aa Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Fri, 20 Mar 2026 20:59:50 -0400 Subject: [PATCH 05/18] Add more heap names for debug --- libs/JSystem/include/JSystem/JKernel/JKRHeap.h | 3 +++ .../src/J3DGraphLoader/J3DModelLoader.cpp | 2 +- libs/JSystem/src/JFramework/JFWSystem.cpp | 1 - libs/JSystem/src/JKernel/JKRExpHeap.cpp | 1 + libs/JSystem/src/JKernel/JKRHeap.cpp | 8 ++++++++ src/d/actor/d_a_alink_swindow.inc | 1 + src/d/actor/d_a_player.cpp | 1 + src/d/actor/d_a_title.cpp | 1 + src/d/d_com_inf_game.cpp | 1 + src/d/d_k_wpillar.cpp | 1 + src/d/d_menu_dmap.cpp | 1 + src/d/d_menu_fmap.cpp | 1 + src/d/d_particle.cpp | 1 + src/d/d_resorce.cpp | 2 ++ src/d/d_s_logo.cpp | 2 ++ src/d/d_s_name.cpp | 1 + src/dusk/imgui/ImGuiHeapOverlay.cpp | 18 +++++++++++++----- src/f_op/f_op_actor_mng.cpp | 11 +++-------- src/m_Do/m_Do_ext.cpp | 1 + src/m_Do/m_Do_graphic.cpp | 1 + 20 files changed, 44 insertions(+), 15 deletions(-) diff --git a/libs/JSystem/include/JSystem/JKernel/JKRHeap.h b/libs/JSystem/include/JSystem/JKernel/JKRHeap.h index db4d40b0a3..2ff883c393 100644 --- a/libs/JSystem/include/JSystem/JKernel/JKRHeap.h +++ b/libs/JSystem/include/JSystem/JKernel/JKRHeap.h @@ -217,11 +217,14 @@ public: #if TARGET_PC void setName(const char* name); + void setNamef(const char* fmt, ...); const char* getName() const; #define JKRHEAP_NAME(heap, name) (heap)->setName(name) +#define JKRHEAP_NAMEF(heap, name, ...) (heap)->setNamef(name, __VA_ARGS__) #else #define JKRHEAP_NAME(heap, name) +#define JKRHEAP_NAMEF(heap, name) #endif }; diff --git a/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp b/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp index b8e412415d..72a48007c0 100644 --- a/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp +++ b/libs/JSystem/src/J3DGraphLoader/J3DModelLoader.cpp @@ -264,7 +264,7 @@ void J3DModelLoader::setupBBoardInfo() { mpModelData->getJointNodePointer(i)->setMtxType(0); break; default: - OSReport("WRONG SHAPE MATRIX TYPE (__FILE__)\n"); + OSReport("WRONG SHAPE MATRIX TYPE (%d)\n", r26->mShapeMtxType); break; } } diff --git a/libs/JSystem/src/JFramework/JFWSystem.cpp b/libs/JSystem/src/JFramework/JFWSystem.cpp index 66a1a19960..e84d19a824 100644 --- a/libs/JSystem/src/JFramework/JFWSystem.cpp +++ b/libs/JSystem/src/JFramework/JFWSystem.cpp @@ -45,7 +45,6 @@ void JFWSystem::firstInit() { OSInit(); DVDInit(); rootHeap = JKRExpHeap::createRoot(CSetUpParam::maxStdHeaps, false); - JKRHEAP_NAME(rootHeap, "Root"); systemHeap = JKRExpHeap::create(CSetUpParam::sysHeapSize, rootHeap, false); JKRHEAP_NAME(systemHeap, "System"); } diff --git a/libs/JSystem/src/JKernel/JKRExpHeap.cpp b/libs/JSystem/src/JKernel/JKRExpHeap.cpp index 7774a33959..4c0c6bf1ae 100644 --- a/libs/JSystem/src/JKernel/JKRExpHeap.cpp +++ b/libs/JSystem/src/JKernel/JKRExpHeap.cpp @@ -51,6 +51,7 @@ JKRExpHeap* JKRExpHeap::createRoot(int maxHeaps, bool errorFlag) { #endif heap = JKR_NEW_ARGS (mem1) JKRExpHeap(start1, alignedSize, NULL, errorFlag); sRootHeap = heap; + JKRHEAP_NAME(sRootHeap, "Root"); } heap->field_0x6e = true; return heap; diff --git a/libs/JSystem/src/JKernel/JKRHeap.cpp b/libs/JSystem/src/JKernel/JKRHeap.cpp index 0670f511e2..bc02d877fb 100644 --- a/libs/JSystem/src/JKernel/JKRHeap.cpp +++ b/libs/JSystem/src/JKernel/JKRHeap.cpp @@ -699,6 +699,14 @@ void JKRHeap::setName(const char* name) { strncpy(mName, name, sizeof(mName) - 1); mName[sizeof(mName) - 1] = '\0'; } + +void JKRHeap::setNamef(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vsnprintf(mName, sizeof(mName), fmt, args); + va_end(args); +} + const char* JKRHeap::getName() const { return mName; } diff --git a/src/d/actor/d_a_alink_swindow.inc b/src/d/actor/d_a_alink_swindow.inc index cff5ebeb05..cf3593dfce 100644 --- a/src/d/actor/d_a_alink_swindow.inc +++ b/src/d/actor/d_a_alink_swindow.inc @@ -43,6 +43,7 @@ void daAlink_c::setOriginalHeap(JKRExpHeap** i_ppheap, u32 i_size) { JKRHeap* parent = mDoExt_getGameHeap(); JKRExpHeap* heap = JKRExpHeap::create(size + (var_r29 + var_r28), parent, true); + JKRHEAP_NAME(heap, "Alink original"); *i_ppheap = heap; } } diff --git a/src/d/actor/d_a_player.cpp b/src/d/actor/d_a_player.cpp index 1c2383511f..c091fae5dd 100644 --- a/src/d/actor/d_a_player.cpp +++ b/src/d/actor/d_a_player.cpp @@ -260,6 +260,7 @@ void daPy_anmHeap_c::createHeap(daPy_anmHeap_c::daAlinkHEAP_TYPE i_heapType) { JKRHeap* tmp; mAnimeHeap = mDoExt_createSolidHeapFromGameToCurrent(&tmp, size, 0x20); + JKRHEAP_NAMEF(mAnimeHeap, "Alink anime type %d", i_heapType); if (i_heapType == 4) { tmpWork = JKR_NEW_ARRAY(char, size); diff --git a/src/d/actor/d_a_title.cpp b/src/d/actor/d_a_title.cpp index 923365993c..88ce62ec5c 100644 --- a/src/d/actor/d_a_title.cpp +++ b/src/d/actor/d_a_title.cpp @@ -138,6 +138,7 @@ int daTitle_c::create() { m2DHeap = JKRCreateExpHeap(0x8000, mDoExt_getGameHeap(), false); JUT_ASSERT(345, m2DHeap != NULL); + JKRHEAP_NAME(m2DHeap, "daTitle_c::m2DHeap"); loadWait_init(); g_daTitHIO.id = mDoHIO_CREATE_CHILD("タイトルロゴ", &g_daTitHIO); diff --git a/src/d/d_com_inf_game.cpp b/src/d/d_com_inf_game.cpp index 8da33212cf..393b6c9762 100644 --- a/src/d/d_com_inf_game.cpp +++ b/src/d/d_com_inf_game.cpp @@ -2080,6 +2080,7 @@ void dComIfGp_createSubExpHeap2D() { if (dComIfGp_getSubExpHeap2D(i) == NULL) { JKRExpHeap* i_heap = JKRCreateExpHeap(size, dComIfGp_getExpHeap2D(), false); JUT_ASSERT(3576, i_heap != NULL); + JKRHEAP_NAMEF(i_heap, "SubExpHeap2D %d", i); dComIfGp_setSubExpHeap2D(i, i_heap); } } diff --git a/src/d/d_k_wpillar.cpp b/src/d/d_k_wpillar.cpp index 7edc491b44..70efec89a2 100644 --- a/src/d/d_k_wpillar.cpp +++ b/src/d/d_k_wpillar.cpp @@ -38,6 +38,7 @@ int dkWpillar_c::create() { mpHeap = mDoExt_createSolidHeapFromGameToCurrent(0x2200, 0x20); if (mpHeap != NULL) { + JKRHEAP_NAME(mpHeap, "d_k_wpillar::mpModel"); J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes(l_arcName, 0x1C); JUT_ASSERT(96, modelData); diff --git a/src/d/d_menu_dmap.cpp b/src/d/d_menu_dmap.cpp index 537d264b3b..109e5aeb20 100644 --- a/src/d/d_menu_dmap.cpp +++ b/src/d/d_menu_dmap.cpp @@ -100,6 +100,7 @@ dMenu_DmapBg_c::dMenu_DmapBg_c(JKRExpHeap* i_heap, STControl* i_stick) { mpTalkHeap = JKRCreateExpHeap(0x32000, mpHeap, false); JUT_ASSERT(624, mpTalkHeap != NULL); + JKRHEAP_NAME(mpTalkHeap, "dMenu_DmapBg_c::mpTalkHeap"); mpItemExplain = NULL; diff --git a/src/d/d_menu_fmap.cpp b/src/d/d_menu_fmap.cpp index cd370a56d7..c8969f2ac3 100644 --- a/src/d/d_menu_fmap.cpp +++ b/src/d/d_menu_fmap.cpp @@ -192,6 +192,7 @@ dMenu_Fmap_c::dMenu_Fmap_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i mpTalkHeap = JKRCreateExpHeap(HEAP_SIZE(0x32000, 0x40000), mpHeap, false); JUT_ASSERT(359, mpTalkHeap != NULL); + JKRHEAP_NAME(mpTalkHeap, "dMenu_Fmap_c::mpTalkHeap"); field_0x200 = 0; mIsWarpMap = false; diff --git a/src/d/d_particle.cpp b/src/d/d_particle.cpp index 2a8e75d82e..6c8d6e3f75 100644 --- a/src/d/d_particle.cpp +++ b/src/d/d_particle.cpp @@ -1173,6 +1173,7 @@ dPa_control_c::dPa_control_c() { size_t heapSize = 0x96000; #endif m_resHeap = JKRCreateExpHeap(heapSize, mDoExt_getArchiveHeap(), false); + JKRHEAP_NAME(m_resHeap, "Particle control"); JUT_ASSERT(2426, m_resHeap != NULL); mHeap = NULL; mSceneHeap = NULL; diff --git a/src/d/d_resorce.cpp b/src/d/d_resorce.cpp index 50192f5a38..1dce982025 100644 --- a/src/d/d_resorce.cpp +++ b/src/d/d_resorce.cpp @@ -606,6 +606,7 @@ int dRes_info_c::setRes() { heap->lock(); mDataHeap = mDoExt_createSolidHeapToCurrent(0, heap, 0x20); JUT_ASSERT(1260, mDataHeap != NULL); + JKRHEAP_NAMEF(mDataHeap, "Resource (%s)", mArchiveName); int rt = loadResource(); mDoExt_restoreCurrentHeap(); @@ -624,6 +625,7 @@ int dRes_info_c::setRes() { OSReport_Error("<%s.arc> mDMCommandsetRes: can't alloc memory\n", mArchiveName); return -1; } + JKRHEAP_NAMEF(mDataHeap, "Resource (%s)", mArchiveName); int rt = loadResource(); mDoExt_restoreCurrentHeap(); r28 = mDoExt_adjustSolidHeap(mDataHeap); diff --git a/src/d/d_s_logo.cpp b/src/d/d_s_logo.cpp index 4923f93d65..a878de8106 100644 --- a/src/d/d_s_logo.cpp +++ b/src/d/d_s_logo.cpp @@ -945,9 +945,11 @@ static int phase_0(dScnLogo_c* i_this) { i_this->mLogoHeap = JKRExpHeap::create(i_this->dummyGameAlloc, var_r29, NULL, false); JUT_ASSERT(1525, i_this->mLogoHeap != NULL); + JKRHEAP_NAME(i_this->mLogoHeap, "Logo"); i_this->mLogo01Heap = JKRCreateExpHeap(var_r28, i_this->mLogoHeap, false); JUT_ASSERT(1528, i_this->mLogo01Heap != NULL); + JKRHEAP_NAME(i_this->mLogo01Heap, "Logo01"); #if VERSION == VERSION_GCN_PAL switch (i_this->getPalLanguage()) { diff --git a/src/d/d_s_name.cpp b/src/d/d_s_name.cpp index 4940d3d604..5f22177654 100644 --- a/src/d/d_s_name.cpp +++ b/src/d/d_s_name.cpp @@ -71,6 +71,7 @@ s32 dScnName_c::create() { if (phase_state == cPhs_COMPLEATE_e) { mHeap = JKRCreateExpHeap(HEAP_SIZE(0x180000, 0x1C0000), mDoExt_getGameHeap(), false); JUT_ASSERT(289, mHeap != NULL); + JKRHEAP_NAME(mHeap, "File select"); field_0x1d0 = (JKRExpHeap*)mDoExt_setCurrentHeap(mHeap); diff --git a/src/dusk/imgui/ImGuiHeapOverlay.cpp b/src/dusk/imgui/ImGuiHeapOverlay.cpp index 43e495587f..588857cedb 100644 --- a/src/dusk/imgui/ImGuiHeapOverlay.cpp +++ b/src/dusk/imgui/ImGuiHeapOverlay.cpp @@ -1,4 +1,5 @@ #include +#include #include "JSystem/JFramework/JFWSystem.h" #include "JSystem/JKernel/JKRHeap.h" @@ -58,10 +59,10 @@ namespace dusk { }; } - static const char* GetHeapName(const JKRHeap* heap) { + static std::optional GetHeapName(const JKRHeap* heap) { const auto name = heap->getName(); if (strlen(name) == 0) { - return "Unknown"; + return std::nullopt; } return name; @@ -74,13 +75,20 @@ namespace dusk { auto indentSize = depth * 16; if (indentSize != 0) ImGui::Indent(indentSize); - ImGui::TextUnformatted(GetHeapName(heap)); + auto heapName = GetHeapName(heap); + if (heapName.has_value()) { + ImGui::TextUnformatted(heapName.value()); + } else { + char unkNameBuf[32]; + snprintf(unkNameBuf, sizeof(unkNameBuf), "Unknown (%p)", heap); + ImGui::TextUnformatted(unkNameBuf); + } if (indentSize != 0) ImGui::Unindent(indentSize); ImGui::TableNextColumn(); ImGui::ProgressBar( - 1 - (f32)heap->getFreeSize() / (f32)heap->getSize(), + heap->getSize() > 0 ? 1 - (f32)heap->getFreeSize() / (f32)heap->getSize() : 0.0f, ImVec2(ImGui::GetContentRegionAvail().x, 0)); ImGui::TableNextColumn(); @@ -100,4 +108,4 @@ namespace dusk { DrawHeap(*iter, depth + 1); } } -} \ No newline at end of file +} diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index fa4da69e68..538d8ff544 100644 --- a/src/f_op/f_op_actor_mng.cpp +++ b/src/f_op/f_op_actor_mng.cpp @@ -412,6 +412,7 @@ bool fopAcM_entrySolidHeap_(fopAc_ac_c* i_actor, heapCallbackFunc i_heapCallback if (dummy_heap != NULL) { heap = mDoExt_createSolidHeap(-1, dummy_heap, 0x20); JUT_ASSERT(1211, heap); + JKRHEAP_NAMEF(heap, "Actor mng (%s)", procNameString); if (fopAcM::HeapAdjustVerbose) { // Attempting registration with max dummy heap. @@ -453,6 +454,7 @@ bool fopAcM_entrySolidHeap_(fopAc_ac_c* i_actor, heapCallbackFunc i_heapCallback heap = mDoExt_createSolidHeapFromGame(i_size, 0x20); if (heap != NULL) { + JKRHEAP_NAMEF(heap, "Actor mng (%s)", procNameString); if (fopAcM::HeapAdjustVerbose) { // Attempting registration with estimated heap size. %08x [%s] OS_REPORT("見積もりヒープサイズで登録してみます。%08x [%s]\n", heap, @@ -734,14 +736,7 @@ u8 var_r30 = fopAcM::HeapAdjustEntry; fopAcM::HeapAdjustEntry = var_r30; #if TARGET_PC - char buf[32]; - snprintf( - buf, - sizeof(buf), - "Actor %d (%s)", - i_actor->id, - GetProcName(i_actor->profname)); - JKRHEAP_NAME(i_actor->heap, buf); + JKRHEAP_NAMEF(i_actor->heap, "Actor %d (%s)", i_actor->id, GetProcName(i_actor->profname)); #endif return result; diff --git a/src/m_Do/m_Do_ext.cpp b/src/m_Do/m_Do_ext.cpp index 8d46884de9..a7829bdb50 100644 --- a/src/m_Do/m_Do_ext.cpp +++ b/src/m_Do/m_Do_ext.cpp @@ -659,6 +659,7 @@ static JKRAssertHeap* AssertHeap; JKRAssertHeap* mDoExt_createAssertHeap(JKRHeap* parentHeap) { JUT_ASSERT(1666, AssertHeap == NULL); AssertHeap = JKRAssertHeap::create(parentHeap); + JKRHEAP_NAME(AssertHeap, "Assert"); return AssertHeap; } diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index 481bf8efff..72180b3c40 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -2220,6 +2220,7 @@ static void dummy() { int mDoGph_Create() { JKRSolidHeap* heap = mDoExt_createSolidHeapToCurrent(0, NULL, 0); + JKRHEAP_NAME(heap, "mDoGph"); mDoGph_gInf_c::create(); dComIfGd_init(); u32 var_r30 = mDoExt_adjustSolidHeap(heap); From 9510c944543072fe7cf38d65958b76f651ce0e9a Mon Sep 17 00:00:00 2001 From: CraftyBoss Date: Sat, 21 Mar 2026 00:56:01 -0400 Subject: [PATCH 06/18] more BE stuff, fix scissors for dmap/fmap --- include/d/d_menu_fmap.h | 4 ++-- libs/JSystem/src/JStudio/JStudio/ctb-data.cpp | 2 +- libs/JSystem/src/JStudio/JStudio/ctb.cpp | 2 +- src/d/actor/d_a_obj_brg.cpp | 10 +++++---- src/d/d_menu_dmap.cpp | 21 ++++++++++++++++++- src/d/d_menu_fmap2D.cpp | 19 ++++++++++++++--- 6 files changed, 46 insertions(+), 12 deletions(-) diff --git a/include/d/d_menu_fmap.h b/include/d/d_menu_fmap.h index a0648698bc..026e98e056 100644 --- a/include/d/d_menu_fmap.h +++ b/include/d/d_menu_fmap.h @@ -96,10 +96,10 @@ public: /* 0x02 */ const char mStageName[8]; /* 0x0A */ u8 mRoomNo; /* 0x0B */ u8 mWarpPlayerNo; - /* 0x0C */ u16 mMessageID; + /* 0x0C */ BE(u16) mMessageID; /* 0x0E */ u8 mStageNo; /* 0x0F */ u8 mSwitchNo; - /* 0x10 */ cXyz mPosition; + /* 0x10 */ BE(Vec) mPosition; }; /* 0x0 */ u8 field_0x0[8]; diff --git a/libs/JSystem/src/JStudio/JStudio/ctb-data.cpp b/libs/JSystem/src/JStudio/JStudio/ctb-data.cpp index 55a83f0d3f..629d542457 100644 --- a/libs/JSystem/src/JStudio/JStudio/ctb-data.cpp +++ b/libs/JSystem/src/JStudio/JStudio/ctb-data.cpp @@ -2,4 +2,4 @@ #include "JSystem/JStudio/JStudio/ctb.h" -const u32 JStudio::ctb::data::ga4cSignature = 'CTB\0'; +const u32 JStudio::ctb::data::ga4cSignature = BSWAP32('CTB\0'); diff --git a/libs/JSystem/src/JStudio/JStudio/ctb.cpp b/libs/JSystem/src/JStudio/JStudio/ctb.cpp index 61046ad35c..9a371ea936 100644 --- a/libs/JSystem/src/JStudio/JStudio/ctb.cpp +++ b/libs/JSystem/src/JStudio/JStudio/ctb.cpp @@ -68,7 +68,7 @@ JStudio::ctb::TObject* JStudio::ctb::TControl::getObject_index(u32 param_0) { JStudio::ctb::TFactory::~TFactory() {} JStudio::ctb::TObject* JStudio::ctb::TFactory::create(JStudio::ctb::data::TParse_TBlock const& param_0) { - switch(param_0.get_scheme()) { + switch(BSWAP16(param_0.get_scheme())) { case 1: return JKR_NEW TObject_TxyzRy(param_0); default: diff --git a/src/d/actor/d_a_obj_brg.cpp b/src/d/actor/d_a_obj_brg.cpp index d0dea6cf98..b2acca8f98 100644 --- a/src/d/actor/d_a_obj_brg.cpp +++ b/src/d/actor/d_a_obj_brg.cpp @@ -588,9 +588,11 @@ static void cut_control2(obj_brg_class* i_this, br_s* i_part) { } static void himo_cut_control1(obj_brg_class* i_this, cXyz* param_1, f32 param_2) { - cXyz sp74; - cXyz sp80; - cXyz sp8C; + STUB_RET(); + + cXyz sp74 = {}; + cXyz sp80 = {}; + cXyz sp8C = {}; sp74.x = 0.0f; sp74.y = 0.0f; @@ -602,7 +604,7 @@ static void himo_cut_control1(obj_brg_class* i_this, cXyz* param_1, f32 param_2) sp74.y = 0.0f; sp74.z = param_2; - int i, temp_r27 = (intptr_t) ++param_1; + intptr_t i, temp_r27 = (intptr_t) ++param_1; f32 var_f31, var_f30, var_f29, var_f28, var_f27; for (i = 1; i < 5; i++, param_1++) { var_f28 = i_this->field_0xaf30 * cM_ssin( (i_this->field_0xaf20 * 6000) + (NREG_S(3) - 10000) * (temp_r27 + i) ) diff --git a/src/d/d_menu_dmap.cpp b/src/d/d_menu_dmap.cpp index 537d264b3b..046f072c62 100644 --- a/src/d/d_menu_dmap.cpp +++ b/src/d/d_menu_dmap.cpp @@ -864,14 +864,23 @@ void dMenu_DmapBg_c::draw() { grafContext->setup2D(); GXGetScissor(&scissor_left, &scissor_top, &scissor_width, &scissor_height); - grafContext->scissor(field_0xd94, 0.0f, FB_WIDTH, FB_HEIGHT); +#if TARGET_PC + grafContext->scissor(field_0xd94, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); +#else + grafContext->scissor(field_0xd94, 0.0f, FB_WIDTH, FB_HEIGHT); +#endif grafContext->setScissor(); mBaseScreen->draw(field_0xd94, field_0xd98, grafContext); dMenu_Dmap_c::myclass->drawFloorScreenBack(mFloorScreen, field_0xd94, field_0xd98, grafContext); +#if TARGET_PC + f32 dVar21 = mDoGph_gInf_c::getWidth() / FB_WIDTH; + f32 dVar16 = mDoGph_gInf_c::getHeight() / FB_HEIGHT; +#else f32 dVar21 = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 dVar16 = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; +#endif mMapScreen[0]->draw(field_0xd94, field_0xd98, grafContext); if (mpBackTexture != NULL) { @@ -896,9 +905,15 @@ void dMenu_DmapBg_c::draw() { mpBackTexture->draw(local_28c, field_0xd94 + mpBackTexture->getBounds().i.y, mpBackTexture->getWidth(), mpBackTexture->getHeight(), false, false, false); +#if TARGET_PC + grafContext->scissor(field_0xd94, + 0, mDoGph_gInf_c::getWidth(), + scissor_height); +#else grafContext->scissor(field_0xd94 + mDoGph_gInf_c::getMinXF(), scissor_top, mDoGph_gInf_c::getWidthF(), scissor_height); +#endif grafContext->setScissor(); } @@ -918,7 +933,11 @@ void dMenu_DmapBg_c::draw() { Vec local_26c = pane.getGlobalVtx(mMapPane, &local_110, 0, false, 0); drawIcon(local_26c.x + field_0xd94, local_26c.y, field_0xda8, 1.0f); +#if TARGET_PC + grafContext->scissor(field_0xd94, scissor_top, mDoGph_gInf_c::getWidth(), scissor_height); +#else grafContext->scissor(field_0xd94 + mDoGph_gInf_c::getMinXF(), scissor_top, mDoGph_gInf_c::getWidthF(), scissor_height); +#endif grafContext->setScissor(); grafContext->scissor(scissor_left, scissor_top, scissor_width, scissor_height); grafContext->setScissor(); diff --git a/src/d/d_menu_fmap2D.cpp b/src/d/d_menu_fmap2D.cpp index 4048ddd4d2..29ec5db854 100644 --- a/src/d/d_menu_fmap2D.cpp +++ b/src/d/d_menu_fmap2D.cpp @@ -275,14 +275,18 @@ void dMenu_Fmap2DBack_c::draw() { u32 scissorLeft, scissorTop, scissorWidth, scissorHeight; GXGetScissor(&scissorLeft, &scissorTop, &scissorWidth, &scissorHeight); +#if TARGET_PC + grafPort->scissor(mTransX, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); +#else grafPort->scissor(mTransX, 0.0f, FB_WIDTH, FB_HEIGHT); +#endif grafPort->setScissor(); mpBackTex->setBlackWhite(field_0x1208, field_0x120c); mpBackTex->setAlpha(mAlphaRate * 255.0f * g_fmapHIO.mBackgroundAlpha); mpBackTex->draw(mTransX + mDoGph_gInf_c::getMinXF(), - mTransZ + mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidthF(), - mDoGph_gInf_c::getHeightF(), false, false, false); + mTransZ + mDoGph_gInf_c::getMinYF(), mDoGph_gInf_c::getWidth(), + mDoGph_gInf_c::getHeight(), false, false, false); mpBackScreen->draw(mTransX, mTransZ, grafPort); mpBaseScreen->draw(mTransX, mTransZ, grafPort); @@ -292,8 +296,13 @@ void dMenu_Fmap2DBack_c::draw() { Vec vec2 = mpMapArea->getGlobalVtx(&mtx, 3, false, 0); - f32 width = mDoGph_gInf_c::getWidthF() / FB_WIDTH; +#if TARGET_PC + f32 width = mDoGph_gInf_c::getWidthF() / mDoGph_gInf_c::getWidth(); + f32 height = mDoGph_gInf_c::getHeightF() / mDoGph_gInf_c::getHeight(); +#else + f32 width = mDoGph_gInf_c::getWidthF() / FB_WIDTH; f32 height = mDoGph_gInf_c::getHeightF() / FB_HEIGHT; +#endif grafPort->scissor(mTransX + ((vec1.x - mDoGph_gInf_c::getMinXF()) / width), mTransZ + (vec1.y / height), (vec2.x - vec1.x) / width, @@ -2554,7 +2563,11 @@ void dMenu_Fmap2DTop_c::draw() { J2DOrthoGraph* ctx = static_cast(dComIfGp_getCurrentGrafPort()); ctx->setup2D(); GXGetScissor(&scissor_left, &scissor_top, &scissor_width, &scissor_height); +#if TARGET_PC + ctx->scissor(mTransX, 0.0f, mDoGph_gInf_c::getWidth(), mDoGph_gInf_c::getHeight()); +#else ctx->scissor(mTransX, 0.0f, FB_WIDTH, FB_HEIGHT); +#endif ctx->setScissor(); mpTitleScreen->draw(mTransX, mTransY, ctx); ctx->scissor(scissor_left, scissor_top, scissor_width, scissor_height); From ae6caa77a0f4be32e7ea8a1c6fab9ae4d66b7398 Mon Sep 17 00:00:00 2001 From: TakaRikka <38417346+TakaRikka@users.noreply.github.com> Date: Sat, 21 Mar 2026 00:56:27 -0700 Subject: [PATCH 07/18] cleanup d_a_obj_wflag (#3135) --- include/d/actor/d_a_obj_wflag.h | 37 ++--- src/d/actor/d_a_obj_wflag.cpp | 267 ++++++++++++++++++-------------- 2 files changed, 173 insertions(+), 131 deletions(-) diff --git a/include/d/actor/d_a_obj_wflag.h b/include/d/actor/d_a_obj_wflag.h index f36e52d1ca..d4dcb2ef98 100644 --- a/include/d/actor/d_a_obj_wflag.h +++ b/include/d/actor/d_a_obj_wflag.h @@ -7,13 +7,13 @@ struct wf_tail_s { ~wf_tail_s() {} wf_tail_s() {} - /* 0x000 */ s16 field_0x000; - /* 0x000 */ u16 field_0x002; - /* 0x004 */ cXyz field_0x004[20]; - /* 0x0F4 */ csXyz field_0x0f4[20]; - /* 0x16C */ cXyz field_0x16c[20]; - /* 0x25C */ J3DModel* mModels[19]; - /* 0x2A8 */ u32 field_0x2a8; + /* 0x000 */ s16 field_0x0; + /* 0x000 */ u16 unk_0x2; + /* 0x004 */ cXyz pos[20]; + /* 0x0F4 */ csXyz rot[20]; + /* 0x16C */ cXyz unk_0x16c[20]; + /* 0x25C */ J3DModel* model[19]; + /* 0x2A8 */ u32 unk_0x2a8; }; /** @@ -24,19 +24,20 @@ struct wf_tail_s { * @details * */ -class obj_wflag_class : public fopAc_ac_c { +class obj_wflag_class { public: - /* 0x568 */ request_of_phase_process_class mPhaseReq; - /* 0x570 */ J3DModel* mpModel; - /* 0x574 */ mDoExt_McaMorf* mMorf; - /* 0x578 */ mDoExt_btkAnm* field_0x578; - /* 0x57C */ mDoExt_btpAnm* field_0x57c; - /* 0x580 */ wf_tail_s mTails[1]; - /* 0x82C */ u8 field_0x82c; + /* 0x000 */ fopAc_ac_c actor; + /* 0x568 */ request_of_phase_process_class phase; + /* 0x570 */ J3DModel* pillar_model; + /* 0x574 */ mDoExt_McaMorf* anm_p; + /* 0x578 */ mDoExt_btkAnm* kolin_btk; + /* 0x57C */ mDoExt_btpAnm* kolin_btp; + /* 0x580 */ wf_tail_s tail_s[1]; + /* 0x82C */ u8 unk_0x82c; /* 0x82E */ s16 field_0x82e; - /* 0x830 */ s16 field_0x830[2]; - /* 0x834 */ s16 field_0x834; - /* 0x836 */ s16 field_0x836; + /* 0x830 */ s16 timers[2]; + /* 0x834 */ s16 unk_timer; + /* 0x836 */ s16 counter; /* 0x838 */ u32 field_0x838; }; diff --git a/src/d/actor/d_a_obj_wflag.cpp b/src/d/actor/d_a_obj_wflag.cpp index 0005a95c3f..82ac438cbe 100644 --- a/src/d/actor/d_a_obj_wflag.cpp +++ b/src/d/actor/d_a_obj_wflag.cpp @@ -7,131 +7,160 @@ #include "d/actor/d_a_obj_wflag.h" #include "d/d_com_inf_game.h" #include "SSystem/SComponent/c_math.h" +#include "d/actor/d_a_e_wb.h" +#include "d/d_s_play.h" static int daObj_Wflag_Draw(obj_wflag_class* i_this) { - g_env_light.settingTevStruct(0, &i_this->current.pos, &i_this->tevStr); - g_env_light.setLightTevColorType_MAJI(i_this->mpModel, &i_this->tevStr); - mDoExt_modelUpdateDL(i_this->mpModel); - J3DModel* morfModel = i_this->mMorf->getModel(); - g_env_light.setLightTevColorType_MAJI(morfModel, &i_this->tevStr); - i_this->field_0x578->entry(morfModel->getModelData()); - i_this->field_0x57c->entry(morfModel->getModelData()); - i_this->mMorf->entryDL(); + fopAc_ac_c* actor = &i_this->actor; + g_env_light.settingTevStruct(0, &actor->current.pos, &actor->tevStr); + g_env_light.setLightTevColorType_MAJI(i_this->pillar_model, &actor->tevStr); + mDoExt_modelUpdateDL(i_this->pillar_model); + + J3DModel* morfModel = i_this->anm_p->getModel(); + g_env_light.setLightTevColorType_MAJI(morfModel, &actor->tevStr); + + i_this->kolin_btk->entry(morfModel->getModelData()); + i_this->kolin_btp->entry(morfModel->getModelData()); + i_this->anm_p->entryDL(); + for (int i = 0; i < 1; i++) { - wf_tail_s* tail = &i_this->mTails[i]; + wf_tail_s* tail = &i_this->tail_s[i]; for (int j = 0; j < 19; j++) { - g_env_light.setLightTevColorType_MAJI(tail->mModels[j], &i_this->tevStr); - mDoExt_modelUpdateDL(tail->mModels[j]); + g_env_light.setLightTevColorType_MAJI(tail->model[j], &actor->tevStr); + mDoExt_modelUpdateDL(tail->model[j]); } } + return 1; } -static void tail_control(fopAc_ac_c* param_1, wf_tail_s* param_2) { - static f32 pd[19] = {1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f, 0.2f, - 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f}; +static void tail_control(fopAc_ac_c* i_this, wf_tail_s* i_tail) { + static f32 pd[19] = { + 1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f, 0.2f, + 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, 0.2f, + }; + + cXyz sp4C; + cXyz sp40; + cXyz sp34; - cXyz local_74; - cXyz cStack_80; int i; - cXyz* ptr; - f32 dVar11; - cXyz local_98; - cXyz local_a4; - f32 dVar9; - f32 dVar14; - f32 dVar13; + cXyz* pPos; + f32 var_f27; + f32 var_f28; + f32 var_f31; + f32 var_f30; f32 speed; csXyz* pAngle; - ptr = ¶m_2->field_0x004[1]; - pAngle = ¶m_2->field_0x0f4[1]; - dVar11 = -20.0f; - cMtx_YrotS(*calc_mtx, param_1->current.angle.y); - local_74.x = 0.0f; - local_74.y = 0.0f; - local_74.z = -(20.0f + param_1->speedF * 10.0f); - MtxPosition(&local_74, &local_98); - speed = param_1->speedF * 2.0f; - local_74.x = 0.0f; - local_74.y = 0.0f; - local_74.z = 20.0f; - for (i = 1; i < 20; i++, ptr++, pAngle++) { - local_a4.x = - local_98.x * pd[i - 1]; - local_a4.z = - local_98.z * pd[i - 1]; - local_a4.x += (speed * cM_ssin(param_2->field_0x000 * 5400 + i * (-3700))) * 0.3f; - local_a4.z += (speed * cM_ssin(param_2->field_0x000 * 5700 + i * (-4200))) * 0.3f; - local_a4.y = speed * cM_ssin(param_2->field_0x000 * 4200 + i * (-2400)); - dVar9 = local_a4.x + (ptr->x - ptr[-1].x); - dVar14 = local_a4.y + (dVar11 + (ptr[0].y - ptr[-1].y)); - dVar13 = local_a4.z + (ptr->z - ptr[-1].z); - s16 xRot = -cM_atan2s(dVar14, dVar13); - s32 yRot = cM_atan2s(dVar9, JMAFastSqrt(dVar14 * dVar14 + dVar13 * dVar13)); + pPos = &i_tail->pos[1]; + pAngle = &i_tail->rot[1]; + var_f27 = NREG_F(2) + -20.0f; + + cXyz sp28; + cXyz sp1C; + cMtx_YrotS(*calc_mtx, i_this->current.angle.y); + sp4C.x = 0.0f; + sp4C.y = 0.0f; + sp4C.z = -(NREG_F(3) + 20.0f + i_this->speedF * 10.0f); + MtxPosition(&sp4C, &sp28); + + speed = i_this->speedF * (NREG_F(7) + 2.0f); + sp4C.x = 0.0f; + sp4C.y = 0.0f; + sp4C.z = NREG_F(0) + 20.0f; + + for (i = 1; i < 20; i++, pPos++, pAngle++) { + sp1C.x = sp28.x * pd[i - 1]; + sp1C.z = sp28.z * pd[i - 1]; + + sp1C.x += (speed * cM_ssin(i_tail->field_0x0 * (XREG_S(6) + 5400) + i * (XREG_S(7) + -3700))) * 0.3f; + sp1C.z += (speed * cM_ssin(i_tail->field_0x0 * (XREG_S(6) + 5700) + i * (XREG_S(7) + -4200))) * 0.3f; + sp1C.y = speed * cM_ssin(i_tail->field_0x0 * (XREG_S(6) + 4200) + i * (XREG_S(7) + -2400)); + + var_f28 = sp1C.x + (pPos->x - pPos[-1].x); + var_f31 = sp1C.y + (var_f27 + (pPos[0].y - pPos[-1].y)); + var_f30 = sp1C.z + (pPos->z - pPos[-1].z); + + s16 xRot = -cM_atan2s(var_f31, var_f30); + s16 yRot = (s16)cM_atan2s(var_f28, JMAFastSqrt(SQUARE(var_f31) + SQUARE(var_f30))); cMtx_XrotS(*calc_mtx, xRot); cMtx_YrotM(*calc_mtx, yRot); - MtxPosition(&local_74, &cStack_80); - pAngle[-1].x = xRot; - pAngle[-1].y = yRot; - *ptr = ptr[-1] + cStack_80; + MtxPosition(&sp4C, &sp40); + + pAngle[-1].x = (s16)xRot; + pAngle[-1].y = (s16)yRot; + *pPos = pPos[-1] + sp40; } } static void tail_mtxset(wf_tail_s* i_tail) { for (int i = 0; i < 19; i++) { - MtxTrans(i_tail->field_0x004[i].x, i_tail->field_0x004[i].y, i_tail->field_0x004[i].z, 0); - cMtx_XrotM(*calc_mtx, i_tail->field_0x0f4[i].x); - cMtx_YrotM(*calc_mtx, i_tail->field_0x0f4[i].y); + MtxTrans(i_tail->pos[i].x, i_tail->pos[i].y, i_tail->pos[i].z, 0); + cMtx_XrotM(*calc_mtx, i_tail->rot[i].x); + cMtx_YrotM(*calc_mtx, i_tail->rot[i].y); cMtx_XrotM(*calc_mtx, -0x8000); cMtx_ZrotM(*calc_mtx, i * 0x2734); - i_tail->mModels[i]->setBaseTRMtx(*calc_mtx); + i_tail->model[i]->setBaseTRMtx(*calc_mtx); } } static int daObj_Wflag_Execute(obj_wflag_class* i_this) { - cXyz cStack_3c; - i_this->field_0x836++; + fopAc_ac_c* actor = &i_this->actor; + cXyz sp14; + + i_this->counter++; + for (int i = 0; i < 2; i++) { - if (i_this->field_0x830[i] != 0) { - i_this->field_0x830[i]--; + if (i_this->timers[i] != 0) { + i_this->timers[i]--; } } - if (i_this->field_0x834 != 0) { - i_this->field_0x834--; + + if (i_this->unk_timer != 0) { + i_this->unk_timer--; } - fopAc_ac_c* actor = fopAcM_SearchByID(i_this->parentActorID); - if (actor != NULL) { - i_this->current.angle.y = actor->shape_angle.y; - i_this->speedF = actor->speedF; - // TODO: Figure out what the actor class is - MTXCopy((*(mDoExt_McaMorfSO**)((char*)actor + 0x5e0))->getModel()->getAnmMtx(16), *calc_mtx); - cMtx_XrotM(*calc_mtx, (i_this->speedF * cM_ssin(i_this->field_0x836 * 5400)) * 5.0f); - i_this->mpModel->setBaseTRMtx(*calc_mtx); + + fopAc_ac_c* parent = fopAcM_SearchByID(actor->parentActorID); + if (parent != NULL) { + actor->current.angle.y = parent->shape_angle.y; + actor->speedF = parent->speedF; + + J3DModel* model = ((e_wb_class*)parent)->anm_p->getModel(); + MTXCopy(model->getAnmMtx(YREG_S(3) + 16), *calc_mtx); + s16 rotX = (actor->speedF * cM_ssin(i_this->counter * 5400)) * 5.0f; + cMtx_XrotM(*calc_mtx, rotX); + i_this->pillar_model->setBaseTRMtx(*calc_mtx); } else { - mDoMtx_stack_c::transS(i_this->current.pos.x, i_this->current.pos.y, i_this->current.pos.z); - mDoMtx_stack_c::YrotM(i_this->shape_angle.y); - i_this->mpModel->setBaseTRMtx(mDoMtx_stack_c::get()); + mDoMtx_stack_c::transS(actor->current.pos.x, actor->current.pos.y, actor->current.pos.z); + mDoMtx_stack_c::YrotM((s16)actor->shape_angle.y); + i_this->pillar_model->setBaseTRMtx(mDoMtx_stack_c::get()); } - MTXCopy(i_this->mpModel->getBaseTRMtx(), mDoMtx_stack_c::get()); - mDoMtx_stack_c::transM(133.0f, 248.0f, 0.0f); - mDoMtx_stack_c::YrotM(0x4000); - mDoMtx_stack_c::XrotM(2100); - mDoMtx_stack_c::ZrotM(0); - i_this->mMorf->getModel()->setBaseTRMtx(mDoMtx_stack_c::get()); - i_this->field_0x578->play(); - i_this->field_0x57c->play(); - i_this->mMorf->play(NULL, 0, 0); - i_this->mMorf->modelCalc(); - MTXCopy(i_this->mpModel->getBaseTRMtx(), mDoMtx_stack_c::get()); + + MTXCopy(i_this->pillar_model->getBaseTRMtx(), mDoMtx_stack_c::get()); + mDoMtx_stack_c::transM(VREG_F(0) + 133.0f, VREG_F(1) + 248.0f, VREG_F(2) + 0.0f); + mDoMtx_stack_c::YrotM(VREG_S(0) + 0x4000); + mDoMtx_stack_c::XrotM(VREG_S(1) + 2100); + mDoMtx_stack_c::ZrotM((s16)VREG_S(2)); + + J3DModel* model = i_this->anm_p->getModel(); + model->setBaseTRMtx(mDoMtx_stack_c::get()); + + i_this->kolin_btk->play(); + i_this->kolin_btp->play(); + i_this->anm_p->play(NULL, 0, 0); + i_this->anm_p->modelCalc(); + MTXCopy(i_this->pillar_model->getBaseTRMtx(), mDoMtx_stack_c::get()); + for (int i = 0; i < 1; i++) { - wf_tail_s* pTail = &i_this->mTails[i]; - mDoMtx_stack_c::transM(143.0f, 418.0f, 0.0f); - mDoMtx_stack_c::multVecZero(pTail->field_0x004); - pTail->field_0x000++; - tail_control(i_this, pTail); - tail_mtxset(pTail); + wf_tail_s* tail = &i_this->tail_s[i]; + mDoMtx_stack_c::transM(VREG_F(3) + 143.0f, VREG_F(4) + 418.0f, VREG_F(5) + 0.0f); + mDoMtx_stack_c::multVecZero(tail->pos); + tail->field_0x0++; + tail_control(actor, tail); + tail_mtxset(tail); } + return 1; } @@ -140,7 +169,9 @@ static int daObj_Wflag_IsDelete(obj_wflag_class* i_this) { } static int daObj_Wflag_Delete(obj_wflag_class* i_this) { - dComIfG_resDelete(&i_this->mPhaseReq, "Obj_wflag"); + fopAc_ac_c* actor = &i_this->actor; + fpc_ProcID id = fopAcM_GetID(i_this); + dComIfG_resDelete(&i_this->phase, "Obj_wflag"); return 1; } @@ -148,61 +179,71 @@ static int useHeapInit(fopAc_ac_c* i_actor) { obj_wflag_class* i_this = (obj_wflag_class*)i_actor; J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes("Obj_wflag", 10); JUT_ASSERT(409, modelData != NULL); - i_this->mpModel = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000084); - if (i_this->mpModel == NULL) { + + i_this->pillar_model = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000084); + if (i_this->pillar_model == NULL) { return 0; } - i_this->mMorf = new mDoExt_McaMorf((J3DModelData*)dComIfG_getObjectRes("Obj_wflag", 11), NULL, NULL, ( J3DAnmTransform*)dComIfG_getObjectRes("Obj_wflag", 6), 2, 1.0f, 0, -1, 1, NULL, 0x80000, 0x11020284); - if (i_this->mMorf == NULL || i_this->mMorf->getModel() == NULL) { + + i_this->anm_p = new mDoExt_McaMorf((J3DModelData*)dComIfG_getObjectRes("Obj_wflag", 11), NULL, NULL, (J3DAnmTransform*)dComIfG_getObjectRes("Obj_wflag", 6), 2, 1.0f, 0, -1, 1, NULL, 0x80000, 0x11020284); + if (i_this->anm_p == NULL || i_this->anm_p->getModel() == NULL) { return 0; } - i_this->field_0x578 = new mDoExt_btkAnm(); - if (i_this->field_0x578 == NULL) { + + i_this->kolin_btk = new mDoExt_btkAnm(); + if (i_this->kolin_btk == NULL) { return 0; } - if (i_this->field_0x578->init(i_this->mMorf->getModel()->getModelData(), (J3DAnmTextureSRTKey*)dComIfG_getObjectRes("Obj_wflag", 14), 1, 2, 1.0f, 0, -1) == 0) { + if (i_this->kolin_btk->init(i_this->anm_p->getModel()->getModelData(), (J3DAnmTextureSRTKey*)dComIfG_getObjectRes("Obj_wflag", 14), 1, 2, 1.0f, 0, -1) == 0) { return 0; } - i_this->field_0x57c = new mDoExt_btpAnm(); - if (i_this->field_0x57c == NULL) { + i_this->kolin_btp = new mDoExt_btpAnm(); + if (i_this->kolin_btp == NULL) { return cPhs_ERROR_e; } - if (i_this->field_0x57c->init(i_this->mMorf->getModel()->getModelData(), (J3DAnmTexPattern*)dComIfG_getObjectRes("Obj_wflag", 18), 1, 2, 1.0f, 0, -1) == 0) { + if (i_this->kolin_btp->init(i_this->anm_p->getModel()->getModelData(), (J3DAnmTexPattern*)dComIfG_getObjectRes("Obj_wflag", 18), 1, 2, 1.0f, 0, -1) == 0) { return cPhs_ERROR_e; } modelData = static_cast(dComIfG_getObjectRes("Obj_wflag", 9)); JUT_ASSERT(479, modelData != NULL); + for (int i = 0; i < 1; i++) { for (int j = 0; j < 19; j++) { - i_this->mTails[i].mModels[j] = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000084); - if (i_this->mTails[i].mModels[j] == NULL) { + i_this->tail_s[i].model[j] = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000084); + if (i_this->tail_s[i].model[j] == NULL) { return 0; } } } + return 1; } -static int daObj_Wflag_Create(fopAc_ac_c* i_this) { - fopAcM_ct(i_this, obj_wflag_class); - int rv = dComIfG_resLoad(&((obj_wflag_class*)i_this)->mPhaseReq, "Obj_wflag"); +static int daObj_Wflag_Create(fopAc_ac_c* actor) { + obj_wflag_class* i_this = (obj_wflag_class*)actor; + fopAcM_ct(actor, obj_wflag_class); + + int rv = dComIfG_resLoad(&i_this->phase, "Obj_wflag"); if (rv == cPhs_COMPLEATE_e) { - OS_REPORT("OBJ_WFLAG PARAM %x\n", fopAcM_GetParam(i_this)); - ((obj_wflag_class*)i_this)->field_0x82c = fopAcM_GetParam(i_this); + OS_REPORT("OBJ_WFLAG PARAM %x\n", fopAcM_GetParam(actor)); + i_this->unk_0x82c = fopAcM_GetParam(actor); + OS_REPORT("OBJ_WFLAG//////////////OBJ_WFLAG SET 1 !!\n"); - if (fopAcM_entrySolidHeap(i_this, useHeapInit, 0xd700) == 0) { + + if (!fopAcM_entrySolidHeap(actor, useHeapInit, 0xd700)) { OS_REPORT("//////////////OBJ_WFLAG SET NON !!\n"); return cPhs_ERROR_e; - } else { - OS_REPORT("//////////////OBJ_WFLAG SET 2 !!\n"); - ((obj_wflag_class*)i_this)->field_0x836 = cM_rndF(65536.0f); - daObj_Wflag_Execute(((obj_wflag_class*)i_this)); } + + OS_REPORT("//////////////OBJ_WFLAG SET 2 !!\n"); + i_this->counter = cM_rndF(65536.0f); + daObj_Wflag_Execute(i_this); } + return rv; } From 1e79756929b0b9f840df4cabb3774be2d8596ac6 Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sat, 21 Mar 2026 01:50:20 -0700 Subject: [PATCH 08/18] fix potential crash with heap name display --- src/f_op/f_op_actor_mng.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index 538d8ff544..f16dc5f686 100644 --- a/src/f_op/f_op_actor_mng.cpp +++ b/src/f_op/f_op_actor_mng.cpp @@ -736,7 +736,9 @@ u8 var_r30 = fopAcM::HeapAdjustEntry; fopAcM::HeapAdjustEntry = var_r30; #if TARGET_PC - JKRHEAP_NAMEF(i_actor->heap, "Actor %d (%s)", i_actor->id, GetProcName(i_actor->profname)); + if (result) { + JKRHEAP_NAMEF(i_actor->heap, "Actor %d (%s)", i_actor->id, GetProcName(i_actor->profname)); + } #endif return result; From ef0f9ef7fd5343a88463211f9090cb76df5193bf Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sat, 21 Mar 2026 05:07:51 -0700 Subject: [PATCH 09/18] various crash fixes --- src/d/actor/d_a_e_pm.cpp | 9 +++++++++ src/d/actor/d_flower.inc | 4 ++++ src/d/d_com_inf_game.cpp | 7 ++++++- src/m_Do/m_Do_machine.cpp | 10 ++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/d/actor/d_a_e_pm.cpp b/src/d/actor/d_a_e_pm.cpp index c994995591..5820985ec1 100644 --- a/src/d/actor/d_a_e_pm.cpp +++ b/src/d/actor/d_a_e_pm.cpp @@ -338,6 +338,10 @@ static s16 s_TargetAngle; void daE_PM_c::SearchFarP() { //! @bug best_distance is not initialized f32 best_distance; + #if AVOID_UB + best_distance = 0.0f; + #endif + int best_index; dPnt* pnt = dPath_GetPnt(mpPath, 0); Vec pos; @@ -2652,6 +2656,11 @@ void daE_PM_c::setGakkiBaseMtx() { void daE_PM_c::setLampBaseMtx() { cXyz vec1, vec2; +#if AVOID_UB + vec1.set(0, 0, 0); + vec2.set(0, 0, 0); +#endif + MTXCopy(mpMorf->getModel()->getAnmMtx(JNT_HAND_R), *calc_mtx); cXyz vec3(0.0f, -30.0f, -5.0f); //! @bug vec1 is not initialized in its first two uses, which are probably supposed to be vec3 diff --git a/src/d/actor/d_flower.inc b/src/d/actor/d_flower.inc index 07c722e521..13bc1ad251 100644 --- a/src/d/actor/d_flower.inc +++ b/src/d/actor/d_flower.inc @@ -510,6 +510,10 @@ dFlower_packet_c::dFlower_packet_c() { } m_deleteRoom = &dFlower_packet_c::deleteRoom; + +#if AVOID_UB + m_playerSwordTop.set(0, 0, 0); +#endif } void dFlower_packet_c::draw() { diff --git a/src/d/d_com_inf_game.cpp b/src/d/d_com_inf_game.cpp index 393b6c9762..6b7f7d6ae3 100644 --- a/src/d/d_com_inf_game.cpp +++ b/src/d/d_com_inf_game.cpp @@ -2080,7 +2080,12 @@ void dComIfGp_createSubExpHeap2D() { if (dComIfGp_getSubExpHeap2D(i) == NULL) { JKRExpHeap* i_heap = JKRCreateExpHeap(size, dComIfGp_getExpHeap2D(), false); JUT_ASSERT(3576, i_heap != NULL); - JKRHEAP_NAMEF(i_heap, "SubExpHeap2D %d", i); + + #if TARGET_PC + if (i_heap != NULL) { + JKRHEAP_NAMEF(i_heap, "SubExpHeap2D %d", i); + } + #endif dComIfGp_setSubExpHeap2D(i, i_heap); } } diff --git a/src/m_Do/m_Do_machine.cpp b/src/m_Do/m_Do_machine.cpp index fef1875e92..f50c8a6fdb 100644 --- a/src/m_Do/m_Do_machine.cpp +++ b/src/m_Do/m_Do_machine.cpp @@ -514,6 +514,11 @@ void exceptionRestart() { } void myExceptionCallback(u16, OSContext*, u32, u32) { + #if TARGET_PC + printf("myExceptionCallback abort"); + abort(); + #endif + u32 btnHold; u32 btnTrig; @@ -971,8 +976,13 @@ int mDoMch_Create() { sysConsole->setPosition(16, 42); JUTException::setMapFile(MAP_FOLDER MAP_FILE); + #if TARGET_PC + JUTException::setPreUserCallback(nullptr); + JUTException::setPostUserCallback(nullptr); + #else JUTException::setPreUserCallback(myExceptionCallback); JUTException::setPostUserCallback(fault_callback_scroll); + #endif cMl::init(mDoExt_getZeldaHeap()); cM_initRnd(100, 100, 100); From 7c03087600392271edd39f9b5d177ea21c0b14ec Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sat, 21 Mar 2026 18:05:29 -0700 Subject: [PATCH 10/18] fix d_a_peru animation data --- src/d/actor/d_a_peru.cpp | 76 +++++++++++++++------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/src/d/actor/d_a_peru.cpp b/src/d/actor/d_a_peru.cpp index ea3c104b66..df134aa5b6 100644 --- a/src/d/actor/d_a_peru.cpp +++ b/src/d/actor/d_a_peru.cpp @@ -34,60 +34,40 @@ static s8* l_loadResPtrnList[3] = { l_loadResPtrn0, }; -static u8 l_faceMotionAnmData[140] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +static daNpcT_faceMotionAnmData_c l_faceMotionAnmData[5] = { + {-1, 0, 0, 30, 2, 1, 1}, + {10, 0, 1, 30, 2, 1, 1}, + {8, 2, 1, 32, 2, 1, 0}, + {9, 0, 1, 33, 0, 1, 0}, + {7, 0, 1, 31, 0, 1, 0}, }; -static u8 l_motionAnmData[308] = { - 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, +static daNpcT_motionAnmData_c l_motionAnmData[11] = { + {20, 2, 1, 27, 0, 1, 1, 0}, + {17, 2, 1, 27, 0, 1, 1, 0}, + {18, 2, 1, 27, 0, 1, 1, 0}, + {21, 2, 1, 27, 0, 1, 1, 0}, + {16, 2, 1, 27, 0, 1, 1, 0}, + {15, 2, 1, 27, 0, 1, 1, 0}, + {19, 0, 1, 27, 0, 1, 1, 0}, + {13, 0, 1, 27, 0, 1, 1, 0}, + {14, 2, 1, 27, 0, 1, 1, 0}, + {12, 0, 1, 27, 0, 1, 1, 0}, + {11, 0, 1, 27, 0, 1, 1, 0}, }; -static u8 l_faceMotionSequenceData[80] = { - 0x00, 0x01, 0xFF, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x02, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x03, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x04, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, +static daNpcT_MotionSeqMngr_c::sequenceStepData_c l_faceMotionSequenceData[20] = { + {1, -1, 1}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {2, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {0, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {3, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {4, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, }; -static u8 l_motionSequenceData[160] = { - 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x02, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x05, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x06, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x07, 0xFF, 0x00, 0x00, 0x08, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x09, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x0A, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x03, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x04, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, +static daNpcT_MotionSeqMngr_c::sequenceStepData_c l_motionSequenceData[40] = { + {0, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {1, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {2, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {5, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {6, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {7, -1, 0}, {8, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, + {9, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {10, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, + {3, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {4, -1, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, }; const char* daPeru_c::mCutNameList[3] = { From 07e7348b325ca5a6b021ee7c089cc667e0d7bf1f Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sat, 21 Mar 2026 19:06:51 -0700 Subject: [PATCH 11/18] fix fopAcM_createItemFromEnemyID --- src/f_op/f_op_actor_mng.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index f16dc5f686..9a9b9c7db5 100644 --- a/src/f_op/f_op_actor_mng.cpp +++ b/src/f_op/f_op_actor_mng.cpp @@ -1471,12 +1471,21 @@ struct EnemyTable { fpc_ProcID fopAcM_createItemFromEnemyID(u8 i_enemyID, cXyz const* i_pos, int i_itemBitNo, int i_roomNo, csXyz const* i_angle, cXyz const* i_scale, f32* i_speedF, f32* i_speedY) { - int itemNo; + int itemNo; int tableNo = 0xFF; - uintptr_t* data = (uintptr_t*)dEnemyItem_c::getItemData(); + +#if TARGET_PC + u8* data = (u8*)dEnemyItem_c::getItemData(); + data += 4; + BE(int) tableNum = *(int*)data; + data += 4; +#else + u32* data = (u32*)dEnemyItem_c::getItemData(); data++; - BE(int) tableNum = (int) *data; + int tableNum = (int)*data; data++; +#endif + EnemyTable* table = (EnemyTable*)data; for (u32 i = 0; i < tableNum; i++) { From aefdbd9ab118dd773d560d0fbd55029adf7e3c77 Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sat, 21 Mar 2026 20:30:41 -0700 Subject: [PATCH 12/18] fix fopAcM_createItemFromEnemyID fix --- src/f_op/f_op_actor_mng.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index 9a9b9c7db5..082c721418 100644 --- a/src/f_op/f_op_actor_mng.cpp +++ b/src/f_op/f_op_actor_mng.cpp @@ -1477,7 +1477,7 @@ fpc_ProcID fopAcM_createItemFromEnemyID(u8 i_enemyID, cXyz const* i_pos, int i_i #if TARGET_PC u8* data = (u8*)dEnemyItem_c::getItemData(); data += 4; - BE(int) tableNum = *(int*)data; + int tableNum = *(BE(int)*)data; data += 4; #else u32* data = (u32*)dEnemyItem_c::getItemData(); From 58c406173a73d4d53f9fe7d73f8394c23c1eb50e Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sat, 21 Mar 2026 22:56:44 -0700 Subject: [PATCH 13/18] aeralfos UB fix --- src/d/actor/d_a_b_gg.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/d/actor/d_a_b_gg.cpp b/src/d/actor/d_a_b_gg.cpp index 69c2060bf2..dac161d266 100644 --- a/src/d/actor/d_a_b_gg.cpp +++ b/src/d/actor/d_a_b_gg.cpp @@ -3323,6 +3323,9 @@ void daB_GG_c::DeathCam() { void daB_GG_c::GroundAction() { s16 var_r30 = 0; +#if AVOID_UB + var_r30 = 1; +#endif switch (mSubAction) { case SUBACT_MOVE: From 68df2391978f808b4ce191b4493ef5c99ec4f8f8 Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Sun, 22 Mar 2026 00:20:37 -0700 Subject: [PATCH 14/18] enable cs fades again --- src/m_Do/m_Do_graphic.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index 72180b3c40..1264e54dd8 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -442,6 +442,14 @@ void darwFilter(GXColor matColor) { GXLoadPosMtxImm(cMtx_getIdentity(), GX_PNMTX0); GXSetChanMatColor(GX_COLOR0A0, matColor); GXSetCurrentMtx(0); + +#if TARGET_PC + 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); +#endif + GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_RGB8, 0); @@ -478,7 +486,7 @@ void mDoGph_gInf_c::calcFade() { } if (mFadeColor.a != 0) { - //darwFilter(mFadeColor); + darwFilter(mFadeColor); } } From 364400d56f68f7029a572cdbeb930e3d8721732d Mon Sep 17 00:00:00 2001 From: TakaRikka Date: Mon, 23 Mar 2026 05:01:42 -0700 Subject: [PATCH 15/18] save editor wip --- files.cmake | 1 + include/d/d_save.h | 30 -- src/dusk/imgui/ImGuiConsole.cpp | 86 +++ src/dusk/imgui/ImGuiConsole.hpp | 2 + src/dusk/imgui/ImGuiMenuGame.cpp | 85 --- src/dusk/imgui/ImGuiMenuTools.cpp | 5 + src/dusk/imgui/ImGuiMenuTools.hpp | 4 + src/dusk/imgui/ImGuiSaveEditor.cpp | 816 +++++++++++++++++++++++++++++ src/dusk/imgui/ImGuiSaveEditor.hpp | 26 + 9 files changed, 940 insertions(+), 115 deletions(-) create mode 100644 src/dusk/imgui/ImGuiSaveEditor.cpp create mode 100644 src/dusk/imgui/ImGuiSaveEditor.hpp diff --git a/files.cmake b/files.cmake index cae7f66aed..d57eaec490 100644 --- a/files.cmake +++ b/files.cmake @@ -1348,6 +1348,7 @@ set(DUSK_FILES src/dusk/imgui/ImGuiControllerOverlay.cpp src/dusk/imgui/ImGuiStubLog.cpp src/dusk/imgui/ImGuiMapLoader.cpp + src/dusk/imgui/ImGuiSaveEditor.cpp src/dusk/offset_ptr.cpp src/dusk/OSContext.cpp src/dusk/OSThread.cpp diff --git a/include/d/d_save.h b/include/d/d_save.h index 4511bc47e8..b0682e7ed6 100644 --- a/include/d/d_save.h +++ b/include/d/d_save.h @@ -163,7 +163,6 @@ public: u8 getTransformStatus() const { return mTransformStatus; } void setTransformStatus(u8 i_status) { mTransformStatus = i_status; } -private: /* 0x00 */ BE(u16) mMaxLife; /* 0x02 */ BE(u16) mLife; /* 0x04 */ BE(u16) mRupee; @@ -201,7 +200,6 @@ public: u16 getDate() const { return mDate; } void setDate(u16 i_date) { mDate = i_date; } -private: /* 0x00 */ BE(OSTime) mDateIpl; /* 0x08 */ u8 mTransformLevelFlag; /* 0x09 */ u8 mDarkClearLevelFlag; @@ -228,7 +226,6 @@ public: const char* getStageName() const { return mName; } s8 getRoomNo() const { return mRoomNo; } -private: #if TARGET_PC /* 0x00 */ BE(Vec) mPos; #else @@ -248,7 +245,6 @@ public: u8 getPlayerStatus() const { return mPlayerStatus; } s8 getRoomNo() const { return mRoomNo; } -private: /* 0x00 */ char mName[8]; /* 0x08 */ u8 mPlayerStatus; /* 0x09 */ s8 mRoomNo; @@ -277,8 +273,6 @@ public: void offFieldDataExistFlag() { mFieldDataExistFlag = false; } void onFieldDataExistFlag() { mFieldDataExistFlag = true; } - -private: #if TARGET_PC /* 0x00 */ BE(Vec) mPos; #else @@ -312,7 +306,6 @@ public: void setWarpAcceptStage(s8 accept) { mWarpAcceptStage = accept; } void resetWarpAcceptStage() { mWarpAcceptStage = -1; } -private: #if TARGET_PC /* 0x00 */ BE(Vec) mPos; #else @@ -356,7 +349,6 @@ public: static const int BOMB_BAG_MAX = 3; static const int BOTTLE_MAX = 4; -private: /* 0x00 */ u8 mItems[24]; /* 0x18 */ u8 mItemSlots[24]; }; // Size: 0x30 @@ -368,7 +360,6 @@ public: void offFirstBit(u8 i_itemNo); int isFirstBit(u8 i_itemNo) const; -private: /* 0x0 */ BE(u32) mItemFlags[8]; }; // Size: 0x20 @@ -386,7 +377,6 @@ public: u8 getPachinkoNum() const { return mPachinkoNum; } void setPachinkoNum(u8 i_num) { mPachinkoNum = i_num; } -private: /* 0x0 */ u8 mArrowNum; /* 0x1 */ u8 mBombNum[3]; /* 0x4 */ u8 mBottleNum[4]; @@ -403,7 +393,6 @@ public: u8 getArrowNum() const { return mItemMax[ARROW_MAX]; } void setArrowNum(u8 i_maxNum) { mItemMax[ARROW_MAX] = i_maxNum; } -private: /* 0x0 */ u8 mItemMax[8]; }; // Size: 0x8 @@ -429,7 +418,6 @@ public: } } -private: /* 0x0 */ u8 mItem[8]; /* 0x8 */ u8 unk8; /* 0x9 */ u8 mCrystal; @@ -443,7 +431,6 @@ class dSv_player_wolf_c { public: void init(); -private: /* 0x0 */ u8 unk0[3]; /* 0x3 */ u8 unk3; }; // Size: 0x4 @@ -457,7 +444,6 @@ public: void offLightDropGetFlag(u8 i_nowLevel); BOOL isLightDropGetFlag(u8 i_nowLevel) const; -private: /* 0x0 */ u8 mLightDropNum[4]; /* 0x4 */ u8 mLightDropGetFlag; /* 0x5 */ u8 unk5[3]; @@ -473,7 +459,6 @@ public: u8 getGetNumber(int i_no) { return mGetNumber[i_no]; } void setGetNumber(int i_no, u8 i_value) { mGetNumber[i_no] = i_value; } -private: /* 0x00 */ BE(u32) mLetterGetFlags[2]; /* 0x08 */ BE(u32) mLetterReadFlags[2]; /* 0x10 */ u8 mGetNumber[64]; @@ -487,7 +472,6 @@ public: u8 getMaxSize(int i_sizeIndex) const { return mMaxSize[i_sizeIndex]; } void setMaxSize(int i_sizeIndex, u8 i_size) { mMaxSize[i_sizeIndex] = i_size; } -private: /* 0x00 */ BE(u16) mFishCount[16]; /* 0x20 */ u8 mMaxSize[16]; }; // Size: 0x34 @@ -508,7 +492,6 @@ public: void setHorseName(const char* i_name) { strcpy(mHorseName, i_name); } u8 getClearCount() const { return mClearCount; } -private: /* 0x00 */ BE(u64) unk0; /* 0x08 */ BE(s64) mTotalTime; /* 0x10 */ BE(u16) unk16; @@ -555,7 +538,6 @@ public: LANGUAGE_ITALIAN, }; -private: /* 0x0 */ u8 mRuby; /* 0x1 */ u8 mSoundMode; /* 0x2 */ u8 mAttentionType; // Lock-On Type; 0 : hold, 1 : switch @@ -682,7 +664,6 @@ public: void offStageBossEnemy2() { offDungeonItem(STAGE_BOSS_ENEMY_2); } s32 isStageBossEnemy2() const { return isDungeonItem(STAGE_BOSS_ENEMY_2); } -private: /* 0x00 */ BE(u32) mTbox[2]; /* 0x08 */ BE(u32) mSwitch[4]; /* 0x18 */ BE(u32) mItem[1]; @@ -701,7 +682,6 @@ public: void* getPEventBit() { return (void*)mEvent; } -private: /* 0x0 */ u8 mEvent[256]; }; // Size: 0x100 @@ -716,7 +696,6 @@ public: u32 getRaceGameTime() const { return mRaceGameTime; } void setRaceGameTime(u32 i_time) { mRaceGameTime = i_time; } -private: /* 0x00 */ u8 unk0[1][4]; /* 0x04 */ BE(u32) mHookGameTime; /* 0x08 */ BE(u32) mBalloonScore; @@ -732,7 +711,6 @@ public: dSv_memBit_c& getBit() { return mBit; } const dSv_memBit_c& getBit() const { return mBit; } -private: /* 0x0 */ dSv_memBit_c mBit; }; // Size: 0x20 @@ -746,7 +724,6 @@ public: void offVisitedRoom(int i_no); BOOL isVisitedRoom(int i_no); -private: /* 0x0 */ BE(u32) mVisitedRoom[2]; }; // Size: 0x8 @@ -765,7 +742,6 @@ public: void reset() { mStageNo = -1; } -private: /* 0x00 */ s8 mStageNo; /* 0x01 */ u8 unk1; /* 0x04 */ u32 mSwitch[2]; @@ -793,7 +769,6 @@ public: void offOneItem(int i_no); BOOL isOneItem(int i_no) const; -private: /* 0x00 */ BE(u16) mSwitch[2]; /* 0x04 */ BE(u16) mRoomSwitch; /* 0x06 */ BE(u16) mItem[2]; @@ -810,7 +785,6 @@ public: static const int ACTOR_MAX = 0x80; -private: /* 0x00 */ u32 mActorFlags[4]; }; // Size: 0x10 @@ -826,7 +800,6 @@ public: dSv_zoneActor_c& getActor() { return mActor; } const dSv_zoneActor_c& getActor() const { return mActor; } -private: /* 0x00 */ s8 mRoomNo; /* 0x01 */ u8 unk1; /* 0x02 */ dSv_zoneBit_c mBit; @@ -855,7 +828,6 @@ public: mLastAngleY = angle; } -private: /* 0x00 */ s8 mRoomNo; /* 0x01 */ u8 field_0x01[3]; /* 0x04 */ s16 mStartPoint; @@ -891,7 +863,6 @@ public: f32 getCameraFvy() const { return mCameraFvy; } void setCameraFvy(f32 i_fvy) { mCameraFvy = i_fvy; } -private: /* 0x00 */ cXyz mPosition; /* 0x0C */ u32 mParam; /* 0x10 */ s16 mAngleY; @@ -928,7 +899,6 @@ public: static const int STAGE_MAX = 32; static const int STAGE2_MAX = 64; - // private: /* 0x000 */ dSv_player_c mPlayer; /* 0x1F0 */ dSv_memory_c mSave[STAGE_MAX]; /* 0x5F0 */ dSv_memory2_c mSave2[STAGE2_MAX]; diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index 003d5e5f62..cc8b758cb7 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -7,6 +7,7 @@ #include "fmt/format.h" #include "imgui.h" #include "aurora/gfx.h" +#include #include "ImGuiConsole.hpp" @@ -82,6 +83,91 @@ namespace dusk { return result; } + // from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444 + void ImGuiBeginGroupPanel(const char* name, const ImVec2& size) { + ImGui::BeginGroup(); + + auto cursorPos = ImGui::GetCursorScreenPos(); + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + + auto frameHeight = ImGui::GetFrameHeight(); + ImGui::BeginGroup(); + + ImVec2 effectiveSize = size; + if (size.x < 0.0f) + effectiveSize.x = ImGui::GetContentRegionAvail().x; + else + effectiveSize.x = size.x; + ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f)); + + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::SameLine(0.0f, 0.0f); + ImGui::BeginGroup(); + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::SameLine(0.0f, 0.0f); + ImGui::TextUnformatted(name); + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y)); + ImGui::BeginGroup(); + + ImGui::PopStyleVar(2); + + ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f; + ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f; + ImGui::GetCurrentWindow()->Size.x -= frameHeight; + + ImGui::PushItemWidth(effectiveSize.x - frameHeight); + } + + // from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444 + void ImGuiEndGroupPanel() { + ImGui::PopItemWidth(); + + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + + auto frameHeight = ImGui::GetFrameHeight(); + + // workaround for incorrect capture of columns/table width by placing + // zero-sized dummy element in the same group, this ensure + // max X cursor position is updated correctly + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + + ImGui::EndGroup(); + ImGui::EndGroup(); + + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y)); + + ImGui::EndGroup(); + + auto itemMin = ImGui::GetItemRectMin(); + auto itemMax = ImGui::GetItemRectMax(); + + ImVec2 halfFrame = ImVec2((frameHeight * 0.25f) * 0.5f, frameHeight * 0.5f); + ImGui::GetWindowDrawList()->AddRect( + ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y), + ImVec2(itemMax.x - halfFrame.x, itemMax.y), + ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)), + halfFrame.x); + + ImGui::PopStyleVar(2); + + ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f; + ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f; + ImGui::GetCurrentWindow()->Size.x += frameHeight; + + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + + ImGui::EndGroup(); + } + ImGuiConsole g_imguiConsole; ImGuiConsole::ImGuiConsole() {} diff --git a/src/dusk/imgui/ImGuiConsole.hpp b/src/dusk/imgui/ImGuiConsole.hpp index 47fa435626..82f0658e7a 100644 --- a/src/dusk/imgui/ImGuiConsole.hpp +++ b/src/dusk/imgui/ImGuiConsole.hpp @@ -33,6 +33,8 @@ namespace dusk { void SetOverlayWindowLocation(int corner); bool ShowCornerContextMenu(int& corner, int avoidCorner); void ImGuiStringViewText(std::string_view text); + void ImGuiBeginGroupPanel(const char* name, const ImVec2& size); + void ImGuiEndGroupPanel(); } void DuskDebugPad(); diff --git a/src/dusk/imgui/ImGuiMenuGame.cpp b/src/dusk/imgui/ImGuiMenuGame.cpp index 3d9af4fdc5..2366fb6a42 100644 --- a/src/dusk/imgui/ImGuiMenuGame.cpp +++ b/src/dusk/imgui/ImGuiMenuGame.cpp @@ -68,91 +68,6 @@ namespace dusk { } } - // from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444 - void ImGuiBeginGroupPanel(const char* name, const ImVec2& size) { - ImGui::BeginGroup(); - - auto cursorPos = ImGui::GetCursorScreenPos(); - auto itemSpacing = ImGui::GetStyle().ItemSpacing; - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - - auto frameHeight = ImGui::GetFrameHeight(); - ImGui::BeginGroup(); - - ImVec2 effectiveSize = size; - if (size.x < 0.0f) - effectiveSize.x = ImGui::GetContentRegionAvail().x; - else - effectiveSize.x = size.x; - ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f)); - - ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); - ImGui::SameLine(0.0f, 0.0f); - ImGui::BeginGroup(); - ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); - ImGui::SameLine(0.0f, 0.0f); - ImGui::TextUnformatted(name); - ImGui::SameLine(0.0f, 0.0f); - ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y)); - ImGui::BeginGroup(); - - ImGui::PopStyleVar(2); - - ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f; - ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f; - ImGui::GetCurrentWindow()->Size.x -= frameHeight; - - ImGui::PushItemWidth(effectiveSize.x - frameHeight); - } - - // from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444 - void ImGuiEndGroupPanel() { - ImGui::PopItemWidth(); - - auto itemSpacing = ImGui::GetStyle().ItemSpacing; - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - - auto frameHeight = ImGui::GetFrameHeight(); - - // workaround for incorrect capture of columns/table width by placing - // zero-sized dummy element in the same group, this ensure - // max X cursor position is updated correctly - ImGui::SameLine(0.0f, 0.0f); - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - - ImGui::EndGroup(); - ImGui::EndGroup(); - - ImGui::SameLine(0.0f, 0.0f); - ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); - ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y)); - - ImGui::EndGroup(); - - auto itemMin = ImGui::GetItemRectMin(); - auto itemMax = ImGui::GetItemRectMax(); - - ImVec2 halfFrame = ImVec2((frameHeight * 0.25f) * 0.5f, frameHeight * 0.5f); - ImGui::GetWindowDrawList()->AddRect( - ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y), - ImVec2(itemMax.x - halfFrame.x, itemMax.y), - ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)), - halfFrame.x); - - ImGui::PopStyleVar(2); - - ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f; - ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f; - ImGui::GetCurrentWindow()->Size.x += frameHeight; - - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - - ImGui::EndGroup(); - } - static void drawVirtualStick(const char* id, const ImVec2& stick) { ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5, ImGui::GetCursorPos().y)); diff --git a/src/dusk/imgui/ImGuiMenuTools.cpp b/src/dusk/imgui/ImGuiMenuTools.cpp index 9f68e11b40..d848690063 100644 --- a/src/dusk/imgui/ImGuiMenuTools.cpp +++ b/src/dusk/imgui/ImGuiMenuTools.cpp @@ -44,6 +44,7 @@ namespace dusk { ImGui::MenuItem("Debug Camera", "F6", &m_showCameraOverlay); ImGui::MenuItem("Map Loader", nullptr, &m_showMapLoader); ImGui::MenuItem("Player Info", nullptr, &m_showPlayerInfo); + ImGui::MenuItem("Save Editor", nullptr, &m_showSaveEditor); ImGui::EndMenu(); } @@ -59,6 +60,10 @@ namespace dusk { ShowMapLoader(); ShowPlayerInfo(); + if (m_showSaveEditor) { + m_saveEditor.draw(); + } + DuskDebugPad(); // temporary, remove later } diff --git a/src/dusk/imgui/ImGuiMenuTools.hpp b/src/dusk/imgui/ImGuiMenuTools.hpp index 5650e49c8e..325181268a 100644 --- a/src/dusk/imgui/ImGuiMenuTools.hpp +++ b/src/dusk/imgui/ImGuiMenuTools.hpp @@ -5,6 +5,7 @@ #include #include "imgui.h" +#include "ImGuiSaveEditor.hpp" namespace dusk { class ImGuiMenuTools { @@ -63,6 +64,9 @@ namespace dusk { bool m_showPlayerInfo = false; CollisionViewSettings m_collisionViewSettings; + + bool m_showSaveEditor = false; + ImGuiSaveEditor m_saveEditor; }; } diff --git a/src/dusk/imgui/ImGuiSaveEditor.cpp b/src/dusk/imgui/ImGuiSaveEditor.cpp new file mode 100644 index 0000000000..b21196fa54 --- /dev/null +++ b/src/dusk/imgui/ImGuiSaveEditor.cpp @@ -0,0 +1,816 @@ +#include "fmt/format.h" +#include "imgui.h" +#include "aurora/gfx.h" + +#include "ImGuiConsole.hpp" +#include "ImGuiSaveEditor.hpp" + +#include "d/d_com_inf_game.h" +#include "d/d_item_data.h" + +#include + +namespace dusk { + std::map itemMap = { + {dItemNo_HEART_e, "Heart"}, + {dItemNo_GREEN_RUPEE_e, "Green Rupee"}, + {dItemNo_BLUE_RUPEE_e, "Blue Rupee"}, + {dItemNo_YELLOW_RUPEE_e, "Yellow Rupee"}, + {dItemNo_RED_RUPEE_e, "Red Rupee"}, + {dItemNo_PURPLE_RUPEE_e, "Purple Rupee"}, + {dItemNo_ORANGE_RUPEE_e, "Orange Rupee"}, + {dItemNo_SILVER_RUPEE_e, "Silver Rupee"}, + {dItemNo_S_MAGIC_e, "Small Magic"}, + {dItemNo_L_MAGIC_e, "Large Magic"}, + {dItemNo_BOMB_5_e, "Bombs (5)"}, + {dItemNo_BOMB_10_e, "Bombs (10)"}, + {dItemNo_BOMB_20_e, "Bombs (20)"}, + {dItemNo_BOMB_30_e, "Bombs (30)"}, + {dItemNo_ARROW_10_e, "Arrows (10)"}, + {dItemNo_ARROW_20_e, "Arrows (20)"}, + {dItemNo_ARROW_30_e, "Arrows (30)"}, + {dItemNo_ARROW_1_e, "Arrows (1)"}, + {dItemNo_PACHINKO_SHOT_e, "Pumpkin Seeds"}, + {dItemNo_NOENTRY_19_e, "Unknown"}, + {dItemNo_NOENTRY_20_e, "Unknown"}, + {dItemNo_NOENTRY_21_e, "Unknown"}, + {dItemNo_WATER_BOMB_5_e, "Water Bombs (5)"}, + {dItemNo_WATER_BOMB_10_e, "Water Bombs (10)"}, + {dItemNo_WATER_BOMB_20_e, "Water Bombs (20)"}, + {dItemNo_WATER_BOMB_30_e, "Water Bombs (30)"}, + {dItemNo_BOMB_INSECT_5_e, "Bomblings (5)"}, + {dItemNo_BOMB_INSECT_10_e, "Bomblings (10)"}, + {dItemNo_BOMB_INSECT_20_e, "Bomblings (20)"}, + {dItemNo_BOMB_INSECT_30_e, "Bomblings (30)"}, + {dItemNo_RECOVERY_FAILY_e, "Fairy"}, + {dItemNo_TRIPLE_HEART_e, "Triple Hearts"}, + {dItemNo_SMALL_KEY_e, "Small Key"}, + {dItemNo_KAKERA_HEART_e, "Piece of Heart"}, + {dItemNo_UTAWA_HEART_e, "Heart Container"}, + {dItemNo_MAP_e, "Map"}, + {dItemNo_COMPUS_e, "Compass"}, + {dItemNo_DUNGEON_EXIT_e, "Ooccoo Sr."}, + {dItemNo_BOSS_KEY_e, "Boss Key"}, + {dItemNo_DUNGEON_BACK_e, "Ooccoo Jr."}, + {dItemNo_SWORD_e, "Ordon Sword"}, + {dItemNo_MASTER_SWORD_e, "Master Sword"}, + {dItemNo_WOOD_SHIELD_e, "Wooden Shield"}, + {dItemNo_SHIELD_e, "Ordon Shield"}, + {dItemNo_HYLIA_SHIELD_e, "Hylian Shield"}, + {dItemNo_TKS_LETTER_e, "Ooccoo's Letter"}, + {dItemNo_WEAR_CASUAL_e, "Ordon Clothes"}, + {dItemNo_WEAR_KOKIRI_e, "Hero's Clothes"}, + {dItemNo_ARMOR_e, "Magic Armor"}, + {dItemNo_WEAR_ZORA_e, "Zora Armor"}, + {dItemNo_MAGIC_LV1_e, "Magic Level 1"}, + {dItemNo_DUNGEON_EXIT_2_e, "Ooccoo Sr."}, + {dItemNo_WALLET_LV1_e, "Wallet"}, + {dItemNo_WALLET_LV2_e, "Big Wallet"}, + {dItemNo_WALLET_LV3_e, "Giant Wallet"}, + {dItemNo_NOENTRY_55_e, "Unknown"}, + {dItemNo_NOENTRY_56_e, "Unknown"}, + {dItemNo_NOENTRY_57_e, "Unknown"}, + {dItemNo_NOENTRY_58_e, "Unknown"}, + {dItemNo_NOENTRY_59_e, "Unknown"}, + {dItemNo_NOENTRY_60_e, "Unknown"}, + {dItemNo_ZORAS_JEWEL_e, "Coral Earring"}, + {dItemNo_HAWK_EYE_e, "Hawkeye"}, + {dItemNo_WOOD_STICK_e, "Wooden Sword"}, + {dItemNo_BOOMERANG_e, "Gale Boomerang"}, + {dItemNo_SPINNER_e, "Spinner"}, + {dItemNo_IRONBALL_e, "Ball and Chain"}, + {dItemNo_BOW_e, "Hero's Bow"}, + {dItemNo_HOOKSHOT_e, "Clawshot"}, + {dItemNo_HVY_BOOTS_e, "Iron Boots"}, + {dItemNo_COPY_ROD_e, "Dominion Rod"}, + {dItemNo_W_HOOKSHOT_e, "Double Clawshots"}, + {dItemNo_KANTERA_e, "Lantern"}, + {dItemNo_LIGHT_SWORD_e, "Light Sword"}, + {dItemNo_FISHING_ROD_1_e, "Fishing Rod"}, + {dItemNo_PACHINKO_e, "Slingshot"}, + {dItemNo_COPY_ROD_2_e, "Dominion Rod"}, + {dItemNo_NOENTRY_77_e, "Unknown"}, + {dItemNo_NOENTRY_78_e, "Unknown"}, + {dItemNo_BOMB_BAG_LV2_e, "Giant Bomb Bag"}, + {dItemNo_BOMB_BAG_LV1_e, "Bomb Bag"}, + {dItemNo_BOMB_IN_BAG_e, "Bomb Bag"}, + {dItemNo_NOENTRY_82_e, "Unknown"}, + {dItemNo_LIGHT_ARROW_e, "Light Arrow"}, + {dItemNo_ARROW_LV1_e, "Quiver"}, + {dItemNo_ARROW_LV2_e, "Big Quiver"}, + {dItemNo_ARROW_LV3_e, "Giant Quiver"}, + {dItemNo_NOENTRY_87_e, "Unknown"}, + {dItemNo_LURE_ROD_e, "Fishing Rod (Lure)"}, + {dItemNo_BOMB_ARROW_e, "Bomb Arrow"}, + {dItemNo_HAWK_ARROW_e, "Hawk Arrow"}, + {dItemNo_BEE_ROD_e, "Fishing Rod (Bee Larva)"}, + {dItemNo_JEWEL_ROD_e, "Fishing Rod (Earring)"}, + {dItemNo_WORM_ROD_e, "Fishing Rod (Worm)"}, + {dItemNo_JEWEL_BEE_ROD_e, "Fishing Rod (Earring + Bee Larva)"}, + {dItemNo_JEWEL_WORM_ROD_e, "Fishing Rod (Earring + Worm)"}, + {dItemNo_EMPTY_BOTTLE_e, "Empty Bottle"}, + {dItemNo_RED_BOTTLE_e, "Red Potion"}, + {dItemNo_GREEN_BOTTLE_e, "Green Potion"}, + {dItemNo_BLUE_BOTTLE_e, "Blue Potion"}, + {dItemNo_MILK_BOTTLE_e, "Milk Bottle"}, + {dItemNo_HALF_MILK_BOTTLE_e, "Half Milk Bottle"}, + {dItemNo_OIL_BOTTLE_e, "Lantern Oil"}, + {dItemNo_WATER_BOTTLE_e, "Water Bottle"}, + {dItemNo_OIL_BOTTLE_2_e, "Oil Bottle"}, + {dItemNo_RED_BOTTLE_2_e, "Red Potion"}, + {dItemNo_UGLY_SOUP_e, "Nasty Soup"}, + {dItemNo_HOT_SPRING_e, "Hotspring Water"}, + {dItemNo_FAIRY_e, "Fairy"}, + {dItemNo_HOT_SPRING_2_e, "Hotspring Water"}, + {dItemNo_OIL2_e, "Lantern Oil"}, + {dItemNo_OIL_e, "Lantern Oil"}, + {dItemNo_NORMAL_BOMB_e, "Bombs"}, + {dItemNo_WATER_BOMB_e, "Water Bombs"}, + {dItemNo_POKE_BOMB_e, "Bomblings"}, + {dItemNo_FAIRY_DROP_e, "Great Fairy's Tears"}, + {dItemNo_WORM_e, "Worm"}, + {dItemNo_DROP_BOTTLE_e, ""}, + {dItemNo_BEE_CHILD_e, ""}, + {dItemNo_CHUCHU_RARE_e, "Rare Chu Jelly"}, + {dItemNo_CHUCHU_RED_e, "Red Chu Jelly"}, + {dItemNo_CHUCHU_BLUE_e, "Blue Chu Jelly"}, + {dItemNo_CHUCHU_GREEN_e, "Green Chu Jelly"}, + {dItemNo_CHUCHU_YELLOW_e, "Yellow Chu Jelly"}, + {dItemNo_CHUCHU_PURPLE_e, "Purple Chu Jelly"}, + {dItemNo_LV1_SOUP_e, "Simple Soup"}, + {dItemNo_LV2_SOUP_e, "Good Soup"}, + {dItemNo_LV3_SOUP_e, "Superb Soup"}, + {dItemNo_LETTER_e, "Renado's Letter"}, + {dItemNo_BILL_e, "Invoice"}, + {dItemNo_WOOD_STATUE_e, "Wooden Statue"}, + {dItemNo_IRIAS_PENDANT_e, "Ilia's Charm"}, + {dItemNo_HORSE_FLUTE_e, "Horse Call"}, + {dItemNo_NOENTRY_133_e, "Unknown"}, + {dItemNo_NOENTRY_134_e, "Unknown"}, + {dItemNo_NOENTRY_135_e, "Unknown"}, + {dItemNo_NOENTRY_136_e, "Unknown"}, + {dItemNo_NOENTRY_137_e, "Unknown"}, + {dItemNo_NOENTRY_138_e, "Unknown"}, + {dItemNo_NOENTRY_139_e, "Unknown"}, + {dItemNo_NOENTRY_140_e, "Unknown"}, + {dItemNo_NOENTRY_141_e, "Unknown"}, + {dItemNo_NOENTRY_142_e, "Unknown"}, + {dItemNo_NOENTRY_143_e, "Unknown"}, + {dItemNo_RAFRELS_MEMO_e, "Auru's Memo"}, + {dItemNo_ASHS_SCRIBBLING_e, "Ashei's Sketch"}, + {dItemNo_NOENTRY_146_e, "Unknown"}, + {dItemNo_NOENTRY_147_e, "Unknown"}, + {dItemNo_NOENTRY_148_e, "Unknown"}, + {dItemNo_NOENTRY_149_e, "Unknown"}, + {dItemNo_NOENTRY_150_e, "Unknown"}, + {dItemNo_NOENTRY_151_e, "Unknown"}, + {dItemNo_NOENTRY_152_e, "Unknown"}, + {dItemNo_NOENTRY_153_e, "Unknown"}, + {dItemNo_NOENTRY_154_e, "Unknown"}, + {dItemNo_NOENTRY_155_e, "Unknown"}, + {dItemNo_CHUCHU_YELLOW2_e, "Yellow Chu Jelly"}, + {dItemNo_OIL_BOTTLE3_e, "Lantern Oil"}, + {dItemNo_SHOP_BEE_CHILD_e, ""}, + {dItemNo_CHUCHU_BLACK_e, "Black Chu Jelly"}, + {dItemNo_LIGHT_DROP_e, "Tear of Light"}, + {dItemNo_DROP_CONTAINER_e, "Vessel of Light (Faron)"}, + {dItemNo_DROP_CONTAINER02_e, "Vessel of Light (Eldin)"}, + {dItemNo_DROP_CONTAINER03_e, "Vessel of Light (Lanayru)"}, + {dItemNo_FILLED_CONTAINER_e, "Vessel of Light (Filled)"}, + {dItemNo_MIRROR_PIECE_2_e, "Mirror Shard (Snowpeak Ruins)"}, + {dItemNo_MIRROR_PIECE_3_e, "Mirror Shard (Temple of Time)"}, + {dItemNo_MIRROR_PIECE_4_e, "Mirror Shard (City in the Sky)"}, + {dItemNo_NOENTRY_168_e, "Unknown"}, + {dItemNo_NOENTRY_169_e, "Unknown"}, + {dItemNo_NOENTRY_170_e, "Unknown"}, + {dItemNo_NOENTRY_171_e, "Unknown"}, + {dItemNo_NOENTRY_172_e, "Unknown"}, + {dItemNo_NOENTRY_173_e, "Unknown"}, + {dItemNo_NOENTRY_174_e, "Unknown"}, + {dItemNo_NOENTRY_175_e, "Unknown"}, + {dItemNo_SMELL_YELIA_POUCH_e, "Scent of Ilia"}, + {dItemNo_SMELL_PUMPKIN_e, "Pumpkin Scent"}, + {dItemNo_SMELL_POH_e, "Poe Scent"}, + {dItemNo_SMELL_FISH_e, "Reekfish Scent"}, + {dItemNo_SMELL_CHILDREN_e, "Youth's Scent"}, + {dItemNo_SMELL_MEDICINE_e, "Medicine Scent"}, + {dItemNo_NOENTRY_182_e, "Unknown"}, + {dItemNo_NOENTRY_183_e, "Unknown"}, + {dItemNo_NOENTRY_184_e, "Unknown"}, + {dItemNo_NOENTRY_185_e, "Unknown"}, + {dItemNo_NOENTRY_186_e, "Unknown"}, + {dItemNo_NOENTRY_187_e, "Unknown"}, + {dItemNo_NOENTRY_188_e, "Unknown"}, + {dItemNo_NOENTRY_189_e, "Unknown"}, + {dItemNo_NOENTRY_190_e, "Unknown"}, + {dItemNo_NOENTRY_191_e, "Unknown"}, + {dItemNo_M_BEETLE_e, "Beetle ♂"}, + {dItemNo_F_BEETLE_e, "Beetle ♀"}, + {dItemNo_M_BUTTERFLY_e, "Butterfly ♂"}, + {dItemNo_F_BUTTERFLY_e, "Butterfly ♀"}, + {dItemNo_M_STAG_BEETLE_e, "Stag Beetle ♂"}, + {dItemNo_F_STAG_BEETLE_e, "Stag Beetle ♀"}, + {dItemNo_M_GRASSHOPPER_e, "Grasshopper ♂"}, + {dItemNo_F_GRASSHOPPER_e, "Grasshopper ♀"}, + {dItemNo_M_NANAFUSHI_e, "Phasmid ♂"}, + {dItemNo_F_NANAFUSHI_e, "Phasmid ♀"}, + {dItemNo_M_DANGOMUSHI_e, "Pill Bug ♂"}, + {dItemNo_F_DANGOMUSHI_e, "Pill Bug ♀"}, + {dItemNo_M_MANTIS_e, "Mantis ♂"}, + {dItemNo_F_MANTIS_e, "Mantis ♀"}, + {dItemNo_M_LADYBUG_e, "Ladybug ♂"}, + {dItemNo_F_LADYBUG_e, "Ladybug ♀"}, + {dItemNo_M_SNAIL_e, "Snail ♂"}, + {dItemNo_F_SNAIL_e, "Snail ♀"}, + {dItemNo_M_DRAGONFLY_e, "Dragonfly ♂"}, + {dItemNo_F_DRAGONFLY_e, "Dragonfly ♀"}, + {dItemNo_M_ANT_e, "Ant ♂"}, + {dItemNo_F_ANT_e, "Ant ♀"}, + {dItemNo_M_MAYFLY_e, "Mayfly ♂"}, + {dItemNo_F_MAYFLY_e, "Mayfly ♀"}, + {dItemNo_NOENTRY_216_e, "Unknown"}, + {dItemNo_NOENTRY_217_e, "Unknown"}, + {dItemNo_NOENTRY_218_e, "Unknown"}, + {dItemNo_NOENTRY_219_e, "Unknown"}, + {dItemNo_NOENTRY_220_e, "Unknown"}, + {dItemNo_NOENTRY_221_e, "Unknown"}, + {dItemNo_NOENTRY_222_e, "Unknown"}, + {dItemNo_NOENTRY_223_e, "Unknown"}, + {dItemNo_POU_SPIRIT_e, ""}, + {dItemNo_NOENTRY_225_e, "Unknown"}, + {dItemNo_NOENTRY_226_e, "Unknown"}, + {dItemNo_NOENTRY_227_e, "Unknown"}, + {dItemNo_NOENTRY_228_e, "Unknown"}, + {dItemNo_NOENTRY_229_e, "Unknown"}, + {dItemNo_NOENTRY_230_e, "Unknown"}, + {dItemNo_NOENTRY_231_e, "Unknown"}, + {dItemNo_NOENTRY_232_e, "Unknown"}, + {dItemNo_ANCIENT_DOCUMENT_e, "Ancient Sky Book"}, + {dItemNo_AIR_LETTER_e, "Sky Character"}, + {dItemNo_ANCIENT_DOCUMENT2_e, "Ancient Sky Book (Filled)"}, + {dItemNo_LV7_DUNGEON_EXIT_e, "Ooccoo Sr. (City in the Sky)"}, + {dItemNo_LINKS_SAVINGS_e, "Link's Savings"}, + {dItemNo_SMALL_KEY2_e, ""}, + {dItemNo_POU_FIRE1_e, ""}, + {dItemNo_POU_FIRE2_e, ""}, + {dItemNo_POU_FIRE3_e, ""}, + {dItemNo_POU_FIRE4_e, ""}, + {dItemNo_BOSSRIDER_KEY_e, ""}, + {dItemNo_TOMATO_PUREE_e, ""}, + {dItemNo_TASTE_e, ""}, + {dItemNo_LV5_BOSS_KEY_e, "Bedroom Key"}, + {dItemNo_SURFBOARD_e, ""}, + {dItemNo_KANTERA2_e, ""}, + {dItemNo_L2_KEY_PIECES1_e, "Key Shard (1)"}, + {dItemNo_L2_KEY_PIECES2_e, "Key Shard (2)"}, + {dItemNo_L2_KEY_PIECES3_e, "Key Shard (3)"}, + {dItemNo_KEY_OF_CARAVAN_e, "Bulblin Camp Key"}, + {dItemNo_LV2_BOSS_KEY_e, "Key Shard (Completed)"}, + {dItemNo_KEY_OF_FILONE_e, "Faron Gate Key"}, + {dItemNo_NONE_e, "None"}, + }; + + ImGuiSaveEditor::ImGuiSaveEditor() {} + + void ImGuiSaveEditor::draw() { + ImGuiIO& io = ImGui::GetIO(); + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize; + + ImGui::SetNextWindowBgAlpha(0.65f); + ImGui::SetNextWindowSizeConstraints(ImVec2(600, 700), ImVec2(600, 700)); + + if (ImGui::Begin("Save Editor", nullptr, windowFlags)) { + if (ImGui::BeginTabBar("SaveEditorTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { + if (ImGui::BeginTabItem("Player Status")) { + drawPlayerStatusTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Location")) { + drawLocationTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Inventory")) { + //DrawInventoryTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Collection")) { + //DrawFlagsTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Flags")) { + drawFlagsTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Minigame")) { + //DrawFlagsTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Config")) { + drawConfigTab(); + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + } + } + + ImGui::End(); + } + + void InputScalarBE(const char* label, ImGuiDataType dataType, void* pData) { + switch (dataType) { + case ImGuiDataType_U16: { + u16 temp = *(BE(u16)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(u16)*)pData = temp; + } + break; + } + case ImGuiDataType_S16: { + s16 temp = *(BE(s16)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(s16)*)pData = temp; + } + break; + } + case ImGuiDataType_U32: { + u32 temp = *(BE(u32)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(u32)*)pData = temp; + } + break; + } + case ImGuiDataType_S32: { + s32 temp = *(BE(s32)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(s32)*)pData = temp; + } + break; + } + case ImGuiDataType_U64: { + u64 temp = *(BE(u64)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(u64)*)pData = temp; + } + break; + } + case ImGuiDataType_S64: { + s64 temp = *(BE(s64)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(s64)*)pData = temp; + } + break; + } + case ImGuiDataType_Float: { + f32 temp = *(BE(f32)*)pData; + if (ImGui::InputScalar(label, dataType, &temp)) { + *(BE(f32)*)pData = temp; + } + break; + } + } + } + + void genSelectItemComboBox(const char* label, u8& selectItemData) { + dSv_player_status_a_c& statusA = dComIfGs_getSaveData()->getPlayer().getPlayerStatusA(); + dSv_player_item_c& item = dComIfGs_getSaveData()->getPlayer().getItem(); + + int currentSlotNo = selectItemData; + std::string defaultLabel = + currentSlotNo != 0xFF + ? fmt::format("Slot {0} ({1})", currentSlotNo, itemMap.find(item.mItems[currentSlotNo])->second) + : "None"; + + // TODO: live update equips + if (ImGui::BeginCombo(label, defaultLabel.c_str())) { + if (ImGui::Selectable("None")) { + selectItemData = 0xFF; + } + + for (int i = 0; i < 24; i++) { + u8 itemNo = item.mItems[i]; + if (ImGui::Selectable(fmt::format("Slot {0} ({1})", i, itemMap.find(itemNo)->second).c_str())) { + selectItemData = i; + } + } + ImGui::EndCombo(); + } + } + + void ImGuiSaveEditor::drawPlayerStatusTab() { + const char* playerName = dComIfGs_getPlayerName(); + ImGui::Text("Player Name: "); + ImGui::SameLine(); + char nameBuffer[8]; + snprintf(nameBuffer, sizeof(nameBuffer), "%s", playerName); + if (ImGui::InputText("##PlayerNameInput", nameBuffer, 8)) { + strcpy(dComIfGs_getPlayerName(), nameBuffer); + } + + const char* horseName = dComIfGs_getHorseName(); + ImGui::Text("Horse Name: "); + ImGui::SameLine(); + char horseNameBuffer[8]; + snprintf(horseNameBuffer, sizeof(horseNameBuffer), "%s", horseName); + if (ImGui::InputText("##HorseNameInput", horseNameBuffer, 8)) { + strcpy(dComIfGs_getHorseName(), horseNameBuffer); + } + + ImGui::Separator(); + + dSv_player_status_a_c& statusA = dComIfGs_getSaveData()->getPlayer().getPlayerStatusA(); + dSv_player_status_b_c& statusB = dComIfGs_getSaveData()->getPlayer().getPlayerStatusB(); + + InputScalarBE("Max Health", ImGuiDataType_U16, &statusA.mMaxLife); + InputScalarBE("Health", ImGuiDataType_U16, &statusA.mLife); + InputScalarBE("Rupees", ImGuiDataType_U16, &statusA.mRupee); + InputScalarBE("Max Oil", ImGuiDataType_U16, &statusA.mMaxOil); + InputScalarBE("Oil", ImGuiDataType_U16, &statusA.mOil); + + genSelectItemComboBox("Equip X", statusA.mSelectItem[0]); + genSelectItemComboBox("Equip Y", statusA.mSelectItem[1]); + genSelectItemComboBox("Combo Equip X", statusA.mMixItem[0]); + genSelectItemComboBox("Combo Equip Y", statusA.mMixItem[1]); + + + if (ImGui::BeginCombo("Clothes", itemMap.find(statusA.mSelectEquip[0])->second.c_str())) { + if (ImGui::Selectable("None")) { + statusA.mSelectEquip[0] = dItemNo_NONE_e; + } + if (ImGui::Selectable("Ordon Clothes")) { + statusA.mSelectEquip[0] = dItemNo_WEAR_CASUAL_e; + } + if (ImGui::Selectable("Hero's Clothes")) { + statusA.mSelectEquip[0] = dItemNo_WEAR_KOKIRI_e; + } + if (ImGui::Selectable("Zora Armor")) { + statusA.mSelectEquip[0] = dItemNo_WEAR_ZORA_e; + } + if (ImGui::Selectable("Magic Armor")) { + statusA.mSelectEquip[0] = dItemNo_ARMOR_e; + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Sword", itemMap.find(statusA.mSelectEquip[1])->second.c_str())) { + if (ImGui::Selectable("None")) { + statusA.mSelectEquip[1] = dItemNo_NONE_e; + } + if (ImGui::Selectable("Wooden Sword")) { + statusA.mSelectEquip[1] = dItemNo_WOOD_STICK_e; + } + if (ImGui::Selectable("Ordon Sword")) { + statusA.mSelectEquip[1] = dItemNo_SWORD_e; + } + if (ImGui::Selectable("Master Sword")) { + statusA.mSelectEquip[1] = dItemNo_MASTER_SWORD_e; + } + if (ImGui::Selectable("Light Sword")) { + statusA.mSelectEquip[1] = dItemNo_LIGHT_SWORD_e; + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Shield", itemMap.find(statusA.mSelectEquip[2])->second.c_str())) { + if (ImGui::Selectable("None")) { + statusA.mSelectEquip[2] = dItemNo_NONE_e; + } + if (ImGui::Selectable("Wooden Shield")) { + statusA.mSelectEquip[2] = dItemNo_SHIELD_e; + } + if (ImGui::Selectable("Ordon Shield")) { + statusA.mSelectEquip[2] = dItemNo_WOOD_SHIELD_e; + } + if (ImGui::Selectable("Hylian Shield")) { + statusA.mSelectEquip[2] = dItemNo_HYLIA_SHIELD_e; + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Scent", itemMap.find(statusA.mSelectEquip[3])->second.c_str())) { + if (ImGui::Selectable("None")) { + statusA.mSelectEquip[3] = dItemNo_NONE_e; + } + if (ImGui::Selectable("Youth's Scent")) { + statusA.mSelectEquip[3] = dItemNo_SMELL_CHILDREN_e; + } + if (ImGui::Selectable("Scent of Ilia")) { + statusA.mSelectEquip[3] = dItemNo_SMELL_YELIA_POUCH_e; + } + if (ImGui::Selectable("Poe Scent")) { + statusA.mSelectEquip[3] = dItemNo_SMELL_POH_e; + } + if (ImGui::Selectable("Reekfish Scent")) { + statusA.mSelectEquip[3] = dItemNo_SMELL_FISH_e; + } + if (ImGui::Selectable("Medicine Scent")) { + statusA.mSelectEquip[3] = dItemNo_SMELL_MEDICINE_e; + } + ImGui::EndCombo(); + } + + const char* walletSizeNames[] = { + "Normal", + "Big", + "Giant", + }; + int walletSize = statusA.getWalletSize(); + if (ImGui::BeginCombo("Wallet Size", walletSizeNames[walletSize])) { + if (ImGui::Selectable(walletSizeNames[WALLET])) { + statusA.setWalletSize(WALLET); + } + if (ImGui::Selectable(walletSizeNames[BIG_WALLET])) { + statusA.setWalletSize(BIG_WALLET); + } + if (ImGui::Selectable(walletSizeNames[GIANT_WALLET])) { + statusA.setWalletSize(GIANT_WALLET); + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Form", statusA.mTransformStatus == 0 ? "Human" : "Wolf")) { + if (ImGui::Selectable("Human")) { + statusA.mTransformStatus = TF_STATUS_HUMAN; + } + if (ImGui::Selectable("Wolf")) { + statusA.mTransformStatus = TF_STATUS_WOLF; + } + ImGui::EndCombo(); + } + + ImGui::Separator(); + + s32 hours = dKy_getdaytime_hour(); + s32 min = dKy_getdaytime_minute(); + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); + if (ImGui::InputScalar("##TimeHours", ImGuiDataType_S32, &hours)) { + hours = std::clamp(hours, 0, 23); + statusB.setTime((hours * 15.0f) + (min / 60.0f * 15.0f)); + } + + ImGui::SameLine(); + ImGui::Text(":"); + ImGui::SameLine(); + + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2); + if (ImGui::InputScalar("Time##TimeMinutes", ImGuiDataType_S32, &min)) { + min = std::clamp(min, 0, 59); + statusB.setTime((hours * 15.0f) + (min / 60.0f * 15.0f)); + } + + InputScalarBE("Date", ImGuiDataType_U16, &statusB.mDate); + + int transformLevel = 0; + for (int i = 0; i < 4; i++) { + if (statusB.mTransformLevelFlag & (1 << i)) { + transformLevel++; + } + } + if (ImGui::SliderInt("Transform Level", &transformLevel, 0, 3)) { + u8 newFlags = 0; + for (int i = 0; i < transformLevel; i++) { + newFlags |= (1 << i); + } + statusB.mTransformLevelFlag = newFlags; + } + + int darkClearLevel = 0; + for (int i = 0; i < 4; i++) { + if (statusB.mDarkClearLevelFlag & (1 << i)) { + darkClearLevel++; + } + } + if (ImGui::SliderInt("Twilight Clear Level", &darkClearLevel, 0, 3)) { + u8 newFlags = 0; + for (int i = 0; i < darkClearLevel; i++) { + newFlags |= (1 << i); + } + statusB.mDarkClearLevelFlag = newFlags; + } + } + + void ImGuiSaveEditor::drawLocationTab() { + dSv_player_return_place_c& returnPlace = dComIfGs_getSaveData()->getPlayer().getPlayerReturnPlace(); + dSv_horse_place_c& horsePlace = dComIfGs_getSaveData()->getPlayer().getHorsePlace(); + ImGui::Text("Save Location"); + + ImGui::Text("Stage: "); + ImGui::SameLine(); + char nameBuffer[8]; + snprintf(nameBuffer, sizeof(nameBuffer), "%s", returnPlace.mName); + if (ImGui::InputText("##SaveStageNameInput", nameBuffer, 8)) { + strcpy(returnPlace.mName, nameBuffer); + } + + ImGui::Text("Room: "); + ImGui::SameLine(); + int tempRoom = returnPlace.mRoomNo; + if (ImGui::InputInt("##SaveRoomInput", &tempRoom)) { + returnPlace.mRoomNo = tempRoom; + } + + ImGui::Text("Spawn ID: "); + ImGui::SameLine(); + int tempSpawn = returnPlace.mPlayerStatus; + if (ImGui::InputInt("##SaveSpawnInput", &tempSpawn)) { + returnPlace.mPlayerStatus = tempSpawn; + } + + ImGui::Separator(); + + ImGui::Text("Horse Location"); + + ImGui::Text("Position: "); + ImGui::SameLine(); + Vec tempPos = horsePlace.mPos; + if (ImGui::InputFloat3("##HorsePosition", &tempPos.x)) { + horsePlace.mPos.x = tempPos.x; + horsePlace.mPos.y = tempPos.y; + horsePlace.mPos.z = tempPos.z; + } + + ImGui::Text("Angle: "); + ImGui::SameLine(); + int tempAngle = horsePlace.mAngleY; + if (ImGui::InputInt("##HorsePosition", &tempAngle)) { + horsePlace.mAngleY = tempAngle; + } + + ImGui::Text("Stage: "); + ImGui::SameLine(); + char horseStageBuffer[8]; + snprintf(horseStageBuffer, sizeof(horseStageBuffer), "%s", horsePlace.mName); + if (ImGui::InputText("##HorseStageNameInput", horseStageBuffer, 8)) { + strcpy(horsePlace.mName, horseStageBuffer); + } + + ImGui::Text("Room: "); + ImGui::SameLine(); + int tempHorseRoom = horsePlace.mRoomNo; + if (ImGui::InputInt("##HorseRoomInput", &tempHorseRoom)) { + horsePlace.mRoomNo = tempHorseRoom; + } + + ImGui::Text("Spawn ID: "); + ImGui::SameLine(); + int tempHorseSpawn = horsePlace.mSpawnId; + if (ImGui::InputInt("##HorseSpawnInput", &tempHorseSpawn)) { + horsePlace.mSpawnId = tempHorseSpawn; + } + } + + void ImGuiSaveEditor::drawInventoryTab() { + + } + + void drawFlagList(const char* id, BE(u32)& flags) { + u32 tempFlagField = flags; + + for (int i = 31; i >= 0; i--) { + if ((31 - i) % 8) { + ImGui::SameLine(); + } + + bool flag = tempFlagField & (1 << i); + if (ImGui::Checkbox(fmt::format("{0}{1}", id, i).c_str(), &flag)) { + if (flag) + tempFlagField |= (1 << i); + else + tempFlagField &= ~(1 << i); + + flags = tempFlagField; + } + } + } + + void genMembitFlags(const char* id, dSv_memBit_c& membit) { + ImGuiBeginGroupPanel("Chest", { 100, 100 }); + for (int j = 0; j < 2; j++) { + drawFlagList(fmt::format("##_tbox{}", j).c_str(), membit.mTbox[j]); + } + ImGuiEndGroupPanel(); + + ImVec2 cursor = ImGui::GetCursorPos(); + + ImGui::SameLine(); + + ImGuiBeginGroupPanel("Switch", { 100, 100 }); + for (int j = 0; j < 4; j++) { + drawFlagList(fmt::format("##_switch{}", j).c_str(), membit.mSwitch[j]); + } + ImGuiEndGroupPanel(); + + ImGui::SetCursorPos(cursor); + + ImGuiBeginGroupPanel("Item", { 100, 100 }); + for (int j = 0; j < 1; j++) { + drawFlagList(fmt::format("##_item{}", j).c_str(), membit.mItem[j]); + } + ImGuiEndGroupPanel(); + } + + void ImGuiSaveEditor::drawFlagsTab() { + if (ImGui::TreeNode("Current Region Flags")) { + dSv_memBit_c& membit = g_dComIfG_gameInfo.info.mMemory.mBit; + genMembitFlags("##TempSceneFlags", membit); + + int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); + if (ImGui::Button("Save##SaveTempFlags")) { + dComIfGs_putSave(stageNo); + } + + ImGui::SameLine(); + + if (ImGui::Button("Load##LoadSaveFlags")) { + dComIfGs_getSave(stageNo); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Region Saved Flags")) { + static std::array regionNames = { + "Ordon", + "Hyrule Sewers", + "Faron", + "Eldin", + "Lanayru", + "Unknown", + "Hyrule Field", + "Sacred Grove", + "Snowpeak", + "Castle Town", + "Gerudo Desert", + "Fishing Pond", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Forest Temple", + "Goron Mines", + "Lakebed Temple", + "Arbiter's Grounds", + "Snowpeak Ruins", + "Temple of Time", + "City in the Sky", + "Palace of Twilight", + "Hyrule Castle", + "Caves", + "Grottos", + }; + + if (ImGui::BeginCombo("Region", regionNames[m_selectedRegion])) { + for (int i = 0; i < regionNames.size(); i++) { + if (strcmp(regionNames[i], "Reserved") == 0) continue; + + if (ImGui::Selectable(regionNames[i])) { + m_selectedRegion = i; + } + } + + ImGui::EndCombo(); + } + + dSv_memBit_c* membit = &dComIfGs_getSaveData()->mSave[m_selectedRegion].mBit; + if (membit != nullptr) { + genMembitFlags("##SaveSceneFlags", *membit); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Event Flags")) { + dSv_event_c& event = dComIfGs_getSaveData()->mEvent; + for (int e = 0; e < 255; e++) { + ImGui::Text("%03d ", e); + ImGui::SameLine(); + for (int i = 8; i >= 0; i--) { + bool flag = event.mEvent[e] & (1 << i); + if (ImGui::Checkbox(fmt::format("##event{0}{1}", e, i).c_str(), &flag)) { + if (flag) + event.mEvent[e] |= (1 << i); + else + event.mEvent[e] &= ~(1 << i); + } + ImGui::SameLine(); + } + ImGui::NewLine(); + } + ImGui::TreePop(); + } + } + + void ImGuiSaveEditor::drawConfigTab() { + dSv_player_config_c& config = dComIfGs_getSaveData()->getPlayer().getConfig(); + ImGui::Checkbox("Enable Vibration", (bool*)&config.mVibration); + if (ImGui::BeginCombo("Target Type", "Hold")) { + ImGui::EndCombo(); + } + } +} \ No newline at end of file diff --git a/src/dusk/imgui/ImGuiSaveEditor.hpp b/src/dusk/imgui/ImGuiSaveEditor.hpp new file mode 100644 index 0000000000..f6668a75db --- /dev/null +++ b/src/dusk/imgui/ImGuiSaveEditor.hpp @@ -0,0 +1,26 @@ +#ifndef DUSK_IMGUI_SAVEEDITOR_HPP +#define DUSK_IMGUI_SAVEEDITOR_HPP + +#include +#include + +#include "imgui.h" + +namespace dusk { + class ImGuiSaveEditor { + public: + ImGuiSaveEditor(); + + void draw(); + void drawPlayerStatusTab(); + void drawLocationTab(); + void drawInventoryTab(); + void drawFlagsTab(); + void drawConfigTab(); + + private: + int m_selectedRegion = 0; + }; +} + +#endif // DUSK_IMGUI_SAVEEDITOR_HPP From 946d1ae9b7027dc88c2f2824d946cc882f2fc92c Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Mon, 23 Mar 2026 13:34:08 +0100 Subject: [PATCH 16/18] Threading cleanup: remove MallocAllocator stuff Not necessary anymore now that JKRHeap is isolated --- src/dusk/OSMutex.cpp | 53 +++++-------------------------------------- src/dusk/OSThread.cpp | 51 +++++------------------------------------ src/dusk/stubs.cpp | 43 ++++------------------------------- 3 files changed, 16 insertions(+), 131 deletions(-) diff --git a/src/dusk/OSMutex.cpp b/src/dusk/OSMutex.cpp index 55d8ccb52f..8e26402e0d 100644 --- a/src/dusk/OSMutex.cpp +++ b/src/dusk/OSMutex.cpp @@ -14,43 +14,6 @@ #include "JSystem/JKernel/JKRHeap.h" -// ============================================================================ -// Malloc-based allocator to bypass JKRHeap operator new/delete -// Without this, side-table allocations call operator new -> JKRHeap::alloc -// -> OSLockMutex -> GetMutexData -> operator new ... infinite recursion. -// ============================================================================ - -template -struct MallocAllocator { - using value_type = T; - MallocAllocator() = default; - template MallocAllocator(const MallocAllocator&) noexcept {} - T* allocate(std::size_t n) { - void* p = std::malloc(n * sizeof(T)); - if (!p) throw std::bad_alloc(); - return static_cast(p); - } - void deallocate(T* p, std::size_t) noexcept { std::free(p); } - template bool operator==(const MallocAllocator&) const noexcept { return true; } - template bool operator!=(const MallocAllocator&) const noexcept { return false; } -}; - -template -struct MallocDeleter { - void operator()(T* p) const { - p->~T(); - std::free(p); - } -}; - -template -std::unique_ptr> make_malloc_unique(Args&&... args) { - void* mem = std::malloc(sizeof(T)); - if (!mem) throw std::bad_alloc(); - T* obj = JKR_NEW_ARGS (mem) T(std::forward(args)...); - return std::unique_ptr>(obj); -} - // ============================================================================ // Side-table: native mutex per OSMutex // ============================================================================ @@ -59,17 +22,13 @@ struct PCMutexData { std::recursive_mutex nativeMutex; }; -template -using MallocMap = std::unordered_map, std::equal_to, - MallocAllocator>>; - // Lazy-initialized to avoid DLL static init crashes static std::mutex& GetMutexMapMutex() { static std::mutex mtx; return mtx; } -static MallocMap>>& GetMutexMap() { - static MallocMap>> map; +static std::unordered_map>& GetMutexMap() { + static std::unordered_map> map; return map; } @@ -78,7 +37,7 @@ static PCMutexData& GetMutexData(OSMutex* mutex) { auto& map = GetMutexMap(); auto it = map.find(mutex); if (it == map.end()) { - auto result = map.emplace(mutex, make_malloc_unique()); + auto result = map.emplace(mutex, std::make_unique()); return *result.first->second; } return *it->second; @@ -97,8 +56,8 @@ static std::mutex& GetCondMapMutex() { static std::mutex mtx; return mtx; } -static MallocMap>>& GetCondMap() { - static MallocMap>> map; +static std::unordered_map>& GetCondMap() { + static std::unordered_map> map; return map; } @@ -107,7 +66,7 @@ static PCCondData& GetCondData(OSCond* cond) { auto& map = GetCondMap(); auto it = map.find(cond); if (it == map.end()) { - auto result = map.emplace(cond, make_malloc_unique()); + auto result = map.emplace(cond, std::make_unique()); return *result.first->second; } return *it->second; diff --git a/src/dusk/OSThread.cpp b/src/dusk/OSThread.cpp index 2d19139272..0be30f4aaf 100644 --- a/src/dusk/OSThread.cpp +++ b/src/dusk/OSThread.cpp @@ -18,45 +18,6 @@ #include "JSystem/JKernel/JKRHeap.h" -// ============================================================================ -// Malloc-based allocator to bypass JKRHeap operator new/delete -// ============================================================================ - -template -struct MallocAllocator { - using value_type = T; - MallocAllocator() = default; - template MallocAllocator(const MallocAllocator&) noexcept {} - T* allocate(std::size_t n) { - void* p = std::malloc(n * sizeof(T)); - if (!p) throw std::bad_alloc(); - return static_cast(p); - } - void deallocate(T* p, std::size_t) noexcept { std::free(p); } - template bool operator==(const MallocAllocator&) const noexcept { return true; } - template bool operator!=(const MallocAllocator&) const noexcept { return false; } -}; - -template -struct MallocDeleter { - void operator()(T* p) const { - p->~T(); - std::free(p); - } -}; - -template -std::unique_ptr> make_malloc_unique(Args&&... args) { - void* mem = std::malloc(sizeof(T)); - if (!mem) throw std::bad_alloc(); - T* obj = JKR_NEW_ARGS (mem) T(std::forward(args)...); - return std::unique_ptr>(obj); -} - -template -using MallocMap = std::unordered_map, std::equal_to, - MallocAllocator>>; - // ============================================================================ // Side-table: native thread data per OSThread // ============================================================================ @@ -76,8 +37,8 @@ static std::mutex& GetThreadDataMutex() { static std::mutex mtx; return mtx; } -static MallocMap>>& GetThreadDataMap() { - static MallocMap>> map; +static std::unordered_map>& GetThreadDataMap() { + static std::unordered_map> map; return map; } @@ -86,8 +47,8 @@ static std::mutex& GetQueueCvMutex() { static std::mutex mtx; return mtx; } -static MallocMap>>& GetQueueCvMap() { - static MallocMap>> map; +static std::unordered_map>& GetQueueCvMap() { + static std::unordered_map> map; return map; } @@ -96,7 +57,7 @@ static std::condition_variable& GetQueueCV(OSThreadQueue* queue) { auto& map = GetQueueCvMap(); auto it = map.find(queue); if (it == map.end()) { - auto result = map.emplace(queue, make_malloc_unique()); + auto result = map.emplace(queue, std::make_unique()); return *result.first->second; } return *it->second; @@ -295,7 +256,7 @@ int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param, // Create side-table entry (but don't start the thread yet) { - auto data = make_malloc_unique(); + auto data = std::make_unique(); data->func = func; data->param = param; diff --git a/src/dusk/stubs.cpp b/src/dusk/stubs.cpp index 73f4e93d80..f4d1b2688b 100644 --- a/src/dusk/stubs.cpp +++ b/src/dusk/stubs.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -55,42 +56,6 @@ u32 OSGetSoundMode() { // Message Queue (thread-safe implementation) // ========================================================================== -// Malloc-based allocator to bypass JKRHeap operator new/delete -template -struct MallocAllocator { - using value_type = T; - MallocAllocator() = default; - template MallocAllocator(const MallocAllocator&) noexcept {} - T* allocate(std::size_t n) { - void* p = std::malloc(n * sizeof(T)); - if (!p) throw std::bad_alloc(); - return static_cast(p); - } - void deallocate(T* p, std::size_t) noexcept { std::free(p); } - template bool operator==(const MallocAllocator&) const noexcept { return true; } - template bool operator!=(const MallocAllocator&) const noexcept { return false; } -}; - -template -struct MallocDeleter { - void operator()(T* p) const { - p->~T(); - std::free(p); - } -}; - -template -std::unique_ptr> make_malloc_unique(Args&&... args) { - void* mem = std::malloc(sizeof(T)); - if (!mem) throw std::bad_alloc(); - T* obj = new (mem) T(std::forward(args)...); - return std::unique_ptr>(obj); -} - -template -using MallocMap = std::unordered_map, std::equal_to, - MallocAllocator>>; - // Side-table for native synchronization per OSMessageQueue struct PCMessageQueueData { std::mutex mtx; @@ -103,8 +68,8 @@ static std::mutex& GetMsgQueueMapMutex() { static std::mutex mtx; return mtx; } -static MallocMap>>& GetMsgQueueMap() { - static MallocMap>> map; +static std::unordered_map>& GetMsgQueueMap() { + static std::unordered_map> map; return map; } @@ -113,7 +78,7 @@ static PCMessageQueueData& GetMsgQueueData(OSMessageQueue* mq) { auto& map = GetMsgQueueMap(); auto it = map.find(mq); if (it == map.end()) { - auto result = map.emplace(mq, make_malloc_unique()); + auto result = map.emplace(mq, std::make_unique()); return *result.first->second; } return *it->second; From 0148d913e152cc37a9eec688c8426be5730b4283 Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Mon, 23 Mar 2026 13:46:46 +0100 Subject: [PATCH 17/18] Add a bunch of missing imgui close buttons --- src/dusk/imgui/ImGuiMapLoader.cpp | 6 ++---- src/dusk/imgui/ImGuiMenuGame.cpp | 2 +- src/dusk/imgui/ImGuiMenuTools.cpp | 4 ++-- src/dusk/imgui/ImGuiProcessOverlay.cpp | 2 +- src/dusk/imgui/ImGuiSaveEditor.cpp | 4 ++-- src/dusk/imgui/ImGuiSaveEditor.hpp | 2 +- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/dusk/imgui/ImGuiMapLoader.cpp b/src/dusk/imgui/ImGuiMapLoader.cpp index 4b52fd1b04..74e60e4974 100644 --- a/src/dusk/imgui/ImGuiMapLoader.cpp +++ b/src/dusk/imgui/ImGuiMapLoader.cpp @@ -12,19 +12,17 @@ namespace dusk { return; } - ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; ImGui::SetNextWindowBgAlpha(0.65f); ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(FLT_MAX, FLT_MAX)); - if (!ImGui::Begin("Map Loader", nullptr, windowFlags)) { + if (!ImGui::Begin("Map Loader", &m_showMapLoader, windowFlags)) { ImGui::End(); return; } - ImGui::SeparatorText("Map Loader"); - ImGui::Checkbox("Show Internal Names", &m_mapLoaderInfo.showInternalNames); const char* previewRegion = "None"; diff --git a/src/dusk/imgui/ImGuiMenuGame.cpp b/src/dusk/imgui/ImGuiMenuGame.cpp index 2366fb6a42..a0b79579eb 100644 --- a/src/dusk/imgui/ImGuiMenuGame.cpp +++ b/src/dusk/imgui/ImGuiMenuGame.cpp @@ -110,7 +110,7 @@ namespace dusk { ImGui::SetNextWindowBgAlpha(0.65f); ImGui::SetNextWindowSizeConstraints(ImVec2(850, 400), ImVec2(850, 400)); - if (!ImGui::Begin("Controller Config", nullptr, windowFlags)) { + if (!ImGui::Begin("Controller Config", &m_showControllerConfig, windowFlags)) { ImGui::End(); return; } diff --git a/src/dusk/imgui/ImGuiMenuTools.cpp b/src/dusk/imgui/ImGuiMenuTools.cpp index d848690063..e84dbc1f08 100644 --- a/src/dusk/imgui/ImGuiMenuTools.cpp +++ b/src/dusk/imgui/ImGuiMenuTools.cpp @@ -61,7 +61,7 @@ namespace dusk { ShowPlayerInfo(); if (m_showSaveEditor) { - m_saveEditor.draw(); + m_saveEditor.draw(m_showSaveEditor); } DuskDebugPad(); // temporary, remove later @@ -141,7 +141,7 @@ namespace dusk { ImGui::SetNextWindowBgAlpha(0.65f); ImGui::SetNextWindowSizeConstraints(ImVec2(300, 200), ImVec2(300, 200)); - if (ImGui::Begin("Player Info", nullptr, windowFlags)) { + if (ImGui::Begin("Player Info", &m_showPlayerInfo, windowFlags)) { daAlink_c* player = (daAlink_c*)dComIfGp_getPlayer(0); daHorse_c* horse = dComIfGp_getHorseActor(); diff --git a/src/dusk/imgui/ImGuiProcessOverlay.cpp b/src/dusk/imgui/ImGuiProcessOverlay.cpp index cf2d22402e..04a87f00b6 100644 --- a/src/dusk/imgui/ImGuiProcessOverlay.cpp +++ b/src/dusk/imgui/ImGuiProcessOverlay.cpp @@ -74,7 +74,7 @@ namespace dusk { return; } - if (ImGui::Begin("Processes")) { + if (ImGui::Begin("Processes", &m_showProcessManagement)) { if (ImGui::BeginTabBar("Tabs")) { showTreeRecursive = true; if (ImGui::BeginTabItem("Tree")) { diff --git a/src/dusk/imgui/ImGuiSaveEditor.cpp b/src/dusk/imgui/ImGuiSaveEditor.cpp index b21196fa54..00cadfaa4a 100644 --- a/src/dusk/imgui/ImGuiSaveEditor.cpp +++ b/src/dusk/imgui/ImGuiSaveEditor.cpp @@ -272,14 +272,14 @@ namespace dusk { ImGuiSaveEditor::ImGuiSaveEditor() {} - void ImGuiSaveEditor::draw() { + void ImGuiSaveEditor::draw(bool& open) { ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize; ImGui::SetNextWindowBgAlpha(0.65f); ImGui::SetNextWindowSizeConstraints(ImVec2(600, 700), ImVec2(600, 700)); - if (ImGui::Begin("Save Editor", nullptr, windowFlags)) { + if (ImGui::Begin("Save Editor", &open, windowFlags)) { if (ImGui::BeginTabBar("SaveEditorTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Player Status")) { drawPlayerStatusTab(); diff --git a/src/dusk/imgui/ImGuiSaveEditor.hpp b/src/dusk/imgui/ImGuiSaveEditor.hpp index f6668a75db..3afc1b8145 100644 --- a/src/dusk/imgui/ImGuiSaveEditor.hpp +++ b/src/dusk/imgui/ImGuiSaveEditor.hpp @@ -11,7 +11,7 @@ namespace dusk { public: ImGuiSaveEditor(); - void draw(); + void draw(bool& open); void drawPlayerStatusTab(); void drawLocationTab(); void drawInventoryTab(); From a7fbdd6ece979d6e5cc1b8cc272a9e82cae1db51 Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Mon, 23 Mar 2026 13:53:23 +0100 Subject: [PATCH 18/18] Add note about `DUSK_SELECTED_OPT` to README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 53a726fac7..200913770a 100644 --- a/README.md +++ b/README.md @@ -68,3 +68,6 @@ Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ, build/dusk/dusk /path/to/game.rvz ``` If no path is specified, Dusk defaults to `game.iso` in the current working directory. + +#### 30 FPS on Debug +When compiled fully in a Debug the game runs too slowly to hit playable 30 FPS. To avoid this, you can set a CMake cache variable to optimize specific critical files without hampering debuggability in the rest of the program: `-DDUSK_SELECTED_OPT=ON`. When building for MSVC (Windows) you must also modify `CMAKE_CXX_FLAGS_DEBUG` and `CMAKE_C_FLAGS_DEBUG` to remove `/RTC1` from the flags, like so: `-DCMAKE_CXX_FLAGS_DEBUG="/MDd /Zi /Ob0 /Od" -DCMAKE_C_FLAGS_DEBUG="/MDd /Zi /Ob0 /Od"`