From 98546475798f6523f160fd2abe868e2deadd35ea Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Thu, 29 Oct 2026 22:30:08 +0000 Subject: [PATCH] Decompile 4 functions in Source/Archive/GPak.cpp Batch #3427 by KWDev: 0 byte-identical, 4 confirmed by peer review. - fn_05051 VectorUint32_654D10::sub_654D10: logic confirmed by peer review - fn_05052 VectorInt32_654E00::sub_654E00: logic confirmed by peer review - fn_05062 HashTable_655340::sub_6553C0: logic confirmed by peer review - fn_05069 HashTable_655340::sub_655D70: logic confirmed by peer review Peer-reviewed-by: eAthena, meitogi, bigodeira Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Archive/GPak.cpp | 189 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 2 deletions(-) diff --git a/Source/Archive/GPak.cpp b/Source/Archive/GPak.cpp index 61b39da7..75bcbdb2 100644 --- a/Source/Archive/GPak.cpp +++ b/Source/Archive/GPak.cpp @@ -3,6 +3,7 @@ #include "Archive/PakCipher.h" #include +#include #include #include #include @@ -602,6 +603,126 @@ bool sub_654D00() { return true; } +void sub_6468C0(void* first, void* last, const void* val); +void sub_646930(void* first, void* last, const void* val); +[[noreturn]] void sub_4F9440(); + +struct VectorUint32_654D10 { + unsigned int* first; + unsigned int* last; + unsigned int* end; + + void sub_654D10(unsigned int count, unsigned int val); +}; + +// OFFSET: 0x00654D10 +// FUNCTION: fn_05051 +void VectorUint32_654D10::sub_654D10(unsigned int count, unsigned int val) { + unsigned int old_size = static_cast(this->last - this->first); + if (count <= old_size) { + sub_6468C0(this->first, this->last, &val); + return; + } + if (count > 0x3fffffff) { + sub_4F9440(); + } + unsigned int bytes = count * sizeof(unsigned int); + unsigned int* new_ptr; + if (bytes < 0x1000) { + if (bytes == 0) { + new_ptr = nullptr; + } else { + new_ptr = static_cast(::operator new(bytes)); + } + } else { + if (bytes + 0x23 <= bytes) { + sub_4F9440(); + } + void* raw = ::operator new(bytes + 0x23); + if (!raw) { + _invalid_parameter_noinfo_noreturn(); + } + new_ptr = reinterpret_cast((reinterpret_cast(raw) + 0x23) & ~static_cast(0x1f)); + reinterpret_cast(new_ptr)[-1] = raw; + } + if (old_size != 0) { + unsigned int old_bytes = old_size * sizeof(unsigned int); + void* old_raw = this->first; + if (old_bytes >= 0x1000) { + old_raw = reinterpret_cast(this->first)[-1]; + if ((reinterpret_cast(this->first) - reinterpret_cast(old_raw) - 4) > 0x1f) { + _invalid_parameter_noinfo_noreturn(); + } + old_bytes += 0x23; + } + ::operator delete(old_raw, old_bytes); + } + this->first = new_ptr; + this->last = new_ptr + count; + this->end = new_ptr + count; + for (unsigned int* p = new_ptr; p != this->last; ++p) { + *p = val; + } +} + +struct VectorInt32_654E00 { + int* first; + int* last; + int* end; + + void sub_654E00(unsigned int count, int val); +}; + +// OFFSET: 0x00654E00 +// FUNCTION: fn_05052 +void VectorInt32_654E00::sub_654E00(unsigned int count, int val) { + unsigned int old_size = static_cast(this->last - this->first); + if (count <= old_size) { + sub_646930(this->first, this->last, &val); + return; + } + if (count > 0x3fffffff) { + sub_4F9440(); + } + unsigned int bytes = count * sizeof(int); + int* new_ptr; + if (bytes < 0x1000) { + if (bytes == 0) { + new_ptr = nullptr; + } else { + new_ptr = static_cast(::operator new(bytes)); + } + } else { + if (bytes + 0x23 <= bytes) { + sub_4F9440(); + } + void* raw = ::operator new(bytes + 0x23); + if (!raw) { + _invalid_parameter_noinfo_noreturn(); + } + new_ptr = reinterpret_cast((reinterpret_cast(raw) + 0x23) & ~static_cast(0x1f)); + reinterpret_cast(new_ptr)[-1] = raw; + } + if (old_size != 0) { + unsigned int old_bytes = old_size * sizeof(int); + void* old_raw = this->first; + if (old_bytes >= 0x1000) { + old_raw = reinterpret_cast(this->first)[-1]; + if ((reinterpret_cast(this->first) - reinterpret_cast(old_raw) - 4) > 0x1f) { + _invalid_parameter_noinfo_noreturn(); + } + old_bytes += 0x23; + } + ::operator delete(old_raw, old_bytes); + } + this->first = new_ptr; + this->last = new_ptr + count; + this->end = new_ptr + count; + for (int* p = new_ptr; p != this->last; ++p) { + *p = val; + } +} + // OFFSET: 0x00654EF0 // FUNCTION: fn_05053 bool __fastcall sub_654EF0(const void* self) { @@ -630,6 +751,7 @@ bool FuncImpl_654FB0::sub_654FB0(const Span8_654FB0* a1, const Span4_654FB0* a2, struct HashNode_655340 { HashNode_655340* prev; HashNode_655340* next; + short key; }; struct HashBucket_655340 { @@ -637,16 +759,28 @@ struct HashBucket_655340 { HashNode_655340* last; }; +struct HashSearchResult_655D70 { + HashNode_655340* first; + HashNode_655340* second; + + HashSearchResult_655D70() {} + HashSearchResult_655D70(HashNode_655340* f, HashNode_655340* s) : first(f), second(s) {} +}; + struct HashTable_655340 { - void* unknown_00; + float max_load_factor; HashNode_655340* head; - unsigned int size; + int size; HashBucket_655340* buckets; unsigned int unknown_10; unsigned int unknown_14; unsigned int mask; + unsigned int bucket_count; + void sub_654FF0(unsigned int buckets); HashNode_655340* sub_655340(unsigned int hash, HashNode_655340* prev, HashNode_655340* node); + void sub_6553C0(); + HashSearchResult_655D70 sub_655D70(const short* key, unsigned int hash); }; // OFFSET: 0x00655340 @@ -684,6 +818,57 @@ int* __fastcall sub_655330(int* a) { return a + 1; } +// OFFSET: 0x006553C0 +// FUNCTION: fn_05062 +void HashTable_655340::sub_6553C0() { + unsigned int bucket_count = static_cast(std::ceil(static_cast(this->size + 1) / this->max_load_factor)); + if (bucket_count < 8) { + bucket_count = 8; + } + unsigned int buckets = this->bucket_count; + if (buckets < bucket_count) { + if (buckets < 512) { + buckets *= 8; + if (buckets < bucket_count) { + buckets = bucket_count; + } + } else { + buckets = bucket_count; + } + } + this->sub_654FF0(buckets); +} + +// OFFSET: 0x00655D70 +// FUNCTION: fn_05069 +HashSearchResult_655D70 HashTable_655340::sub_655D70(const short* key, unsigned int hash) { + HashSearchResult_655D70 result; + HashBucket_655340* bucket = &this->buckets[this->mask & hash]; + HashNode_655340* node = bucket->last; + if (node == this->head) { + result.first = this->head; + result.second = nullptr; + return result; + } + short target = *key; + if (target == node->key) { + result.first = node->prev; + result.second = node; + return result; + } + while (node != bucket->first) { + node = node->next; + if (target == node->key) { + result.first = node->prev; + result.second = node; + return result; + } + } + result.first = node; + result.second = nullptr; + return result; +} + // INLINED CGPak::CGPak() : m_file(nullptr), m_version(0), m_entryCount(0), m_tableOffset(0), m_tableSize(0) { this->Reset();