From 42622ad4e6f0ee9370e4aad0d0404f8ebd85e25b Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 07:46:12 +0000 Subject: [PATCH] Decompile 4 functions in Source/UI/Text/NavigationLink.cpp Batch #5045 by Yommy: 0 byte-identical, 4 confirmed by peer review. - fn_10414 ExtractInnerItemLink: logic confirmed by peer review - fn_10422 RemoveLineBreakTag: logic confirmed by peer review - fn_10470 UIItemImage::Paint: logic confirmed by peer review - fn_10471 LineCutter::UIText::Paint: logic confirmed by peer review Peer-reviewed-by: alisonrag, youko Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/UI/Text/NavigationLink.cpp | 105 +++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/Source/UI/Text/NavigationLink.cpp b/Source/UI/Text/NavigationLink.cpp index 4360d5d7..3b686961 100644 --- a/Source/UI/Text/NavigationLink.cpp +++ b/Source/UI/Text/NavigationLink.cpp @@ -17,6 +17,8 @@ #include "Contents/Items/ItemInfo.h" #include "Contents/MessageTable.h" #include "Network/TextEncoding.h" +#include "Render/Text/FontCache.h" +#include "Render/Text/TextContext.h" #include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" #include "Resource/Sprites/ActionResource.h" @@ -49,7 +51,6 @@ namespace LineCutter { /* 0090 */ unsigned char m_shadowed; /* 0094 */ std::uint32_t m_shadowColor; /* 0098 */ std::string m_text; - UIButtonContext* m_controls; }; } @@ -73,11 +74,10 @@ public: protected: /* 007C */ std::string m_itemId; - ItemDescriptions* m_descriptions; }; #if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(LineCutter::UIText) == 0xB4); +static_assert(sizeof(LineCutter::UIText) == 0xB0); #endif // GLOBAL: gl_24668 @@ -314,6 +314,22 @@ std::string FormatNavigationLink(std::string value, bool brackets) { return text; } +// OFFSET: 0x00835B00 +// FUNCTION: fn_10422 +std::pair RemoveLineBreakTag(std::string value) { + std::string text = value; + const std::size_t position = text.find(""); + + if (position == std::string::npos) { + return std::pair(false, value); + } + + std::string head = text.substr(0, position); + const std::string tail = text.substr(position + std::strlen("")); + head.append(tail.c_str(), tail.size()); + return std::pair(true, head); +} + // OFFSET: 0x00833550 // FUNCTION: fn_10411 void DisplayNavigationLink(std::string& output, std::string value) { @@ -338,6 +354,51 @@ void DisplayNavigationLink(std::string& output, std::string value) { } } +// OFFSET: 0x00833A20 +// FUNCTION: fn_10414 +bool ExtractInnerItemLink(std::string& text, std::string& link, int& offset, const char* source) { + std::size_t closePos = text.find(g_itemLinkCloseTag); + + if (closePos == std::string::npos) { + return false; + } + + do { + text = text.substr(0, closePos); + std::size_t openPos = text.find(g_itemLinkTag); + + if (closePos != std::string::npos && openPos == std::string::npos) { + offset += g_itemLinkCloseTag.size(); + text = source; + text = text.substr(offset); + return true; + } + + closePos = text.find(g_itemLinkCloseTag); + + if (openPos != std::string::npos) { + for (;;) { + offset += openPos; + text = text.substr(openPos + g_itemLinkTag.size()); + openPos = text.find(g_itemLinkTag); + closePos = text.find(g_itemLinkCloseTag); + + if (openPos == std::string::npos) { + break; + } + + offset += g_itemLinkTag.size(); + } + + link = text; + text = source; + text = text.substr(link.size() + offset + g_itemLinkTag.size() + g_itemLinkCloseTag.size()); + } + } while (closePos != std::string::npos); + + return true; +} + // OFFSET: 0x00834980 // FUNCTION: fn_10417 void ExtractNavigationLink(std::string& output, std::string value) { @@ -495,6 +556,28 @@ void LineCutter::UIText::Slot35(int value) { } // OFFSET: 0x0083B150 +// FUNCTION: fn_10471 +void LineCutter::UIText::Paint() { + this->ClearSurface(0xFFFF00FF); + const TextLocale locale = {}; + + if (this->m_shadowed) { + this->DrawTextAt( + g_fontCache, locale, 1, 1, this->m_text.c_str(), this->m_text.size(), 0, this->m_fontHeight, this->m_shadowColor, this->m_bold, + this->m_italic + ); + } + + if (this->m_outlined == 1) { + DrawOutlinedText( + *this, 1, 1, this->m_text.c_str(), this->m_text.size(), this->m_color, this->m_outlineColor, 0, this->m_fontHeight, this->m_bold, this->m_italic + ); + } else { + this->DrawTextAt( + g_fontCache, locale, 0, 0, this->m_text.c_str(), this->m_text.size(), 0, this->m_fontHeight, this->m_color, this->m_bold, this->m_italic + ); + } +} // OFFSET: 0x0083B460 // FUNCTION: fn_10478 @@ -521,6 +604,22 @@ void UIEmotion::Slot19() { } // OFFSET: 0x0083B0A0 +// FUNCTION: fn_10470 +void UIItemImage::Paint() { + if (!this->geometry.surface || this->m_itemId.empty()) { + return; + } + + this->ClearSurface(0xFFFF00FF); + char path[128] = {}; + ItemDescriptions descriptions{g_itemDescriptions}; + descriptions.IconPath(path, this->m_itemId.c_str(), 1); + CBitmapRes* bitmap = static_cast(ResourceMgr::Instance().Load(Resolve(path))); + + if (bitmap) { + this->DrawBitmap(0, 0, &bitmap->image, true); + } +} // OFFSET: 0x00837390 // FUNCTION: fn_10441