diff --git a/src/game/warden_module.cpp b/src/game/warden_module.cpp index bad36430..68a2fc9c 100644 --- a/src/game/warden_module.cpp +++ b/src/game/warden_module.cpp @@ -529,34 +529,23 @@ bool WardenModule::parseExecutableFormat(const std::vector& 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& 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 diff --git a/src/pipeline/asset_manager.cpp b/src/pipeline/asset_manager.cpp index bacb3aa5..f7ffbdbb 100644 --- a/src/pipeline/asset_manager.cpp +++ b/src/pipeline/asset_manager.cpp @@ -294,10 +294,36 @@ std::shared_ptr AssetManager::loadDBC(const std::string& name) { if (dbcData.empty()) { std::string dbcPath = "DBFilesClient\\" + name; dbcData = readFile(dbcPath); - if (dbcData.empty()) { - LOG_WARNING("DBC not found: ", name); - return nullptr; + } + + // 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)); + f.read(reinterpret_cast(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();