From e5031b68a91aba3efff0afa83139b569357fae81 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Mon, 26 Oct 2026 22:06:51 +0000 Subject: [PATCH] Decompile fn_17631 (MatchLexicon) Batch #842 by ragnarok-clanker: 0 byte-identical, 1 confirmed by peer review. - fn_17631 MatchLexicon: logic confirmed by peer review Reviewed-by: ragnarok-clanker Adds to the build: Source/Utility/LexiconMatcher.cpp --- Source/Utility/LexiconMatcher.cpp | 68 +++++++++++++++++++++++++++++++ Source/Utility/LexiconMatcher.h | 6 +++ compile.json | 1 + 3 files changed, 75 insertions(+) create mode 100644 Source/Utility/LexiconMatcher.cpp create mode 100644 Source/Utility/LexiconMatcher.h diff --git a/Source/Utility/LexiconMatcher.cpp b/Source/Utility/LexiconMatcher.cpp new file mode 100644 index 0000000..fe7cb18 --- /dev/null +++ b/Source/Utility/LexiconMatcher.cpp @@ -0,0 +1,68 @@ +#include "Utility/LexiconMatcher.h" + +#include + +// FUNCTION: fn_17631 +int __stdcall MatchLexicon(const unsigned char* data, int, const unsigned char* text, const unsigned char* end, int) { + if (*text == 0) { + return 1000; + } + + int accepted = 0; + int matched = 0; + bool failed = false; + const unsigned char* entry = data; + while (text < end && !failed) { + if ((*entry & 0x40) != 0) { + return matched; + } + + std::uint32_t offset = (static_cast(entry[0] & 0x3F) << 16) | + (static_cast(entry[1]) << 8) | entry[2]; + entry += 3; + const unsigned char* candidate = data + offset; + const unsigned int count = *candidate; + if (count < 0x20 && candidate[1] == *text) { + ++offset; + for (unsigned int index = 0; index < count; ++index) { + if (data[offset++] != *text) { + failed = true; + break; + } + + ++matched; + ++text; + const unsigned char marker = data[offset]; + if (marker < 0x20) { + if ((marker & 2) != 0) { + accepted = matched; + } + + if ((marker & 4) != 0) { + entry = data + offset + 1; + break; + } + + ++offset; + } + } + } else if (count >= *text) { + if (count != *text) { + return accepted; + } + + ++matched; + entry = candidate + 1; + ++text; + if (static_cast(*entry) < 0) { + accepted = matched; + } + } + + if (*text == 0) { + return accepted; + } + } + + return accepted; +} diff --git a/Source/Utility/LexiconMatcher.h b/Source/Utility/LexiconMatcher.h new file mode 100644 index 0000000..963a7a2 --- /dev/null +++ b/Source/Utility/LexiconMatcher.h @@ -0,0 +1,6 @@ +#ifndef RAGNAROK_SOURCE_UTILITY_LEXICONMATCHER_H +#define RAGNAROK_SOURCE_UTILITY_LEXICONMATCHER_H + +int __stdcall MatchLexicon(const unsigned char* data, int mode, const unsigned char* text, const unsigned char* end, int options); + +#endif diff --git a/compile.json b/compile.json index 4aac58b..ccfaa0a 100644 --- a/compile.json +++ b/compile.json @@ -585,6 +585,7 @@ "Source/Utility/Base64.cpp": 0, "Source/Utility/GuidParse.cpp": 0, "Source/Utility/LexiconBoundary.cpp": 0, + "Source/Utility/LexiconMatcher.cpp": 0, "Source/Utility/LexiconSerializer.cpp": 0, "Source/Utility/MD5.cpp": 0, "Source/Utility/Math/AffineLookAt.cpp": 0,