Fix Warden module parsing and DBC loading for Classic expansion

Warden: copy/skip pair order was reversed — format is [copy][data][skip]
per MaNGOS/TrinityCore, not [skip][copy][data]. All copy sizes read as 0,
causing module load failure and server disconnect.

DBC: when binary DBCs aren't available (no MPQ extraction), fall back to
expansion CSV files even for visual DBCs (CreatureDisplayInfo, CharSections,
ItemDisplayInfo, etc.) instead of failing with "DBC not found".
This commit is contained in:
Kelsi 2026-02-24 04:42:36 -08:00
parent 60c26a17aa
commit d045c1215a
2 changed files with 49 additions and 24 deletions

View file

@ -529,34 +529,23 @@ bool WardenModule::parseExecutableFormat(const std::vector<uint8_t>& exeData) {
std::cout << "[WardenModule] Allocated " << moduleSize_ << " bytes of executable memory at "
<< moduleMemory_ << '\n';
// Parse skip/copy pairs
// Format: repeated [2B skip_count][2B copy_count][copy_count bytes data]
// Skip = advance dest pointer (zeros), Copy = copy from source to dest
// Terminates when skip_count == 0
// Parse copy/skip pairs (MaNGOS/TrinityCore format)
// Format: repeated [2B copy_count][copy_count bytes data][2B skip_count]
// Copy = copy from source to dest, Skip = advance dest pointer (zeros)
// Terminates when copy_count == 0
size_t pos = 4; // Skip 4-byte size header
size_t destOffset = 0;
int pairCount = 0;
while (pos + 2 <= exeData.size()) {
// Read skip count (2 bytes LE)
uint16_t skipCount = exeData[pos] | (exeData[pos + 1] << 8);
pos += 2;
if (skipCount == 0) {
break; // End of skip/copy pairs
}
// Advance dest pointer by skipCount (gaps are zero-filled from memset)
destOffset += skipCount;
// Read copy count (2 bytes LE)
if (pos + 2 > exeData.size()) {
std::cerr << "[WardenModule] Unexpected end of data reading copy count" << '\n';
break;
}
uint16_t copyCount = exeData[pos] | (exeData[pos + 1] << 8);
pos += 2;
if (copyCount == 0) {
break; // End of copy/skip pairs
}
if (copyCount > 0) {
if (pos + copyCount > exeData.size()) {
std::cerr << "[WardenModule] Copy section extends beyond data bounds" << '\n';
@ -589,9 +578,19 @@ bool WardenModule::parseExecutableFormat(const std::vector<uint8_t>& exeData) {
destOffset += copyCount;
}
// Read skip count (2 bytes LE)
uint16_t skipCount = 0;
if (pos + 2 <= exeData.size()) {
skipCount = exeData[pos] | (exeData[pos + 1] << 8);
pos += 2;
}
// Advance dest pointer by skipCount (gaps are zero-filled from memset)
destOffset += skipCount;
pairCount++;
std::cout << "[WardenModule] Pair " << pairCount << ": skip " << skipCount
<< ", copy " << copyCount << " (dest offset=" << destOffset << ")" << '\n';
std::cout << "[WardenModule] Pair " << pairCount << ": copy " << copyCount
<< ", skip " << skipCount << " (dest offset=" << destOffset << ")" << '\n';
}
// Save position — remaining decompressed data contains relocation entries

View file

@ -294,11 +294,37 @@ std::shared_ptr<DBCFile> AssetManager::loadDBC(const std::string& name) {
if (dbcData.empty()) {
std::string dbcPath = "DBFilesClient\\" + name;
dbcData = readFile(dbcPath);
}
// If binary DBC not found and we skipped CSV earlier (forceBinaryForVisualDbc),
// try CSV as a last resort — better than no data at all (e.g. Classic expansion
// where binary DBCs come from MPQ extraction the user may not have done).
if (dbcData.empty() && forceBinaryForVisualDbc && !expansionDataPath_.empty()) {
std::string baseName = name;
auto dot = baseName.rfind('.');
if (dot != std::string::npos) {
baseName = baseName.substr(0, dot);
}
std::string csvPath = expansionDataPath_ + "/db/" + baseName + ".csv";
if (std::filesystem::exists(csvPath)) {
std::ifstream f(csvPath, std::ios::binary | std::ios::ate);
if (f) {
auto size = f.tellg();
if (size > 0) {
f.seekg(0);
dbcData.resize(static_cast<size_t>(size));
f.read(reinterpret_cast<char*>(dbcData.data()), size);
LOG_INFO("Binary DBC not found, using CSV fallback: ", csvPath);
loadedFromCSV = true;
}
}
}
}
if (dbcData.empty()) {
LOG_WARNING("DBC not found: ", name);
return nullptr;
}
}
auto dbc = std::make_shared<DBCFile>();
if (!dbc->load(dbcData)) {