diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 4287dc06..5ffd5cd3 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -7269,7 +7269,7 @@ executeState_Out__19dLytMsgWindowWood_cFv = .text:0x801260E0; // type:function s finalizeState_Out__19dLytMsgWindowWood_cFv = .text:0x80126160; // type:function size:0x4 execute__19dLytMsgWindowWood_cFv = .text:0x80126170; // type:function size:0xBC draw__19dLytMsgWindowWood_cFv = .text:0x80126230; // type:function size:0x14 -open__19dLytMsgWindowWood_cFv = .text:0x80126250; // type:function size:0xC +open__19dLytMsgWindowWood_cFP12dAcObjBase_cUl = .text:0x80126250; // type:function size:0xC isDoneOpening__19dLytMsgWindowWood_cCFv = .text:0x80126260; // type:function size:0x4C close__19dLytMsgWindowWood_cFv = .text:0x801262B0; // type:function size:0xC isDoneClosing__19dLytMsgWindowWood_cCFv = .text:0x801262C0; // type:function size:0x4C @@ -7297,7 +7297,7 @@ executeState_Out__20dLytMsgWindowStone_cFv = .text:0x80126D40; // type:function finalizeState_Out__20dLytMsgWindowStone_cFv = .text:0x80126DC0; // type:function size:0x4 execute__20dLytMsgWindowStone_cFv = .text:0x80126DD0; // type:function size:0xBC draw__20dLytMsgWindowStone_cFv = .text:0x80126E90; // type:function size:0x14 -open__20dLytMsgWindowStone_cFv = .text:0x80126EB0; // type:function size:0xC +open__20dLytMsgWindowStone_cFP12dAcObjBase_cUl = .text:0x80126EB0; // type:function size:0xC isDoneOpening__20dLytMsgWindowStone_cCFv = .text:0x80126EC0; // type:function size:0x4C close__20dLytMsgWindowStone_cFv = .text:0x80126F10; // type:function size:0xC isDoneClosing__20dLytMsgWindowStone_cCFv = .text:0x80126F20; // type:function size:0x4C @@ -7437,7 +7437,7 @@ build__17dLytAutoCaption_cFPQ23d2d10ResAccIf_cPQ23d2d10ResAccIf_cP15dTagProcesso remove__17dLytAutoCaption_cFv = .text:0x8012BDE0; // type:function size:0x50 execute__17dLytAutoCaption_cFv = .text:0x8012BE30; // type:function size:0xA8 draw__17dLytAutoCaption_cFv = .text:0x8012BEE0; // type:function size:0x14 -open__17dLytAutoCaption_cFv = .text:0x8012BF00; // type:function size:0xC +open__17dLytAutoCaption_cFP12dAcObjBase_cUl = .text:0x8012BF00; // type:function size:0xC isDoneOpening__17dLytAutoCaption_cCFv = .text:0x8012BF10; // type:function size:0x4C close__17dLytAutoCaption_cFv = .text:0x8012BF60; // type:function size:0xC isDoneClosing__17dLytAutoCaption_cCFv = .text:0x8012BF70; // type:function size:0x4C @@ -7463,7 +7463,7 @@ build__17dLytAutoExplain_cFPQ23d2d10ResAccIf_cPQ23d2d10ResAccIf_cP15dTagProcesso remove__17dLytAutoExplain_cFv = .text:0x8012C9F0; // type:function size:0x50 execute__17dLytAutoExplain_cFv = .text:0x8012CA40; // type:function size:0xA8 draw__17dLytAutoExplain_cFv = .text:0x8012CAF0; // type:function size:0x14 -open__17dLytAutoExplain_cFv = .text:0x8012CB10; // type:function size:0xC +open__17dLytAutoExplain_cFP12dAcObjBase_cUl = .text:0x8012CB10; // type:function size:0xC isDoneOpening__17dLytAutoExplain_cCFv = .text:0x8012CB20; // type:function size:0x4C close__17dLytAutoExplain_cFv = .text:0x8012CB70; // type:function size:0xC isDoneClosing__17dLytAutoExplain_cCFv = .text:0x8012CB80; // type:function size:0x4C @@ -10915,23 +10915,23 @@ create__10dMessage_cFv = .text:0x801B21E0; // type:function size:0x268 doDelete__10dMessage_cFv = .text:0x801B2450; // type:function size:0xBC execute__10dMessage_cFv = .text:0x801B2510; // type:function size:0x7C draw__10dMessage_cFv = .text:0x801B2590; // type:function size:0x8 -getTextMessageByLabel = .text:0x801B25A0; // type:function size:0x24 -fn_801B25D0 = .text:0x801B25D0; // type:function size:0x2C -fn_801B2600 = .text:0x801B2600; // type:function size:0xC -fn_801B2610 = .text:0x801B2610; // type:function size:0x180 -fn_801B2790 = .text:0x801B2790; // type:function size:0x98 +getTextMessageByLabel__10dMessage_cFPCcbPwUl = .text:0x801B25A0; // type:function size:0x24 +getTextMessageByLabel__10dMessage_cFPCcP15dTagProcessor_cbPwUl = .text:0x801B25D0; // type:function size:0x2C +formatText__10dMessage_cFPCw = .text:0x801B2600; // type:function size:0xC +getTextMessageByLabelInternal__10dMessage_cFPCcP15dTagProcessor_cbPwUl = .text:0x801B2610; // type:function size:0x180 +formatTextInternal__10dMessage_cFPCw = .text:0x801B2790; // type:function size:0x98 isValidTextLabel__10dMessage_cFPCc = .text:0x801B2830; // type:function size:0xC -fn_801B2840 = .text:0x801B2840; // type:function size:0x38 +checkIsValidTextLabel__10dMessage_cFPCc = .text:0x801B2840; // type:function size:0x38 getMsbtFileName__10dMessage_cFl = .text:0x801B2880; // type:function size:0x88 getMsbfFileName__10dMessage_cFl = .text:0x801B2910; // type:function size:0x88 getMsbtNumberByIndex__10dMessage_cFl = .text:0x801B29A0; // type:function size:0x24 getMsbfNumberByIndex__10dMessage_cFl = .text:0x801B29D0; // type:function size:0x24 fn_801B2A00 = .text:0x801B2A00; // type:function size:0x14 -fn_801B2A20 = .text:0x801B2A20; // type:function size:0x4C +getTextIndexForLabel__10dMessage_cFPCc = .text:0x801B2A20; // type:function size:0x4C fn_801B2A70 = .text:0x801B2A70; // type:function size:0xC -fn_801B2A80 = .text:0x801B2A80; // type:function size:0xA4 -getMsbtInfoForIndex = .text:0x801B2B30; // type:function size:0xC -fn_801B2B40 = .text:0x801B2B40; // type:function size:0x38 +getMsbtIndexForLabelInternal__10dMessage_cFPCc = .text:0x801B2A80; // type:function size:0xA4 +getMsbtInfoForIndex__10dMessage_cFl = .text:0x801B2B30; // type:function size:0xC +getMsbtInfoForIndexInternal__10dMessage_cFl = .text:0x801B2B40; // type:function size:0x38 getMsbfInfoForIndex = .text:0x801B2B80; // type:function size:0xC fn_801B2B90 = .text:0x801B2B90; // type:function size:0x38 fn_801B2BD0 = .text:0x801B2BD0; // type:function size:0x10 diff --git a/include/d/d_message.h b/include/d/d_message.h index bf641ffd..d5e1b2f9 100644 --- a/include/d/d_message.h +++ b/include/d/d_message.h @@ -5,6 +5,7 @@ #include "d/d_base.h" #include "d/d_tag_processor.h" #include "libms/flowfile.h" +#include "libms/msgfile.h" #include "sized_string.h" class dMessage_c : public dBase_c { @@ -42,10 +43,23 @@ public: static bool isValidTextLabel(const char *name); static void loadTextByLabel(const char *label, dTagProcessor_c *tagProcessor, bool, u32, u32); + static const wchar_t *getTextMessageByLabel(const char *label, bool global, wchar_t *dstBuf, u32 maxLen); + static const wchar_t * + getTextMessageByLabel(const char *label, dTagProcessor_c *pTagProcessor, bool global, wchar_t *dstBuf, u32 maxLen); + + static const wchar_t *formatText(const wchar_t *text); + private: + const wchar_t *formatTextInternal(const wchar_t *text); + const wchar_t *getTextMessageByLabelInternal( + const char *label, dTagProcessor_c *pTagProcessor, bool global, wchar_t *dstBuf, u32 maxLen + ); + static s32 getArcIndexForFile(const char *fileName); static const char *getArcNameByIndex(s32 idx, bool); + bool checkIsValidTextLabel(const char *name); + static void setZevFromMsbArc(); static const char *getMsbtFileName(s32 index); static s32 getMsbtNumberByIndex(s32 index); @@ -53,13 +67,18 @@ private: static s32 getMsbfNumberByIndex(s32 index); static void *getDataFromMsbArc(s32 number, const char *fileName, bool); + s32 getTextIndexForLabel(const char *label); + s32 getMsbtIndexForLabelInternal(const char *label); + static MsbtInfo *getMsbtInfoForIndex(s32 index); + MsbtInfo *getMsbtInfoForIndexInternal(s32 index); + static dMessage_c *sInstance; static dTagProcessor_c *sTagProcessor; /* 0x068 */ MsbtInfo *mpMsgs[82]; /* 0x1B0 */ MsbfInfo *mpFlows[80]; /* 0x2F0 */ SizedString<8> mLanguage; - /* 0x2F8 */ s32 mCurrentTextFileNumber; + /* 0x2F8 */ u32 mCurrentTextFileNumber; /* 0x2FC */ s32 field_0x2FC; diff --git a/include/d/d_tag_processor.h b/include/d/d_tag_processor.h index d5f6ddc0..56cc29e1 100644 --- a/include/d/d_tag_processor.h +++ b/include/d/d_tag_processor.h @@ -98,6 +98,10 @@ public: field_0x90C = type; } + void setField_0x90D(u8 val) { + field_0x90D = val; + } + void setField_0xEE1(u8 val) { field_0xEE1 = val; } diff --git a/include/d/d_textunk.h b/include/d/d_textunk.h index 587d5376..c2ceddf5 100644 --- a/include/d/d_textunk.h +++ b/include/d/d_textunk.h @@ -125,6 +125,14 @@ public: field_0x104 = str; } + bool getField_0x7B4() const { + return field_0x7B4; + } + + MsbtInfo *getMsbtInfo(s32 index) const { + return field_buf2[index]; + } + private: static UnkTextThing *sInstance; diff --git a/src/d/d_message.cpp b/src/d/d_message.cpp index 1b7a49eb..4633ff8a 100644 --- a/src/d/d_message.cpp +++ b/src/d/d_message.cpp @@ -181,6 +181,9 @@ static char *sMsbfFileNames[80] = { "599-Demo.msbf", }; +dMessage_c *dMessage_c::sInstance; +dTagProcessor_c *dMessage_c::sTagProcessor; + static void *msbAlloc(size_t size) {} static void msbFree(void *ptr) {} @@ -255,6 +258,107 @@ int dMessage_c::draw() { return SUCCEEDED; } +const wchar_t *dMessage_c::getTextMessageByLabel(const char *label, bool global, wchar_t *dstBuf, u32 maxLen) { + return sInstance->getTextMessageByLabelInternal(label, nullptr, global, dstBuf, maxLen); +} + +const wchar_t *dMessage_c::getTextMessageByLabel( + const char *label, dTagProcessor_c *pTagProcessor, bool global, wchar_t *dstBuf, u32 maxLen +) { + return sInstance->getTextMessageByLabelInternal(label, pTagProcessor, global, dstBuf, maxLen); +} + +const wchar_t *dMessage_c::formatText(const wchar_t *text) { + return sInstance->formatTextInternal(text); +} + +const wchar_t *dMessage_c::getTextMessageByLabelInternal( + const char *label, dTagProcessor_c *pTagProcessor, bool global, wchar_t *dstBuf, u32 maxLen +) { + s32 fileIndex = mCurrentTextFileNumber; + MsbtInfo *info = nullptr; + + if (global) { + fileIndex = getMsbtIndexForLabelInternal(label); + } + + if (fileIndex >= 0) { + info = getMsbtInfoForIndex(fileIndex); + } + + const wchar_t *text = LMS_GetTextByLabel(info, label); + if (pTagProcessor == nullptr) { + pTagProcessor = sTagProcessor; + } + + u32 outLen = 0; + s32 textIdx = LMS_GetTextIndexByLabel(info, label); + MsbtAttrInfo *att = LMS_GetAttribute(info, textIdx); + pTagProcessor->setMsgWindowSubtype(att->c_0x00); + pTagProcessor->setField_0x90D(att->c_0x01); + + // Strip trailing newline + wchar_t *end; + s32 i; + + if (dstBuf != nullptr) { + pTagProcessor->format(nullptr, text, dstBuf, maxLen, &outLen, nullptr); + i = outLen - 1; + end = &dstBuf[i]; + for (; i > 0; i--) { + if (*end != L'\n') { + break; + } + *end-- = L'\0'; + } + // no return - might be intentional since dstBuf already has the result + } else { + static wchar_t sBuf[0x400] = {}; + pTagProcessor->format(nullptr, text, sBuf, ARRAY_LENGTH(sBuf) - 1, &outLen, nullptr); + i = outLen - 1; + end = &sBuf[i]; + for (; i > 0; i--) { + if (*end != L'\n') { + break; + } + *end = L'\0'; + end--; + } + + return sBuf; + } + + return nullptr; +} + +const wchar_t *dMessage_c::formatTextInternal(const wchar_t *text) { + u32 outLen = 0; + static wchar_t sBuf[0x200] = {}; + sTagProcessor->format(nullptr, text, sBuf, ARRAY_LENGTH(sBuf), &outLen, nullptr); + s32 i = outLen - 1; + wchar_t *end = &sBuf[i]; + for (; i > 0; i--) { + if (*end != L'\n') { + break; + } + *end = L'\0'; + end--; + } + + return sBuf; +} + +bool dMessage_c::isValidTextLabel(const char *name) { + return sInstance->checkIsValidTextLabel(name); +} + +bool dMessage_c::checkIsValidTextLabel(const char *name) { + if (name == nullptr) { + return false; + } + return getTextIndexForLabel(name) >= 0; +} + const char *dMessage_c::getMsbtFileName(s32 idx) { static SizedString<128> sPath; @@ -281,6 +385,47 @@ s32 dMessage_c::getMsbfNumberByIndex(s32 index) { return atoi(getMsbfFileName(index)); } +s32 dMessage_c::getTextIndexForLabel(const char *label) { + s32 idx = getMsbtIndexForLabelInternal(label); + MsbtInfo *info = nullptr; + if (idx >= 0) { + info = getMsbtInfoForIndex(idx); + } + return LMS_GetTextIndexByLabel(info, label); +} + +s32 dMessage_c::getMsbtIndexForLabelInternal(const char *label) { + if (mCurrentTextFileNumber <= 81) { + MsbtInfo *info = getMsbtInfoForIndex(mCurrentTextFileNumber); + if (LMS_GetTextIndexByLabel(info, label) >= 0) { + return mCurrentTextFileNumber; + } + } + + for (s32 i = 0; i < 82; i++) { + if (getMsbtInfoForIndex(i) != nullptr) { + if (LMS_GetTextIndexByLabel(getMsbtInfoForIndex(i), label) >= 0) { + return i; + } + } + } + + return -1; +} + +MsbtInfo *dMessage_c::getMsbtInfoForIndex(s32 index) { + return sInstance->getMsbtInfoForIndexInternal(index); +} + +MsbtInfo *dMessage_c::getMsbtInfoForIndexInternal(s32 index) { + UnkTextThing *thing = UnkTextThing::getInstance(); + MsbtInfo *overrideMsbt = thing->getMsbtInfo(index); + if (overrideMsbt != nullptr && thing->getField_0x7B4() == true) { + return overrideMsbt; + } + return mpMsgs[index]; +} + extern "C" u8 fn_80054F30(); static SizedString<8> sCurrentLanguage; diff --git a/src/d/lyt/d2d.cpp b/src/d/lyt/d2d.cpp index c36d25fc..5a625aaf 100644 --- a/src/d/lyt/d2d.cpp +++ b/src/d/lyt/d2d.cpp @@ -439,8 +439,6 @@ void LytBase_c::setPropertiesRecursive(nw4r::lyt::Pane *pane, f32 posX, f32 posY } } -extern "C" const wchar_t *fn_801B2600(const wchar_t *); - void LytBase_c::setProperties(nw4r::lyt::Pane *pane, f32 posX, f32 posY, f32 scale, f32 spaceX, f32 spaceY) { if (pane->GetName()[0] != 'T') { return; @@ -608,7 +606,7 @@ bool LytBase_c::fn_800ABCE0( return false; } - textbox1->setTextWithGlobalTextProcessor(fn_801B2600(text)); + textbox1->setTextWithGlobalTextProcessor(dMessage_c::formatText(text)); return true; } @@ -678,8 +676,6 @@ bool LytBase_c::fn_800AC040(dTextBox_c *textbox1, dTextBox_c *textbox2, wchar_t return fn_800AC1AC(list, textbox1, textbox2, destBuf, maxLen); } -extern "C" void fn_800AF840(dTextBox_c *textbox1, MsbtInfo *, const char *, int arg, void *unk); - bool LytBase_c::fn_800AC1AC( const nw4r::lyt::res::ExtUserData *userDatum, dTextBox_c *textbox1, dTextBox_c *textbox2, wchar_t *destBuf, u32 maxLen ) { diff --git a/src/d/lyt/d_textbox.cpp b/src/d/lyt/d_textbox.cpp index a7ede0a3..7413b8b8 100644 --- a/src/d/lyt/d_textbox.cpp +++ b/src/d/lyt/d_textbox.cpp @@ -300,8 +300,6 @@ s32 dTextBox_c::calcTextLines(const wchar_t *src, dTagProcessor_c *tagProcessor) return tagProcessor->getNumLinesMaybe(); } -extern "C" const wchar_t *getTextMessageByLabel(const char *labelId, int, int, int); - void dTextBox_c::setMessageWithGlobalTextProcessor(const char *labelId, void *unused, void *unk, ...) { va_list l; va_start(l, str); @@ -310,7 +308,7 @@ void dTextBox_c::setMessageWithGlobalTextProcessor(const char *labelId, void *un } void dTextBox_c::setMessageWithGlobalTextProcessorV(const char *labelId, void *unused, void *unk, va_list list) { - const wchar_t *text = getTextMessageByLabel(labelId, 1, 0, 0); + const wchar_t *text = dMessage_c::getTextMessageByLabel(labelId, true, nullptr, 0); setTextWithGlobalTextProcessorV(text, unk, list); if (GetFont() != nullptr) { resizeTextToFit(GetSize().width);