From 601950c6e4295d1c62bcff186350bd5aea1e825a Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sat, 9 Aug 2025 19:53:56 +0200 Subject: [PATCH 01/10] Don't run --verify-obj during CI --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f42c3d0..f5f5296e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,7 +65,7 @@ jobs: run: python configure.py && ninja - name: Run progress script - run: python progress.py --verify-obj --verify-bin --progress-summary + run: python progress.py --verify-bin --progress-summary - name: Run DTK and objdiff to generate progress file for decomp.dev run: | From 81d90ec19f9a4d7c71ffead1ba8e595fb9a3bd1e Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 10 Aug 2025 14:31:04 +0200 Subject: [PATCH 02/10] Begin with `LytBase_c` --- include/game/bases/d_2d/multi.hpp | 2 +- include/game/bases/d_game_com.hpp | 7 +- include/game/bases/d_info.hpp | 2 +- include/game/bases/d_lytbase.hpp | 6 +- include/game/bases/d_message.hpp | 4 +- include/game/bases/d_tag_processor.hpp | 2 + include/game/mLib/m_2d/animation.hpp | 12 ++- include/lib/egg/core/eggMsgRes.h | 2 +- slices/wiimj2d.json | 9 ++ source/dol/bases/d_lytbase.cpp | 138 +++++++++++++++++++++++++ source/dol/bases/d_lyttextbox.cpp | 18 ++-- 11 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 source/dol/bases/d_lytbase.cpp diff --git a/include/game/bases/d_2d/multi.hpp b/include/game/bases/d_2d/multi.hpp index ac3aac37..580b9f2c 100644 --- a/include/game/bases/d_2d/multi.hpp +++ b/include/game/bases/d_2d/multi.hpp @@ -44,7 +44,7 @@ class Multi_c : public m2d::Base_c { nw4r::lyt::Picture *findPictureByName(const char *name); ///< Finds a picture pane by name. nw4r::lyt::Window *findWindowByName(const char *name); ///< Finds a window pane by name. -private: +protected: m2d::Layout_c mLayout; ///< The layout instance. nw4r::lyt::DrawInfo mDrawInfo; ///< The parameters for drawing the layout. diff --git a/include/game/bases/d_game_com.hpp b/include/game/bases/d_game_com.hpp index ddb4aba6..f48a5136 100644 --- a/include/game/bases/d_game_com.hpp +++ b/include/game/bases/d_game_com.hpp @@ -99,7 +99,10 @@ namespace dGameCom { bool checkRectangleOverlap(mVec3_c *, mVec3_c *, mVec3_c *, mVec3_c *, float); ///< @unofficial + void SelectCursorSetup(); void SelectCursorSetup(nw4r::lyt::Pane *pane, int index, bool useSpecialDraw); + + void WindowPaneColorSet(nw4r::lyt::Window *, int); float getDispCenterY(); void DispSizeScale(nw4r::math::VEC2 &scale); @@ -107,9 +110,7 @@ namespace dGameCom { void LayoutDispNumber(const int &value, const int &fillLeft, LytTextBox_c *textBox, bool fillWidth); bool isNowCourseClear(); - void SelectCursorSetup(); - void SelectCursorSetup(nw4r::lyt::Pane *, int, bool); - void WindowPaneColorSet(nw4r::lyt::Window *, int); void initGame(); + void AreaLanguageFolder(const char *, char *); } diff --git a/include/game/bases/d_info.hpp b/include/game/bases/d_info.hpp index c1f9b316..a539512e 100644 --- a/include/game/bases/d_info.hpp +++ b/include/game/bases/d_info.hpp @@ -69,8 +69,8 @@ class dInfo_c { int mDisplayCourseWorld; int mDisplayCourseNum; u8 pad6[0x14]; - int mTextBoxMessageID; int mTextBoxMessageGroup; + int mTextBoxMessageID; u8 pad7[0x1]; bool mExtensionAttached; u8 m_3da; diff --git a/include/game/bases/d_lytbase.hpp b/include/game/bases/d_lytbase.hpp index 46e33ab6..1e224a2b 100644 --- a/include/game/bases/d_lytbase.hpp +++ b/include/game/bases/d_lytbase.hpp @@ -9,10 +9,10 @@ class LytBase_c : public d2d::Multi_c { public: LytBase_c(); ~LytBase_c(); - virtual bool build(const char *, d2d::ResAccMult_c *); + virtual bool build(const char *name, d2d::ResAccMult_c *resAcc); - LytTextBox_c *findTextBox(const char *); - void allocStringBuffer(nw4r::lyt::Pane *); + LytTextBox_c *findTextBox(const char *name); + void allocStringBuffer(nw4r::lyt::Pane *pane); bool ReadResourceEx(const char *, int, bool); bool ReadResource(const char *, bool); diff --git a/include/game/bases/d_message.hpp b/include/game/bases/d_message.hpp index 2dba8711..f042f349 100644 --- a/include/game/bases/d_message.hpp +++ b/include/game/bases/d_message.hpp @@ -6,8 +6,8 @@ class MsgRes_c : public EGG::MsgRes { public: - u8 getFont(ulong messageID, ulong messageGroup); - u16 getScale(ulong messageID, ulong messageGroup); + u8 getFont(ulong messageGroup, ulong messageID); + u16 getScale(ulong messageGroup, ulong messageID); }; class dMessage_c { diff --git a/include/game/bases/d_tag_processor.hpp b/include/game/bases/d_tag_processor.hpp index 0691e1d4..5e9ca2d3 100644 --- a/include/game/bases/d_tag_processor.hpp +++ b/include/game/bases/d_tag_processor.hpp @@ -6,6 +6,8 @@ class TagProcessor_c : public nw4r::ut::WideTagProcessor { public: + TagProcessor_c(); + u8 mPad[0xc0]; u8 mFontIndex; diff --git a/include/game/mLib/m_2d/animation.hpp b/include/game/mLib/m_2d/animation.hpp index 15751c0c..46e2e5ea 100644 --- a/include/game/mLib/m_2d/animation.hpp +++ b/include/game/mLib/m_2d/animation.hpp @@ -16,7 +16,7 @@ struct GroupAnimTransform_s { class AnmResV2_c { public: - AnmResV2_c() {} + AnmResV2_c() : mGroupAnim(nullptr), mGroupNum(0) {} virtual ~AnmResV2_c() {} bool create(const char *name, m2d::ResAccIf_c *resAcc, m2d::Layout_c *layout, bool useOverride); @@ -39,6 +39,7 @@ class AnmGroupBase_c { }; AnmGroupBase_c() {} + AnmGroupBase_c(FrameCtrl_c *fc) : mpFrameCtrl(fc), mpAnmRes(nullptr), mpGroupAnim(nullptr), mFlags(0) {} bool create(AnmResV2_c *anmRes, const char *name); void setAnmEnable(bool enable); @@ -52,7 +53,16 @@ class AnmGroupBase_c { class AnmGroup_c : public AnmGroupBase_c { public: + AnmGroup_c() : AnmGroupBase_c(&mFrameCtrl) { + mFrameCtrl.mEndFrame = 1.0f; + mFrameCtrl.mCurrFrame = 1.0f; + mFrameCtrl.mPrevFrame = 1.0f; + mFrameCtrl.mRate = 0.0f; + } + void setAndUpdate(float frame) { mpFrameCtrl->setFrame(frame); updateFrame(); } + + FrameCtrl_c mFrameCtrl; }; } // namespace m2d diff --git a/include/lib/egg/core/eggMsgRes.h b/include/lib/egg/core/eggMsgRes.h index b7b93d94..5714b3e1 100644 --- a/include/lib/egg/core/eggMsgRes.h +++ b/include/lib/egg/core/eggMsgRes.h @@ -6,7 +6,7 @@ namespace EGG { class MsgRes { public: - wchar_t *getMsg(ulong messageID, ulong messageGroup); + wchar_t *getMsg(ulong messageGroup, ulong messageID); }; } // namespace EGG diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index e4f02a11..f7c0fe3b 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -287,6 +287,15 @@ ".sdata2": "0x1380-0x1388" } }, + { + "source": "dol/bases/d_lytbase.cpp", + "nonMatching": true, + "memoryRanges": { + ".text": "0xc2220-0xc33d0", + ".ctors": "0x11c-0x120", + ".rodata": "0x3338-0x33a0" + } + }, { "source": "dol/bases/d_lyttextbox.cpp", "memoryRanges": { diff --git a/source/dol/bases/d_lytbase.cpp b/source/dol/bases/d_lytbase.cpp new file mode 100644 index 00000000..c9726811 --- /dev/null +++ b/source/dol/bases/d_lytbase.cpp @@ -0,0 +1,138 @@ +#include "game/bases/d_game_com.hpp" +#include "game/bases/d_lyttextBox.hpp" +#include + +TagProcessor_c LytBase_c::s_TagPrc; + +LytBase_c::LytBase_c() { +} + +LytBase_c::~LytBase_c() {} + +bool LytBase_c::build(const char *name, d2d::ResAccMult_c *resAcc) { + bool res = d2d::Multi_c::build(name, resAcc); + if (res) { + allocStringBuffer(getRootPane()); + mLayout.SetTagProcessor(&s_TagPrc); + } + return res; +} + +LytTextBox_c *LytBase_c::findTextBox(const char *name) { + return (LytTextBox_c *) d2d::Multi_c::findTextBoxByName(name); +} + +void LytBase_c::allocStringBuffer(nw4r::lyt::Pane *pane) { + nw4r::lyt::TextBox *box = nw4r::ut::DynamicCast(pane); + if (box != nullptr) { + const wchar_t *buf = box->GetStringBuffer(); + box->AllocStringBuffer(0x1ff); + if (buf != nullptr) { + box->SetString(buf, 0); + } + } + for ( + nw4r::lyt::PaneList::Iterator it = pane->GetChildList().GetBeginIter(); + it != pane->GetChildList().GetEndIter(); + ++it + ) { + allocStringBuffer(&*it); + } +} + +bool LytBase_c::ReadResourceEx(const char *name, int i, bool isLocalized) { + char resourcePath[100]; + if (isLocalized) { + char nonLocalizedPath[100] = "Layout/"; + strncat(nonLocalizedPath, name, sizeof(nonLocalizedPath) - 1); + dGameCom::AreaLanguageFolder(nonLocalizedPath, resourcePath); + } else { + memset(resourcePath, 0, sizeof(resourcePath)); + strncat(resourcePath, "Layout/", sizeof(resourcePath) - 1); + strncat(resourcePath, name, sizeof(resourcePath) - 1); + } + if (!mResAccessorLoader.requestEx(resourcePath, i)) { + return false; + } + mpResAccessor = &mResAccessorLoader; + return true; +} + +bool LytBase_c::ReadResource(const char *name, bool isLocalized) { + return ReadResourceEx(name, 0, isLocalized); +} + +bool LytBase_c::ReadResource2(const char *name, int i) { + char resourcePath[100]; + memset(resourcePath, 0, sizeof(resourcePath)); + strncat(resourcePath, "EU/", sizeof(resourcePath) - 1); + strncat(resourcePath, "Layout/", sizeof(resourcePath) - 1); + strncat(resourcePath, name, sizeof(resourcePath) - 1); + if (!mResAccessorLoader.requestEx(resourcePath, 0)) { + return false; + } + mpResAccessor = &mResAccessorLoader; + return true; +} + +bool LytBase_c::ReadResource3(const char *name, int i) { + char resourcePath[100]; + memset(resourcePath, 0, sizeof(resourcePath)); + strncat(resourcePath, "EU/NedEU/Layout/", sizeof(resourcePath) - 1); + strncat(resourcePath, name, sizeof(resourcePath) - 1); + if (!mResAccessorLoader.requestEx(resourcePath, i)) { + return false; + } + mpResAccessor = &mResAccessorLoader; + return true; +} + +void LytBase_c::NPaneRegister(const char **paneNames, nw4r::lyt::Pane **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findPaneByName(paneNames[i]); + } +} + +void LytBase_c::WPaneRegister(const char **paneNames, nw4r::lyt::Window **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findWindowByName(paneNames[i]); + } +} + +void LytBase_c::PPaneRegister(const char **paneNames, nw4r::lyt::Picture **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findPictureByName(paneNames[i]); + } +} + +void LytBase_c::TPaneRegister(const char **paneNames, LytTextBox_c **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findTextBox(paneNames[i]); + } +} + +void LytBase_c::TPaneNameRegister(const char **textboxNames, const int *messageIDs, int messageGroup, int count) { + MsgRes_c *bmg = dMessage_c::getMesRes(); + for (int i = 0; i < count; i++) { + LytTextBox_c *box = findTextBox(textboxNames[i]); + box->setMessage(bmg, messageGroup, messageIDs[i], 0); + } +} + +void LytBase_c::AnimeResRegister(const char **animeNames, int count) { + d2d::ResAccMult_c *resAcc = mpResAccessor; + mpAnimRes = new m2d::AnmResV2_c[count]; + mAnimCount = count; + for (int i = 0; i < count; i++) { + mpAnimRes[i].create(animeNames[i], resAcc, &mLayout, true); + } +} + +void LytBase_c::GroupRegister(const char **groupNames, const int *animeIdxs, int count) { + mpAnimGroup = new m2d::AnmGroup_c[count]; + mpEnabledAnims = new bool[count]; + mGroupCount = count; + for (int i = 0; i < count; i++) { + mpAnimGroup[i].create(&mpAnimRes[animeIdxs[i]], groupNames[i]); + } +} diff --git a/source/dol/bases/d_lyttextbox.cpp b/source/dol/bases/d_lyttextbox.cpp index 45723eb2..71020691 100644 --- a/source/dol/bases/d_lyttextbox.cpp +++ b/source/dol/bases/d_lyttextbox.cpp @@ -4,14 +4,14 @@ #include #include -void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageID, ulong messageGroup, long placeholderCount, ...) { +void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageGroup, ulong messageID, long param, ...) { dInfo_c *info = dInfo_c::getInstance(); - info->mTextBoxMessageID = messageID; info->mTextBoxMessageGroup = messageGroup; + info->mTextBoxMessageID = messageID; va_list args; - va_start(args, placeholderCount); - setMessage(bmg, messageID, messageGroup, placeholderCount, &args); + va_start(args, param); + setMessage(bmg, messageGroup, messageID, param, &args); va_end(args); } @@ -23,10 +23,10 @@ void LytTextBox_c::ExtensionUserDataSetup() { } } -void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageID, ulong messageGroup, long placeholderCount, va_list *vargs) { +void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageGroup, ulong messageID, long param, va_list *vargs) { nw4r::lyt::Size fontSize = GetFontSize(); - u8 fontIndex = bmg->getFont(messageID, messageGroup); + u8 fontIndex = bmg->getFont(messageGroup, messageID); SetFont(dFontMng_c::getFont(fontIndex)); LytBase_c::s_TagPrc.mFontIndex = fontIndex; @@ -37,11 +37,11 @@ void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageID, ulong messageGroup if (extUserDataNum != 0) { ExtensionUserDataSetup(); } - info->mTextBoxMessageID = messageID; info->mTextBoxMessageGroup = messageGroup; - setText(bmg->getMsg(messageID, messageGroup), placeholderCount, vargs, bmg); + info->mTextBoxMessageID = messageID; + setText(bmg->getMsg(messageGroup, messageID), param, vargs, bmg); - float charWScale = bmg->getScale(messageID, messageGroup) * 0.01f; + float charWScale = bmg->getScale(messageGroup, messageID) * 0.01f; fontSize.width = GetFont()->GetWidth() * charWScale; SetFontSize(fontSize); From af6dda9600288adb91d46e0158a77748c616bd77 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 10 Aug 2025 19:05:33 +0200 Subject: [PATCH 03/10] `LytBase_c` almost matching - A few regswaps left in `LytBase_c::FUN_800c9770` --- include/game/bases/d_2d/multi.hpp | 22 +++- include/game/bases/d_lytbase.hpp | 42 +++---- include/game/mLib/m_2d/animation.hpp | 3 + include/game/mLib/m_vec.hpp | 5 + source/dol/bases/d_2d.cpp | 8 +- source/dol/bases/d_lytbase.cpp | 172 +++++++++++++++++++++++++-- 6 files changed, 215 insertions(+), 37 deletions(-) diff --git a/include/game/bases/d_2d/multi.hpp b/include/game/bases/d_2d/multi.hpp index 580b9f2c..ea9084e3 100644 --- a/include/game/bases/d_2d/multi.hpp +++ b/include/game/bases/d_2d/multi.hpp @@ -8,16 +8,28 @@ namespace d2d { /// @brief Stores clipping settings for a layout. /// @unofficial -struct ScissorMask { - ScissorMask &operator=(const ScissorMask &other) { +struct ClipSettings { + ClipSettings() {} + ClipSettings(const mVec2_c &pos, const mVec2_c &size) : mPos(pos), mSize(size) { + mEnabled = true; + } + void setPos(const mVec2_c &pos) { mPos = pos; } + void setSize(const mVec2_c &size) { mSize = size; } + void set(const mVec2_c &pos, const mVec2_c &size) { + mPos = pos; + mSize = size; + } + void enable() { mEnabled = true; } + + ClipSettings &operator=(const ClipSettings &other) { mPos = other.mPos; mSize = other.mSize; mEnabled = other.mEnabled; return *this; } - nw4r::math::VEC2 mPos; - nw4r::math::VEC2 mSize; + mVec2_c mPos; + mVec2_c mSize; bool mEnabled; }; @@ -52,7 +64,7 @@ class Multi_c : public m2d::Base_c { ResAccMult_c *mpResAccessor; ///< The resource accessor for the layout. mVec2_c mPos; ///< The position of the layout. - ScissorMask mScissorMask; ///< The scissor mask for the layout. + ClipSettings mClipSettings; ///< The clip settings for the layout. private: u32 mFlags; ///< The flags for the layout. diff --git a/include/game/bases/d_lytbase.hpp b/include/game/bases/d_lytbase.hpp index 1e224a2b..5ed0afe8 100644 --- a/include/game/bases/d_lytbase.hpp +++ b/include/game/bases/d_lytbase.hpp @@ -14,35 +14,38 @@ class LytBase_c : public d2d::Multi_c { LytTextBox_c *findTextBox(const char *name); void allocStringBuffer(nw4r::lyt::Pane *pane); - bool ReadResourceEx(const char *, int, bool); - bool ReadResource(const char *, bool); - bool ReadResource2(const char *, int); - bool ReadResource3(const char *, int); ///< @unofficial [Not in Shield version.] - - void NPaneRegister(const char **, nw4r::lyt::Pane **, int); - void WPaneRegister(const char **, nw4r::lyt::Window **, int); - void PPaneRegister(const char **, nw4r::lyt::Picture **, int); - void TPaneRegister(const char **, LytTextBox_c **, int); - void TPaneNameRegister(const char **, const int *, int, int); - void AnimeResRegister(const char **, int); - void GroupRegister(const char **, const int *, int); - - void AnimeStartBaseSetup(int); - void AnimeStartSetup(int, bool); - void LoopAnimeStartSetup(int); - void ReverseAnimeStartSetup(int, bool); - void AnimeEndSetup(int); + bool ReadResourceEx(const char *name, int i, bool isLocalized); + bool ReadResource(const char *name, bool isLocalized); + bool ReadResource2(const char *name, int i); + bool ReadResource3(const char *name, int i); ///< @unofficial [Not in Shield version]. + + void NPaneRegister(const char **paneNames, nw4r::lyt::Pane **panes, int count); + void WPaneRegister(const char **windowPaneNames, nw4r::lyt::Window **panes, int count); + void PPaneRegister(const char **picPaneNames, nw4r::lyt::Picture **panes, int count); + void TPaneRegister(const char **textboxNames, LytTextBox_c **panes, int count); + void TPaneNameRegister(const char **textboxNames, const int *messageIDs, int messageGroup, int count); + void AnimeResRegister(const char **animeNames, int count); + void GroupRegister(const char **groupNames, const int *animeIdxs, int count); + + void AnimeStartBaseSetup(int animeIdx); + void AnimeStartSetup(int animeIdx, bool b); + void LoopAnimeStartSetup(int animeIdx); + void ReverseAnimeStartSetup(int animeIdx, bool b); + void AnimeEndSetup(int animeIdx); void AllAnimeEndSetup(); void AnimePlay(); bool isAnime(int); bool isAllAnime(); - void FUN_800c9770(void *, float *); ///< @unofficial + void FUN_800c9770(const nw4r::lyt::Pane *, d2d::ClipSettings &); ///< @unofficial bool doDelete(); public: + m2d::AnmGroup_c &getAnmGroup(int index) const { return mpAnimGroup[index]; } + +private: d2d::ResAccMultLoader_c mResAccessorLoader; m2d::AnmResV2_c *mpAnimRes; @@ -50,7 +53,6 @@ class LytBase_c : public d2d::Multi_c { bool *mpEnabledAnims; int mAnimCount; - int mGroupCount; int mLastStartedAnimNum; diff --git a/include/game/mLib/m_2d/animation.hpp b/include/game/mLib/m_2d/animation.hpp index 46e2e5ea..3d4cec14 100644 --- a/include/game/mLib/m_2d/animation.hpp +++ b/include/game/mLib/m_2d/animation.hpp @@ -60,6 +60,9 @@ class AnmGroup_c : public AnmGroupBase_c { mFrameCtrl.mRate = 0.0f; } + void play() { mpFrameCtrl->play(); updateFrame(); } + void setStart() { mpFrameCtrl->setFrame(1.0f); updateFrame(); } + void setEnd() { mpFrameCtrl->setFrame(mpFrameCtrl->getLastActiveFrame()); updateFrame(); } void setAndUpdate(float frame) { mpFrameCtrl->setFrame(frame); updateFrame(); } FrameCtrl_c mFrameCtrl; diff --git a/include/game/mLib/m_vec.hpp b/include/game/mLib/m_vec.hpp index b62a374e..1c8a914a 100644 --- a/include/game/mLib/m_vec.hpp +++ b/include/game/mLib/m_vec.hpp @@ -29,6 +29,7 @@ class mVec2_c : public EGG::Vector2f { /// @brief Copy constructor. mVec2_c(const mVec2_c &v) { set(v.x, v.y); } + mVec2_c(const nw4r::math::VEC2 &v) { set(v.x, v.y); } void set(float x, float y) { this->x = x; @@ -101,6 +102,10 @@ class mVec2_c : public EGG::Vector2f { bool operator!=(const mVec2_c &v) const { return x != v.x || y != v.y; } }; +inline mVec2_c operator*(float f, const mVec2_c &v) { + return mVec2_c(f * v.x, f * v.y); +} + /// @brief A three-dimensional floating point vector. /// @ingroup mlib /// @todo Add EGG::vector3f operators. diff --git a/source/dol/bases/d_2d.cpp b/source/dol/bases/d_2d.cpp index e525e729..90eb0581 100644 --- a/source/dol/bases/d_2d.cpp +++ b/source/dol/bases/d_2d.cpp @@ -113,7 +113,7 @@ d2d::Multi_c::Multi_c() { mDrawInfo.SetLocationAdjustScale(mVec2_c(19.0f / 26.0f, 1.0f)); mDrawInfo.SetLocationAdjust(true); } - mScissorMask.mEnabled = false; + mClipSettings.mEnabled = false; } d2d::Multi_c::~Multi_c() {} @@ -161,12 +161,12 @@ void d2d::Multi_c::draw() { screen.mScale = nw4r::math::VEC3(w_4_3 / w_16_9, 1.0f, 1.0f); } screen.SetProjectionGX(); - if (mScissorMask.mEnabled) { + if (mClipSettings.mEnabled) { u32 x, y, w, h; GXGetScissor(&x, &y, &w, &h); GXSetScissor( - mScissorMask.mPos.x, mScissorMask.mPos.y, - mScissorMask.mSize.x, mScissorMask.mSize.y + mClipSettings.mPos.x, mClipSettings.mPos.y, + mClipSettings.mSize.x, mClipSettings.mSize.y ); mLayout.Draw(mDrawInfo); GXSetScissor(x, y, w, h); diff --git a/source/dol/bases/d_lytbase.cpp b/source/dol/bases/d_lytbase.cpp index c9726811..97bc8a30 100644 --- a/source/dol/bases/d_lytbase.cpp +++ b/source/dol/bases/d_lytbase.cpp @@ -1,10 +1,13 @@ -#include "game/bases/d_game_com.hpp" -#include "game/bases/d_lyttextBox.hpp" #include +#include +#include +#include TagProcessor_c LytBase_c::s_TagPrc; LytBase_c::LytBase_c() { + mAnimCount = 0; + mGroupCount = 0; } LytBase_c::~LytBase_c() {} @@ -93,21 +96,21 @@ void LytBase_c::NPaneRegister(const char **paneNames, nw4r::lyt::Pane **panes, i } } -void LytBase_c::WPaneRegister(const char **paneNames, nw4r::lyt::Window **panes, int count) { +void LytBase_c::WPaneRegister(const char **windowPaneNames, nw4r::lyt::Window **panes, int count) { for (int i = 0; i < count; i++) { - panes[i] = findWindowByName(paneNames[i]); + panes[i] = findWindowByName(windowPaneNames[i]); } } -void LytBase_c::PPaneRegister(const char **paneNames, nw4r::lyt::Picture **panes, int count) { +void LytBase_c::PPaneRegister(const char **picPaneNames, nw4r::lyt::Picture **panes, int count) { for (int i = 0; i < count; i++) { - panes[i] = findPictureByName(paneNames[i]); + panes[i] = findPictureByName(picPaneNames[i]); } } -void LytBase_c::TPaneRegister(const char **paneNames, LytTextBox_c **panes, int count) { +void LytBase_c::TPaneRegister(const char **textboxNames, LytTextBox_c **panes, int count) { for (int i = 0; i < count; i++) { - panes[i] = findTextBox(paneNames[i]); + panes[i] = findTextBox(textboxNames[i]); } } @@ -136,3 +139,156 @@ void LytBase_c::GroupRegister(const char **groupNames, const int *animeIdxs, int mpAnimGroup[i].create(&mpAnimRes[animeIdxs[i]], groupNames[i]); } } + +void LytBase_c::AnimeStartBaseSetup(int animeIdx) { + mpAnimGroup[animeIdx].setAnmEnable(true); + m2d::AnmGroup_c &animeGroup = mpAnimGroup[animeIdx]; + animeGroup.mpFrameCtrl->setFrame(0.0f); + animeGroup.updateFrame(); + mpEnabledAnims[animeIdx] = true; + mLastStartedAnimNum = animeIdx; +} + +void LytBase_c::AnimeStartSetup(int animeIdx, bool b) { + AnimeStartBaseSetup(animeIdx); + if (b) { + mpAnimGroup[animeIdx].setEnd(); + } + mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 1; +} + +void LytBase_c::LoopAnimeStartSetup(int animeIdx) { + AnimeStartBaseSetup(animeIdx); + mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 0; +} + +void LytBase_c::ReverseAnimeStartSetup(int animeIdx, bool b) { + AnimeStartBaseSetup(animeIdx); + if (b) { + mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 1; + mpAnimGroup[animeIdx].setEnd(); + } else { + mpAnimGroup[animeIdx].setStart(); + } + mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 3; +} + +void LytBase_c::AnimeEndSetup(int animeIdx) { + if (mpEnabledAnims[animeIdx]) { + mpAnimGroup[animeIdx].setAnmEnable(false); + mpEnabledAnims[animeIdx] = false; + } +} + +void LytBase_c::AllAnimeEndSetup() { + for (int i = 0; i < mGroupCount; i++) { + AnimeEndSetup(i); + } + mLastStartedAnimNum = mGroupCount; +} + +void LytBase_c::AnimePlay() { + for (int i = 0; i < mGroupCount; i++) { + if (mpEnabledAnims[i]) { + if (mpAnimGroup[i].mpFrameCtrl->isStop()) { + AnimeEndSetup(i); + } else { + mpAnimGroup[i].play(); + } + } + } +} + +bool LytBase_c::isAnime(int animeIdx) { + if (animeIdx < 0) { + return mpEnabledAnims[mLastStartedAnimNum]; + } + return mpEnabledAnims[animeIdx]; +} + +bool LytBase_c::isAllAnime() { + for (int i = 0; i < mGroupCount; i++) { + if (mpEnabledAnims[i]) { + return true; + } + } + return false; +} + +void LytBase_c::FUN_800c9770(const nw4r::lyt::Pane *pane, d2d::ClipSettings &clipData) { + nw4r::ut::Rect view = mDrawInfo.GetViewRect(); + mVec2_c paneScale; + mVec2_c pos; + mVec2_c clipSize; + mVec2_c scale = mDrawInfo.GetLocationAdjustScale(); + + float actualScaleY = scale.y; + if (actualScaleY <= 1e-6f) { + actualScaleY = 1e-6f; + } + float height = view.GetHeight() / actualScaleY; + + float actualScaleX = scale.x; + if (actualScaleX <= 1e-6f) { + actualScaleX = 1e-6f; + } + float width = view.GetWidth() / actualScaleX; + + if (width < 0.0f) { + width *= -1.0f; + } + if (height < 0.0f) { + height *= -1.0f; + } + + nw4r::math::MTX34 mtx = pane->GetGlobalMtx(); + + paneScale.x = pane->GetSize().width; + paneScale.y = pane->GetSize().height; + + float tmpx = mtx._03 / actualScaleX; + float tmpy = mtx._13 * -1.0f; + + float scaledW = mVideo::m_video->mRenderModeObj.fbWidth / width; + float scaledH = mVideo::m_video->mRenderModeObj.efbHeight / height; + + float scX = paneScale.x * scaledW; + float scY = paneScale.y * scaledH; + + scX = mtx._11 * scX; + scY = mtx._11 * scY; + + tmpx *= scaledW; + tmpy *= scaledH; + + u32 x, y, w, h; + GXGetScissor(&x, &y, &w, &h); + pos.x = x + w * 0.5f + (tmpx - scX * 0.5f); + pos.y = y + h * 0.5f + (tmpy - scY * 0.5f); + clipSize.x = scX + 0.5f; + clipSize.y = scY + 0.5f; + clipData.setSize(clipSize); + clipData.setPos(pos); + clipData.mEnabled = true; +} + +bool LytBase_c::doDelete() { + if (mAnimCount != 0) { + for (int i = 0; i < mAnimCount; i++) { + if (!mpAnimRes[i].remove()) { + return false; + } + } + delete[] mpAnimRes; + mAnimCount = 0; + } + if (mGroupCount != 0) { + delete[] mpAnimGroup; + delete[] mpEnabledAnims; + mGroupCount = 0; + } + if (!mResAccessorLoader.remove()) { + return false; + } + return true; +} From 4a6c1a8bd45e7b645add02cfd218ba8b7d9b1848 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 10 Aug 2025 23:23:41 +0200 Subject: [PATCH 04/10] `LytBase_c::FUN_800c9770` 99.10% matching --- include/game/mLib/m_video.hpp | 3 +++ source/dol/bases/d_lytbase.cpp | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/game/mLib/m_video.hpp b/include/game/mLib/m_video.hpp index 36b518c0..611a842e 100644 --- a/include/game/mLib/m_video.hpp +++ b/include/game/mLib/m_video.hpp @@ -5,6 +5,9 @@ class mVideo { public: static void create(); + float getScaledWidth(float scale) const { return mRenderModeObj.fbWidth / scale; } + float getScaledHeight(float scale) const { return mRenderModeObj.efbHeight / scale; } + static float getSmth(float offs) { return (m_video->mRenderModeObj.efbHeight - offs) * 0.5f; } GXRenderModeObj &mRenderModeObj; diff --git a/source/dol/bases/d_lytbase.cpp b/source/dol/bases/d_lytbase.cpp index 97bc8a30..3a755462 100644 --- a/source/dol/bases/d_lytbase.cpp +++ b/source/dol/bases/d_lytbase.cpp @@ -249,24 +249,24 @@ void LytBase_c::FUN_800c9770(const nw4r::lyt::Pane *pane, d2d::ClipSettings &cli float tmpx = mtx._03 / actualScaleX; float tmpy = mtx._13 * -1.0f; - float scaledW = mVideo::m_video->mRenderModeObj.fbWidth / width; - float scaledH = mVideo::m_video->mRenderModeObj.efbHeight / height; + float sx = mVideo::m_video->getScaledWidth(width); + float sy = mVideo::m_video->getScaledHeight(height); - float scX = paneScale.x * scaledW; - float scY = paneScale.y * scaledH; + float scX = paneScale.x * sx; + float scY = paneScale.y * sy; - scX = mtx._11 * scX; - scY = mtx._11 * scY; + float scX2 = mtx._11 * scX; + float scY2 = mtx._11 * scY; - tmpx *= scaledW; - tmpy *= scaledH; + tmpx *= sx; + tmpy *= sy; u32 x, y, w, h; GXGetScissor(&x, &y, &w, &h); - pos.x = x + w * 0.5f + (tmpx - scX * 0.5f); - pos.y = y + h * 0.5f + (tmpy - scY * 0.5f); - clipSize.x = scX + 0.5f; - clipSize.y = scY + 0.5f; + pos.x = x + w * 0.5f + (tmpx - scX2 * 0.5f); + pos.y = y + h * 0.5f + (tmpy - scY2 * 0.5f); + clipSize.x = scX2 + 0.5f; + clipSize.y = scY2 + 0.5f; clipData.setSize(clipSize); clipData.setPos(pos); clipData.mEnabled = true; From 3ffac666fe18296736db637f0e6a76e72f6ad41b Mon Sep 17 00:00:00 2001 From: RootCubed Date: Mon, 13 Apr 2026 18:05:13 +0200 Subject: [PATCH 05/10] `LytBase_c` matching --- include/game/mLib/m_video.hpp | 4 ++-- source/dol/bases/d_lytbase.cpp | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/include/game/mLib/m_video.hpp b/include/game/mLib/m_video.hpp index 611a842e..9fbd8319 100644 --- a/include/game/mLib/m_video.hpp +++ b/include/game/mLib/m_video.hpp @@ -5,8 +5,8 @@ class mVideo { public: static void create(); - float getScaledWidth(float scale) const { return mRenderModeObj.fbWidth / scale; } - float getScaledHeight(float scale) const { return mRenderModeObj.efbHeight / scale; } + float getWidth() const { return mRenderModeObj.fbWidth; } + float getHeight() const { return mRenderModeObj.efbHeight; } static float getSmth(float offs) { return (m_video->mRenderModeObj.efbHeight - offs) * 0.5f; } diff --git a/source/dol/bases/d_lytbase.cpp b/source/dol/bases/d_lytbase.cpp index 3a755462..e8502915 100644 --- a/source/dol/bases/d_lytbase.cpp +++ b/source/dol/bases/d_lytbase.cpp @@ -246,17 +246,14 @@ void LytBase_c::FUN_800c9770(const nw4r::lyt::Pane *pane, d2d::ClipSettings &cli paneScale.x = pane->GetSize().width; paneScale.y = pane->GetSize().height; - float tmpx = mtx._03 / actualScaleX; - float tmpy = mtx._13 * -1.0f; - - float sx = mVideo::m_video->getScaledWidth(width); - float sy = mVideo::m_video->getScaledHeight(height); + float sx = mVideo::m_video->getWidth() / width; + float sy = mVideo::m_video->getHeight() / height; - float scX = paneScale.x * sx; - float scY = paneScale.y * sy; + float scX2 = mtx._11 * (paneScale.x * sx); + float scY2 = mtx._11 * (paneScale.y * sy); - float scX2 = mtx._11 * scX; - float scY2 = mtx._11 * scY; + float tmpx = mtx._03 / actualScaleX; + float tmpy = mtx._13 * -1.0f; tmpx *= sx; tmpy *= sy; From c40dadc781c8e4ab6bd186c4c73fe65f37b9f4d9 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Mon, 13 Apr 2026 19:25:24 +0200 Subject: [PATCH 06/10] Fully match and link `LytBase_c` --- include/game/bases/d_2d/multi.hpp | 10 +-- include/game/bases/d_lytbase.hpp | 6 +- include/game/bases/d_tag_processor.hpp | 1 + include/game/mLib/m_2d/animation.hpp | 11 ++-- include/game/mLib/m_2d/frame_ctrl.hpp | 6 +- include/game/mLib/m_mtx.hpp | 3 + slices/wiimj2d.json | 7 +- source/dol/bases/d_2d.cpp | 8 +-- source/dol/bases/d_lytbase.cpp | 88 ++++++++++++++------------ source/dol/bases/d_s_boot.cpp | 6 +- source/dol/mLib/m_2d.cpp | 6 +- syms.txt | 4 ++ 12 files changed, 89 insertions(+), 67 deletions(-) diff --git a/include/game/bases/d_2d/multi.hpp b/include/game/bases/d_2d/multi.hpp index ea9084e3..5424020d 100644 --- a/include/game/bases/d_2d/multi.hpp +++ b/include/game/bases/d_2d/multi.hpp @@ -8,9 +8,9 @@ namespace d2d { /// @brief Stores clipping settings for a layout. /// @unofficial -struct ClipSettings { - ClipSettings() {} - ClipSettings(const mVec2_c &pos, const mVec2_c &size) : mPos(pos), mSize(size) { +struct ScissorMask { + ScissorMask() {} + ScissorMask(const mVec2_c &pos, const mVec2_c &size) : mPos(pos), mSize(size) { mEnabled = true; } void setPos(const mVec2_c &pos) { mPos = pos; } @@ -21,7 +21,7 @@ struct ClipSettings { } void enable() { mEnabled = true; } - ClipSettings &operator=(const ClipSettings &other) { + ScissorMask &operator=(const ScissorMask &other) { mPos = other.mPos; mSize = other.mSize; mEnabled = other.mEnabled; @@ -64,7 +64,7 @@ class Multi_c : public m2d::Base_c { ResAccMult_c *mpResAccessor; ///< The resource accessor for the layout. mVec2_c mPos; ///< The position of the layout. - ClipSettings mClipSettings; ///< The clip settings for the layout. + ScissorMask mScissorMask; ///< The scissor mask for the layout. private: u32 mFlags; ///< The flags for the layout. diff --git a/include/game/bases/d_lytbase.hpp b/include/game/bases/d_lytbase.hpp index 5ed0afe8..8fc9769b 100644 --- a/include/game/bases/d_lytbase.hpp +++ b/include/game/bases/d_lytbase.hpp @@ -28,9 +28,9 @@ class LytBase_c : public d2d::Multi_c { void GroupRegister(const char **groupNames, const int *animeIdxs, int count); void AnimeStartBaseSetup(int animeIdx); - void AnimeStartSetup(int animeIdx, bool b); + void AnimeStartSetup(int animeIdx, bool startAtEnd); void LoopAnimeStartSetup(int animeIdx); - void ReverseAnimeStartSetup(int animeIdx, bool b); + void ReverseAnimeStartSetup(int animeIdx, bool startAtEnd); void AnimeEndSetup(int animeIdx); void AllAnimeEndSetup(); @@ -38,7 +38,7 @@ class LytBase_c : public d2d::Multi_c { bool isAnime(int); bool isAllAnime(); - void FUN_800c9770(const nw4r::lyt::Pane *, d2d::ClipSettings &); ///< @unofficial + void SetScissorMask(const nw4r::lyt::Pane *pane, d2d::ScissorMask &scissorMask); ///< @unofficial bool doDelete(); diff --git a/include/game/bases/d_tag_processor.hpp b/include/game/bases/d_tag_processor.hpp index 5e9ca2d3..7eb8a678 100644 --- a/include/game/bases/d_tag_processor.hpp +++ b/include/game/bases/d_tag_processor.hpp @@ -7,6 +7,7 @@ class TagProcessor_c : public nw4r::ut::WideTagProcessor { public: TagProcessor_c(); + ~TagProcessor_c(); u8 mPad[0xc0]; u8 mFontIndex; diff --git a/include/game/mLib/m_2d/animation.hpp b/include/game/mLib/m_2d/animation.hpp index 3d4cec14..0b3a1bf5 100644 --- a/include/game/mLib/m_2d/animation.hpp +++ b/include/game/mLib/m_2d/animation.hpp @@ -54,15 +54,16 @@ class AnmGroupBase_c { class AnmGroup_c : public AnmGroupBase_c { public: AnmGroup_c() : AnmGroupBase_c(&mFrameCtrl) { - mFrameCtrl.mEndFrame = 1.0f; - mFrameCtrl.mCurrFrame = 1.0f; - mFrameCtrl.mPrevFrame = 1.0f; - mFrameCtrl.mRate = 0.0f; + mFrameCtrl.mEndFrame = 0.0f; + mFrameCtrl.mCurrFrame = 0.0f; + mFrameCtrl.mPrevFrame = 0.0f; + mFrameCtrl.mRate = 1.0f; } void play() { mpFrameCtrl->play(); updateFrame(); } void setStart() { mpFrameCtrl->setFrame(1.0f); updateFrame(); } - void setEnd() { mpFrameCtrl->setFrame(mpFrameCtrl->getLastActiveFrame()); updateFrame(); } + void setLast() { mpFrameCtrl->setFrame(mpFrameCtrl->getLastActiveFrame()); updateFrame(); } + void setEnd() { mpFrameCtrl->setFrame(mpFrameCtrl->getLastFrame()); updateFrame(); } void setAndUpdate(float frame) { mpFrameCtrl->setFrame(frame); updateFrame(); } FrameCtrl_c mFrameCtrl; diff --git a/include/game/mLib/m_2d/frame_ctrl.hpp b/include/game/mLib/m_2d/frame_ctrl.hpp index 0c0f7cb6..a24321b3 100644 --- a/include/game/mLib/m_2d/frame_ctrl.hpp +++ b/include/game/mLib/m_2d/frame_ctrl.hpp @@ -19,8 +19,12 @@ class FrameCtrl_c { void setRate(float rate); bool isStop() const; + void setFlags(bool loop, bool reverse) { + mFlags = (!loop ? FrameCtrl_c::NO_LOOP : 0) | (reverse ? FrameCtrl_c::REVERSE : 0); + } float getFrame() const { return mCurrFrame; } - float getLastActiveFrame() const { return mEndFrame - 1.0f; } + float getLastFrame() const { return mEndFrame - 1.0f; } + float getLastActiveFrame() const { return mEndFrame - 2.0f; } float mEndFrame; float mCurrFrame; diff --git a/include/game/mLib/m_mtx.hpp b/include/game/mLib/m_mtx.hpp index cb701ca8..46a88a86 100644 --- a/include/game/mLib/m_mtx.hpp +++ b/include/game/mLib/m_mtx.hpp @@ -11,6 +11,9 @@ class mMtx_c : public nw4r::math::MTX34 { /// @brief Constructs an empty matrix. mMtx_c() {} + /// @brief Constructs a matrix from an MTX34. + mMtx_c(const nw4r::math::MTX34 &mtx) : MTX34(mtx) {} + /// @brief Constructs a matrix with the given components. mMtx_c(float _00, float _01, float _02, float _03, float _10, float _11, float _12, float _13, float _20, float _21, float _22, float _23); diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index f7c0fe3b..f9ce7c8e 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -289,11 +289,14 @@ }, { "source": "dol/bases/d_lytbase.cpp", - "nonMatching": true, "memoryRanges": { ".text": "0xc2220-0xc33d0", ".ctors": "0x11c-0x120", - ".rodata": "0x3338-0x33a0" + ".rodata": "0x3338-0x33a0", + ".data": "0x19098-0x190e0", + ".sdata": "0x588-0x598", + ".bss": "0x7de0-0x7eb8", + ".sdata2": "0x1878-0x1898" } }, { diff --git a/source/dol/bases/d_2d.cpp b/source/dol/bases/d_2d.cpp index 90eb0581..e525e729 100644 --- a/source/dol/bases/d_2d.cpp +++ b/source/dol/bases/d_2d.cpp @@ -113,7 +113,7 @@ d2d::Multi_c::Multi_c() { mDrawInfo.SetLocationAdjustScale(mVec2_c(19.0f / 26.0f, 1.0f)); mDrawInfo.SetLocationAdjust(true); } - mClipSettings.mEnabled = false; + mScissorMask.mEnabled = false; } d2d::Multi_c::~Multi_c() {} @@ -161,12 +161,12 @@ void d2d::Multi_c::draw() { screen.mScale = nw4r::math::VEC3(w_4_3 / w_16_9, 1.0f, 1.0f); } screen.SetProjectionGX(); - if (mClipSettings.mEnabled) { + if (mScissorMask.mEnabled) { u32 x, y, w, h; GXGetScissor(&x, &y, &w, &h); GXSetScissor( - mClipSettings.mPos.x, mClipSettings.mPos.y, - mClipSettings.mSize.x, mClipSettings.mSize.y + mScissorMask.mPos.x, mScissorMask.mPos.y, + mScissorMask.mSize.x, mScissorMask.mSize.y ); mLayout.Draw(mDrawInfo); GXSetScissor(x, y, w, h); diff --git a/source/dol/bases/d_lytbase.cpp b/source/dol/bases/d_lytbase.cpp index e8502915..5e79e351 100644 --- a/source/dol/bases/d_lytbase.cpp +++ b/source/dol/bases/d_lytbase.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include TagProcessor_c LytBase_c::s_TagPrc; @@ -37,7 +38,7 @@ void LytBase_c::allocStringBuffer(nw4r::lyt::Pane *pane) { for ( nw4r::lyt::PaneList::Iterator it = pane->GetChildList().GetBeginIter(); it != pane->GetChildList().GetEndIter(); - ++it + it++ ) { allocStringBuffer(&*it); } @@ -47,16 +48,17 @@ bool LytBase_c::ReadResourceEx(const char *name, int i, bool isLocalized) { char resourcePath[100]; if (isLocalized) { char nonLocalizedPath[100] = "Layout/"; - strncat(nonLocalizedPath, name, sizeof(nonLocalizedPath) - 1); + strncat(nonLocalizedPath, name, ARRAY_MAX_STRLEN(nonLocalizedPath)); dGameCom::AreaLanguageFolder(nonLocalizedPath, resourcePath); } else { memset(resourcePath, 0, sizeof(resourcePath)); - strncat(resourcePath, "Layout/", sizeof(resourcePath) - 1); - strncat(resourcePath, name, sizeof(resourcePath) - 1); + strncat(resourcePath, "Layout/", ARRAY_MAX_STRLEN(resourcePath)); + strncat(resourcePath, name, ARRAY_MAX_STRLEN(resourcePath)); } if (!mResAccessorLoader.requestEx(resourcePath, i)) { return false; } + mpResAccessor = &mResAccessorLoader; return true; } @@ -68,9 +70,9 @@ bool LytBase_c::ReadResource(const char *name, bool isLocalized) { bool LytBase_c::ReadResource2(const char *name, int i) { char resourcePath[100]; memset(resourcePath, 0, sizeof(resourcePath)); - strncat(resourcePath, "EU/", sizeof(resourcePath) - 1); - strncat(resourcePath, "Layout/", sizeof(resourcePath) - 1); - strncat(resourcePath, name, sizeof(resourcePath) - 1); + strncat(resourcePath, "EU/", ARRAY_MAX_STRLEN(resourcePath)); + strncat(resourcePath, "Layout/", ARRAY_MAX_STRLEN(resourcePath)); + strncat(resourcePath, name, ARRAY_MAX_STRLEN(resourcePath)); if (!mResAccessorLoader.requestEx(resourcePath, 0)) { return false; } @@ -81,8 +83,8 @@ bool LytBase_c::ReadResource2(const char *name, int i) { bool LytBase_c::ReadResource3(const char *name, int i) { char resourcePath[100]; memset(resourcePath, 0, sizeof(resourcePath)); - strncat(resourcePath, "EU/NedEU/Layout/", sizeof(resourcePath) - 1); - strncat(resourcePath, name, sizeof(resourcePath) - 1); + strncat(resourcePath, "EU/NedEU/Layout/", ARRAY_MAX_STRLEN(resourcePath)); + strncat(resourcePath, name, ARRAY_MAX_STRLEN(resourcePath)); if (!mResAccessorLoader.requestEx(resourcePath, i)) { return false; } @@ -141,6 +143,7 @@ void LytBase_c::GroupRegister(const char **groupNames, const int *animeIdxs, int } void LytBase_c::AnimeStartBaseSetup(int animeIdx) { + float dummy_float = 0.5f; // [For .sdata2 ordering] mpAnimGroup[animeIdx].setAnmEnable(true); m2d::AnmGroup_c &animeGroup = mpAnimGroup[animeIdx]; animeGroup.mpFrameCtrl->setFrame(0.0f); @@ -149,28 +152,28 @@ void LytBase_c::AnimeStartBaseSetup(int animeIdx) { mLastStartedAnimNum = animeIdx; } -void LytBase_c::AnimeStartSetup(int animeIdx, bool b) { +void LytBase_c::AnimeStartSetup(int animeIdx, bool startAtEnd) { AnimeStartBaseSetup(animeIdx); - if (b) { - mpAnimGroup[animeIdx].setEnd(); + if (startAtEnd) { + mpAnimGroup[animeIdx].setLast(); } - mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 1; + mpAnimGroup[animeIdx].mpFrameCtrl->setFlags(false, false); } void LytBase_c::LoopAnimeStartSetup(int animeIdx) { AnimeStartBaseSetup(animeIdx); - mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 0; + mpAnimGroup[animeIdx].mpFrameCtrl->setFlags(true, false); } -void LytBase_c::ReverseAnimeStartSetup(int animeIdx, bool b) { +void LytBase_c::ReverseAnimeStartSetup(int animeIdx, bool startAtEnd) { AnimeStartBaseSetup(animeIdx); - if (b) { - mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 1; + if (startAtEnd) { + mpAnimGroup[animeIdx].mpFrameCtrl->setFlags(false, false); mpAnimGroup[animeIdx].setEnd(); } else { mpAnimGroup[animeIdx].setStart(); } - mpAnimGroup[animeIdx].mpFrameCtrl->mFlags = 3; + mpAnimGroup[animeIdx].mpFrameCtrl->setFlags(false, true); } void LytBase_c::AnimeEndSetup(int animeIdx) { @@ -215,11 +218,11 @@ bool LytBase_c::isAllAnime() { return false; } -void LytBase_c::FUN_800c9770(const nw4r::lyt::Pane *pane, d2d::ClipSettings &clipData) { +void LytBase_c::SetScissorMask(const nw4r::lyt::Pane *pane, d2d::ScissorMask &scissorMask) { nw4r::ut::Rect view = mDrawInfo.GetViewRect(); - mVec2_c paneScale; + mVec2_c paneSize; mVec2_c pos; - mVec2_c clipSize; + mVec2_c scissorSize; mVec2_c scale = mDrawInfo.GetLocationAdjustScale(); float actualScaleY = scale.y; @@ -241,32 +244,32 @@ void LytBase_c::FUN_800c9770(const nw4r::lyt::Pane *pane, d2d::ClipSettings &cli height *= -1.0f; } - nw4r::math::MTX34 mtx = pane->GetGlobalMtx(); + mMtx_c mtx = pane->GetGlobalMtx(); - paneScale.x = pane->GetSize().width; - paneScale.y = pane->GetSize().height; + paneSize.x = pane->GetSize().width; + paneSize.y = pane->GetSize().height; - float sx = mVideo::m_video->getWidth() / width; - float sy = mVideo::m_video->getHeight() / height; + float ratioX = mVideo::m_video->getWidth() / width; + float ratioY = mVideo::m_video->getHeight() / height; - float scX2 = mtx._11 * (paneScale.x * sx); - float scY2 = mtx._11 * (paneScale.y * sy); + float trueSizeX = mtx.m[1][1] * (paneSize.x * ratioX); + float trueSizeY = mtx.m[1][1] * (paneSize.y * ratioY); - float tmpx = mtx._03 / actualScaleX; - float tmpy = mtx._13 * -1.0f; + float translateX = mtx.m[0][3] / actualScaleX; + float translateY = mtx.m[1][3] * -1.0f; - tmpx *= sx; - tmpy *= sy; + translateX *= ratioX; + translateY *= ratioY; - u32 x, y, w, h; - GXGetScissor(&x, &y, &w, &h); - pos.x = x + w * 0.5f + (tmpx - scX2 * 0.5f); - pos.y = y + h * 0.5f + (tmpy - scY2 * 0.5f); - clipSize.x = scX2 + 0.5f; - clipSize.y = scY2 + 0.5f; - clipData.setSize(clipSize); - clipData.setPos(pos); - clipData.mEnabled = true; + u32 scX, scY, scW, scH; + GXGetScissor(&scX, &scY, &scW, &scH); + pos.x = scX + scW * 0.5f + (translateX - trueSizeX * 0.5f); + pos.y = scY + scH * 0.5f + (translateY - trueSizeY * 0.5f); + scissorSize.x = trueSizeX + 0.5f; + scissorSize.y = trueSizeY + 0.5f; + scissorMask.setSize(scissorSize); + scissorMask.setPos(pos); + scissorMask.mEnabled = true; } bool LytBase_c::doDelete() { @@ -279,13 +282,16 @@ bool LytBase_c::doDelete() { delete[] mpAnimRes; mAnimCount = 0; } + if (mGroupCount != 0) { delete[] mpAnimGroup; delete[] mpEnabledAnims; mGroupCount = 0; } + if (!mResAccessorLoader.remove()) { return false; } + return true; } diff --git a/source/dol/bases/d_s_boot.cpp b/source/dol/bases/d_s_boot.cpp index b3df995e..fed425bc 100644 --- a/source/dol/bases/d_s_boot.cpp +++ b/source/dol/bases/d_s_boot.cpp @@ -449,7 +449,7 @@ int dScBoot_c::draw() { void dScBoot_c::initializeState_ResetWait() { mIsResetting = false; - mpWiiStrap->mLayout.mpAnimGroup->setAndUpdate(0.0f); + mpWiiStrap->mLayout.getAnmGroup(0).setAndUpdate(0.0f); } void dScBoot_c::executeState_ResetWait() { @@ -522,7 +522,7 @@ void dScBoot_c::initializeState_ResetFadeIn() { dReset::Manage_c::GetInstance()->ActiveSaveWindow(true); dFader_c::setFader(dFader_c::FADE); dFader_c::startFadeIn(30); - mpWiiStrap->mLayout.mpAnimGroup->setAndUpdate(0.0f); + mpWiiStrap->mLayout.getAnmGroup(0).setAndUpdate(0.0f); } void dScBoot_c::executeState_ResetFadeIn() { @@ -564,7 +564,7 @@ void dScBoot_c::finalizeState_FadeOutWait() {} void dScBoot_c::initializeState_WiiStrapKeyWait() { mAutoAdvanceTimer = 1200; mMinWaitTimer = 60; - mpWiiStrap->mLayout.mpAnimGroup->setAndUpdate(0.0f); + mpWiiStrap->mLayout.getAnmGroup(0).setAndUpdate(0.0f); } void dScBoot_c::executeState_WiiStrapKeyWait() { diff --git a/source/dol/mLib/m_2d.cpp b/source/dol/mLib/m_2d.cpp index e1fb226e..9c2e86a4 100644 --- a/source/dol/mLib/m_2d.cpp +++ b/source/dol/mLib/m_2d.cpp @@ -158,8 +158,8 @@ void m2d::FrameCtrl_c::play() { } else { frame += mRate; if (mFlags & NO_LOOP) { - if (frame > getLastActiveFrame()) { - frame = getLastActiveFrame(); + if (frame > getLastFrame()) { + frame = getLastFrame(); } } else if (frame >= mEndFrame) { frame -= mEndFrame; @@ -191,7 +191,7 @@ void m2d::FrameCtrl_c::setRate(float rate) { bool m2d::FrameCtrl_c::isStop() const { switch (mFlags) { case NO_LOOP: - return mCurrFrame >= getLastActiveFrame(); + return mCurrFrame >= getLastFrame(); case NO_LOOP | REVERSE: return mCurrFrame <= 0.0f; default: diff --git a/syms.txt b/syms.txt index 2a5428f6..b2d569b7 100644 --- a/syms.txt +++ b/syms.txt @@ -155,6 +155,7 @@ SetSoftLight_Enemy__8dGameComFRQ23m3d6bmdl_ci=0x800B4170 SetSoftLight_MapObj__8dGameComFRQ23m3d6bmdl_ci=0x800B42B0 SelectCursorSetup__8dGameComFPQ34nw4r3lyt4Paneib=0x800B44D0 GetLanguageHBM__8dGameComFv=0x800B4630 +AreaLanguageFolder__8dGameComFPCcPc=0x800B4670 PlayerEnterCheck__8dGameComFi=0x800B4760 Player1upColor__8dGameComFP12LytTextBox_ci=0x800B4780 isNowCourseClear__8dGameComFv=0x800B4E30 @@ -242,6 +243,8 @@ createEffectManagerPhase2__7dSystemFPv=0x800E5170 createFontManagerPhase__7dSystemFPv=0x800E51E0 createMessageManagerPhase__7dSystemFPv=0x800E5220 fixArena__7dSystemFv=0x800E52B0 +__ct__14TagProcessor_cFv=0x800E5510 +__dt__14TagProcessor_cFv=0x800E5590 preProcess__14TagProcessor_cFPCwPwUlPilP16__va_list_structP8MsgRes_c=0x800E72D0 create__6mVideoFv=0x800E8BC0 GetPointFromIndex__12dWmConnect_cFi=0x800F3400 @@ -517,6 +520,7 @@ __dt__Q34nw4r3lyt8DrawInfoFv=0x802B4EF0 GetFrameSize__Q34nw4r3lyt13AnimTransformCFv=0x802B51E0 IsLoopData__Q34nw4r3lyt13AnimTransformCFv=0x802B51F0 __ct__Q34nw4r3lyt18AnimTransformBasicFv=0x802B5210 +__ct__Q34nw4r3lyt12AnimResourceFv=0x802B5C30 Set__Q34nw4r3lyt12AnimResourceFPCv=0x802B5C50 GetGroupNum__Q34nw4r3lyt12AnimResourceCFv=0x802B5D60 GetGroupArray__Q34nw4r3lyt12AnimResourceCFv=0x802B5D80 From 15ff6d33f922c9c3a5d23ba7d96c98e10cac10cd Mon Sep 17 00:00:00 2001 From: user Date: Sun, 10 Aug 2025 22:50:38 +0200 Subject: [PATCH 07/10] `dGameDisplay_c` 96% matching --- include/constants/game_constants.h | 2 + include/game/bases/d_a_player_manager.hpp | 2 + include/game/bases/d_game_com.hpp | 1 + include/game/bases/d_gamedisplay.hpp | 292 +++++++ include/game/bases/d_s_stage.hpp | 18 +- include/game/framework/f_profile_name.hpp | 2 +- include/game/mLib/m_fader_base.hpp | 4 + include/game/mLib/m_vec.hpp | 7 + include/game/snd/snd_audio_mgr.hpp | 1 + slices/wiimj2d.json | 13 + source/dol/bases/d_gamedisplay.cpp | 948 ++++++++++++++++++++++ syms.txt | 56 ++ 12 files changed, 1340 insertions(+), 6 deletions(-) create mode 100644 include/game/bases/d_gamedisplay.hpp create mode 100644 source/dol/bases/d_gamedisplay.cpp diff --git a/include/constants/game_constants.h b/include/constants/game_constants.h index c715c3fb..515447ab 100644 --- a/include/constants/game_constants.h +++ b/include/constants/game_constants.h @@ -21,6 +21,8 @@ #define MAX_MAP_ACTOR_COUNT 1000 ///< The maximum number of map actors that can exist simultaneously. +#define MAX_SCORE 99999950 ///< The maximum score that can be achieved. + #define MAX_STOCK_ITEM 99 ///< The maximum inventory amount per item. #define MAX_EXTRA_MODE_SCORE 1000000 ///< The maximum possible score in Free Mode and Coin Battle. diff --git a/include/game/bases/d_a_player_manager.hpp b/include/game/bases/d_a_player_manager.hpp index d254018e..5841bc0c 100644 --- a/include/game/bases/d_a_player_manager.hpp +++ b/include/game/bases/d_a_player_manager.hpp @@ -19,6 +19,8 @@ class daPyMng_c { static int mNum; static u8 mActPlayerInfo; + static int mScore; + static int mPlayerEntry[4]; static PLAYER_TYPE_e mPlayerType[4]; static int mPlayerMode[4]; static int mRest[4]; diff --git a/include/game/bases/d_game_com.hpp b/include/game/bases/d_game_com.hpp index f48a5136..b0bc5205 100644 --- a/include/game/bases/d_game_com.hpp +++ b/include/game/bases/d_game_com.hpp @@ -113,4 +113,5 @@ namespace dGameCom { void initGame(); void AreaLanguageFolder(const char *, char *); + void fn_800B37E0(mVec3_c &, bool); ///< @unofficial } diff --git a/include/game/bases/d_gamedisplay.hpp b/include/game/bases/d_gamedisplay.hpp new file mode 100644 index 00000000..008701df --- /dev/null +++ b/include/game/bases/d_gamedisplay.hpp @@ -0,0 +1,292 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace EGG { + +class Effect { +public: + enum ERecursive {}; + + Effect(); + virtual ~Effect(); + virtual void create(); + virtual void fade(); + virtual void followFade(); + virtual void kill(); + virtual void setDisableCalc(bool); + virtual void setDisableDraw(bool); + virtual void setDisableCalcDraw(bool); + virtual void setLife(unsigned short, EGG::Effect::ERecursive); + virtual void setEmitRatio(float, EGG::Effect::ERecursive); + virtual void setEmitInterval(unsigned short, EGG::Effect::ERecursive); + virtual void setEmitEmitDiv(unsigned short, EGG::Effect::ERecursive); + virtual void setInitVelocityRandom(signed char, EGG::Effect::ERecursive); + virtual void setPowerYAxis(float, EGG::Effect::ERecursive); + virtual void setPowerRadiationDir(float, EGG::Effect::ERecursive); + virtual void setPowerSpecDir(float, EGG::Effect::ERecursive); + virtual void setPowerSpecDirAdd(float, EGG::Effect::ERecursive); + virtual void setSpecDir(const nw4r::math::VEC3&, EGG::Effect::ERecursive); + virtual void setSpecDirAdd(const nw4r::math::VEC3&, EGG::Effect::ERecursive); + virtual void setVelocity(const nw4r::math::VEC3&); + virtual void setColor(unsigned char, unsigned char, unsigned char, unsigned char, EGG::Effect::ERecursive); + virtual void setDefaultParticleSize(nw4r::math::VEC2&, EGG::Effect::ERecursive); + virtual void setParticleScale(nw4r::math::VEC2&, EGG::Effect::ERecursive); + virtual void setDefaultParticleRotate(const nw4r::math::VEC3&, EGG::Effect::ERecursive); + virtual void setParticleRotate(const nw4r::math::VEC3&, EGG::Effect::ERecursive); + virtual void setEmitterSize(const nw4r::math::VEC3&, bool, EGG::Effect::ERecursive); + virtual void setLocalScale(const nw4r::math::VEC3&, EGG::Effect::ERecursive); + virtual void setDynamicsScale(const nw4r::math::VEC3&, const nw4r::math::VEC2*); + virtual void setScale(float); + virtual void setScale(const nw4r::math::VEC3&); + virtual void setPos(const nw4r::math::VEC3&); + virtual void setMtx(const nw4r::math::MTX34&); + virtual void setPtclAnim(int, bool); + virtual void update(); + virtual void getEffect() const; + virtual void getRootEmitter() const; + virtual void reset(); + + u8 mPad[0x7c]; +}; + +} // namespace EGG +namespace mEf { + +class effect_c : public EGG::Effect { +public: + effect_c() {} + + virtual void createEffect(const char *, int); + virtual void createEffect(const char *, ulong, const mVec3_c *, const mAng3_c *, const mVec3_c *); + virtual void createEffect(const char *, ulong, const mMtx_c *); + // virtual void vfa8(); + // virtual void vfac(); + virtual void follow(const mVec3_c *, const mAng3_c *, const mVec3_c *); + virtual void follow(const mMtx_c *); + + u8 mPad[0x92]; + mAng mAng; +}; + +class levelEffect_c : public effect_c { +public: + levelEffect_c() : m_114(0), m_118(0), m_11c(0), m_11d(0), m_120(0), m_124(0) {} + virtual ~levelEffect_c() { cleanup(); } + + // [tmp, so that vtable doesn't generate in this TU] + virtual void createEffect(const char *, int); + + void cleanup(); + + u32 m_114, m_118; + u8 m_11c, m_11d; + u32 m_120, m_124; +}; + +void createEffect(const char *, unsigned long, const mVec3_c *, const mAng3_c *, const mVec3_c *); + +}; // namespace mEf +class PauseManager_c { +public: + u8 m_00[0x1D]; // TODO + u8 mDisablePause; + static bool m_OtasukeAfter; + static PauseManager_c *m_instance; +}; +class dActorCreateMng_c { +public: + u8 m_00[0xBCB]; // TODO + u8 m_bcb; + static dActorCreateMng_c *m_instance; +}; +class dStageTimer_c { +public: + char mPad1[4]; + u32 mPreciseTime; + void setTimer(short time); + static dStageTimer_c *m_instance; +}; + +struct mRect_c { + float left, top, right, bottom; +}; + +class dGameDisplay_c : public dBase_c { + + /// @brief The picture panes used in the layout. + /// @unofficial + enum P_PANE_e { + P_collectOff_00, + P_collection_00, + P_collectOff_01, + P_collection_01, + P_collectOff_02, + P_collection_02, + P_marioIcon_00, + P_luijiIcon_00, + P_kinoB_00, + P_kinoY_00, + P_COUNT + }; + + /// @brief The text boxes used in the layout. + /// @unofficial + enum T_PANE_e { + T_left_00, + T_x_01, + T_left_01, + T_x_02, + T_left_02, + T_x_03, + T_left_03, + T_x_04, + T_coin_00, + T_time_00, + T_score_00, + T_COUNT + }; + + /// @brief The null panes used in the layout. + /// @unofficial + enum N_PANE_e { + N_otasukeInfo_00, + N_otasukeChu_00, + N_left_00, + N_coin_00, + N_collection_00, + N_score_00, + N_areaZanki_00, + N_areaCoin_00, + N_areaScore_00, + N_marioIcon_00, + N_luigiIcon_00, + N_kinoB_00, + N_kinoY_00, + N_coin_01, + N_time_00, + N_proportionL_00, + N_proportionR_00, + N_coin1st_00, + N_coin2nd_00, + N_coin3rd_00, + N_COUNT + }; + +public: + dGameDisplay_c(); + + virtual int create(); + virtual int execute(); + virtual int doDelete(); + virtual int draw(); + virtual ~dGameDisplay_c(); + +private: + void AlphaEnterAndExit(); + void AreaCheck(); + void AreaSetup(int, int); + bool createLayout(); + void Effect1UP(int); + void EffectCollectionCoinClear(); + void EffectCollectionCoinGet(int); + void GrayColorSet(int); + bool NormalSettle(); + bool OtasukeSettle(); + void OtehonPosChange(); + void RestCoinAnimeCheck(); + void RestCoinAnimeSetup(); + void RestDispSetup(); + void ReturnGrayColorSet(int); + void setCoinNum(int); + void setCollect(); + void setPlayNum(int *); + void setScore(int); + void setTime(int); + void fn_801585c0(); + + LytBase_c mLayout; + mEf::levelEffect_c mEffect; + GXColorS10 mColorBackup[3][PLAYER_COUNT]; + + sFStateMgr_c mStateMgr; + + STATE_FUNC_DECLARE(dGameDisplay_c, ProcGoalEnd); + STATE_FUNC_DECLARE(dGameDisplay_c, ProcGoalSettleUp); + STATE_FUNC_DECLARE(dGameDisplay_c, ProcMainGame); + STATE_FUNC_DECLARE(dGameDisplay_c, ProcMainPause); + + int mPlayNum[PLAYER_COUNT]; + int mCoins; + int mTimer; + u32 m_3E4; + int mScore; + int m_3EC[3]; // one for each star coin + u32 m_3F8; + u32 m_3FC; + int m_400; + int m_404; + int m_408; + u32 m_40C; + u32 m_410; + int m_414; + int mAreaAlpha[3]; + + u32 m_424[PLAYER_COUNT]; + + int m_434; + int m_438; + u32 m_43C; + int m_440; + u32 m_444; + + u8 m_448; + u8 m_449; + u8 m_44A; + bool mHasLoadedLayout; + u8 m_44C; + u8 m_44D[3]; + u8 m_450; + u8 m_451; + u8 m_452; + u8 m_453; + u8 m_454[PLAYER_COUNT]; + mRect_c m_458[3]; + u32 m_488; + u32 m_48C; + + nw4r::lyt::Pane *mpRootPane; ///< The root pane of the view. + + nw4r::lyt::Picture *mpPicturePanes[P_COUNT]; ///< The picture panes of the view. + LytTextBox_c *mpTextBoxes[T_COUNT]; ///< The textboxes of the view. + nw4r::lyt::Pane *mpNullPanes[N_COUNT]; ///< The null panes of the view. + + float m_538; + float m_53C; + float m_540; + + mVec3_c m_544; + mVec3_c m_550; + mVec3_c m_55C; + mVec3_c m_568; + mVec3_c m_574; + mVec3_c m_580; + mVec3_c m_58C; + mVec3_c m_598; + +public: + static dGameDisplay_c *m_instance; + static const int c_COINNUM_DIGIT; + static const int c_PLAYNUM_DIGIT; + static const int c_TIME_DIGIT; + static const int c_SCORE_DIGIT; +}; diff --git a/include/game/bases/d_s_stage.hpp b/include/game/bases/d_s_stage.hpp index 573dcbb7..7eac3c7f 100644 --- a/include/game/bases/d_s_stage.hpp +++ b/include/game/bases/d_s_stage.hpp @@ -21,8 +21,16 @@ class dScStage_c : public dScene_c { LOOP_COUNT, }; + u8 getCurrWorld() const { return mCurrWorld; } + u8 getCurrArea() const { return mCurrArea; } + u8 getCurrCourse() const { return mCurrCourse; } + u8 getCurrFile() const { return mCurrFile; } + + static void play(); + static float getLoopPosX(float x); + typedef void (*changePosFunc)(mVec3_c *); static void setChangePosFunc(int); @@ -30,17 +38,15 @@ class dScStage_c : public dScene_c { static void createReplayDataHeap(EGG::Heap *heap, ulong size, int options); + static dScStage_c *getInstance() { return m_instance; } + + char pad[0x1198]; u8 mCurrWorld; u8 mCurrCourse; u8 mCurrFile; u8 mCurrArea; - u8 getCurrWorld() const { return mCurrWorld; } - u8 getCurrArea() const { return mCurrArea; } - - static dScStage_c *getInstance() { return m_instance; } - static float getLoopPosX(float x); static u32 m_exeFrame; static int m_loopType; static PLAYER_TYPE_e mCollectionCoin[STAR_COIN_COUNT]; @@ -51,6 +57,8 @@ class dScStage_c : public dScene_c { static bool m_KoopaJrEscape; static dInfo_c::GameMode_e m_gameMode; static Exit_e m_exitMode; + static u32 m_miniGame; + static bool m_isStaffCredit; static changePosFunc changePos; static dScStage_c *m_instance; diff --git a/include/game/framework/f_profile_name.hpp b/include/game/framework/f_profile_name.hpp index 38cfcbed..a74aa7dc 100644 --- a/include/game/framework/f_profile_name.hpp +++ b/include/game/framework/f_profile_name.hpp @@ -716,7 +716,7 @@ namespace fProfile { COURSE_SELECT_MANAGER, FUKIDASHI_MANAGER, SMALL_SCORE_MANAGER, - GAMEDISPLAY, + GAMEDISPLAY, ///< The profile for dGameDisplay_c. OTASUKE_INFO, PAUSEWINDOW, RESULT, diff --git a/include/game/mLib/m_fader_base.hpp b/include/game/mLib/m_fader_base.hpp index 14a180e2..e63cde94 100644 --- a/include/game/mLib/m_fader_base.hpp +++ b/include/game/mLib/m_fader_base.hpp @@ -51,6 +51,10 @@ class mFaderBase_c { void setFrame(u16 duration); ///< Sets the duration of the fade. Duration must not be zero. void setColor(const mColor &color); ///< Sets the fader's color. Alpha is not modified. + bool isHidden() const { + return getStatus() == HIDDEN; + } + protected: EStatus mStatus; ///< The fader's status. u8 mFlag; ///< The fader's flags. diff --git a/include/game/mLib/m_vec.hpp b/include/game/mLib/m_vec.hpp index 1c8a914a..7b29ed01 100644 --- a/include/game/mLib/m_vec.hpp +++ b/include/game/mLib/m_vec.hpp @@ -194,6 +194,13 @@ class mVec3_c : public EGG::Vector3f { /// @brief Inequality operator. bool operator!=(const mVec3_c &v) const { return x != v.x || y != v.y || z != v.z; } + mVec3_c &setToShifted(const mVec3_c &v, float sx, float sy, float sz) { + x = sx + v.x; + y = sy + v.y; + z = sz + v.z; + return *this; + } + float xzLen() const { return EGG::Mathf::sqrt(x * x + z * z); } diff --git a/include/game/snd/snd_audio_mgr.hpp b/include/game/snd/snd_audio_mgr.hpp index bbb7b9a8..faeabb40 100644 --- a/include/game/snd/snd_audio_mgr.hpp +++ b/include/game/snd/snd_audio_mgr.hpp @@ -3,6 +3,7 @@ class SndAudioMgr { public: void startSystemSe(unsigned int soundID, unsigned long); + void holdSystemSe(unsigned int soundID, unsigned long); public: static SndAudioMgr *sInstance; diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index f9ce7c8e..153e2670 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -528,6 +528,19 @@ ".sdata": "0x1cd8-0x1ce0" } }, + { + "source": "dol/bases/d_gamedisplay.cpp", + "nonMatching": true, + "memoryRanges": { + ".text": "0x1510a0-0x153d00", + ".data": "0x28fc8-0x29660", + ".sbss2": "0x28-0x30", + ".rodata": "0x7c48-0x7d00", + ".sdata": "0x1d28-0x1d50", + ".sdata2": "0x2b30-0x2b48", + ".bss": "0x259e8-0x25ae8" + } + }, { "source": "dol/bases/d_pausewindow.cpp", "memoryRanges": { diff --git a/source/dol/bases/d_gamedisplay.cpp b/source/dol/bases/d_gamedisplay.cpp new file mode 100644 index 00000000..53bdef9c --- /dev/null +++ b/source/dol/bases/d_gamedisplay.cpp @@ -0,0 +1,948 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ACTOR_PROFILE(GAMEDISPLAY, dGameDisplay_c, 0); + +STATE_DEFINE(dGameDisplay_c, ProcMainGame); +STATE_DEFINE(dGameDisplay_c, ProcMainPause); +STATE_DEFINE(dGameDisplay_c, ProcGoalSettleUp); +STATE_DEFINE(dGameDisplay_c, ProcGoalEnd); + +dGameDisplay_c *dGameDisplay_c::m_instance; +const int dGameDisplay_c::c_COINNUM_DIGIT = 2; +const int dGameDisplay_c::c_PLAYNUM_DIGIT = 2; +const int dGameDisplay_c::c_TIME_DIGIT = 3; +const int dGameDisplay_c::c_SCORE_DIGIT = 8; + + +dGameDisplay_c::~dGameDisplay_c() { + m_instance = nullptr; +} + +dGameDisplay_c::dGameDisplay_c() : + mStateMgr(*this, StateID_ProcMainGame), + m_452(1), + mHasLoadedLayout(false) +{ + m_instance = this; +} + +int dGameDisplay_c::create() { + if (mHasLoadedLayout) { + return 1; + } + + if (!createLayout()) { + return 0; + } + + mLayout.mDrawOrder = 0x11; + + for (int i = 0; i < PLAYER_COUNT; i++) { + mPlayNum[i] = -1; + m_424[i] = 0; + m_454[i] = 0; + } + + m_454[3] = 0; + mScore = 1; + m_3E4 = 1; + mCoins = 1; + mTimer = -1; + m_434 = 2; + + setPlayNum(mPlayNum); + setCoinNum(0); + setTime(0); + setScore(0); + + m_438 = 0; + m_440 = 0; + m_3FC = -1; + m_3F8 = -1; + m_444 = 0; + m_453 = 0; + m_400 = 0; + m_404 = 0x1e; + m_408 = 0x1e; + m_40C = 0; + m_43C = 0; + m_540 = 0; + m_53C = 0; + m_538 = 0; + + RestDispSetup(); + fn_801585c0(); + mLayout.AllAnimeEndSetup(); + + if ((dScStage_c::m_gameMode == 2) || (dScStage_c::m_gameMode == 3) || dScStage_c::m_miniGame || (dInfo_c::m_startGameInfo.mLevel1 == STAGE_PEACH_CASTLE) || dScStage_c::m_isStaffCredit) { + mpRootPane->SetVisible(false); + } else { + mpRootPane->SetVisible(true); + } + + if (dScStage_c::m_gameMode == 1) { + mpNullPanes[N_otasukeInfo_00]->SetVisible(true); + } else { + mpNullPanes[N_otasukeInfo_00]->SetVisible(false); + } + + if (PauseManager_c::m_OtasukeAfter) { + m_448 = 1; + mpNullPanes[N_otasukeChu_00]->SetVisible(true); + mpNullPanes[N_left_00]->SetVisible(false); + mLayout.ReverseAnimeStartSetup(0, false); + } else { + m_448 = 0; + mpNullPanes[N_otasukeChu_00]->SetVisible(false); + mpNullPanes[N_left_00]->SetVisible(true); + } + + if (dInfo_c::m_startGameInfo.mLevel1 == STAGE_CANNON) { + mpNullPanes[N_collection_00]->SetVisible(false); + mpNullPanes[N_score_00]->SetVisible(false); + mpNullPanes[N_time_00]->SetVisible(false); + } else { + mpNullPanes[N_collection_00]->SetVisible(true); + mpNullPanes[N_score_00]->SetVisible(true); + mpNullPanes[N_time_00]->SetVisible(true); + } + + if (dInfo_c::mGameFlag & 0x40) { + mpNullPanes[N_score_00]->SetVisible(false); + } + + + dMj2dGame_c *save = dSaveMng_c::m_instance->getSaveGame(-1); + u32 w = dInfo_c::m_startGameInfo.mWorld1; + u32 l = dInfo_c::m_startGameInfo.mLevel1; + if (w > WORLD_USED_COUNT) { + w = 0; + } + if (l > STAGE_STAFFROLL) { + l = STAGE_1; + } + + if (!(dInfo_c::mGameFlag & 0x10) && !(dInfo_c::mGameFlag & 0x80000000) && !dScWMap_c::IsCourseType(w, l, dScWMap_c::COURSE_TYPE_NO_STAR_COINS)) { + mpNullPanes[N_collection_00]->SetVisible(false); + } + + for (u32 i = 0; i < 3; i++) { + m_3EC[i] = 3; + if ((dScStage_c::mCollectionCoin[i] != 4) || save->isCollectCoin(w, l, i)) { + mpPicturePanes[P_collectOff_00 + 2 * i]->SetVisible(false); + mpPicturePanes[P_collection_00 + 2 * i]->SetVisible(true); + m_3EC[i] = 2; + } + } + + mVec2_c disp_scale; + dGameCom::DispSizeScale(disp_scale); + mpNullPanes[N_proportionL_00]->SetScale(disp_scale); + mpNullPanes[N_proportionR_00]->SetScale(disp_scale); + + m_544 = mpNullPanes[N_proportionL_00]->GetTranslate(); + m_550 = mpNullPanes[N_proportionR_00]->GetTranslate(); + m_55C = mpNullPanes[N_otasukeChu_00]->GetTranslate(); + m_568 = mpNullPanes[N_areaZanki_00]->GetTranslate(); + m_574 = mpNullPanes[N_otasukeInfo_00]->GetTranslate(); + m_580 = mpNullPanes[N_areaCoin_00]->GetTranslate(); + m_58C = mpNullPanes[N_areaScore_00]->GetTranslate(); + m_598 = mpNullPanes[N_time_00]->GetTranslate(); + + OtehonPosChange(); + + m_449 = 0; + m_44A = 0; + mHasLoadedLayout = true; + m_44C = 0; + for (int i = 0; i < 3; i++) { + mAreaAlpha[i] = 0xFF; + m_44D[i] = 0; + } + m_450 = 0; + m_451 = 0; + + mLayout.calc(); + + return SUCCEEDED; +} + +int dGameDisplay_c::execute() { + if (mHasLoadedLayout) { + + RestCoinAnimeCheck(); + mStateMgr.executeState(); + + if (mLayout.isAllAnime() || m_450 || m_451) { + mLayout.AnimePlay(); + mLayout.calc(); + } + + AreaCheck(); + AlphaEnterAndExit(); + + for (int i = 0; i < PLAYER_COUNT; i++) { + if (m_424[i]) { + m_424[i]--; + } + } + } + + return SUCCEEDED; +} + +int dGameDisplay_c::draw() { + if (!m_452) { + return 1; + } + + if (mHasLoadedLayout) { + mLayout.entry(); + } + + return SUCCEEDED; +} + +int dGameDisplay_c::doDelete() { + return mLayout.doDelete(); +} + +// Doesn't match - weird float trickery +void dGameDisplay_c::OtehonPosChange() { + if (dScStage_c::m_gameMode != 4) { + return; + } + + float a = 0.0f; + float offs1 = 16.0f; + float offs2 = 23.0f; + + float x = a + offs1; // 16.0f + float e = a - offs1; // -16.0f + + float d = a - offs2; // -23.0f + float f = a + offs2; // 23.0f + + mVec3_c v; + + v.setToShifted(m_544, x, 0.0f, 0.0f); + mpNullPanes[N_proportionL_00]->SetTranslate(v); + + v.setToShifted(m_550, e, 0.0f, 0.0f); + mpNullPanes[N_proportionR_00]->SetTranslate(v); + + v.setToShifted(m_55C, 0.0f, d, 0.0f); + mpNullPanes[N_otasukeChu_00]->SetTranslate(v); + + v.setToShifted(m_568, 0.0f, d, 0.0f); + mpNullPanes[N_areaZanki_00]->SetTranslate(v); + + v.setToShifted(m_574, 0.0f, f, 0.0f); + mpNullPanes[N_otasukeInfo_00]->SetTranslate(v); + + v.setToShifted(m_580, 0.0f, d, 0.0f); + mpNullPanes[N_areaCoin_00]->SetTranslate(v); + + v.setToShifted(m_58C, 0.0f, d, 0.0f); + mpNullPanes[N_areaScore_00]->SetTranslate(v); + + v.setToShifted(m_598, 0.0f, d, 0.0f); + mpNullPanes[N_time_00]->SetTranslate(v); + + mLayout.calc(); +} + +void dGameDisplay_c::AreaSetup(int a, int areaPane) { + nw4r::math::MTX34 mtx = mpNullPanes[areaPane]->GetGlobalMtx(); + m_458[a].right = mtx._03; + m_458[a].bottom = mtx._03; + m_458[a].left = mtx._13; + m_458[a].top = mtx._13; + nw4r::lyt::Size size = mpNullPanes[areaPane]->GetSize(); + + float w = size.width; + switch (mpNullPanes[areaPane]->GetBasePositionH()) { + case 0: + m_458[a].bottom += w; + break; + case 1: + w /= 2; + m_458[a].right -= w; + m_458[a].bottom += w; + break; + case 2: + m_458[a].right -= w; + break; + } + + float h = size.height; + switch (mpNullPanes[areaPane]->GetBasePositionV()) { + case 0: + m_458[a].top -= h; + break; + case 1: + h /= 2; + m_458[a].left += h; + m_458[a].top -= h; + break; + case 2: + m_458[a].left += h; + break; + } +} + + + +void dGameDisplay_c::fn_801585c0() { + for (int i = 0; i < 3; i++) { + AreaSetup(i, N_areaZanki_00 + i); + } + + if (m_414 != P_marioIcon_00) { + nw4r::lyt::Pane *pane = mpPicturePanes[m_414]; + nw4r::math::MTX34 mtx = pane->GetGlobalMtx(); + nw4r::lyt::Size size = pane->GetSize(); + + float f = mtx._03 + size.width * 0.5f; + f += 60.0f; + m_458[0].bottom = f; + } +} + + +void dGameDisplay_c::RestDispSetup() { + mVec3_c iconPos[4]; + + static const PLAYER_TYPE_e lbl_802F5C28[PLAYER_COUNT] = { + PLAYER_MARIO, + PLAYER_LUIGI, + PLAYER_BLUE_TOAD, + PLAYER_YELLOW_TOAD, + }; + + static const u32 lbl_802F5C38[PLAYER_COUNT] = { + P_marioIcon_00, P_luijiIcon_00, P_kinoY_00, P_kinoB_00, + }; + + iconPos[PLAYER_MARIO] = mpPicturePanes[P_marioIcon_00]->GetTranslate(); + mpPicturePanes[P_marioIcon_00]->SetVisible(false); + iconPos[PLAYER_LUIGI] = mpPicturePanes[P_luijiIcon_00]->GetTranslate(); + mpPicturePanes[P_luijiIcon_00]->SetVisible(false); + iconPos[PLAYER_YELLOW_TOAD] = mpPicturePanes[P_kinoB_00]->GetTranslate(); + mpPicturePanes[P_kinoB_00]->SetVisible(false); + iconPos[PLAYER_BLUE_TOAD] = mpPicturePanes[P_kinoY_00]->GetTranslate(); + mpPicturePanes[P_kinoY_00]->SetVisible(false); + + int iconPosIdx = 0; + for (int i = 0; i < PLAYER_COUNT; i++) { + int idx = daPyMng_c::getPlayerIndex(lbl_802F5C28[i]); + if (!daPyMng_c::mPlayerEntry[idx]) { + continue; + } + + mpPicturePanes[lbl_802F5C38[i]]->SetVisible(true); + mpPicturePanes[lbl_802F5C38[i]]->SetTranslate(iconPos[iconPosIdx]); + iconPosIdx++; + m_414 = P_marioIcon_00 + i; + } +} + +bool dGameDisplay_c::createLayout() { + static const char *AnmNameTbl[] = { + "gameScene_37_inMarioCoin.brlan" + }; + + static const char *GROUP_NAME_DT[] = { + "C00_inMarioCoin" + }; + static const int ANIME_INDEX_TBL[] = { + 0 + }; + + static const int MESSAGE_DATA_TBL[] = { + 0x14, 0x14, 0x13, 0x13 + }; + + static const char *NPANE_NAME_DT[] = { + "N_otasukeInfo_00", "N_otasukeChu_00", + "N_left_00", + "N_coin_00", + "N_collection_00", + "N_score_00", + "N_areaZanki_00", "N_areaCoin_00", "N_areaScore_00", + "N_marioIcon_00", "N_luigiIcon_00", "N_kinoB_00", "N_kinoY_00", + "N_coin_01", + "N_time_00", + "N_proportionL_00", "N_proportionR_00", + "N_coin1st_00", "N_coin2nd_00", "N_coin3rd_00" + }; + + static const char *PPANE_NAME_DT[] = { + "P_collectOff_00", "P_collection_00", + "P_collectOff_01", "P_collection_01", + "P_collectOff_02", "P_collection_02", + "P_marioIcon_00", "P_luijiIcon_00", + "P_kinoB_00", "P_kinoY_00" + }; + + static const char *T_PANE_NAME_DT[] = { + "T_left_00", "T_x_01", + "T_left_01", "T_x_02", + "T_left_02", "T_x_03", + "T_left_03", "T_x_04", + "T_coin_00", + "T_time_00", + "T_score_00" + }; + + static const char *T_PANE_NAME_TBL[] = { + "T_otaChuS_00", "T_otaChu_01", + "T_InfoS_00", "T_Info_00" + }; + + if (!mLayout.ReadResource("gameScene/gameScene.arc", false)) { + return false; + } + + mLayout.build("gameScene_37.brlyt", nullptr); + mLayout.AnimeResRegister(AnmNameTbl, 1); + mLayout.GroupRegister(GROUP_NAME_DT, ANIME_INDEX_TBL, 1); + + mpRootPane = mLayout.getRootPane(); + mLayout.NPaneRegister(NPANE_NAME_DT, mpNullPanes, N_COUNT); + mLayout.PPaneRegister(PPANE_NAME_DT, mpPicturePanes, P_COUNT); + + mpPicturePanes[P_collectOff_00]->SetVisible(true); + mpPicturePanes[P_collection_00]->SetVisible(false); + mpPicturePanes[P_collectOff_01]->SetVisible(false); // [???] + mpPicturePanes[P_collectOff_01]->SetVisible(true); + mpPicturePanes[P_collection_01]->SetVisible(false); + mpPicturePanes[P_collectOff_02]->SetVisible(false); // [???] + mpPicturePanes[P_collectOff_02]->SetVisible(true); + mpPicturePanes[P_collection_02]->SetVisible(false); + + mpPicturePanes[P_marioIcon_00]->SetVisible(false); + + mLayout.TPaneRegister(T_PANE_NAME_DT, mpTextBoxes, T_COUNT); + mLayout.TPaneNameRegister(T_PANE_NAME_TBL, MESSAGE_DATA_TBL, 1, 4); + + return true; +} + + +void dGameDisplay_c::RestCoinAnimeCheck() { + if (m_44A) { + m_449 = 0; + } + if (!m_449) { + return; + } + + m_449 = 0; + m_44A = 1; + mLayout.AnimeStartSetup(0, false); + + if (dActorCreateMng_c::m_instance->m_bcb) { + PauseManager_c::m_instance->mDisablePause = true; + } +} + + +void dGameDisplay_c::AreaCheck() { + if (!mpRootPane->IsVisible()) { + return; + } + + for (int i = 0; i < PLAYER_COUNT; i++) { + if (!daPyMng_c::checkPlayer(i)) { + continue; + } + + dAcPy_c *player = daPyMng_c::getPlayer(i); + if (player == nullptr) { + continue; + } + + mVec3_c pos = player->getCenterPos(); + dGameCom::getGlbPosToLyt(pos); + + for (int i = 0; i < 3; i++) { + if (!m_44D[i] && m_458[i].right < pos.x && m_458[i].bottom > pos.x && m_458[i].left > pos.y && m_458[i].top < pos.y) { + m_44D[i] = 1; + m_450 = 1; + } + } + } +} + + +void dGameDisplay_c::AlphaEnterAndExit() { + if (!mpRootPane->IsVisible()) { + return; + } + + int x = 0; + for (int i = 0; i < 3; i++) { + int a = mpNullPanes[N_areaZanki_00 + i]->GetAlpha(); + if (m_44D[i]) { + if (a <= 70) { + x++; + } + } else if (a >= 0xFF) { + x++; + } + } + + if (x >= 3) { + m_450 = 0; + } else { + m_450 = 1; + } + + int max_alpha = 0xFF; + int min_alpha = 70; + int step = 12; + + for (int i = 0; i < 3; i++) { + int d = step; + if (m_44D[i]) { + d *= -1; + } + mAreaAlpha[i] += d; + if (mAreaAlpha[i] <= min_alpha) { + mAreaAlpha[i] = min_alpha; + } + if (mAreaAlpha[i] >= max_alpha) { + mAreaAlpha[i] = max_alpha; + } + + mpNullPanes[N_areaZanki_00 + i]->SetAlpha(mAreaAlpha[i]); + m_44D[i] = 0; + } +} + +bool dGameDisplay_c::NormalSettle() { + short t = ((int)(dStageTimer_c::m_instance->mPreciseTime + 0xFFF) >> 12); + bool ret; + if (t > 0) { + int x = m_40C; + int score = 0; + while (x > 0) { + t--; + score += m_410; + if (t <= 0) { + break; + } + x--; + } + + dStageTimer_c::m_instance->setTimer((short) t); + + if (!(dInfo_c::mGameFlag & 0x40)) { + SndAudioMgr::sInstance->holdSystemSe(SE_SYS_SCORE_COUNT, 1); + } + + daPyMng_c::addScore(score, -1); + ret = false; + } else { + ret = true; + } + + return ret; +} + +bool dGameDisplay_c::OtasukeSettle() { + dStageTimer_c *timer = dStageTimer_c::m_instance; + short t = ((int)(timer->mPreciseTime + 0xFFF) >> 12); + int score = daPyMng_c::mScore; + + if (!t && !score && !mCoins) { + return true; + } + + if (mCoins) { + mCoins += -3; + if (mCoins < 0) { + mCoins = 0; + } + } + + dGameCom::LayoutDispNumber(mCoins, c_COINNUM_DIGIT, mpTextBoxes[N_areaScore_00], false); + + if (t) { + t -= m_40C; + if (t < 0) { + t = 0; + } + } + timer->setTimer(t); + + if (score) { + score -= m_410 * m_40C; + if (score < 0) { + score = 0; + } + } + daPyMng_c::mScore = score; + + SndAudioMgr::sInstance->holdSystemSe(SE_SYS_SCORE_COUNT, 1); + + return false; +} + +// ---------------- +// StateID_ProcMainGame +// ---------------- + +void dGameDisplay_c::initializeState_ProcMainGame() { + m_43C = 0; + m_451 = 0; + m_453 = 0; +} + +void dGameDisplay_c::executeState_ProcMainGame() { + if (m_438 != 1) { + if (m_44C) { + mStateMgr.changeState(StateID_ProcGoalSettleUp); + } + return; + } else { + m_440 = 0; + mStateMgr.changeState(StateID_ProcMainPause); + } +} + +void dGameDisplay_c::finalizeState_ProcMainGame() { + m_451 = 1; +} + +// ---------------- +// StateID_ProcMainPause +// ---------------- + +void dGameDisplay_c::initializeState_ProcMainPause() { + m_43C = 1; + m_438 = 0; +} + +void dGameDisplay_c::executeState_ProcMainPause() { + if (m_440 == 1) { + mStateMgr.changeState(StateID_ProcMainGame); + } +} +void dGameDisplay_c::finalizeState_ProcMainPause() { + m_440 = 0; +} + +// ---------------- +// StateID_ProcGoalSettleUp +// ---------------- + +void dGameDisplay_c::initializeState_ProcGoalSettleUp() { + m_40C = 10; + m_410 = 0x32; + m_444 = 1; + m_453 = 1; + m_400 = 0; + + dMultiMng_c::mspInstance->m_04 = (short)((int)(dStageTimer_c::m_instance->mPreciseTime + 0xFFF) >> 12); + + if (PauseManager_c::m_OtasukeAfter) { + EffectCollectionCoinClear(); + } +} + +void dGameDisplay_c::executeState_ProcGoalSettleUp() { + if (m_400 < m_404) { + m_400++; + } else if (PauseManager_c::m_OtasukeAfter) { + if (OtasukeSettle()) { + m_400 = 0; + SndAudioMgr::sInstance->startSystemSe(SE_SYS_SCORE_COUNT_FINISH, 1); + mStateMgr.changeState(StateID_ProcGoalEnd); + } + } else { + if (NormalSettle()) { + m_400 = 0; + if (!(dInfo_c::mGameFlag & 0x40)) { + SndAudioMgr::sInstance->startSystemSe(SE_SYS_SCORE_COUNT_FINISH, 1); + } + mStateMgr.changeState(StateID_ProcGoalEnd); + } + } +} + +void dGameDisplay_c::finalizeState_ProcGoalSettleUp() {} + +// ---------------- +// StateID_ProcGoalEnd +// ---------------- + +void dGameDisplay_c::initializeState_ProcGoalEnd() {} + +void dGameDisplay_c::executeState_ProcGoalEnd() { + if (m_400 < m_408) { + m_400++; + } else { + m_444 = 0; + } +} + +void dGameDisplay_c::finalizeState_ProcGoalEnd() {} + + +void dGameDisplay_c::Effect1UP(int a) { + if ( + !mFader_c::mFader->isHidden() || + PauseManager_c::m_OtasukeAfter || + dScStage_c::m_miniGame || + dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_TITLE_REPLAY + ) { + return; + } + if (m_424[a] == 0) { + m_424[a] = 0xF; + + nw4r::lyt::Pane *icon = mpNullPanes[N_marioIcon_00 + a]; + + nw4r::math::MTX34 mtx = icon->GetGlobalMtx(); + + mVec3_c tmp; + tmp.x = mtx._03; + tmp.y = mtx._13; + tmp.z = 0.0f; + dGameCom::fn_800B37E0(tmp, false); + mEf::createEffect("Wm_2d_1up01", 0, &tmp, nullptr, nullptr); + + tmp.x = mtx._03; + tmp.y = mtx._13; + tmp.z = 0.0f; + dGameCom::fn_800B37E0(tmp, true); + mEf::createEffect("Wm_2d_1up02", 0, &tmp, nullptr, nullptr); + } +} + +void dGameDisplay_c::GrayColorSet(int player) { + static const int lbl_802f5c88[] = { + T_left_00, T_x_01, + T_left_01, T_x_02, + T_left_02, T_x_03, + T_left_03, T_x_04 + }; + static const int lbl_802f5ca8[] = { P_marioIcon_00, P_luijiIcon_00, P_kinoB_00, P_kinoY_00 }; + + + if (m_454[player] == 0) { + static nw4r::ut::Color grayColor(160, 160, 160, 255); + m_454[player] = true; + nw4r::lyt::Pane *icon1 = mpPicturePanes[lbl_802f5ca8[player]]; + nw4r::lyt::Material *mat1 = icon1->GetMaterial(); + mColorBackup[0][player] = mat1->GetTevColor(1); + mat1->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(grayColor)); + nw4r::lyt::Pane *icon2 = mpTextBoxes[lbl_802f5c88[player * 2]]; + nw4r::lyt::Material *mat2 = icon2->GetMaterial(); + mColorBackup[1][player] = mat2->GetTevColor(1); + mat2->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(grayColor)); + nw4r::lyt::Pane *icon3 = mpTextBoxes[lbl_802f5c88[player * 2 + 1]]; + nw4r::lyt::Material *mat3 = icon3->GetMaterial(); + mColorBackup[2][player] = mat3->GetTevColor(1); + mat3->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(grayColor)); + } +} + +void dGameDisplay_c::ReturnGrayColorSet(int player) { + static const int lbl_802f5c88[] = { + T_left_00, T_x_01, + T_left_01, T_x_02, + T_left_02, T_x_03, + T_left_03, T_x_04 + }; + static const int lbl_802f5ca8[] = { P_marioIcon_00, P_luijiIcon_00, P_kinoB_00, P_kinoY_00 }; + + if (m_454[player] != 0) { + m_454[player] = 0; + nw4r::lyt::Pane *icon1 = mpPicturePanes[lbl_802f5ca8[player]]; + icon1->GetMaterial()->SetTevColor(1, mColorBackup[0][player]); + nw4r::lyt::Pane *icon2 = mpTextBoxes[lbl_802f5c88[player * 2]]; + icon2->GetMaterial()->SetTevColor(1, mColorBackup[1][player]); + nw4r::lyt::Pane *icon3 = mpTextBoxes[lbl_802f5c88[player * 2 + 1]]; + icon3->GetMaterial()->SetTevColor(1, mColorBackup[2][player]); + } +} + +void dGameDisplay_c::EffectCollectionCoinClear() { + static const int lbl_802f5cb8[] = { 0, 2, 4 }; + static const int lbl_802f5cc4[] = { 1, 3, 5 }; + + for (int i = 0; i < 3; i++) { + mpPicturePanes[lbl_802f5cb8[i]]->SetVisible(true); + if (mpPicturePanes[lbl_802f5cc4[i]]->IsVisible()) { + nw4r::lyt::Pane *icon = mpNullPanes[N_coin1st_00 + i]; + + nw4r::math::MTX34 mtx = icon->GetGlobalMtx(); + + mVec3_c tmp; + tmp.x = mtx._03; + tmp.y = mtx._13; + tmp.z = 0.0f; + dGameCom::fn_800B37E0(tmp, false); + mEf::createEffect("Wm_2d_starcoinvanish", 0, &tmp, nullptr, nullptr); + } + mpPicturePanes[lbl_802f5cc4[i]]->SetVisible(false); + } +} + +void dGameDisplay_c::EffectCollectionCoinGet(int i) { + nw4r::lyt::Pane *icon = mpNullPanes[N_coin1st_00 + i]; + + nw4r::math::MTX34 mtx = icon->GetGlobalMtx(); + + mVec3_c tmp; + tmp.x = mtx._03; + tmp.y = mtx._13; + tmp.z = 0.0f; + dGameCom::fn_800B37E0(tmp, false); + mEf::createEffect("Wm_2d_starcoinget", 0, &tmp, nullptr, nullptr); +} + +void dGameDisplay_c::setPlayNum(int *life_nums) { + static const int PANE_INDEX_TBL[PLAYER_COUNT] = { + T_left_00, T_left_01, T_left_02, T_left_03 + }; + + for (int i = 0; i < PLAYER_COUNT; i++) { + if (mPlayNum[i] == life_nums[i]) { + continue; + } + + if (mPlayNum[i] < life_nums[i]) { + Effect1UP(i); + } + if (life_nums[i] == 0) { + GrayColorSet(i); + } else if (mPlayNum[i] == 0) { + ReturnGrayColorSet(i); + } + + mPlayNum[i] = life_nums[i]; + dGameCom::LayoutDispNumber(mPlayNum[i], c_PLAYNUM_DIGIT, mpTextBoxes[PANE_INDEX_TBL[i]], false); + } +} + +void dGameDisplay_c::setCoinNum(int num_coins) { + if (!m_453 && (mCoins != num_coins)) { + mCoins = num_coins; + dGameCom::LayoutDispNumber(mCoins, c_COINNUM_DIGIT, mpTextBoxes[T_coin_00], false); + + if (num_coins || m_444 || !mFader_c::mFader->isHidden()) { + return; + } + if ( + dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_TITLE || + dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_TITLE_REPLAY + ) { + return; + } + + nw4r::lyt::Pane *pane = mpNullPanes[N_coin_01]; + + nw4r::math::MTX34 mtx = pane->GetGlobalMtx(); + + mVec3_c tmp; + tmp.x = mtx._03; + tmp.y = mtx._13; + tmp.z = 0.0f; + + dGameCom::fn_800B37E0(tmp, false); + mEf::createEffect("Wm_2d_coin100", 0, &tmp, nullptr, nullptr); + } +} + +void dGameDisplay_c::setTime(int time) { + if (mTimer == time) { + return; + } + + mTimer = time; + dGameCom::LayoutDispNumber(mTimer, c_TIME_DIGIT, mpTextBoxes[9], true); +} + +void dGameDisplay_c::setCollect() { + if (m_453) { + return; + } + + dMj2dGame_c *save = dSaveMng_c::m_instance->getSaveGame(-1); + u8 l = dScStage_c::m_instance->getCurrCourse(); + u8 w = dScStage_c::m_instance->getCurrWorld(); + if (w >= WORLD_COUNT || l >= STAGE_COUNT) { + return; + } + + if ( + dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_TITLE || + dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_TITLE_REPLAY + ) { + return; + } + + for (u32 coinIdx = 0; coinIdx < 3; coinIdx++) { + if (save->isCollectCoin(w, l, coinIdx) && (dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_NORMAL)) { + mpPicturePanes[P_collectOff_00 + 2 * coinIdx]->SetVisible(false); + mpPicturePanes[P_collection_00 + 2 * coinIdx]->SetVisible(true); + if (m_3EC[coinIdx] != 2) { + m_3EC[coinIdx] = 2; + } + } else if (dScStage_c::mCollectionCoin[coinIdx] != 4) { + mpPicturePanes[P_collectOff_00 + 2 * coinIdx]->SetVisible(false); + mpPicturePanes[P_collection_00 + 2 * coinIdx]->SetVisible(true); + if (m_3EC[coinIdx] != 2) { + m_3EC[coinIdx] = 2; + EffectCollectionCoinGet(coinIdx); + } + } else { + mpPicturePanes[P_collectOff_00 + 2 * coinIdx]->SetVisible(true); + mpPicturePanes[P_collection_00 + 2 * coinIdx]->SetVisible(false); + if (m_3EC[coinIdx] != 0) { + m_3EC[coinIdx] = 0; + } + } + } + mLayout.calc(); +} + +void dGameDisplay_c::setScore(int score) { + if ((mScore == score) || (mScore >= MAX_SCORE)) { + return; + } + + // Only let 1 in 3 calls to 'setScore' actually update the scrore. + if (++m_434 < 2) { + return; + } + + m_434 = 0; + mScore = score; + if (score >= MAX_SCORE) { + mScore = MAX_SCORE; + } + + dGameCom::LayoutDispNumber(mScore, c_SCORE_DIGIT, mpTextBoxes[T_score_00], true); +} + +void dGameDisplay_c::RestCoinAnimeSetup() { + if (PauseManager_c::m_OtasukeAfter) { + m_449 = 1; + } +} diff --git a/syms.txt b/syms.txt index b2d569b7..ca722c24 100644 --- a/syms.txt +++ b/syms.txt @@ -143,6 +143,7 @@ showFukidashi__8dGameComFii=0x800B3600 hideFukidashiForLevel__8dGameComFiii=0x800B3720 hideFukidashiTemporarily__8dGameComFiii=0x800B3750 hideFukidashiForSession__8dGameComFii=0x800B3780 +fn_800B37E0__8dGameComFR7mVec3_cb=0x800B37E0 clearGameStop__8dGameComFv=0x800B3A20 setGameStop__8dGameComFv=0x800B3A30 isGameStop__8dGameComFUl=0x800B3B50 @@ -233,6 +234,7 @@ ScoreSet__11dScoreMng_cFR7mVec3_cUlii=0x800E2070 ScoreSet__11dScoreMng_cFP8dActor_cUliff=0x800E2190 ScoreSet2__11dScoreMng_cFR7mVec3_cUli=0x800E2310 UnKnownScoreSet__11dScoreMng_cFP8dActor_cUlff=0x800E24B0 +setTimer__13dStageTimer_cFs=0x800E3A00 setBlack__6dSys_cFb=0x800E4890 setFrameRate__6dSys_cFUc=0x800E4920 setClearColor__6dSys_cFQ34nw4r2ut5Color=0x800E4940 @@ -341,12 +343,20 @@ create__22mDvd_mountMemArchive_cFPCcUcPQ23EGG4Heap=0x8016BE00 getArcBinary__22mDvd_mountMemArchive_cCFv=0x8016BFA0 create__16mDvd_toMainRam_cFPCcUcPQ23EGG4Heap=0x8016C0B0 createEffect__3mEfFPCcUlPC7mVec3_cPC7mAng3_cPC7mVec3_c=0x8016C9D0 +createEffect__Q23mEf8effect_cFPCci=0x8016CAA0 +createEffect__Q23mEf8effect_cFPCcUlPC7mVec3_cPC7mAng3_cPC7mVec3_c=0x8016CBF0 +createEffect__Q23mEf8effect_cFPCcUlPC6mMtx_c=0x8016CCA0 +follow__Q23mEf8effect_cFPC7mVec3_cPC7mAng3_cPC7mVec3_c=0x8016CFE0 +follow__Q23mEf8effect_cFPC6mMtx_c=0x8016D090 +cleanup__Q23mEf13levelEffect_cFv=0x8016D5F0 +createExpHeap__5mHeapFUlPQ23EGG4HeapPCcUlQ25mHeap13AllocOptBit_t=0x8016E640 create__4mPadFv=0x8016F330 beginPad__4mPadFv=0x8016F360 endPad__4mPadFv=0x8016F550 __dt__Q36nw4hbm3lyt8DrawInfoFv=0x8017F550 GetLayoutRect__Q36nw4hbm3lyt6LayoutCFv=0x80180160 startSystemSe__11SndAudioMgrFUiUl=0x801954C0 +holdSystemSe__11SndAudioMgrFUiUl=0x801954E0 startSound__14SndObjctCmnEmyFUlRCQ34nw4r4math4VEC2Ul=0x80198040 startSound__14SndObjctCmnMapFUlRCQ34nw4r4math4VEC2Ul=0x80198D70 FUN_8019d5b0__11SndSceneMgrFUc=0x8019D5B0 @@ -609,6 +619,44 @@ initialize__Q23EGG13TextureBufferFUlPQ23EGG4Heap=0x802D3780 create__Q23EGG9ExceptionFUsUsUsPQ23EGG4Heapi=0x802D7700 setPadInfo__Q23EGG9ExceptionFPCUs=0x802D77A0 getMsg__Q23EGG6MsgResFUlUl=0x802D7B50 +__ct__Q23EGG6EffectFv=0x802D7D90 +__dt__Q23EGG6EffectFv=0x802D7E10 +create__Q23EGG6EffectFv=0x802D7E70 +fade__Q23EGG6EffectFv=0x802D7F40 +followFade__Q23EGG6EffectFv=0x802D7FD0 +kill__Q23EGG6EffectFv=0x802D8040 +setDisableCalc__Q23EGG6EffectFb=0x802D80E0 +setDisableDraw__Q23EGG6EffectFb=0x802D8180 +setDisableCalcDraw__Q23EGG6EffectFb=0x802D8220 +setLife__Q23EGG6EffectFUsQ33EGG6Effect10ERecursive=0x802D82F0 +setEmitRatio__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=0x802D8300 +setEmitInterval__Q23EGG6EffectFUsQ33EGG6Effect10ERecursive=0x802D8310 +setEmitEmitDiv__Q23EGG6EffectFUsQ33EGG6Effect10ERecursive=0x802D8320 +setInitVelocityRandom__Q23EGG6EffectFScQ33EGG6Effect10ERecursive=0x802D8330 +setPowerYAxis__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=0x802D8340 +setPowerRadiationDir__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=0x802D8350 +setPowerSpecDir__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=0x802D8360 +setPowerSpecDirAdd__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=0x802D8370 +setSpecDir__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=0x802D8380 +setSpecDirAdd__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=0x802D8390 +setVelocity__Q23EGG6EffectFRCQ34nw4r4math4VEC3=0x802D83A0 +setColor__Q23EGG6EffectFUcUcUcUcQ33EGG6Effect10ERecursive=0x802D8430 +setDefaultParticleSize__Q23EGG6EffectFRQ34nw4r4math4VEC2Q33EGG6Effect10ERecursive=0x802D84C0 +setParticleScale__Q23EGG6EffectFRQ34nw4r4math4VEC2Q33EGG6Effect10ERecursive=0x802D84D0 +setDefaultParticleRotate__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=0x802D84E0 +setParticleRotate__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=0x802D84F0 +setEmitterSize__Q23EGG6EffectFRCQ34nw4r4math4VEC3bQ33EGG6Effect10ERecursive=0x802D8500 +setLocalScale__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=0x802D8510 +setDynamicsScale__Q23EGG6EffectFRCQ34nw4r4math4VEC3PCQ34nw4r4math4VEC2=0x802D8520 +setScale__Q23EGG6EffectFf=0x802D8620 +setScale__Q23EGG6EffectFRCQ34nw4r4math4VEC3=0x802D8640 +setPos__Q23EGG6EffectFRCQ34nw4r4math4VEC3=0x802D8670 +setMtx__Q23EGG6EffectFRCQ34nw4r4math5MTX34=0x802D86A0 +setPtclAnim__Q23EGG6EffectFib=0x802D86C0 +update__Q23EGG6EffectFv=0x802D88B0 +getEffect__Q23EGG6EffectCFv=0x802D8A30 +getRootEmitter__Q23EGG6EffectCFv=0x802D8AB0 +reset__Q23EGG6EffectFv=0x802D8B30 strlen=0x802DC98C __ptmf_test=0x802DCE80 __ptmf_cmpr=0x802DCEB0 @@ -701,6 +749,7 @@ g_profile_YOSHI=0x80326A50 g_profile_FUKIDASHI_MANAGER=0x803275E0 g_profile_GAMEDISPLAY=0x80327668 sTVModeInfo__Q23EGG6Screen=0x80350820 +mPlayerEntry__9daPyMng_c=0x80355150 mPlayerType__9daPyMng_c=0x80355160 mPlayerMode__9daPyMng_c=0x80355170 mRest__9daPyMng_c=0x80355190 @@ -720,8 +769,10 @@ mspInstance__13daPyDemoMng_c=0x80429F74 mNum__9daPyMng_c=0x80429F80 mCtrlPlrNo__9daPyMng_c=0x80429F84 mActPlayerInfo__9daPyMng_c=0x80429F88 +mScore__9daPyMng_c=0x80429FA0 m_instance__18dActorGroupIdMng_c=0x8042A010 m_instance__11dActorMng_c=0x8042A020 +m_instance__17dActorCreateMng_c=0x8042A028 mspInstance__12dAttention_c=0x8042A030 g_pSndObjEmy__6dAudio=0x8042A03C g_pSndObjMap__6dAudio=0x8042A040 @@ -736,9 +787,12 @@ ms_Instance__8dGraph_c=0x8042A238 m_instance__7dInfo_c=0x8042A25C mGameFlag__7dInfo_c=0x8042A260 m_instance__13dNandThread_c=0x8042A298 +m_instance__14PauseManager_c=0x8042A2B8 +m_OtasukeAfter__14PauseManager_c=0x8042A2C2 m_instance__8dQuake_c=0x8042A2E8 m_instance__10dSaveMng_c=0x8042A320 m_instance__11dScoreMng_c=0x8042A330 +m_instance__13dStageTimer_c=0x8042A350 isZeroWidthSpace__14TagProcessor_c=0x8042A3A8 m_instance__9daWmMap_c=0x8042A46C ms_instance__12daWmPlayer_c=0x8042A480 @@ -749,6 +803,8 @@ m_exeFrame__10dScStage_c=0x8042A4E0 m_gameMode__10dScStage_c=0x8042A4E4 m_loopType__10dScStage_c=0x8042A4E8 m_isCourseOut__10dScStage_c=0x8042A4FD +m_isStaffCredit__10dScStage_c=0x8042A4FF +m_miniGame__10dScStage_c=0x8042A500 m_KoopaJrEscape__10dScStage_c=0x8042A507 changePos__10dScStage_c=0x8042A508 m_WorldNo__9dScWMap_c=0x8042A52D From 748a568d93c51cbdf5ed2107a386092af5669f89 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Tue, 12 Aug 2025 10:44:40 +0200 Subject: [PATCH 08/10] Clean up, use official symbols --- source/dol/bases/d_gamedisplay.cpp | 63 +++++++++++++----------------- syms.txt | 1 + 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/source/dol/bases/d_gamedisplay.cpp b/source/dol/bases/d_gamedisplay.cpp index 53bdef9c..c73919dc 100644 --- a/source/dol/bases/d_gamedisplay.cpp +++ b/source/dol/bases/d_gamedisplay.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -324,13 +325,6 @@ void dGameDisplay_c::fn_801585c0() { void dGameDisplay_c::RestDispSetup() { mVec3_c iconPos[4]; - static const PLAYER_TYPE_e lbl_802F5C28[PLAYER_COUNT] = { - PLAYER_MARIO, - PLAYER_LUIGI, - PLAYER_BLUE_TOAD, - PLAYER_YELLOW_TOAD, - }; - static const u32 lbl_802F5C38[PLAYER_COUNT] = { P_marioIcon_00, P_luijiIcon_00, P_kinoY_00, P_kinoB_00, }; @@ -346,7 +340,7 @@ void dGameDisplay_c::RestDispSetup() { int iconPosIdx = 0; for (int i = 0; i < PLAYER_COUNT; i++) { - int idx = daPyMng_c::getPlayerIndex(lbl_802F5C28[i]); + int idx = daPyMng_c::getPlayerIndex(daPyCom_c::sc_PLAYER_ORDER[i]); if (!daPyMng_c::mPlayerEntry[idx]) { continue; } @@ -734,49 +728,48 @@ void dGameDisplay_c::Effect1UP(int a) { } void dGameDisplay_c::GrayColorSet(int player) { - static const int lbl_802f5c88[] = { - T_left_00, T_x_01, - T_left_01, T_x_02, - T_left_02, T_x_03, - T_left_03, T_x_04 - }; - static const int lbl_802f5ca8[] = { P_marioIcon_00, P_luijiIcon_00, P_kinoB_00, P_kinoY_00 }; - - if (m_454[player] == 0) { - static nw4r::ut::Color grayColor(160, 160, 160, 255); + static nw4r::ut::Color GrayColor(160, 160, 160, 255); + static const int TPANE_IDX_TBL[] = { + T_left_00, T_x_01, + T_left_01, T_x_02, + T_left_02, T_x_03, + T_left_03, T_x_04 + }; + static const int PPANE_IDX_TBL[] = { P_marioIcon_00, P_luijiIcon_00, P_kinoB_00, P_kinoY_00 }; + m_454[player] = true; - nw4r::lyt::Pane *icon1 = mpPicturePanes[lbl_802f5ca8[player]]; + nw4r::lyt::Pane *icon1 = mpPicturePanes[PPANE_IDX_TBL[player]]; nw4r::lyt::Material *mat1 = icon1->GetMaterial(); mColorBackup[0][player] = mat1->GetTevColor(1); - mat1->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(grayColor)); - nw4r::lyt::Pane *icon2 = mpTextBoxes[lbl_802f5c88[player * 2]]; + mat1->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(GrayColor)); + nw4r::lyt::Pane *icon2 = mpTextBoxes[TPANE_IDX_TBL[player * 2]]; nw4r::lyt::Material *mat2 = icon2->GetMaterial(); mColorBackup[1][player] = mat2->GetTevColor(1); - mat2->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(grayColor)); - nw4r::lyt::Pane *icon3 = mpTextBoxes[lbl_802f5c88[player * 2 + 1]]; + mat2->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(GrayColor)); + nw4r::lyt::Pane *icon3 = mpTextBoxes[TPANE_IDX_TBL[player * 2 + 1]]; nw4r::lyt::Material *mat3 = icon3->GetMaterial(); mColorBackup[2][player] = mat3->GetTevColor(1); - mat3->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(grayColor)); + mat3->SetTevColor(1, nw4r::g3d::detail::GetRGBAS10(GrayColor)); } } void dGameDisplay_c::ReturnGrayColorSet(int player) { - static const int lbl_802f5c88[] = { - T_left_00, T_x_01, - T_left_01, T_x_02, - T_left_02, T_x_03, - T_left_03, T_x_04 - }; - static const int lbl_802f5ca8[] = { P_marioIcon_00, P_luijiIcon_00, P_kinoB_00, P_kinoY_00 }; - if (m_454[player] != 0) { + static const int TPANE_IDX_TBL[] = { + T_left_00, T_x_01, + T_left_01, T_x_02, + T_left_02, T_x_03, + T_left_03, T_x_04 + }; + static const int PPANE_IDX_TBL[] = { P_marioIcon_00, P_luijiIcon_00, P_kinoB_00, P_kinoY_00 }; + m_454[player] = 0; - nw4r::lyt::Pane *icon1 = mpPicturePanes[lbl_802f5ca8[player]]; + nw4r::lyt::Pane *icon1 = mpPicturePanes[PPANE_IDX_TBL[player]]; icon1->GetMaterial()->SetTevColor(1, mColorBackup[0][player]); - nw4r::lyt::Pane *icon2 = mpTextBoxes[lbl_802f5c88[player * 2]]; + nw4r::lyt::Pane *icon2 = mpTextBoxes[TPANE_IDX_TBL[player * 2]]; icon2->GetMaterial()->SetTevColor(1, mColorBackup[1][player]); - nw4r::lyt::Pane *icon3 = mpTextBoxes[lbl_802f5c88[player * 2 + 1]]; + nw4r::lyt::Pane *icon3 = mpTextBoxes[TPANE_IDX_TBL[player * 2 + 1]]; icon3->GetMaterial()->SetTevColor(1, mColorBackup[2][player]); } } diff --git a/syms.txt b/syms.txt index ca722c24..e78a7340 100644 --- a/syms.txt +++ b/syms.txt @@ -748,6 +748,7 @@ g_profile_PLAYER_ICE=0x80326960 g_profile_YOSHI=0x80326A50 g_profile_FUKIDASHI_MANAGER=0x803275E0 g_profile_GAMEDISPLAY=0x80327668 +__vt__Q23mEf13levelEffect_c=0x80329CA0 sTVModeInfo__Q23EGG6Screen=0x80350820 mPlayerEntry__9daPyMng_c=0x80355150 mPlayerType__9daPyMng_c=0x80355160 From 1bf4a2ee5e8def9e5083abb896a1a446024ea267 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 26 Oct 2025 18:31:11 +0100 Subject: [PATCH 09/10] Fix CI issue --- slices/wiimj2d.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index 153e2670..50a695e5 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -533,10 +533,12 @@ "nonMatching": true, "memoryRanges": { ".text": "0x1510a0-0x153d00", + ".ctors": "0x1f4-0x1f8", ".data": "0x28fc8-0x29660", ".sbss2": "0x28-0x30", ".rodata": "0x7c48-0x7d00", ".sdata": "0x1d28-0x1d50", + ".sbss": "0x768-0x778", ".sdata2": "0x2b30-0x2b48", ".bss": "0x259e8-0x25ae8" } From 6bc39031a8c02a310f7b8f97f8be4f06f85a745b Mon Sep 17 00:00:00 2001 From: RootCubed Date: Mon, 13 Apr 2026 19:52:35 +0200 Subject: [PATCH 10/10] Match `dGameDisplay_c::setCollect` --- source/dol/bases/d_gamedisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dol/bases/d_gamedisplay.cpp b/source/dol/bases/d_gamedisplay.cpp index c73919dc..beeaae21 100644 --- a/source/dol/bases/d_gamedisplay.cpp +++ b/source/dol/bases/d_gamedisplay.cpp @@ -877,8 +877,8 @@ void dGameDisplay_c::setCollect() { } dMj2dGame_c *save = dSaveMng_c::m_instance->getSaveGame(-1); - u8 l = dScStage_c::m_instance->getCurrCourse(); u8 w = dScStage_c::m_instance->getCurrWorld(); + u8 l = dScStage_c::m_instance->getCurrCourse(); if (w >= WORLD_COUNT || l >= STAGE_COUNT) { return; }