diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index d93cac13..c723d6c4 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -3935,11 +3935,11 @@ fn_800B6450__15dTagProcessor_cFPQ34nw4r2ut4RectPQ34nw4r2ut15PrintContextUcPw fn_800B6790 = .text:0x800B6790; // type:function size:0x750 makeSpaceForIconMaybe__15dTagProcessor_cFPQ34nw4r2ut4RectPQ34nw4r2ut15PrintContextPw = .text:0x800B6EE0; // type:function size:0x1E8 fn_800B70D0 = .text:0x800B70D0; // type:function size:0x3A4 -somethingWithScrapperAndMusic = .text:0x800B7480; // type:function size:0xB8 +somethingWithScrapperAndMusic__15dTagProcessor_cFPw = .text:0x800B7480; // type:function size:0xB8 restoreColor__15dTagProcessor_cFPQ34nw4r2ut15PrintContextUc = .text:0x800B7540; // type:function size:0x250 writeTextNormal__15dTagProcessor_cFPCwPwPlUcl = .text:0x800B7790; // type:function size:0xD8 symbolToFontIdx__15dTagProcessor_cFl = .text:0x800B7870; // type:function size:0x10 -fn_800B7880 = .text:0x800B7880; // type:function size:0x210 +fn_800B7880__15dTagProcessor_cFUl = .text:0x800B7880; // type:function size:0x210 fn_800B7A90 = .text:0x800B7A90; // type:function size:0x9C fn_800B7B30 = .text:0x800B7B30; // type:function size:0x46C setStringArg__15dTagProcessor_cFPCwl = .text:0x800B7FA0; // type:function size:0xA0 @@ -3947,8 +3947,8 @@ fn_800B8040__15dTagProcessor_cFScUl = .text:0x800B8040; // type:function size:0x fn_800B8230 = .text:0x800B8230; // type:function size:0x10C fn_800B8340 = .text:0x800B8340; // type:function size:0x18C fn_800B84D0 = .text:0x800B84D0; // type:function size:0x8C -fn_800B8560 = .text:0x800B8560; // type:function size:0x54 -fn_800B85C0 = .text:0x800B85C0; // type:function size:0x290 +fn_800B8560__15dTagProcessor_cFl = .text:0x800B8560; // type:function size:0x54 +fn_800B85C0__15dTagProcessor_cFl = .text:0x800B85C0; // type:function size:0x290 getMaxNumLines__15dTagProcessor_cFl = .text:0x800B8850; // type:function size:0x38 getTextCommand__15dTagProcessor_cFwPCwPUcPlPPw = .text:0x800B8890; // type:function size:0x38 process0xFCommand__15dTagProcessor_cFwPCwPl = .text:0x800B88D0; // type:function size:0xC diff --git a/include/d/d_message.h b/include/d/d_message.h index aa86ffbe..3c232312 100644 --- a/include/d/d_message.h +++ b/include/d/d_message.h @@ -73,6 +73,10 @@ public: static const wchar_t *formatText(const wchar_t *text); + static MsbtInfo *getMsbtInfoForIndex(s32 index); + static MsbfInfo *getMsbfInfoForIndex(s32 index); + static const char *getArcNameByIndex(s32 idx, bool); + private: static void *sZev0; static void *sZevStage; @@ -88,7 +92,6 @@ private: ); static s32 getArcIndexForFile(const char *fileName); - static const char *getArcNameByIndex(s32 idx, bool); bool checkIsValidTextLabel(const char *name); @@ -101,10 +104,8 @@ private: s32 getTextIndexForLabel(const char *label); s32 getMsbtIndexForLabelInternal(const char *label); - static MsbtInfo *getMsbtInfoForIndex(s32 index); MsbtInfo *getMsbtInfoForIndexInternal(s32 index); - static MsbfInfo *getMsbfInfoForIndex(s32 index); MsbfInfo *getMsbfInfoForIndexInternal(s32 index); static const char *getArcNameByIndexInternal(s32 idx, bool global); diff --git a/include/d/d_tag_processor.h b/include/d/d_tag_processor.h index f4195865..d1b6fa0e 100644 --- a/include/d/d_tag_processor.h +++ b/include/d/d_tag_processor.h @@ -28,6 +28,10 @@ public: nw4r::ut::Operation ProcessTags(nw4r::ut::Rect *rect, u16 ch, nw4r::ut::PrintContext *ctx); + f32 fn_800B8560(s32); + f32 fn_800B85C0(s32); + void somethingWithScrapperAndMusic(wchar_t* src); + void changeScale(nw4r::ut::Rect *rect, nw4r::ut::PrintContext *ctx, bool); wchar_t *writeItem(wchar_t *dest, wchar_t *src, s32 *, s32); wchar_t *writeStringArg(wchar_t *dest, wchar_t *src, s32 *, s32); @@ -161,6 +165,16 @@ public: } private: + wchar_t *getTmpBuffer() { + return field_0x008[field_0x90E - 1]; + } + + void onWriteTmpBuffer() { + if (field_0x90E - 1 < 4) { + field_0x808[field_0x90E - 1]++; + } + } + /* 0x004 */ dTextBox_c *field_0x004; /* 0x008 */ wchar_t field_0x008[4][256]; /* 0x808 */ wchar_t field_0x808[4]; diff --git a/include/d/d_textunk.h b/include/d/d_textunk.h index a76d5c99..eea6de23 100644 --- a/include/d/d_textunk.h +++ b/include/d/d_textunk.h @@ -38,6 +38,14 @@ public: inline static f32 getField0x760() { if (sInstance != nullptr) { return sInstance->field_0x760; + } else { + return 0.0f; + } + } + + inline static f32 getField0x764() { + if (sInstance != nullptr) { + return sInstance->field_0x764; } return 0.0f; } @@ -56,6 +64,10 @@ public: return 0.0f; } + inline static f32 getField0x788() { + return sInstance->field_0x788; + } + inline static f32 getFn800B1F70() { if (sInstance != nullptr) { return sInstance->fn_800B1F70(); diff --git a/src/REL/d/d_s_boot.cpp b/src/REL/d/d_s_boot.cpp index 22f9982d..973fb92d 100644 --- a/src/REL/d/d_s_boot.cpp +++ b/src/REL/d/d_s_boot.cpp @@ -43,7 +43,6 @@ sFPhaseBase::sFPhaseState dScBoot_c::executeLoadPhase() { } extern "C" u8 getUsedLanguageNTSCNum(); -extern "C" const char *getEventFlowFileNameByIndex(int, int); extern "C" u8 fn_80054F30(); sFPhaseBase::sFPhaseState dScBoot_c::cb1() { @@ -54,7 +53,7 @@ sFPhaseBase::sFPhaseState dScBoot_c::cb1() { for (int i = 0; i < 6; i++) { SizedString<128> str; - str.sprintf("%s/%s", dMessage_c::getLanguageIdentifier(), getEventFlowFileNameByIndex(i, 1)); + str.sprintf("%s/%s", dMessage_c::getLanguageIdentifier(), dMessage_c::getArcNameByIndex(i, true)); OarcManager::GetInstance()->loadObjectArcFromDisk(str, mHeap::g_archiveHeap); } OarcManager::GetInstance()->loadObjectArcFromDisk("System", mHeap::g_archiveHeap); diff --git a/src/d/d_tag_processor.cpp b/src/d/d_tag_processor.cpp index af13af38..0ef8892a 100644 --- a/src/d/d_tag_processor.cpp +++ b/src/d/d_tag_processor.cpp @@ -2,7 +2,9 @@ #include "common.h" #include "d/d_font_manager.h" +#include "d/d_message.h" #include "d/d_textunk.h" +#include "d/d_textwindow_unk.h" #include "nw4r/lyt/lyt_types.h" #include "nw4r/ut/ut_CharWriter.h" #include "nw4r/ut/ut_Color.h" @@ -119,6 +121,10 @@ nw4r::ut::Color FontColors2[] = { nw4r::ut::Color(), }; +extern const u16 flags[2050] = { + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, +}; + dTagProcessor_c::dTagProcessor_c() { field_0x82C = -1; field_0x828 = -1; @@ -230,12 +236,11 @@ void dTagProcessor_c::formatV( s32 state1 = -1; s32 state2 = -1; - // FPR regswap between float1 and float2 - f32 float1, float2; - float2 = float1 = fn_800B8040(0, mMsgWindowSubtype); + f32 currScale, backupScale; + backupScale = currScale = fn_800B8040(0, mMsgWindowSubtype); if (textBox != nullptr) { - float1 *= textBox->getMyScale(); + currScale *= textBox->getMyScale(); resetLineData(); textBox->set0x1F8(0); } @@ -278,10 +283,8 @@ void dTagProcessor_c::formatV( const wchar_t *t = src; u32 len = (cmdLen / 2) + 1; for (int i = 0; i < len; i++) { - field_0x008[field_0x90E - 1][local_b4] = *(t++); - if (field_0x90E - 1 < 4) { - field_0x808[field_0x90E - 1]++; - } + getTmpBuffer()[local_b4] = *(t++); + onWriteTmpBuffer(); local_b4++; } } else { @@ -353,23 +356,23 @@ void dTagProcessor_c::formatV( } break; case 0x10008: if (textBox != nullptr) { - float1 = fn_800B8040(((u8 *)endPtr)[0], mMsgWindowSubtype); - float1 *= textBox->getMyScale(); + currScale = fn_800B8040(((u8 *)endPtr)[0], mMsgWindowSubtype); + currScale *= textBox->getMyScale(); } writePtr = writeTextNormal(src, writePtr, &local_b4, cmdLen, state4); break; case 0x30000: { if (textBox != nullptr) { - float2 = float1; - float1 *= UnkTextThing::getField0x768(); - float1 *= textBox->getMyScale(); + backupScale = currScale; + currScale *= UnkTextThing::getField0x768(); + currScale *= textBox->getMyScale(); } writePtr = writeTextNormal(src, writePtr, &local_b4, cmdLen, state4); } break; case 0x10010: fn_800B5520(endPtr); break; case 0x20004: if (textBox != nullptr) { - writeIcon(textBox, endPtr, float1); + writeIcon(textBox, endPtr, currScale); } writePtr = writeTextNormal(src, writePtr, &local_b4, cmdLen, state4); break; @@ -399,7 +402,7 @@ void dTagProcessor_c::formatV( s32 tmp = 0; process0xFCommand(c, src + 1, &tmp); if (tmp == 0x30000) { - float1 = float2; + currScale = backupScale; } writePtr[0] = src[0]; writePtr[1] = src[1]; @@ -408,12 +411,9 @@ void dTagProcessor_c::formatV( src += 3; } else if (state4 != 0 && field_0x90E != 0) { // Note: Return ignored here - fn_800B5FD0(c, &field_0x008[field_0x90E - 1][local_b4], &local_b4); + fn_800B5FD0(c, &getTmpBuffer()[local_b4], &local_b4); src++; - // This looks like an inline tbh - if (field_0x90E - 1 < 4) { - field_0x808[field_0x90E - 1]++; - } + onWriteTmpBuffer(); } else { if (textBox != nullptr) { if (c == L'\n') { @@ -423,8 +423,8 @@ void dTagProcessor_c::formatV( mLineData.mNumLines++; s32 i10 = getMaxNumLines(mMsgWindowSubtype); if (mLineData.mNumLines % i10 == 0) { - float1 = fn_800B8040(0, mMsgWindowSubtype); - float1 *= textBox->getMyScale(); + currScale = fn_800B8040(0, mMsgWindowSubtype); + currScale *= textBox->getMyScale(); } if (textBox != nullptr) { wchar_t *buf = (wchar_t *)&x; @@ -438,7 +438,7 @@ void dTagProcessor_c::formatV( } else { const nw4r::ut::Font *fnt = textBox->GetFont(); mLineData.mLineWidths[mLineData.mNumLines] += - float1 * fnt->GetCharWidth(*src) + textBox->GetCharSpace(); + currScale * fnt->GetCharWidth(*src) + textBox->GetCharSpace(); writePtr = fn_800B5FD0(*src, writePtr, nullptr); src++; } @@ -458,6 +458,176 @@ end: } } +void dTagProcessor_c::fn_800B4290( + dTextBox_c *textBox, const wchar_t *src_, wchar_t *dest, s32 unkArg, u16 *pOutLen, dLytMsgWindowCharData *charData +) { + const wchar_t *src = src_; + wchar_t *writePtr = dest; + bool b1 = false; + s32 lineNum = 0; + bool b2 = false; + s32 charDataIdx; + + f32 currScale = fn_800B8040(0, mMsgWindowSubtype); + f32 backupScale = currScale; + + charDataIdx = 0; + + f32 posX = 0.0f; + f32 posY = 0.0f; + + if (textBox != nullptr) { + currScale *= textBox->getMyScale(); + } + +beginning: + bool r22 = !b1; + while (!b1) { + wchar_t c = *src; + if (c == '\0') { + *writePtr = '\0'; + break; + } else if (c == 0xE) { + u8 cmdLen = 0; + s32 cmd = 0; + wchar_t *endPtr = nullptr; + getTextCommand(c, src + 1, &cmdLen, &cmd, &endPtr); + switch (cmd) { + case 0x0F0F0F0F: { + if (lineNum / getMaxNumLines(mMsgWindowSubtype) == unkArg) { + nw4r::lyt::Size fontSize = field_0x004->GetFontSize(); + posX = fn_800B8560(lineNum); + if ((mMsgWindowSubtype < 6 || mMsgWindowSubtype >= 10) && mMsgWindowSubtype != 30) { + posX = 0.0f; + } + + f32 tmp3; + f32 tmp = fn_800B8040(0, mMsgWindowSubtype); + + if (textBox != nullptr) { + tmp *= textBox->getMyScale(); + } + + if (lineNum % getMaxNumLines(mMsgWindowSubtype) == 0) { + currScale = fn_800B8040(0, mMsgWindowSubtype); + if (textBox != nullptr) { + currScale *= textBox->getMyScale(); + } + if (mMsgWindowSubtype == 30) { + tmp3 = -2.0f; + } else { + tmp3 = 3.0f; + } + posY = (fn_800B85C0(lineNum) - (fontSize.height * (currScale / tmp) / 2.0f)) - tmp3; + } else { + posY = (posY - (fontSize.height * (currScale / tmp) + field_0x004->GetLineSpace())); + } + if (!b2) { + b2 = true; + } + } else if (b2) { + b2 = false; + b1 = true; + } + lineNum++; + } break; + case 0x10000: + case 0x10001: + case 0x10002: + case 0x10003: b1 = true; break; + case 0x10008: { + if (b2) { + f32 newScale = fn_800B8040(*(u8 *)endPtr, mMsgWindowSubtype); + f32 baseScale = fn_800B8040(0, mMsgWindowSubtype); + if (textBox != nullptr) { + newScale *= textBox->getMyScale(); + baseScale *= textBox->getMyScale(); + } + if (currScale != newScale) { + nw4r::lyt::Size fontSize = field_0x004->GetFontSize(); + posY -= (fontSize.height * ((currScale - newScale) / baseScale) / 2.0f) * + UnkTextThing::getField0x788(); + currScale = newScale; + } + } + } break; + case 0x30000: { + if (b2) { + backupScale = currScale; + f32 tmp = backupScale * UnkTextThing::getField0x768(); + if (textBox != nullptr) { + tmp *= textBox->getMyScale(); + } + if (currScale != tmp) { + nw4r::lyt::Size _size = field_0x004->GetFontSize(); + currScale = tmp; + } + } + } break; + case 0x20004: + if (b2) { + *writePtr = -1; + const nw4r::ut::Font *fnt = dFontMng_c::getFont(4); + wchar_t c = fn_800B7880(*(u8 *)endPtr); + f32 tmp = UnkTextThing::getField0x764(); + f32 wid = tmp / fnt->GetWidth() * currScale; + f32 charSpace = textBox->GetCharSpace(); + f32 charWidth = wid * fnt->GetCharWidth(c); + posX += charWidth + charSpace; + writePtr++; + } + break; + case 0x10012: + if (b2) { + somethingWithScrapperAndMusic(endPtr); + } + break; + } + src += cmdLen / 2 + 1; + // For some reason the compiler believes that this branch affects something about + // charData/charDataIdx and branches to a re-calculation of the strength-reduced + // pointer, which means the compiler keepts charDataIdx actually around while still + // incrementing the strength-reduced charData pointer by 0x14. Very weird! + // This charDataIdx++, charDataIdx-- causes this behavior, not sure what the real match would be. + charDataIdx++; + charDataIdx--; + goto beginning; + } else if (c == 0xF) { + s32 cmd = 0; + process0xFCommand(c, &src[1], &cmd); + if (cmd == 0x30000) { + currScale = backupScale; + } + src += 3; + } else { + if (b2) { + *writePtr = c; + const nw4r::ut::Font *fnt = textBox->GetFont(); + f32 tmp = currScale * fnt->GetCharWidth(*src) * 0.5f; + posX += tmp; + if (charData != nullptr) { + wchar_t s = *writePtr; + if (s != 10 && s != 0x20 && s != 0x3000) { + charData[charDataIdx].posX = posX; + charData[charDataIdx].posY = posY; + charData[charDataIdx].field_0x08 = currScale; + charData[charDataIdx].character = *writePtr; + charDataIdx++; + } + } + writePtr++; + posX += (tmp + textBox->GetCharSpace()); + } + src++; + } + } + +end: + if (pOutLen != nullptr) { + *pOutLen = writePtr - dest; + } +} + nw4r::ut::Operation dTagProcessor_c::Process(u16 ch, nw4r::ut::PrintContext *ctx) { return ProcessTags(nullptr, ch, ctx); } @@ -785,19 +955,147 @@ wchar_t *dTagProcessor_c::writeHeroname(wchar_t *dest, s32 *outArg, s32 arg) { if (FileManager::GetInstance()->getHeroname()[0] != '\0') { for (int i = 0; FileManager::GetInstance()->getHeroname()[i] != '\0'; i++) { if (arg != 0 && field_0x90E != 0) { - wchar_t c = FileManager::GetInstance()->getHeroname()[i]; - fn_800B5FD0(c, &field_0x008[field_0x90E - 1][*outArg], outArg); + wchar_t *heroName = FileManager::GetInstance()->getHeroname(); + fn_800B5FD0(heroName[i], &getTmpBuffer()[*outArg], outArg); if (field_0x90E - 1 < 4) { field_0x808[field_0x90E - 1]++; } } else { - dest = fn_800B5FD0(FileManager::GetInstance()->getHeroname()[i], dest, nullptr); + wchar_t *heroName = FileManager::GetInstance()->getHeroname(); + dest = fn_800B5FD0(heroName[i], dest, nullptr); } } } return dest; } +wchar_t *dTagProcessor_c::writeItem(wchar_t *dest, wchar_t *src, s32 *outArg, s32 arg) { + int itemIndex = *src; + wchar_t c; + const wchar_t *readPtr; + + int i = 0; + SizedString<16> mName; + mName.sprintf("NAME_ITEM_%03d", itemIndex); + MsbtInfo *info = dMessage_c::getMsbtInfoForIndex(/* ItemGet */ 3); + const wchar_t *text = LMS_GetTextByLabel(info, mName); + + while (readPtr = &text[i], (c = text[i]) != 0) { + if (c == 0xE) { + int len = ((readPtr[3] / 2) & 0x7F) + 4; + if (arg != 0 && field_0x90E != 0) { + for (int j = 0; j < len; j++) { + fn_800B5FD0(*readPtr, &getTmpBuffer()[*outArg], outArg); + onWriteTmpBuffer(); + readPtr++; + i++; + } + } else { + for (int j = 0; j < len; j++) { + dest = fn_800B5FD0(*readPtr, dest, nullptr); + readPtr++; + i++; + } + } + } else { + if (arg != 0 && field_0x90E != 0) { + fn_800B5FD0(c, &getTmpBuffer()[*outArg], outArg); + onWriteTmpBuffer(); + } else { + dest = fn_800B5FD0(c, dest, nullptr); + } + i++; + } + } + + return dest; +} + +wchar_t *dTagProcessor_c::writeNumericArg(wchar_t *dest, wchar_t *src, s32 *outArg, s32 arg) { + int numZeroDigits = ((u8 *)src)[4]; + bool writeZeroDigits = false; + s32 argIdx = *((s32 *)src); + s32 numberArg = mNumericArgs[argIdx]; + mNumericArgsCopy[0] = numberArg; + + // This could potentially be an unrolled loop + + s32 digit = numberArg / 10000; + s32 number = numberArg % 10000; + + if (!writeZeroDigits && numZeroDigits == 5) { + writeZeroDigits = true; + } + if (digit > 0 || writeZeroDigits) { + if (arg != 0 && field_0x90E != 0) { + getTmpBuffer()[*outArg] = '0' + digit; + onWriteTmpBuffer(); + (*outArg)++; + } else { + *(dest++) = '0' + digit; + } + writeZeroDigits = true; + } + + digit = number / 1000; + number = number % 1000; + if (!writeZeroDigits && numZeroDigits == 4) { + writeZeroDigits = true; + } + if (digit > 0 || writeZeroDigits) { + if (arg != 0 && field_0x90E != 0) { + getTmpBuffer()[*outArg] = '0' + digit; + onWriteTmpBuffer(); + (*outArg)++; + } else { + *(dest++) = '0' + digit; + } + writeZeroDigits = true; + } + + digit = number / 100; + number = number % 100; + if (!writeZeroDigits && numZeroDigits == 3) { + writeZeroDigits = true; + } + if (digit > 0 || writeZeroDigits) { + if (arg != 0 && field_0x90E != 0) { + getTmpBuffer()[*outArg] = '0' + digit; + onWriteTmpBuffer(); + (*outArg)++; + } else { + *(dest++) = '0' + digit; + } + writeZeroDigits = true; + } + + digit = number / 10; + number = number % 10; + if (!writeZeroDigits && numZeroDigits == 2) { + writeZeroDigits = true; + } + if (digit > 0 || writeZeroDigits) { + if (arg != 0 && field_0x90E != 0) { + getTmpBuffer()[*outArg] = '0' + digit; + onWriteTmpBuffer(); + (*outArg)++; + } else { + *(dest++) = '0' + digit; + } + writeZeroDigits = true; + } + + digit = number; + if (arg != 0 && field_0x90E != 0) { + getTmpBuffer()[*outArg] = '0' + digit; + onWriteTmpBuffer(); + (*outArg)++; + } else { + *(dest++) = '0' + digit; + } + return dest; +} + void dTagProcessorDataStuff() { SizedString<32> s; s.sprintf("NAME_ITEM_%03d"); @@ -860,6 +1158,14 @@ void dTagProcessor_c::changeScale(nw4r::ut::Rect *rect, nw4r::ut::PrintContextwriter->SetScale(scale, scale); } +void dTagProcessor_c::writeIcon(dTextBox_c *textBox, wchar_t *cmd, f32 arg) { + nw4r::ut::Font *f = dFontMng_c::getFont(4); + u32 c3 = fn_800B7880(*(u8 *)cmd); + arg = UnkTextThing::getField0x764() / f->GetWidth() * arg; + + mLineData.mLineWidths[mLineData.mNumLines] += arg * f->GetCharWidth(c3) + textBox->GetCharSpace(); +} + void dTagProcessor_c::makeSpaceForIconMaybe(nw4r::ut::Rect *rect, nw4r::ut::PrintContext *ctx, wchar_t *ptr) { nw4r::ut::Font *f = dFontMng_c::getFont(4); u32 c3 = fn_800B7880(*(u8 *)ptr); @@ -929,10 +1235,8 @@ void dTagProcessor_c::restoreColor(nw4r::ut::PrintContext *ctx, u8 wind wchar_t *dTagProcessor_c::writeTextNormal(const wchar_t *src, wchar_t *dest, s32 *pArg, u8 cmdLen, s32 arg) { if (arg != 0 && field_0x90E != 0) { for (u32 i = 0; i < (cmdLen / 2 + 1); i++) { - field_0x008[field_0x90E - 1][*pArg] = *(src++); - if (field_0x90E - 1 < 4) { - field_0x808[field_0x90E - 1]++; - } + getTmpBuffer()[*pArg] = *(src++); + onWriteTmpBuffer(); (*pArg)++; } } else {