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).
This commit is contained in:
ragnarok-clanker 2026-10-29 22:30:08 +00:00
commit 9854647579

View file

@ -3,6 +3,7 @@
#include "Archive/PakCipher.h"
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <zlib.h>
@ -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<unsigned int>(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<unsigned int*>(::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<unsigned int*>((reinterpret_cast<uintptr_t>(raw) + 0x23) & ~static_cast<uintptr_t>(0x1f));
reinterpret_cast<void**>(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<void**>(this->first)[-1];
if ((reinterpret_cast<uintptr_t>(this->first) - reinterpret_cast<uintptr_t>(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<unsigned int>(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<int*>(::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<int*>((reinterpret_cast<uintptr_t>(raw) + 0x23) & ~static_cast<uintptr_t>(0x1f));
reinterpret_cast<void**>(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<void**>(this->first)[-1];
if ((reinterpret_cast<uintptr_t>(this->first) - reinterpret_cast<uintptr_t>(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<unsigned int>(std::ceil(static_cast<float>(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();