From b1bbae6062eed535b8a4a4e15b356d77a4a6848c Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sat, 9 Aug 2025 16:54:49 +0200 Subject: [PATCH 1/9] Match and link `d2d` --- include/constants/sjis_constants.h | 4 +- include/game/bases/d_2d.hpp | 52 +--- include/game/bases/d_2d/global.hpp | 17 ++ include/game/bases/d_2d/multi.hpp | 55 +++++ .../{d_resource.hpp => d_2d/resource.hpp} | 21 +- include/game/bases/d_SmallScore.hpp | 2 +- include/game/bases/d_SmallScoreManager.hpp | 2 +- include/game/bases/d_actor.hpp | 1 + include/game/bases/d_dvd.hpp | 4 + include/game/bases/d_font_manager.hpp | 11 + include/game/bases/d_game_com.hpp | 1 + include/game/bases/m_2d.hpp | 9 + include/game/mLib/m_2d/resource.hpp | 4 +- include/game/mLib/m_bound_box.hpp | 28 +++ include/game/mLib/m_heap.hpp | 7 + include/game/mLib/m_vec.hpp | 32 --- include/lib/nw4r/ut/ut_RuntimeTypeInfo.h | 6 +- slices/wiimj2d.json | 15 +- source/dol/bases/d_2d.cpp | 232 ++++++++++++++++++ source/dol/bases/d_CourseSelectGuide.cpp | 5 + source/dol/bases/d_SmallScore.cpp | 5 + source/dol/bases/d_actor.cpp | 4 +- syms.txt | 18 +- 23 files changed, 439 insertions(+), 96 deletions(-) create mode 100644 include/game/bases/d_2d/global.hpp create mode 100644 include/game/bases/d_2d/multi.hpp rename include/game/bases/{d_resource.hpp => d_2d/resource.hpp} (54%) create mode 100644 include/game/bases/d_font_manager.hpp create mode 100644 include/game/bases/m_2d.hpp create mode 100644 include/game/mLib/m_bound_box.hpp create mode 100644 source/dol/bases/d_2d.cpp diff --git a/include/constants/sjis_constants.h b/include/constants/sjis_constants.h index f2ca86e5..5e0cee5c 100644 --- a/include/constants/sjis_constants.h +++ b/include/constants/sjis_constants.h @@ -12,8 +12,10 @@ #define D_ACTOR_KIND_STRING "アクター" // [Translation: 2D display heap (m2d::create)] -#define M2D_HEAP_NAME "2D表\示用ヒープ(m2d::create)" +#define M2D_HEAP_NAME "2D表\\示用ヒープ(m2d::create)" // [Translation: Animation switching allocator (m3d::banm_c::m_heap)] #define M3D_BANM_HEAP_NAME "アニメ切り替え用アロケータ(m3d::banm_c::m_heap)" +// [Translation: 2D resource heap (d2d::ResAccMultLoader_c::create)] +#define D2D_HEAP_NAME "2Dリソ\\ース用ヒープ(d2d::ResAccMultLoader_c::create)" diff --git a/include/game/bases/d_2d.hpp b/include/game/bases/d_2d.hpp index 23821bab..e5ce1c4f 100644 --- a/include/game/bases/d_2d.hpp +++ b/include/game/bases/d_2d.hpp @@ -1,51 +1,5 @@ #pragma once -#include -#include -#include -#include -#include -namespace d2d { - -/// @unofficial -struct ClipSettings { - ClipSettings() : mPos(0.0f, 0.0f), mSize(0.0f, 0.0f), mEnabled(false) {} - - ClipSettings &operator=(const ClipSettings &other) { - mPos = other.mPos; - mSize = other.mSize; - mEnabled = other.mEnabled; - return *this; - } - - mVec2_c mPos; - mVec2_c mSize; - bool mEnabled; -}; - -class Multi_c : public m2d::Base_c { -public: - virtual ~Multi_c(); - virtual void draw(); - virtual void calc(); - virtual bool build(const char *, ResAccMult_c *); - - void entry(); - nw4r::lyt::Pane *getRootPane(); - -private: - nw4r::lyt::Layout mLayout; - nw4r::lyt::DrawInfo mDrawInfo; - -public: - ResAccMult_c *mpResAccessor; - mVec2_c mPos; - - ClipSettings mClipSettings; - -private: - u32 mFlags; - u32 mUnknown_98; -}; - -} // namespace d2d +#include +#include +#include diff --git a/include/game/bases/d_2d/global.hpp b/include/game/bases/d_2d/global.hpp new file mode 100644 index 00000000..4287cd36 --- /dev/null +++ b/include/game/bases/d_2d/global.hpp @@ -0,0 +1,17 @@ +#pragma once +#include +#include +#include +#include + +namespace d2d { + +void init(); +void draw(); +void drawBefore(); +void drawAfter(); +void drawBtween(u8, u8); +int setAlpha_patrolPane_patrol(nw4r::lyt::Pane *, void *); +void setAlpha(m2d::Simple_c *, u8); + +} // namespace d2d diff --git a/include/game/bases/d_2d/multi.hpp b/include/game/bases/d_2d/multi.hpp new file mode 100644 index 00000000..26593d9a --- /dev/null +++ b/include/game/bases/d_2d/multi.hpp @@ -0,0 +1,55 @@ +#pragma once +#include +#include +#include +#include + +namespace d2d { + +/// @unofficial +struct ClipSettings { + ClipSettings &operator=(const ClipSettings &other) { + mPos = other.mPos; + mSize = other.mSize; + mEnabled = other.mEnabled; + return *this; + } + + nw4r::math::VEC2 mPos; + nw4r::math::VEC2 mSize; + bool mEnabled; +}; + +class Multi_c : public m2d::Base_c { +public: + Multi_c(); + virtual ~Multi_c(); + virtual void draw(); + virtual void calc(); + virtual bool build(const char *, ResAccMult_c *); + + void entry(); + void calcBefore(); + void calcAfter(); + nw4r::lyt::Pane *getRootPane(); + nw4r::lyt::Pane *findPaneByName(const char *name); + nw4r::lyt::TextBox *findTextBoxByName(const char *name); + nw4r::lyt::Picture *findPictureByName(const char *name); + nw4r::lyt::Window *findWindowByName(const char *name); + +private: + m2d::Layout_c mLayout; + nw4r::lyt::DrawInfo mDrawInfo; + +public: + ResAccMult_c *mpResAccessor; + mVec2_c mPos; + + ClipSettings mClipSettings; + +private: + u32 mFlags; + u32 mUnknown_98; +}; + +} // namespace d2d diff --git a/include/game/bases/d_resource.hpp b/include/game/bases/d_2d/resource.hpp similarity index 54% rename from include/game/bases/d_resource.hpp rename to include/game/bases/d_2d/resource.hpp index 68c52bd8..b5ddde2e 100644 --- a/include/game/bases/d_resource.hpp +++ b/include/game/bases/d_2d/resource.hpp @@ -1,36 +1,45 @@ #pragma once #include #include +#include #include #include namespace d2d { class ResAccMult_c : public m2d::ResAccIf_c { - class InternalAccessor : nw4r::lyt::ArcResourceAccessor {}; + class InternalAccessor : public nw4r::lyt::ArcResourceAccessor { + public: + virtual void* GetResource(ulong type, const char *name, size_t *size); + virtual nw4r::ut::Font *GetFont(const char *name); + }; public: ResAccMult_c(); - + virtual ~ResAccMult_c(); virtual void creater(); + void *getResource(unsigned long, const char *); + InternalAccessor mInternalAccessor; }; class ResAccMultLoader_c : public ResAccMult_c { public: ResAccMultLoader_c(); - ~ResAccMultLoader_c(); - - bool create(EGG::Heap *, unsigned long); - bool remove(); + virtual ~ResAccMultLoader_c(); bool requestEx(const char *, int); bool request(const char *); + bool remove(); + + static bool create(EGG::Heap *heap, ulong size); private: void *mpResource; dDvd::loader_c mLoader; + + static mAllocator_c *ms_res_allocator; }; } // namespace d2d diff --git a/include/game/bases/d_SmallScore.hpp b/include/game/bases/d_SmallScore.hpp index 3d361c9b..3622403a 100644 --- a/include/game/bases/d_SmallScore.hpp +++ b/include/game/bases/d_SmallScore.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include #include diff --git a/include/game/bases/d_SmallScoreManager.hpp b/include/game/bases/d_SmallScoreManager.hpp index 436eb315..44e2bbcb 100644 --- a/include/game/bases/d_SmallScoreManager.hpp +++ b/include/game/bases/d_SmallScoreManager.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include #include diff --git a/include/game/bases/d_actor.hpp b/include/game/bases/d_actor.hpp index 663d508c..69279376 100644 --- a/include/game/bases/d_actor.hpp +++ b/include/game/bases/d_actor.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include diff --git a/include/game/bases/d_dvd.hpp b/include/game/bases/d_dvd.hpp index 9406a8ce..139f4d1e 100644 --- a/include/game/bases/d_dvd.hpp +++ b/include/game/bases/d_dvd.hpp @@ -6,9 +6,13 @@ namespace dDvd { class loader_c { public: + loader_c(); virtual ~loader_c(); virtual void freeHeap(); + void *request(const char *, u8, EGG::Heap *); + bool remove(); + private: u32 mSize; u32 mCommand; diff --git a/include/game/bases/d_font_manager.hpp b/include/game/bases/d_font_manager.hpp new file mode 100644 index 00000000..d26cb0b3 --- /dev/null +++ b/include/game/bases/d_font_manager.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +class dFontMng_c { +public: + static void *getResFontData(const char *name); + static u8 getResFontIndex(const char *name); + static nw4r::ut::Font *getFont(int index); +}; diff --git a/include/game/bases/d_game_com.hpp b/include/game/bases/d_game_com.hpp index b0dbb7d7..32e294cd 100644 --- a/include/game/bases/d_game_com.hpp +++ b/include/game/bases/d_game_com.hpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff --git a/include/game/bases/m_2d.hpp b/include/game/bases/m_2d.hpp new file mode 100644 index 00000000..e50f0422 --- /dev/null +++ b/include/game/bases/m_2d.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include diff --git a/include/game/mLib/m_2d/resource.hpp b/include/game/mLib/m_2d/resource.hpp index 3b608626..0772097f 100644 --- a/include/game/mLib/m_2d/resource.hpp +++ b/include/game/mLib/m_2d/resource.hpp @@ -5,13 +5,15 @@ namespace m2d { class ResAccIf_c { public: - virtual ~ResAccIf_c() = 0; + ResAccIf_c() : mpResAccessor(nullptr), mpResource(nullptr) {} + virtual ~ResAccIf_c() {} virtual void creater() = 0; bool attach(void *, const char *); void detach(); void *getResource(unsigned long, const char *); + void setResAccessor(nw4r::lyt::ArcResourceAccessor *resAccessor) { mpResAccessor = resAccessor; } nw4r::lyt::ArcResourceAccessor *getResAccessor() const { return mpResAccessor; } private: diff --git a/include/game/mLib/m_bound_box.hpp b/include/game/mLib/m_bound_box.hpp new file mode 100644 index 00000000..2866a753 --- /dev/null +++ b/include/game/mLib/m_bound_box.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +/// @unofficial +class mBoundBox { +public: + mBoundBox() {} + + mBoundBox(float t, float b, float l, float r) { + set(t, b, l, r); + } + + mBoundBox(const mBoundBox &b) { + set(b.mOffset.x, b.mOffset.y, b.mSize.x, b.mSize.y); + } + + void set(float t, float b, float l, float r) { + mOffset.set(t, b); + mSize.set(l, r); + } + + mVec2_c getSize() const { + return mSize; + } + + mVec2_c mOffset, mSize; +}; diff --git a/include/game/mLib/m_heap.hpp b/include/game/mLib/m_heap.hpp index 8f5615b8..67b8f8cd 100644 --- a/include/game/mLib/m_heap.hpp +++ b/include/game/mLib/m_heap.hpp @@ -1,9 +1,14 @@ #pragma once #include #include +#include #include namespace mHeap { + enum AllocOptBit_t { + OPT_4 = 4 + }; + void restoreCurrentHeap(); EGG::Heap *setCurrentHeap(EGG::Heap *); size_t frmHeapCost(size_t, size_t); @@ -11,6 +16,8 @@ namespace mHeap { unsigned long adjustFrmHeap(EGG::FrmHeap *); void saveCurrentHeap(); + EGG::ExpHeap *createExpHeap(size_t, EGG::Heap *, const char *, size_t, mHeap::AllocOptBit_t); + /// @unofficial EGG::FrmHeap *makeFrmHeapAndUpdate(unsigned long size, EGG::Heap *parent, const char *name, u32 align, u32 opt); /// @unofficial diff --git a/include/game/mLib/m_vec.hpp b/include/game/mLib/m_vec.hpp index a8fa3dc5..3694ba27 100644 --- a/include/game/mLib/m_vec.hpp +++ b/include/game/mLib/m_vec.hpp @@ -210,35 +210,3 @@ class mVec3_c : public EGG::Vector3f { static mVec3_c Ey; ///< The unit vector for the Y axis. static mVec3_c Ez; ///< The unit vector for the Z axis. }; - -/// @unofficial -class mBoundBox { -public: - mBoundBox() {} - - mBoundBox(float t, float b, float l, float r) { - set(t, b, l, r); - } - - mBoundBox(const mBoundBox &b) { - set(b.mOffset.x, b.mOffset.y, b.mSize.x, b.mSize.y); - } - - void set(float t, float b, float l, float r) { - mOffset.set(t, b); - mSize.set(l, r); - } - - mVec2_c withPos(const mVec3_c &pos) const { - mVec2_c res; - res.x = pos.x + mOffset.x - mSize.x; - res.y = pos.y + mOffset.y + mSize.y; - return res; - } - - mVec2_c getSize() const { - return mSize; - } - - mVec2_c mOffset, mSize; -}; diff --git a/include/lib/nw4r/ut/ut_RuntimeTypeInfo.h b/include/lib/nw4r/ut/ut_RuntimeTypeInfo.h index 6ddc7d24..be84bed6 100644 --- a/include/lib/nw4r/ut/ut_RuntimeTypeInfo.h +++ b/include/lib/nw4r/ut/ut_RuntimeTypeInfo.h @@ -48,8 +48,10 @@ inline TDerived DynamicCast(TBase* pPtr) { detail::GetTypeInfoFromPtr_(static_cast(NULL)); // Downcast only if possible - if (pPtr->GetRuntimeTypeInfo()->IsDerivedFrom(pDerivedTypeInfo)) { - return static_cast(pPtr); + if (pPtr) { + if (pPtr->GetRuntimeTypeInfo()->IsDerivedFrom(pDerivedTypeInfo)) { + return static_cast(pPtr); + } } return NULL; diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index 6ad8b27b..d9abe5b8 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -51,9 +51,22 @@ "__dt__87sStateMgr_c<18dActorMultiState_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv", "__dt__34sFStateFct_c<18dActorMultiState_c>Fv", "__dt__31sFState_c<18dActorMultiState_c>Fv", - "__dt__7mVec3_cFv" + "__dt__7mVec2_cFv", + "__dt__7mVec3_cFv", + "__dt__Q34nw4r3lyt19ArcResourceAccessorFv", + "GetRuntimeTypeInfo__Q34nw4r3lyt4PaneCFv" ], "slices": [ + { + "source": "dol/bases/d_2d.cpp", + "memoryRanges": { + ".text": "0x10-0xd90", + ".data": "0x0-0x88", + ".sbss": "0x0-0x8", + ".sdata": "0x0-0x8", + ".sdata2": "0x0-0x18" + } + }, { "source": "dol/bases/d_CourseSelectGuide.cpp", "memoryRanges": { diff --git a/source/dol/bases/d_2d.cpp b/source/dol/bases/d_2d.cpp new file mode 100644 index 00000000..a7324443 --- /dev/null +++ b/source/dol/bases/d_2d.cpp @@ -0,0 +1,232 @@ +#include +#include +#include +#include +#include +#include +#include + +mAllocator_c *d2d::ResAccMultLoader_c::ms_res_allocator; + +void d2d::init() {} + +void d2d::draw() { + m2d::draw(); +} + +void d2d::drawBefore() { + m2d::drawBefore(129); +} + +void d2d::drawAfter() { + m2d::drawAfter(128); +} + +void d2d::drawBtween(u8 after, u8 before) { + m2d::drawBtween(after, before); +} + +DECL_WEAK +void DUMMY_ORDERING() { + nw4r::lyt::ArcResourceAccessor r; +} + +int d2d::setAlpha_patrolPane_patrol(nw4r::lyt::Pane *pane, void *alpha) { + u8 *pAlpha = (u8 *) alpha; + pane->SetAlpha(*pAlpha); + pane->SetGlbAlpha(*pAlpha); + return 0; +} + +void d2d::setAlpha(m2d::Simple_c *layout, u8 alpha) { + layout->patrolPane(setAlpha_patrolPane_patrol, nullptr, &alpha); +} + +d2d::ResAccMult_c::ResAccMult_c() { + creater(); +} + +d2d::ResAccMult_c::~ResAccMult_c() { +} + +void *d2d::ResAccMult_c::getResource(unsigned long type, const char *name) { + return mInternalAccessor.GetResource(type, name, nullptr); +} + +void d2d::ResAccMult_c::creater() { + setResAccessor(&mInternalAccessor); +} + +void *d2d::ResAccMult_c::InternalAccessor::GetResource(ulong type, const char *name, size_t *size) { + if (type == RES_TYPE_FONT) { + return dFontMng_c::getResFontData(name); + } + return nw4r::lyt::ArcResourceAccessor::GetResource(type, name, size); +} + +nw4r::ut::Font *d2d::ResAccMult_c::InternalAccessor::GetFont(const char *name) { + return dFontMng_c::getFont(dFontMng_c::getResFontIndex(name)); +} + +d2d::ResAccMultLoader_c::ResAccMultLoader_c() : mpResource(nullptr) {} +d2d::ResAccMultLoader_c::~ResAccMultLoader_c() {} + +bool d2d::ResAccMultLoader_c::requestEx(const char *name, int i) { + if (mpResource != nullptr) { + return true; + } + mpResource = mLoader.request(name, i, ms_res_allocator->mpHeap); + if (mpResource != nullptr) { + attach(mpResource, "arc"); + return true; + } else { + return false; + } +} + +bool d2d::ResAccMultLoader_c::request(const char *name) { + return requestEx(name, 0); +} + +bool d2d::ResAccMultLoader_c::remove() { + if (mpResource != nullptr) { + detach(); + ms_res_allocator->free(mpResource); + mpResource = nullptr; + } + return mLoader.remove(); +} + +bool d2d::ResAccMultLoader_c::create(EGG::Heap *parent, ulong size) { + EGG::Heap *heap = mHeap::createExpHeap(size, parent, D2D_HEAP_NAME, 0x20, mHeap::OPT_4); + ms_res_allocator = new(heap, 4) mAllocator_c(); + ms_res_allocator->attach(heap, 0x20); + return true; +} + +d2d::Multi_c::Multi_c() { + mpResAccessor = nullptr; + mPos.x = 0.0f; + mPos.y = 0.0f; + mFlags = 0; + if (dGameCom::GetAspectRatio() == EGG::Screen::TV_MODE_16_9) { + mDrawInfo.SetLocationAdjustScale(mVec2_c(19.0f / 26.0f, 1.0f)); + mDrawInfo.SetLocationAdjust(true); + } + mClipSettings.mEnabled = false; +} + +d2d::Multi_c::~Multi_c() {} + +void d2d::Multi_c::entry() { + m2d::Base_c::entry(); +} + +void d2d::Multi_c::calc() { + calcBefore(); + mMtx_c mtx; + PSMTXIdentity(mtx); + mVec3_c pos(mPos.x, mPos.y, 0.0f); + PSMTXTransApply(mtx, mtx, pos.x, pos.y, pos.z); + mDrawInfo.SetViewMtx(mtx); + calcAfter(); +} + +void d2d::Multi_c::calcBefore() { + ulong option = 0; + if (mFlags & 1) { + option = 1; + } + mLayout.Animate(option); +} + +void d2d::Multi_c::calcAfter() { + mDrawInfo.SetViewRect(mLayout.GetLayoutRect()); + mLayout.CalculateMtx(mDrawInfo); +} + +void d2d::Multi_c::draw() { + nw4r::ut::Rect rect = mLayout.GetLayoutRect(); + float near = 0.0f; + float far = 500.0f; + EGG::Screen screen; + bool isWide = dGameCom::GetAspectRatio() == EGG::Screen::TV_MODE_16_9; + float w_16_9 = EGG::Screen::sTVModeInfo[EGG::Screen::TV_MODE_16_9].width; + float w_4_3 = EGG::Screen::sTVModeInfo[EGG::Screen::TV_MODE_4_3].width; + float left = isWide ? w_16_9 * rect.left / w_4_3 : rect.left; + float right = isWide ? w_16_9 * rect.right / w_4_3 : rect.right; + screen.mProjType = EGG::Frustum::PROJ_ORTHO; + screen.ResetOrthographic(rect.top, rect.bottom, left, right, near, far); + if (isWide) { + screen.mScale = nw4r::math::VEC3(w_4_3 / w_16_9, 1.0f, 1.0f); + } + screen.SetProjectionGX(); + if (mClipSettings.mEnabled) { + u32 x, y, w, h; + GXGetScissor(&x, &y, &w, &h); + GXSetScissor( + mClipSettings.mPos.x, mClipSettings.mPos.y, + mClipSettings.mSize.x, mClipSettings.mSize.y + ); + mLayout.Draw(mDrawInfo); + GXSetScissor(x, y, w, h); + } else { + mLayout.Draw(mDrawInfo); + } +} + +nw4r::lyt::Pane *d2d::Multi_c::getRootPane() { + return mLayout.GetRootPane(); +} + +bool d2d::Multi_c::build(const char *name, ResAccMult_c *resAcc) { + if (mLayout.GetRootPane() != nullptr) { + return true; + } + if (resAcc == nullptr) { + resAcc = mpResAccessor; + if (resAcc == nullptr) { + return false; + } + } + void *lyt = resAcc->getResource(0, name); + if (lyt == nullptr) { + return false; + } + bool res = mLayout.Build(lyt, &resAcc->mInternalAccessor); + if (res) { + calc(); + } + return res; +} + +nw4r::lyt::Pane *d2d::Multi_c::findPaneByName(const char *name) { + return mLayout.GetRootPane()->FindPaneByName(name, true); +} + +nw4r::lyt::TextBox *d2d::Multi_c::findTextBoxByName(const char *name) { + nw4r::lyt::Pane *pane = findPaneByName(name); + if (pane != nullptr) { + nw4r::lyt::TextBox *box = nw4r::ut::DynamicCast(pane); + return box; + } + return nullptr; +} + +nw4r::lyt::Picture *d2d::Multi_c::findPictureByName(const char *name) { + nw4r::lyt::Pane *pane = findPaneByName(name); + if (pane != nullptr) { + nw4r::lyt::Picture *box = nw4r::ut::DynamicCast(pane); + return box; + } + return nullptr; +} + +nw4r::lyt::Window *d2d::Multi_c::findWindowByName(const char *name) { + nw4r::lyt::Pane *pane = findPaneByName(name); + if (pane != nullptr) { + nw4r::lyt::Window *box = nw4r::ut::DynamicCast(pane); + return box; + } + return nullptr; +} diff --git a/source/dol/bases/d_CourseSelectGuide.cpp b/source/dol/bases/d_CourseSelectGuide.cpp index bddddf62..c5b1c7bd 100644 --- a/source/dol/bases/d_CourseSelectGuide.cpp +++ b/source/dol/bases/d_CourseSelectGuide.cpp @@ -243,6 +243,11 @@ bool dCourseSelectGuide_c::createLayout() { void dCourseSelectGuide_c::ScissorMaskSet() { d2d::ClipSettings clipSettings; + clipSettings.mPos.x = 0.0f; + clipSettings.mPos.y = 0.0f; + clipSettings.mSize.x = 0.0f; + clipSettings.mSize.y = 0.0f; + clipSettings.mEnabled = false; if (dGameCom::GetAspectRatio() == 0) { clipSettings.mPos.y = mVideo::getSmth(330.0f); clipSettings.mSize.x = 640.0f; diff --git a/source/dol/bases/d_SmallScore.cpp b/source/dol/bases/d_SmallScore.cpp index 4ed40ccc..e0150410 100644 --- a/source/dol/bases/d_SmallScore.cpp +++ b/source/dol/bases/d_SmallScore.cpp @@ -182,6 +182,11 @@ void dSmallScore_c::setNormalOrBlueColor() { void dSmallScore_c::ScissorMaskSet() { d2d::ClipSettings clip; + clip.mPos.x = 0.0f; + clip.mPos.y = 0.0f; + clip.mSize.x = 0.0f; + clip.mSize.y = 0.0f; + clip.mEnabled = false; if (dGameCom::GetAspectRatio() == 0) { clip.mPos.y = (mVideo::m_video->mRenderModeObj.efbHeight - mClipScale.y) * 0.5f; diff --git a/source/dol/bases/d_actor.cpp b/source/dol/bases/d_actor.cpp index 0852dd43..1a3b41f1 100644 --- a/source/dol/bases/d_actor.cpp +++ b/source/dol/bases/d_actor.cpp @@ -385,7 +385,9 @@ bool dActor_c::areaCullCheck(const mVec3_c &pos, const mBoundBox &bound, u8 area // [Probably some more inlining going on here] mVec2_c b; - mVec2_c bt = bound.withPos(pos); + mVec2_c bt; + bt.x = pos.x + bound.mOffset.x - bound.mSize.x; + bt.y = pos.y + bound.mOffset.y + bound.mSize.y; b.set(bt.x, bt.y); b.x -= area->x; diff --git a/syms.txt b/syms.txt index e045ecda..d56bbb42 100644 --- a/syms.txt +++ b/syms.txt @@ -244,7 +244,6 @@ getLoopPosX__10dScStage_cFf=80101bb0 m_bg_p__5dBg_c=8042a0b0 sqrt__Q23EGG7MathFf=802be760 normalise__Q23EGG8Vector2fFv=802be930 -__dt__7mVec2_cFv=80006df0 __ct__Q23EGG9AllocatorFPQ23EGG4Heapl=802b8bb0 __dt__Q23EGG9AllocatorFv=802b8c10 alloc__Q23EGG9AllocatorFUl=802b8c50 @@ -606,3 +605,20 @@ calcGroup__15EffectManager_cFv=80093530 calcGroupForWm__15EffectManager_cFv=80093a50 sEffectManager__Q23EGG13EffectManager=0x8042B2B0 m_instance__10dScMovie_c=8042a498 +getResFontIndex__10dFontMng_cFPCc=800b1410 +getFont__10dFontMng_cFi=800b1310 +getResFontData__10dFontMng_cFPCc=800b12d0 +GetResource__Q34nw4r3lyt19ArcResourceAccessorFUlPCcPUl=802b6860 +__dt__Q44nw4r2ut6detail12LinkListImplFv=80229170 +__dt__Q34nw4r3lyt16ResourceAccessorFv=802b64f0 +__ct__Q34nw4r3lyt19ArcResourceAccessorFv=802b6760 +__ct__Q24dDvd8loader_cFv=8008f140 +__dt__Q34nw4r3lyt8DrawInfoFv=802b4ef0 +GXGetScissor=801c9e10 +createExpHeap__5mHeapFUlPQ23EGG4HeapPCcUlQ25mHeap13AllocOptBit_t=8016e640 +typeInfo__Q34nw4r3lyt4Pane=8042b0a0 +typeInfo__Q34nw4r3lyt7Picture=8042b0b0 +typeInfo__Q34nw4r3lyt7TextBox=8042b0b8 +typeInfo__Q34nw4r3lyt6Window=8042b0c0 +remove__Q24dDvd8loader_cFv=8008f2b0 +request__Q24dDvd8loader_cFPCcUcPQ23EGG4Heap=8008f1b0 From 6673e95f618c86561d6798b6cbed2cd26ce3e25c Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sat, 9 Aug 2025 19:53:56 +0200 Subject: [PATCH 2/9] 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 5fa26144..053c3e4e 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 a1c366fec1519cfba1c8d8b3adf142b882128ad8 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sat, 9 Aug 2025 19:54:35 +0200 Subject: [PATCH 3/9] Match and link `LytTextBox_c` --- include/game/bases/d_info.hpp | 16 +++-- include/game/bases/d_lytbase.hpp | 4 ++ include/game/bases/d_lyttextBox.hpp | 6 +- include/game/bases/d_message.hpp | 9 ++- include/game/bases/d_tag_processor.hpp | 20 ++++++ include/lib/MSL/stdarg.h | 15 ++++- include/lib/egg/core/eggMsgRes.h | 12 ++++ include/lib/nw4r/lyt/lyt_pane.h | 4 ++ include/lib/nw4r/lyt/lyt_resources.h | 36 ++++++++++- include/lib/nw4r/lyt/lyt_textBox.h | 22 +++---- source/dol/bases/d_lyttextbox.cpp | 89 ++++++++++++++++++++++++++ syms.txt | 13 ++++ 12 files changed, 225 insertions(+), 21 deletions(-) create mode 100644 include/game/bases/d_tag_processor.hpp create mode 100644 include/lib/egg/core/eggMsgRes.h create mode 100644 source/dol/bases/d_lyttextbox.cpp diff --git a/include/game/bases/d_info.hpp b/include/game/bases/d_info.hpp index 33167282..33c3aa13 100644 --- a/include/game/bases/d_info.hpp +++ b/include/game/bases/d_info.hpp @@ -55,9 +55,7 @@ class dInfo_c { u8 getCourse() const { return m_startGameInfo.mLevel1; } u8 getWorld() const { return m_startGameInfo.mWorld1; } - static dInfo_c *getInstance() { - return m_instance; - } + static dInfo_c *getInstance() { return m_instance; } char pad1[0x8]; dCyuukan_c mCyuukan; @@ -68,15 +66,21 @@ class dInfo_c { u8 pad4[0x2e4]; int mCharIDs[4]; bool mIsWorldSelect; ///< Whether the World Select Menu is being displayed. + int pad5[7]; int mDisplayCourseWorld; int mDisplayCourseNum; - u8 pad6[0x1d]; + u8 pad6[0x14]; + int mTextBoxMessageID; + int mTextBoxMessageGroup; + u8 pad7[0x1]; bool mExtensionAttached; - u8 pad7[0x8]; + u8 field_3da; + u8 pad8[0x7]; int mCourseSelectPageNum; int mCourseSelectIndexInPage; - u8 pad8[0x712]; + u8 pad9[0x712]; + bool mFukidashiActionPerformed[4][0x16]; static dInfo_c *m_instance; diff --git a/include/game/bases/d_lytbase.hpp b/include/game/bases/d_lytbase.hpp index a6ca64d4..242dba79 100644 --- a/include/game/bases/d_lytbase.hpp +++ b/include/game/bases/d_lytbase.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include @@ -53,4 +54,7 @@ class LytBase_c : public d2d::Multi_c { int mGroupCount; int mLastStartedAnimNum; + +public: + static TagProcessor_c s_TagPrc; }; diff --git a/include/game/bases/d_lyttextBox.hpp b/include/game/bases/d_lyttextBox.hpp index 2616f0a9..0b19df8c 100644 --- a/include/game/bases/d_lyttextBox.hpp +++ b/include/game/bases/d_lyttextBox.hpp @@ -4,5 +4,9 @@ class LytTextBox_c : public nw4r::lyt::TextBox { public: - void setMessage(MsgRes_c *bmg, unsigned long messageGroup, unsigned long messageID, long, ...); + void setMessage(MsgRes_c *bmg, ulong messageGroup, ulong messageID, long param, ...); + void setMessage(MsgRes_c *bmg, ulong messageGroup, ulong messageID, long param, va_list *vargs); + void ExtensionUserDataSetup(); + void setText(const wchar_t *text, long param, ...); + void setText(const wchar_t *text, long param, va_list *vargs, MsgRes_c *bmg); }; diff --git a/include/game/bases/d_message.hpp b/include/game/bases/d_message.hpp index fbf6f8d0..0dc226cf 100644 --- a/include/game/bases/d_message.hpp +++ b/include/game/bases/d_message.hpp @@ -1,6 +1,13 @@ #pragma once -class MsgRes_c; +#include +#include + +class MsgRes_c : public EGG::MsgRes { +public: + u8 getFont(ulong messageID, ulong messageGroup); + u16 getScale(ulong messageID, ulong messageGroup); +}; class dMessage_c { public: diff --git a/include/game/bases/d_tag_processor.hpp b/include/game/bases/d_tag_processor.hpp new file mode 100644 index 00000000..0691e1d4 --- /dev/null +++ b/include/game/bases/d_tag_processor.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +class TagProcessor_c : public nw4r::ut::WideTagProcessor { +public: + u8 mPad[0xc0]; + u8 mFontIndex; + + void preProcess( + const wchar_t *text, wchar_t *buf, + unsigned long bufLen, int *writeLen, + long param, va_list *vargs, + MsgRes_c *bmg + ); + + static bool isZeroWidthSpace; ///< @unofficial +}; diff --git a/include/lib/MSL/stdarg.h b/include/lib/MSL/stdarg.h index 369b0b0b..61f06eb7 100644 --- a/include/lib/MSL/stdarg.h +++ b/include/lib/MSL/stdarg.h @@ -4,6 +4,8 @@ extern "C" { #endif +#ifdef __CWCC__ + typedef enum _va_arg_type { arg_ARGPOINTER, arg_WORD, @@ -16,7 +18,7 @@ typedef struct __va_list_struct { char fpr; char* input_arg_area; char* reg_save_area; -} va_list[1]; +} va_list; void* __va_arg(va_list argp, int type); @@ -25,6 +27,17 @@ void* __va_arg(va_list argp, int type); #define va_arg(VA_LIST, ARG_TYPE) \ (*(ARG_TYPE*)__va_arg(VA_LIST, _var_arg_typeof(ARG_TYPE))) +#else + +typedef __builtin_va_list va_list; + +#define va_start(VA_LIST, ARG) __builtin_va_start(VA_LIST, ARG) +#define va_end(VA_LIST) ((void)VA_LIST) +#define va_arg(VA_LIST, ARG_TYPE) \ + (*(ARG_TYPE*)__va_arg(VA_LIST, _var_arg_typeof(ARG_TYPE))) + +#endif + #ifdef __cplusplus } #endif diff --git a/include/lib/egg/core/eggMsgRes.h b/include/lib/egg/core/eggMsgRes.h new file mode 100644 index 00000000..b7b93d94 --- /dev/null +++ b/include/lib/egg/core/eggMsgRes.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace EGG { + +class MsgRes { +public: + wchar_t *getMsg(ulong messageID, ulong messageGroup); +}; + +} // namespace EGG diff --git a/include/lib/nw4r/lyt/lyt_pane.h b/include/lib/nw4r/lyt/lyt_pane.h index d0343f87..96982c67 100644 --- a/include/lib/nw4r/lyt/lyt_pane.h +++ b/include/lib/nw4r/lyt/lyt_pane.h @@ -144,6 +144,10 @@ class Pane : public detail::PaneBase { math::VEC2 GetVtxPos() const; + u16 GetExtUserDataNum() const; + const res::ExtUserData *GetExtUserData() const; + const res::ExtUserData *FindExtUserDataByName(const char *name); + Pane* GetParent() const { return mpParent; } diff --git a/include/lib/nw4r/lyt/lyt_resources.h b/include/lib/nw4r/lyt/lyt_resources.h index 614fd282..f5244bdd 100644 --- a/include/lib/nw4r/lyt/lyt_resources.h +++ b/include/lib/nw4r/lyt/lyt_resources.h @@ -1,4 +1,4 @@ -#ifndef NW4R_LYT_RESOURCES_H + #ifndef NW4R_LYT_RESOURCES_H #define NW4R_LYT_RESOURCES_H #include @@ -32,6 +32,40 @@ struct DataBlockHeader { ulong size; // at 0x4 }; +enum ExtUserDataType { + TYPE_STRING, + TYPE_INT, + TYPE_FLOAT, +}; + +struct ExtUserData { + inline const char *GetString() const { + return detail::ConvertOffsToPtr(this, datOffs); + } + + inline float GetFloat() const { + return *detail::ConvertOffsToPtr(this, datOffs); + } + + inline int GetInt() const { + return *detail::ConvertOffsToPtr(this, datOffs); + } + + inline const char *GetName() const { + return nameOffs != 0 ? detail::ConvertOffsToPtr(this, nameOffs) : nullptr; + } + + inline ExtUserDataType GetType() const { + return (ExtUserDataType)type; + } + + u32 nameOffs; // at 0x00 + u32 datOffs; // at 0x04 + u16 numEntries; // at 0x08 + u8 type; // at 0x0A + u8 padding; // at 0x0B +}; + /****************************************************************************** * * Texture diff --git a/include/lib/nw4r/lyt/lyt_textBox.h b/include/lib/nw4r/lyt/lyt_textBox.h index ece77679..51b0c61f 100644 --- a/include/lib/nw4r/lyt/lyt_textBox.h +++ b/include/lib/nw4r/lyt/lyt_textBox.h @@ -148,22 +148,22 @@ class TextBox : public Pane { ulong MakeDrawFlag() const; protected: - wchar_t* mTextBuf; // at 0xD4 - ut::Color mTextColors[TEXTCOLOR_MAX]; // at 0xD8 + wchar_t* mTextBuf; // at 0xD8 + ut::Color mTextColors[TEXTCOLOR_MAX]; // at 0xDC - const ut::Font* mpFont; // at 0xE0 - Size mFontSize; // at 0xE4 - f32 mLineSpace; // at 0xEC - f32 mCharSpace; // at 0xF0 + const ut::Font* mpFont; // at 0xE4 + Size mFontSize; // at 0xE8 + f32 mLineSpace; // at 0xF0 + f32 mCharSpace; // at 0xF4 - ut::WideTagProcessor* mpTagProcessor; // at 0xF4 - u16 mTextBufBytes; // at 0xF8 - u16 mTextLen; // at 0xFA - u8 mTextPosition; // at 0xFC + ut::WideTagProcessor* mpTagProcessor; // at 0xF8 + u16 mTextBufBytes; // at 0xFC + u16 mTextLen; // at 0xFE + u8 mTextPosition; // at 0x100 struct { u8 bAllocFont : 1; - } mBits; // at 0xFD + } mBits; // at 0x101 private: void Init(u16 len); diff --git a/source/dol/bases/d_lyttextbox.cpp b/source/dol/bases/d_lyttextbox.cpp new file mode 100644 index 00000000..b17778fe --- /dev/null +++ b/source/dol/bases/d_lyttextbox.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include + +void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageID, ulong messageGroup, long param, ...) { + dInfo_c *info = dInfo_c::getInstance(); + info->mTextBoxMessageID = messageID; + info->mTextBoxMessageGroup = messageGroup; + + va_list args; + va_start(args, param); + setMessage(bmg, messageID, messageGroup, param, &args); + va_end(args); +} + +void LytTextBox_c::ExtensionUserDataSetup() { + dInfo_c *info = dInfo_c::getInstance(); + const nw4r::lyt::res::ExtUserData *userData = FindExtUserDataByName("shadow"); + if (userData != nullptr && *(int *) (((u8 *) userData) + userData->datOffs) != 0) { + info->field_3da = true; + } +} + +void LytTextBox_c::setMessage(MsgRes_c *bmg, ulong messageID, ulong messageGroup, long param, va_list *vargs) { + nw4r::lyt::Size fontSize = GetFontSize(); + + u8 fontIndex = bmg->getFont(messageID, messageGroup); + SetFont(dFontMng_c::getFont(fontIndex)); + LytBase_c::s_TagPrc.mFontIndex = fontIndex; + + dInfo_c *info = dInfo_c::getInstance(); + info->field_3da = 0; + + u16 extUserDataNum = GetExtUserDataNum(); + if (extUserDataNum != 0) { + ExtensionUserDataSetup(); + } + info->mTextBoxMessageID = messageID; + info->mTextBoxMessageGroup = messageGroup; + setText(bmg->getMsg(messageID, messageGroup), param, vargs, bmg); + + float charWScale = bmg->getScale(messageID, messageGroup) * 0.01f; + fontSize.width = GetFont()->GetWidth() * charWScale; + SetFontSize(fontSize); + + nw4r::lyt::Size size = GetSize(); + nw4r::lyt::Size newSize = size; + newSize.width = 1024.0f; + SetSize(newSize); + + nw4r::ut::WideTextWriter textWriter; + + float prevSpaceSize = GetCharSpace(); + nw4r::ut::Rect rectWithSpace = GetTextDrawRect(&textWriter); + SetCharSpace(0.0f); + TagProcessor_c::isZeroWidthSpace = true; + nw4r::ut::Rect rectNoSpace = GetTextDrawRect(&textWriter); + TagProcessor_c::isZeroWidthSpace = false; + SetCharSpace(prevSpaceSize); + SetSize(size); + + float widthNoSpace = rectNoSpace.GetWidth(); + float widthWithSpace = rectWithSpace.GetWidth(); + float widthDiff = widthWithSpace - widthNoSpace; + if (size.width < widthWithSpace && widthNoSpace > 0.0f) { + float prevScale = charWScale; + charWScale *= (((size.width - widthDiff) - 4.0f) / widthNoSpace); + if (charWScale < prevScale) { + fontSize.width = GetFont()->GetWidth() * charWScale; + SetFontSize(fontSize); + } + } +} + +void LytTextBox_c::setText(const wchar_t *text, long param, ...) { + va_list args; + va_start(args, param); + setText(text, param, &args, nullptr); + va_end(args); +} + +void LytTextBox_c::setText(const wchar_t *text, long param, va_list *vargs, MsgRes_c *bmg) { + static wchar_t Buffer[0x200]; + int count = 0; + LytBase_c::s_TagPrc.preProcess(text, Buffer, ARRAY_SIZE(Buffer), &count, param, vargs, bmg); + SetString(Buffer, 0, count); +} diff --git a/syms.txt b/syms.txt index d56bbb42..78080fd3 100644 --- a/syms.txt +++ b/syms.txt @@ -622,3 +622,16 @@ typeInfo__Q34nw4r3lyt7TextBox=8042b0b8 typeInfo__Q34nw4r3lyt6Window=8042b0c0 remove__Q24dDvd8loader_cFv=8008f2b0 request__Q24dDvd8loader_cFPCcUcPQ23EGG4Heap=8008f1b0 +getFont__8MsgRes_cFUlUl=800ce8c0 +getScale__8MsgRes_cFUlUl=800ce890 +SetFont__Q34nw4r3lyt7TextBoxFPCQ34nw4r2ut4Font=802af1c0 +s_TagPrc__9LytBase_c=80359770 +GetExtUserDataNum__Q34nw4r3lyt4PaneCFv=802ac5a0 +FindExtUserDataByName__Q34nw4r3lyt4PaneFPCc=802ac5c0 +getMsg__Q23EGG6MsgResFUlUl=802d7b50 +preProcess__14TagProcessor_cFPCwPwUlPilP16__va_list_structP8MsgRes_c=800e72d0 +GetFont__Q34nw4r3lyt7TextBoxCFv=802af1b0 +__ct__Q34nw4r2ut17TextWriterBaseFv=802308c0 +__dt__Q34nw4r2ut17TextWriterBaseFv=80230920 +GetTextDrawRect__Q34nw4r3lyt7TextBoxCFPQ34nw4r2ut17TextWriterBase=802af380 +isZeroWidthSpace__14TagProcessor_c=8042a3a8 From 8e2e415c25265fdb790517439d916b09fd58ae49 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 10 Aug 2025 14:31:04 +0200 Subject: [PATCH 4/9] `LytBase_c` 95% matching --- include/game/bases/d_2d/multi.hpp | 20 +- include/game/bases/d_game_com.hpp | 5 +- include/game/bases/d_info.hpp | 2 +- include/game/bases/d_lytbase.hpp | 51 ++--- include/game/bases/d_message.hpp | 4 +- include/game/bases/d_tag_processor.hpp | 2 + include/game/mLib/m_2d/animation.hpp | 16 +- include/game/mLib/m_vec.hpp | 5 + include/game/mLib/m_video.hpp | 3 + include/lib/egg/core/eggMsgRes.h | 2 +- slices/wiimj2d.json | 18 ++ source/dol/bases/d_lytbase.cpp | 294 +++++++++++++++++++++++++ source/dol/bases/d_lyttextbox.cpp | 16 +- 13 files changed, 393 insertions(+), 45 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 26593d9a..26ff63b0 100644 --- a/include/game/bases/d_2d/multi.hpp +++ b/include/game/bases/d_2d/multi.hpp @@ -8,6 +8,18 @@ namespace d2d { /// @unofficial 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; @@ -15,8 +27,8 @@ struct ClipSettings { return *this; } - nw4r::math::VEC2 mPos; - nw4r::math::VEC2 mSize; + mVec2_c mPos; + mVec2_c mSize; bool mEnabled; }; @@ -26,7 +38,7 @@ class Multi_c : public m2d::Base_c { virtual ~Multi_c(); virtual void draw(); virtual void calc(); - virtual bool build(const char *, ResAccMult_c *); + virtual bool build(const char *name, ResAccMult_c *resAcc); void entry(); void calcBefore(); @@ -37,7 +49,7 @@ class Multi_c : public m2d::Base_c { nw4r::lyt::Picture *findPictureByName(const char *name); nw4r::lyt::Window *findWindowByName(const char *name); -private: +protected: m2d::Layout_c mLayout; nw4r::lyt::DrawInfo mDrawInfo; diff --git a/include/game/bases/d_game_com.hpp b/include/game/bases/d_game_com.hpp index 32e294cd..76785803 100644 --- a/include/game/bases/d_game_com.hpp +++ b/include/game/bases/d_game_com.hpp @@ -98,9 +98,10 @@ namespace dGameCom { void DispSizeScale(nw4r::math::VEC2 &scale); 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); + bool isNowCourseClear(); + + void AreaLanguageFolder(const char *, char *); } diff --git a/include/game/bases/d_info.hpp b/include/game/bases/d_info.hpp index 33c3aa13..91f37399 100644 --- a/include/game/bases/d_info.hpp +++ b/include/game/bases/d_info.hpp @@ -71,8 +71,8 @@ class dInfo_c { int mDisplayCourseWorld; int mDisplayCourseNum; u8 pad6[0x14]; - int mTextBoxMessageID; int mTextBoxMessageGroup; + int mTextBoxMessageID; u8 pad7[0x1]; bool mExtensionAttached; u8 field_3da; diff --git a/include/game/bases/d_lytbase.hpp b/include/game/bases/d_lytbase.hpp index 242dba79..ed7c591e 100644 --- a/include/game/bases/d_lytbase.hpp +++ b/include/game/bases/d_lytbase.hpp @@ -9,39 +9,41 @@ class LytBase_c : public d2d::Multi_c { public: LytBase_c(); ~LytBase_c(); - virtual bool build(const char *, d2d::ResAccMult_c *); - - LytTextBox_c *findTextBox(const char *); - void allocStringBuffer(nw4r::lyt::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); + virtual bool build(const char *name, d2d::ResAccMult_c *resAcc); + + LytTextBox_c *findTextBox(const char *name); + void allocStringBuffer(nw4r::lyt::Pane *pane); + + 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(); + m2d::AnmGroup_c &getAnmGroup(int index) const { return mpAnimGroup[index]; } + private: d2d::ResAccMultLoader_c mResAccessorLoader; @@ -50,7 +52,6 @@ class LytBase_c : public d2d::Multi_c { bool *mpEnabledAnims; int mAnimCount; - int mGroupCount; int mLastStartedAnimNum; diff --git a/include/game/bases/d_message.hpp b/include/game/bases/d_message.hpp index 0dc226cf..ca627003 100644 --- a/include/game/bases/d_message.hpp +++ b/include/game/bases/d_message.hpp @@ -5,8 +5,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 ea0270b7..f392c91d 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); @@ -38,7 +38,7 @@ class AnmGroupBase_c { FLAG_ENABLED = BIT_FLAG(0), }; - 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,6 +52,18 @@ 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 play() { mpFrameCtrl->play(); updateFrame(); } + void setStart() { mpFrameCtrl->setFrame(1.0f); updateFrame(); } + void setEnd() { mpFrameCtrl->setFrame(mpFrameCtrl->getLastActiveFrame()); updateFrame(); } + + FrameCtrl_c mFrameCtrl; }; } // namespace m2d diff --git a/include/game/mLib/m_vec.hpp b/include/game/mLib/m_vec.hpp index 3694ba27..ef14e5cf 100644 --- a/include/game/mLib/m_vec.hpp +++ b/include/game/mLib/m_vec.hpp @@ -22,6 +22,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; @@ -94,6 +95,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/include/game/mLib/m_video.hpp b/include/game/mLib/m_video.hpp index e0070cd5..dd219dec 100644 --- a/include/game/mLib/m_video.hpp +++ b/include/game/mLib/m_video.hpp @@ -5,6 +5,9 @@ class mVideo { public: GXRenderModeObj &mRenderModeObj; + 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; } static mVideo *m_video; 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 d9abe5b8..d6100a7d 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -193,6 +193,24 @@ ".sdata2": "0xf80-0xfa0" } }, + { + "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": { + ".text": "0xc33d0-0xc3880", + ".sdata": "0x598-0x5a0", + ".sdata2": "0x1898-0x18b8", + ".bss": "0x7eb8-0x82b8" + } + }, { "source": "dol/bases/d_main.cpp", "memoryRanges": { diff --git a/source/dol/bases/d_lytbase.cpp b/source/dol/bases/d_lytbase.cpp new file mode 100644 index 00000000..3a755462 --- /dev/null +++ b/source/dol/bases/d_lytbase.cpp @@ -0,0 +1,294 @@ +#include +#include +#include +#include + +TagProcessor_c LytBase_c::s_TagPrc; + +LytBase_c::LytBase_c() { + mAnimCount = 0; + mGroupCount = 0; +} + +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 **windowPaneNames, nw4r::lyt::Window **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findWindowByName(windowPaneNames[i]); + } +} + +void LytBase_c::PPaneRegister(const char **picPaneNames, nw4r::lyt::Picture **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findPictureByName(picPaneNames[i]); + } +} + +void LytBase_c::TPaneRegister(const char **textboxNames, LytTextBox_c **panes, int count) { + for (int i = 0; i < count; i++) { + panes[i] = findTextBox(textboxNames[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]); + } +} + +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 sx = mVideo::m_video->getScaledWidth(width); + float sy = mVideo::m_video->getScaledHeight(height); + + float scX = paneScale.x * sx; + float scY = paneScale.y * sy; + + float scX2 = mtx._11 * scX; + float scY2 = mtx._11 * scY; + + tmpx *= sx; + tmpy *= sy; + + 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; +} + +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; +} diff --git a/source/dol/bases/d_lyttextbox.cpp b/source/dol/bases/d_lyttextbox.cpp index b17778fe..f5c7db4c 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 param, ...) { +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, param); - setMessage(bmg, messageID, messageGroup, param, &args); + 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 param, 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), param, 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 de1dfbd698f56537222edd881e308b1eab55dcea Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 10 Aug 2025 14:51:52 +0200 Subject: [PATCH 5/9] Fix compiler warning for sjis_constants.h --- include/constants/sjis_constants.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/constants/sjis_constants.h b/include/constants/sjis_constants.h index 5e0cee5c..ced3bed7 100644 --- a/include/constants/sjis_constants.h +++ b/include/constants/sjis_constants.h @@ -12,10 +12,10 @@ #define D_ACTOR_KIND_STRING "アクター" // [Translation: 2D display heap (m2d::create)] -#define M2D_HEAP_NAME "2D表\\示用ヒープ(m2d::create)" +#define M2D_HEAP_NAME "2D表\示用ヒープ(m2d::create)" // [Translation: Animation switching allocator (m3d::banm_c::m_heap)] #define M3D_BANM_HEAP_NAME "アニメ切り替え用アロケータ(m3d::banm_c::m_heap)" // [Translation: 2D resource heap (d2d::ResAccMultLoader_c::create)] -#define D2D_HEAP_NAME "2Dリソ\\ース用ヒープ(d2d::ResAccMultLoader_c::create)" +#define D2D_HEAP_NAME "2Dリソ\ース用ヒープ(d2d::ResAccMultLoader_c::create)" From 43aa295d60c04b9bf535ff9e769610d7fcf032d5 Mon Sep 17 00:00:00 2001 From: user Date: Sun, 10 Aug 2025 22:50:38 +0200 Subject: [PATCH 6/9] `dGameDisplay_c` 96% matching --- include/game/bases/d_a_player_manager.hpp | 2 + include/game/bases/d_game_com.hpp | 1 + include/game/bases/d_gamedisplay.hpp | 293 +++++++ include/game/bases/d_info.hpp | 2 +- include/game/bases/d_multi_manager.hpp | 3 + include/game/bases/d_s_stage.hpp | 12 +- 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_actor.cpp | 4 +- source/dol/bases/d_gamedisplay.cpp | 943 ++++++++++++++++++++++ syms.txt | 57 ++ 14 files changed, 1339 insertions(+), 5 deletions(-) create mode 100644 include/game/bases/d_gamedisplay.hpp create mode 100644 source/dol/bases/d_gamedisplay.cpp diff --git a/include/game/bases/d_a_player_manager.hpp b/include/game/bases/d_a_player_manager.hpp index 8d103b4f..95df08f6 100644 --- a/include/game/bases/d_a_player_manager.hpp +++ b/include/game/bases/d_a_player_manager.hpp @@ -17,6 +17,8 @@ class daPyMng_c { static int mNum; static u8 mActPlayerInfo; + static int mScore; + static int mPlayerEntry[4]; static int 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 76785803..c41c8325 100644 --- a/include/game/bases/d_game_com.hpp +++ b/include/game/bases/d_game_com.hpp @@ -104,4 +104,5 @@ namespace dGameCom { bool isNowCourseClear(); void AreaLanguageFolder(const char *, char *); + void fn_800B37E0(mVec3_c &, bool); } diff --git a/include/game/bases/d_gamedisplay.hpp b/include/game/bases/d_gamedisplay.hpp new file mode 100644 index 00000000..b0afdf08 --- /dev/null +++ b/include/game/bases/d_gamedisplay.hpp @@ -0,0 +1,293 @@ +#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_info.hpp b/include/game/bases/d_info.hpp index 91f37399..cf0db3ac 100644 --- a/include/game/bases/d_info.hpp +++ b/include/game/bases/d_info.hpp @@ -29,7 +29,7 @@ class dInfo_c { u8 mEntrance; u8 mArea; bool mIsReplay; - u32 mScreenType; + int mScreenType; u8 mWorld1; u8 mLevel1; u8 mWorld2; diff --git a/include/game/bases/d_multi_manager.hpp b/include/game/bases/d_multi_manager.hpp index dce74df2..8df8d819 100644 --- a/include/game/bases/d_multi_manager.hpp +++ b/include/game/bases/d_multi_manager.hpp @@ -2,6 +2,9 @@ class dMultiMng_c { public: + char m_00[4]; + int m_04; + void setClapSE(); void incEnemyDown(int killedBy); diff --git a/include/game/bases/d_s_stage.hpp b/include/game/bases/d_s_stage.hpp index cf2d2eff..1210f388 100644 --- a/include/game/bases/d_s_stage.hpp +++ b/include/game/bases/d_s_stage.hpp @@ -13,8 +13,14 @@ class dScStage_c : public dScene_c { LOOP_COUNT, }; - char pad[0x119a]; + char pad[0x1198]; + u8 mCurrWorld; u8 mCurrCourse; + u8 mCurrFile; + + u8 getWorld() { return mCurrWorld; } + u8 getCourse() { return mCurrCourse; } + u8 getFile() { return mCurrFile; } static float getLoopPosX(float x); static int m_loopType; @@ -27,4 +33,8 @@ class dScStage_c : public dScene_c { static changePosFunc changePos; static dScStage_c *m_instance; + static s32 m_gameMode; + static u32 m_miniGame; + static bool m_isStaffCredit; + static s32 mCollectionCoin[3]; }; diff --git a/include/game/framework/f_profile_name.hpp b/include/game/framework/f_profile_name.hpp index 3a7223e6..2289b566 100644 --- a/include/game/framework/f_profile_name.hpp +++ b/include/game/framework/f_profile_name.hpp @@ -713,7 +713,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 5dc13255..753a101b 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 ef14e5cf..3c642bd7 100644 --- a/include/game/mLib/m_vec.hpp +++ b/include/game/mLib/m_vec.hpp @@ -187,6 +187,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 d6100a7d..19f95e10 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -341,6 +341,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_actor.cpp b/source/dol/bases/d_actor.cpp index 1a3b41f1..ac16e4f7 100644 --- a/source/dol/bases/d_actor.cpp +++ b/source/dol/bases/d_actor.cpp @@ -59,7 +59,7 @@ dActor_c::dActor_c() : setDefaultMaxBound(); mDestroyBound = mBoundBox(256.0f, 256.0f, 80.0f, 80.0f); - dCdFile_c *file = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrCourse); + dCdFile_c *file = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrFile); mAreaNo = file->getAreaNo(&mPos); mBc.mpRc = &mRc; @@ -377,7 +377,7 @@ void dActor_c::deleteActor(u8 deleteForever) { } bool dActor_c::areaCullCheck(const mVec3_c &pos, const mBoundBox &bound, u8 areaID) const { - dCdFile_c *course = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrCourse); + dCdFile_c *course = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrFile); AreaBoundU16 *area = course->getAreaP(areaID, nullptr); if (area == nullptr) { return true; diff --git a/source/dol/bases/d_gamedisplay.cpp b/source/dol/bases/d_gamedisplay.cpp new file mode 100644 index 00000000..685330f9 --- /dev/null +++ b/source/dol/bases/d_gamedisplay.cpp @@ -0,0 +1,943 @@ +#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_CHARACTER_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.mScreenType == 3 + ) { + 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.mScreenType == 2 || dInfo_c::m_startGameInfo.mScreenType == 3) { + 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->getCourse(); + u8 w = dScStage_c::m_instance->getWorld(); + if (w >= WORLD_COUNT || l >= STAGE_COUNT) { + return; + } + + if (dInfo_c::m_startGameInfo.mScreenType == 2 || dInfo_c::m_startGameInfo.mScreenType == 3) { + return; + } + + for (u32 coin_id = 0; coin_id < 3; coin_id++) { + if (save->isCollectCoin(w, l, coin_id) && (dInfo_c::m_startGameInfo.mScreenType == 0)) { + mpPicturePanes[P_collectOff_00 + 2 * coin_id]->SetVisible(false); + mpPicturePanes[P_collection_00 + 2 * coin_id]->SetVisible(true); + if (m_3EC[coin_id] != 2) { + m_3EC[coin_id] = 2; + } + } else if (dScStage_c::mCollectionCoin[coin_id] != 4) { + mpPicturePanes[P_collectOff_00 + 2 * coin_id]->SetVisible(false); + mpPicturePanes[P_collection_00 + 2 * coin_id]->SetVisible(true); + if (m_3EC[coin_id] != 2) { + m_3EC[coin_id] = 2; + EffectCollectionCoinGet(coin_id); + } + } else { + mpPicturePanes[P_collectOff_00 + 2 * coin_id]->SetVisible(true); + mpPicturePanes[P_collection_00 + 2 * coin_id]->SetVisible(false); + if (m_3EC[coin_id] != 0) { + m_3EC[coin_id] = 0; + } + } + } + mLayout.calc(); +} + +#define MAX_SCORE 99999950 +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 78080fd3..4b62deb0 100644 --- a/syms.txt +++ b/syms.txt @@ -635,3 +635,60 @@ __ct__Q34nw4r2ut17TextWriterBaseFv=802308c0 __dt__Q34nw4r2ut17TextWriterBaseFv=80230920 GetTextDrawRect__Q34nw4r3lyt7TextBoxCFPQ34nw4r2ut17TextWriterBase=802af380 isZeroWidthSpace__14TagProcessor_c=8042a3a8 +__ct__Q23EGG6EffectFv=802D7D90 +__dt__Q23EGG6EffectFv=802D7E10 +create__Q23EGG6EffectFv=802D7E70 +fade__Q23EGG6EffectFv=802D7F40 +followFade__Q23EGG6EffectFv=802D7FD0 +kill__Q23EGG6EffectFv=802D8040 +reset__Q23EGG6EffectFv=802D8B30 +setColor__Q23EGG6EffectFUcUcUcUcQ33EGG6Effect10ERecursive=802D8430 +setDefaultParticleSize__Q23EGG6EffectFRQ34nw4r4math4VEC2Q33EGG6Effect10ERecursive=802D84C0 +setDisableCalc__Q23EGG6EffectFb=802D80E0 +setDisableCalcDraw__Q23EGG6EffectFb=802D8220 +setDisableDraw__Q23EGG6EffectFb=802D8180 +setEmitEmitDiv__Q23EGG6EffectFUsQ33EGG6Effect10ERecursive=802D8320 +setEmitInterval__Q23EGG6EffectFUsQ33EGG6Effect10ERecursive=802D8310 +setEmitRatio__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=802D8300 +setEmitterSize__Q23EGG6EffectFRCQ34nw4r4math4VEC3bQ33EGG6Effect10ERecursive=802D8500 +setInitVelocityRandom__Q23EGG6EffectFScQ33EGG6Effect10ERecursive=802D8330 +setLife__Q23EGG6EffectFUsQ33EGG6Effect10ERecursive=802D82F0 +setLocalScale__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=802D8510 +setMtx__Q23EGG6EffectFRCQ34nw4r4math5MTX34=802D86A0 +setParticleRotate__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=802D84F0 +setPos__Q23EGG6EffectFRCQ34nw4r4math4VEC3=802D8670 +setPowerSpecDir__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=802D8360 +setPowerYAxis__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=802D8340 +setPtclAnim__Q23EGG6EffectFib=802D86C0 +setScale__Q23EGG6EffectFRCQ34nw4r4math4VEC3=802D8640 +setScale__Q23EGG6EffectFf=802D8620 +setSpecDirAdd__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=802D8390 +setSpecDir__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=802D8380 +setVelocity__Q23EGG6EffectFRCQ34nw4r4math4VEC3=802D83A0 +update__Q23EGG6EffectFv=802D88B0 +createEffect__Q23mEf8effect_cFPCci=8016CAA0 +createEffect__Q23mEf8effect_cFPCcUlPC6mMtx_c=8016CCA0 +follow__Q23mEf8effect_cFPC6mMtx_c=0x8016D090 +follow__Q23mEf8effect_cFPC7mVec3_cPC7mAng3_cPC7mVec3_c=0x8016CFE0 +cleanup__Q23mEf13levelEffect_cFv=8016D5F0 +getEffect__Q23EGG6EffectCFv=802D8A30 +getRootEmitter__Q23EGG6EffectCFv=802D8AB0 +setDefaultParticleRotate__Q23EGG6EffectFRCQ34nw4r4math4VEC3Q33EGG6Effect10ERecursive=802D84E0 +createEffect__Q23mEf8effect_cFPCcUlPC7mVec3_cPC7mAng3_cPC7mVec3_c=8016CBF0 +setDynamicsScale__Q23EGG6EffectFRCQ34nw4r4math4VEC3PCQ34nw4r4math4VEC2=802D8520 +setPowerRadiationDir__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=802D8350 +setPowerSpecDirAdd__Q23EGG6EffectFfQ33EGG6Effect10ERecursive=802D8370 +setParticleScale__Q23EGG6EffectFRQ34nw4r4math4VEC2Q33EGG6Effect10ERecursive=802D84D0 +m_OtasukeAfter__14PauseManager_c=0x8042A2C2 +m_gameMode__10dScStage_c=0x8042A4E4 +m_miniGame__10dScStage_c=0x8042A500 +m_isStaffCredit__10dScStage_c=0x8042A4FF +fn_800B37E0__8dGameComFR7mVec3_cb=0x800B37E0 +m_instance__13dStageTimer_c=0x8042A350 +mPlayerEntry__9daPyMng_c=0x80355150 +m_instance__17dActorCreateMng_c=0x8042A028 +mScore__9daPyMng_c=0x80429FA0 +mCollectionCoin__10dScStage_c=0x803744B0 +setTimer__13dStageTimer_cFs=0x800E3A00 +m_instance__14PauseManager_c=0x8042A2B8 +holdSystemSe__11SndAudioMgrFUiUl=0x801954E0 From 4d972629436a08685a0cbb25e51868307bbebe05 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Tue, 12 Aug 2025 10:44:40 +0200 Subject: [PATCH 7/9] 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 685330f9..64a143bb 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_CHARACTER_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 4b62deb0..eefadd73 100644 --- a/syms.txt +++ b/syms.txt @@ -692,3 +692,4 @@ mCollectionCoin__10dScStage_c=0x803744B0 setTimer__13dStageTimer_cFs=0x800E3A00 m_instance__14PauseManager_c=0x8042A2B8 holdSystemSe__11SndAudioMgrFUiUl=0x801954E0 +__vt__Q23mEf13levelEffect_c=80329ca0 From 5292e71c1ba190c4d6b531550a05e2e4b1e01344 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 26 Oct 2025 18:31:11 +0100 Subject: [PATCH 8/9] Fix CI issue --- slices/wiimj2d.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index 19f95e10..3d369a69 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -346,10 +346,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 55e5388ae6ad690c1a4a70c54ebac29157653b29 Mon Sep 17 00:00:00 2001 From: RootCubed Date: Sun, 26 Oct 2025 19:19:55 +0100 Subject: [PATCH 9/9] Fix CI issue --- slices/wiimj2d.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/slices/wiimj2d.json b/slices/wiimj2d.json index 3d369a69..30d9d2cc 100644 --- a/slices/wiimj2d.json +++ b/slices/wiimj2d.json @@ -199,7 +199,11 @@ "memoryRanges": { ".text": "0xc2220-0xc33d0", ".ctors": "0x11c-0x120", - ".rodata": "0x3338-0x33a0" + ".rodata": "0x3338-0x33a0", + ".data": "0x19098-0x190c8", + ".bss": "0x7de0-0x7eb8", + ".sdata": "0x588-0x598", + ".sdata2": "0x1878-0x1898" } }, {