From a790efafc526f79a79fad38186335d222a215cb5 Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Wed, 18 Feb 2026 01:58:52 -0500 Subject: [PATCH] d_cursor_mng mostly matching (#3101) --- include/d/d_cc_s.h | 4 + include/d/d_cursor_mng.h | 116 +++++++++++ include/m_Do/m_Do_graphic.h | 2 + include/m_Do/m_Do_lib.h | 4 + src/d/d_cc_s.cpp | 42 ++++ src/d/d_cursor_mng.cpp | 385 ++++++++++++++++++++++++++++++++++++ src/m_Do/m_Do_graphic.cpp | 8 + src/m_Do/m_Do_lib.cpp | 20 ++ 8 files changed, 581 insertions(+) diff --git a/include/d/d_cc_s.h b/include/d/d_cc_s.h index 2f9b475f70..dbd3c18285 100644 --- a/include/d/d_cc_s.h +++ b/include/d/d_cc_s.h @@ -61,6 +61,10 @@ public: void ChkActor(fopAc_ac_c*); +#if PLATFORM_WII + BOOL ChkLine(cXyz&, cXyz&, f32, fopAc_ac_c**); +#endif + static bool m_mtrl_hit_tbl[64]; // /* 0x0000 */ cCcS mCCcS; diff --git a/include/d/d_cursor_mng.h b/include/d/d_cursor_mng.h index 459d747ffa..d8a84eb381 100644 --- a/include/d/d_cursor_mng.h +++ b/include/d/d_cursor_mng.h @@ -1,9 +1,125 @@ #ifndef D_CURSOR_MNG_H #define D_CURSOR_MNG_H +#include "JSystem/J2DGraph/J2DScreen.h" +#include "m_Do/m_Do_graphic.h" #include "m_Re/m_Re_controller_pad.h" // TODO: putting this here until a more appropriate place is found extern u8 data_8053a730; +class dCsr_mng_c { + struct csr_c; + + struct node_c : mDoGph_gInf_c::csr_c { + BOOL set(u8 i_priority, u8, u16 i_mask); + + /* 0x04 */ u8 m_priority; + /* 0x05 */ u8 field_0x05; + /* 0x06 */ u16 m_mask; + /* 0x08 */ node_c* m_prev; + /* 0x0C */ node_c* m_next; + /* 0x10 */ int m_actor_id; + /* 0x14 */ csr_c* m_csr; + /* 0x18 */ node_c* m_pointed_obj; + }; + + struct obj_c : node_c { + }; + + struct list_c { + list_c() : m_root(NULL) { + } + + virtual ~list_c(void) {} + void entry(node_c* i_node); + node_c* release(node_c* i_node); + node_c* release(u16 i_mask); + BOOL isEntry(const node_c* i_node) const; + + /* 0x04 */ node_c* m_root; + }; + + struct bloObj_c { + struct paneObj_c { + paneObj_c(void) { + m_handle = NULL; + m_min_x = 0; + m_min_y = 0; + m_max_x = 0; + m_max_y = 0; + } + virtual ~paneObj_c(void) {} + + /* 0x04 */ J2DPane* m_handle; + /* 0x08 */ s16 m_min_x; + /* 0x0A */ s16 m_min_y; + /* 0x0C */ s16 m_max_x; + /* 0x0E */ s16 m_max_y; + }; + + bloObj_c() { + m_panes = new paneObj_c[1]; + m_screen = 0; + } + + virtual ~bloObj_c(void); + virtual u32 signature(void) const { + return 0x626c6f20; + } + virtual BOOL isInside(s16 i_x, s16 i_y); + BOOL create(J2DScreen* i_screen, u16 i_mask, u8 i_priority, u8); + void calc(void); + void calcPaneObjNum(J2DPane* i_pane); + void createPaneObj(paneObj_c** i_panes, J2DPane* i_pane); + + /* 0x04 */ u8 field_0x04[0x10 - 0x4]; + /* 0x10 */ J2DScreen* m_screen; + /* 0x14 */ paneObj_c* m_panes; + /* 0x18 */ u16 m_pane_num; + /* 0x1A */ u8 m_is_calc; + /* 0x1C */ J2DPane* m_pane_handle; + }; + + struct ccObj_c : node_c { + virtual ~ccObj_c(void); + virtual int signature(void) const { + return 'cc '; + } + virtual BOOL isInside(s16, s16); + void set(u16, u8, u8); + }; + + struct csr_c : node_c { + virtual ~csr_c(void); + BOOL set(mDoGph_gInf_c::csr_c* i_csr, u16, u8, u8); + }; + +private: + dCsr_mng_c() : is_csr_on(true) { + } + + void update_(void); + void releaseCsr_(csr_c* i_csr); + void insideObjReleaseCheck_(void); + +public: + static void create(void); + static void update(void); + static void entryCsr(csr_c* i_csr); + static void releaseCsr(csr_c* i_csr); + static void entryObj(obj_c* i_obj); + static void releaseObj(obj_c* i_obj); + static void releaseObj(u16 i_mask); + static void onCsr(void); + static void offCsr(void); + + static dCsr_mng_c* m_myObj; + +private: + /* 0x00 */ list_c m_csr_list; + /* 0x08 */ list_c m_obj_list; + /* 0x10 */ bool is_csr_on; +}; + #endif /* D_CURSOR_MNG_H */ diff --git a/include/m_Do/m_Do_graphic.h b/include/m_Do/m_Do_graphic.h index e584fcf7b1..a00d62dbe8 100644 --- a/include/m_Do/m_Do_graphic.h +++ b/include/m_Do/m_Do_graphic.h @@ -69,6 +69,8 @@ public: }; static void entryBaseCsr(csr_c*); + static void releaseCsr(void); + static void entryCsr(csr_c*); #endif static void create(); diff --git a/include/m_Do/m_Do_lib.h b/include/m_Do/m_Do_lib.h index 31b5b5f700..bb4b1e6e2e 100644 --- a/include/m_Do/m_Do_lib.h +++ b/include/m_Do/m_Do_lib.h @@ -42,4 +42,8 @@ u32 mDoLib_setResTimgObj(ResTIMG const* res, GXTexObj* o_texObj, u32 tlut_name, GXTlutObj* o_tlutObj); void mDoLib_pos2camera(Vec* src, Vec* dst); +#if PLATFORM_WII +void mDoLib_2Dto3D(f32, f32, f32, Vec*); +#endif + #endif /* M_DO_M_DO_LIB_H */ diff --git a/src/d/d_cc_s.cpp b/src/d/d_cc_s.cpp index f7e275dea4..ccb8501542 100644 --- a/src/d/d_cc_s.cpp +++ b/src/d/d_cc_s.cpp @@ -536,6 +536,48 @@ bool dCcS::ChkCamera(cXyz& param_0, cXyz& param_1, f32 param_2, fopAc_ac_c* para return false; } +#if PLATFORM_WII +BOOL dCcS::ChkLine(cXyz& i_p_start, cXyz& i_p_end, f32 i_radius, fopAc_ac_c** o_actor) { + u16 obj_co_count = mObjCoCount; + if (obj_co_count == 0) { + return 0; + } + cCcD_Obj** max_obj_pp = &mpObjCo[mObjCoCount]; + cCcD_CpsAttr cps_attr; + cps_attr.Set(i_p_start, i_p_end, i_radius); + cps_attr.CalcAabBox(); + *o_actor = NULL; + f32 z_max = -FLT_MAX; + cCcD_DivideInfo sp18; + mDivideArea.CalcDivideInfoOverArea(&sp18, cps_attr.mAab); + cCcD_Obj** obj_pp = mpObjCo; + while (obj_pp < max_obj_pp) { + cCcD_Obj* obj_p = *obj_pp; + if (obj_p->GetObjCo().getSPrm() & 1) { + fopAc_ac_c* temp_r31 = dComIfGp_getPlayer(0); + if (obj_p->GetAc() != temp_r31 && (*obj_pp)->GetDivideInfo().Chk(sp18) != 0) { + f32 sp8; + if ((*obj_pp)->GetShapeAttr()->CrossCo(cps_attr, &sp8) != 0) { + fopAc_ac_c* actor = (*obj_pp)->GetAc(); + if (actor != NULL && + actor->attention_info.flags & (fopAc_AttnFlag_LOCK_e | fopAc_AttnFlag_BATTLE_e)) { + Vec spC; + PSMTXMultVec(dComIfGd_getViewMtx(), &actor->current.pos, &spC); + if (spC.z < 0.0f && spC.z > z_max) { + *o_actor = actor; + z_max = spC.z; + } + } + } + } + } + obj_pp++; + } + + return *o_actor != NULL; +} +#endif + bool dCcS::chkCameraPoint(cXyz const& param_0, cCcD_ShapeAttr::Shape* param_1, fopAc_ac_c* param_2, fopAc_ac_c* param_3) { if (mObjCoCount == 0) { diff --git a/src/d/d_cursor_mng.cpp b/src/d/d_cursor_mng.cpp index 8b39195217..223d01bffc 100644 --- a/src/d/d_cursor_mng.cpp +++ b/src/d/d_cursor_mng.cpp @@ -1,4 +1,389 @@ +#include "d/dolzel.h" // IWYU pragma: keep + #include "d/d_cursor_mng.h" +#include "d/d_com_inf_game.h" + +dCsr_mng_c* dCsr_mng_c::m_myObj; + // TODO: putting this here until a more appropriate place is found u8 data_8053a730; + +void dCsr_mng_c::update_(void) { + BOOL is_valid = FALSE; + + if (dComIfGs_getOptPointer()) { + mReCPd::enableDpd(0); + is_valid = mReCPd::chkDpdValid(NULL); + } else { + mReCPd::disableDpd(0); + } + + if (is_csr_on == 0) { + mDoGph_gInf_c::entryCsr(NULL); + node_c* cur_node = m_csr_list.m_root; + while (cur_node != NULL) { + cur_node->m_pointed_obj = 0; + cur_node = cur_node->m_next; + } + + return; + } + + mDoGph_gInf_c::releaseCsr(); + Vec2* pos = &mReCPd::getDpd2DPos(0); + int x = pos->x; + int y = pos->y; + + node_c* cur_node = m_csr_list.m_root; + mDoGph_gInf_c::csr_c* csr = NULL; + u16 last_mask = 1; + while (cur_node != NULL) { + cur_node->m_pointed_obj = NULL; + + u16 cur_mask = cur_node->m_mask; + if (!g_dComIfG_gameInfo.play.mItemInfo.mPauseFlag || (cur_node->m_mask & 0x200) == 0) { + if (csr == NULL) { + csr = cur_node->m_csr; + } + + if (is_valid && last_mask != 0) { + last_mask = cur_mask; + if (last_mask != 0) { + node_c* cur_node_2 = m_obj_list.m_root; + while (cur_node_2 != NULL) { + if ((cur_mask & cur_node_2->m_mask) != 0 && + ((bloObj_c*)cur_node_2)->isInside(x, y)) + { + cur_node->m_pointed_obj = cur_node_2; + } + + cur_node_2 = cur_node_2->m_next; + } + } + } + } + + cur_node = cur_node->m_next; + } + + if (!dComIfGs_getOptPointer()) { + if (csr != NULL) { + if (csr->isPointer()) { + csr = NULL; + } + } + } else if (csr == NULL) { + return; + } + + mDoGph_gInf_c::entryCsr(csr); +} + +void dCsr_mng_c::releaseCsr_(csr_c* i_csr) { + mDoGph_gInf_c::csr_c* temp_r5 = i_csr->m_csr; + i_csr->m_pointed_obj = 0; + if (temp_r5 != NULL && temp_r5 == mDoGph_gInf_c::m_csr) { + mDoGph_gInf_c::entryCsr(NULL); + } + m_csr_list.release(i_csr); +} + +void dCsr_mng_c::insideObjReleaseCheck_(void) { + node_c* cur_node = m_csr_list.m_root; + while (cur_node != NULL) { + if (!m_obj_list.isEntry(cur_node->m_pointed_obj)) { + cur_node->m_pointed_obj = NULL; + } + cur_node = cur_node->m_next; + } +} + +void dCsr_mng_c::create(void) { + dCsr_mng_c* mng = new dCsr_mng_c(); + m_myObj = mng; +} + +void dCsr_mng_c::update(void) { + m_myObj->update_(); +} + +void dCsr_mng_c::entryCsr(csr_c* i_csr) { + dCsr_mng_c* mng = m_myObj; + mng->m_csr_list.entry(i_csr); + mng->is_csr_on = true; +} + +void dCsr_mng_c::releaseCsr(csr_c* i_csr) { + m_myObj->releaseCsr_(i_csr); +} + +void dCsr_mng_c::entryObj(obj_c* i_obj) { + m_myObj->m_obj_list.entry(i_obj); +} + +void dCsr_mng_c::releaseObj(obj_c* i_obj) { + m_myObj->m_obj_list.release(i_obj); + m_myObj->insideObjReleaseCheck_(); +} + +void dCsr_mng_c::releaseObj(u16 param_0) { + m_myObj->m_obj_list.release(param_0); + m_myObj->insideObjReleaseCheck_(); +} + +void dCsr_mng_c::onCsr(void) { + m_myObj->is_csr_on = true; +} + +void dCsr_mng_c::offCsr(void) { + m_myObj->is_csr_on = false; +} + +BOOL dCsr_mng_c::node_c::set(u8 i_priority, u8 param_1, u16 i_mask) { + BOOL has_relatives = FALSE; + if (m_prev != NULL || m_next != NULL) { + has_relatives = TRUE; + } + if (has_relatives) { + return FALSE; + } + + m_priority = i_priority; + field_0x05 = param_1; + m_mask = i_mask; + + return TRUE; +} + +void dCsr_mng_c::list_c::entry(node_c* i_node) { + BOOL has_relatives = FALSE; + if (i_node->m_prev != NULL || i_node->m_next != NULL) { + has_relatives = TRUE; + } + if (has_relatives) { + return; + } + + node_c* cur_node = m_root; + if (cur_node == NULL) { + m_root = i_node; + return; + } + + while (i_node->m_priority > cur_node->m_priority) { + node_c* next = cur_node->m_next; + if (next == NULL) { + cur_node->m_next = i_node; + i_node->m_prev = cur_node; + i_node->m_next = NULL; + return; + } + cur_node = next; + } + + node_c* prev = cur_node->m_prev; + if (prev == NULL) { + m_root = i_node; + } else { + i_node->m_prev = prev; + prev->m_next = i_node; + } + i_node->m_next = cur_node; + cur_node->m_prev = i_node; +} + +dCsr_mng_c::node_c* dCsr_mng_c::list_c::release(node_c* i_node) { + node_c *next; + node_c *prev; + + if (!isEntry(i_node)) { + return NULL; + } + + prev = i_node->m_prev; + next = i_node->m_next; + if (prev != NULL) { + prev->m_next = next; + i_node->m_prev = NULL; + } else { + m_root = next; + } + + if (next != NULL) { + next->m_prev = prev; + i_node->m_next = NULL; + } + + return next; +} + +dCsr_mng_c::node_c* dCsr_mng_c::list_c::release(u16 i_mask) { + node_c* cur_node = m_root; + while (cur_node != NULL) { + if (cur_node->m_mask & i_mask) { + cur_node = release(cur_node); + } else { + cur_node = cur_node->m_next; + } + } +} + +BOOL dCsr_mng_c::list_c::isEntry(const node_c* i_node) const { + node_c* cur_node = m_root; + while (cur_node != NULL) { + if (cur_node == i_node) { + return TRUE; + } + cur_node = cur_node->m_next; + } + return FALSE; +} + +dCsr_mng_c::bloObj_c::~bloObj_c() { + if (m_panes != NULL) { + delete[] m_panes; + m_panes = NULL; + } + m_screen = NULL; +} + +BOOL dCsr_mng_c::bloObj_c::isInside(s16 i_x, s16 i_y) { + if (mReCPd::chkSwingBlock(0) == 0) { + paneObj_c* pane = m_panes; + for (u16 i = 0; i < m_pane_num; pane++, i++) { + if (pane->m_min_x <= i_x && i_x <= pane->m_max_x && + pane->m_min_y <= i_y && i_y <= pane->m_max_y) { + J2DPane* pane_handle = pane->m_handle; + m_pane_handle = pane_handle; + if (pane_handle->mAlpha != 0 && pane_handle->mVisible) { + return 1; + } + } + } + } + + m_pane_handle = NULL; + return 0; +} + +BOOL dCsr_mng_c::bloObj_c::create(J2DScreen* i_screen, u16 i_mask, u8 i_priority, u8 param_3) { + if (!((node_c*)this)->set(i_priority, param_3, i_mask)) { + return FALSE; + } + m_screen = i_screen; + m_pane_num = 0; + calcPaneObjNum(i_screen); + m_panes = new paneObj_c[m_pane_num]; + paneObj_c* sp08 = m_panes + m_pane_num; + createPaneObj(&sp08, m_screen); + return TRUE; +} + +void dCsr_mng_c::bloObj_c::calc(void) { + if (m_is_calc == 0) { + paneObj_c* pane_obj = m_panes; + u32 var_r30 = 0; + while ((u16)var_r30 < m_pane_num) { + J2DPane* pane = pane_obj->m_handle; + Vec sp20 = pane->getGlbVtx(0); + pane_obj->m_min_x = sp20.x; + pane_obj->m_min_y = sp20.y; + sp20 = pane->getGlbVtx(3); + var_r30++; + pane_obj->m_max_x = sp20.x; + pane_obj->m_max_y = sp20.y; + pane_obj++; + } + m_is_calc = 1; + } +} + +char* nullSkip(char* buf) { + char* cursor = buf; + while (*cursor == 0) { + cursor += 1; + } + return cursor; +} + +void dCsr_mng_c::bloObj_c::calcPaneObjNum(J2DPane* i_pane) { + u64 info_tag = i_pane->mInfoTag; + char* info_start = nullSkip((char*)&info_tag); + if (info_start[0] == 0x4E && info_start[1] == 0x5F) { + m_pane_num += 1; + } + + JSUTreeIterator iter = i_pane->getPaneTree()->getFirstChild(); + while (iter != NULL) { + calcPaneObjNum(*iter); + ++iter; + } +} + +void dCsr_mng_c::bloObj_c::createPaneObj(paneObj_c** i_panes, J2DPane* i_pane) { + u64 info_tag = i_pane->mInfoTag; + char* info_start = nullSkip((char*)&info_tag); + if (info_start[0] == 0x4E && info_start[1] == 0x5F) { + paneObj_c* pane = *i_panes; + *i_panes -= 1; + pane->m_handle = i_pane; + } + + JSUTreeIterator iter = i_pane->getPaneTree()->getFirstChild(); + while (iter != NULL) { + createPaneObj(i_panes, *iter); + ++iter; + } +} + +BOOL dCsr_mng_c::ccObj_c::isInside(s16 param_0, s16 param_1) { + if (dComIfGd_getView() == NULL) { + return 0; + } + + f32 x = (param_0 - mDoGph_gInf_c::getMinXF()) / mDoGph_gInf_c::getWidthF() * 2.0f - 1.0f; + f32 y = (param_1 - mDoGph_gInf_c::getMinYF()) / mDoGph_gInf_c::getHeightF() * 2.0f - 1.0f; + cXyz sp18; + mDoLib_2Dto3D(x, y, 1000.0f, &sp18); + cXyz sp0C; + PSMTXMultVec(dComIfGd_getInvViewMtx(), &cXyz::Zero, &sp0C); + dBgS_LinChk linChk; + linChk.Set(&sp0C, &sp18, NULL); + if (dComIfG_Bgsp().LineCross(&linChk)) { + sp18 = linChk.GetCross(); + } + + s32 actor_id; + fopAc_ac_c* actor_p = NULL; + dComIfG_Ccsp()->ChkLine(sp0C, sp18, 15.0f, &actor_p); + if (actor_p != NULL) { + actor_id = actor_p->base.base.id; + } else { + actor_id = fpcM_ERROR_PROCESS_ID_e; + } + m_actor_id = actor_id; + return actor_p != 0; +} + +void dCsr_mng_c::ccObj_c::set(u16 param_0, u8 param_1, u8 param_2) { + node_c::set(param_1, param_2, param_0); +} + +dCsr_mng_c::csr_c::~csr_c() { + if (m_csr == mDoGph_gInf_c::m_csr) { + mDoGph_gInf_c::releaseCsr(); + } +} + +BOOL dCsr_mng_c::csr_c::set(mDoGph_gInf_c::csr_c* i_csr, u16 param_1, u8 param_2, u8 param_3) { + if (!node_c::set(param_2, param_3, param_1)) { + return FALSE; + } + m_csr = i_csr; + return TRUE; +} + +dCsr_mng_c::ccObj_c::~ccObj_c() { + // empty function +} diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index 1708067ac4..08842cd792 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -670,6 +670,14 @@ void mDoGph_gInf_c::entryBaseCsr(mDoGph_gInf_c::csr_c* i_entry) { m_baseCsr = i_entry; m_csr = i_entry; } + +void mDoGph_gInf_c::entryCsr(mDoGph_gInf_c::csr_c* i_csr) { + m_csr = i_csr; +} + +void mDoGph_gInf_c::releaseCsr(void) { + m_csr = m_baseCsr; +} #endif void mDoGph_BlankingON() {} diff --git a/src/m_Do/m_Do_lib.cpp b/src/m_Do/m_Do_lib.cpp index 8876beb12d..292a10869a 100644 --- a/src/m_Do/m_Do_lib.cpp +++ b/src/m_Do/m_Do_lib.cpp @@ -118,6 +118,26 @@ void mDoLib_pos2camera(Vec* src, Vec* dst) { cMtx_multVec(dComIfGd_getView()->viewMtx, src, dst); } +#if PLATFORM_WII +void mDoLib_2Dto3D(f32 i_x, f32 i_y, f32 i_z, Vec* o_dst) { + if (dComIfGd_getView() == NULL) { + o_dst->x = 0.0f; + o_dst->y = 0.0f; + o_dst->z = 0.0f; + return; + } + + f32 fovy = dComIfGd_getView()->fovy; + f32 aspect = dComIfGd_getView()->aspect; + f32 temp_f3 = tan(DEG_TO_RAD(0.5f * fovy)); + Vec sp8; + sp8.x = (-i_x * i_z) * (temp_f3 * aspect); + sp8.y = (i_y * -i_z) * temp_f3; + sp8.z = -i_z; + PSMTXMultVec(dComIfGd_getInvViewMtx(), &sp8, o_dst); +} +#endif + static void dummy() { std::tan(0.0f); J3DAlphaComp* alphaComp = NULL;