mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-26 21:13:51 +00:00
Fix all remaining build warnings and eliminate UB in binary parsers
Resolve 57 compiler warnings (unused params/vars, ignored return values, enum mismatch) and replace undefined-behavior reinterpret_cast with memcpy in DBC, BLP, and Warden module loaders for ARM64 portability.
This commit is contained in:
parent
22518f0936
commit
aaab2115d1
12 changed files with 112 additions and 101 deletions
|
|
@ -30,34 +30,39 @@ BLPImage BLPLoader::load(const std::vector<uint8_t>& blpData) {
|
|||
}
|
||||
|
||||
BLPImage BLPLoader::loadBLP1(const uint8_t* data, size_t size) {
|
||||
// BLP1 header has all uint32 fields (different layout from BLP2)
|
||||
const BLP1Header* header = reinterpret_cast<const BLP1Header*>(data);
|
||||
// Copy header to stack to avoid unaligned reinterpret_cast (UB on strict platforms)
|
||||
if (size < sizeof(BLP1Header)) {
|
||||
LOG_ERROR("BLP1 data too small for header");
|
||||
return BLPImage();
|
||||
}
|
||||
BLP1Header header;
|
||||
std::memcpy(&header, data, sizeof(BLP1Header));
|
||||
|
||||
BLPImage image;
|
||||
image.format = BLPFormat::BLP1;
|
||||
image.width = header->width;
|
||||
image.height = header->height;
|
||||
image.width = header.width;
|
||||
image.height = header.height;
|
||||
image.channels = 4;
|
||||
image.mipLevels = header->hasMips ? 16 : 1;
|
||||
image.mipLevels = header.hasMips ? 16 : 1;
|
||||
|
||||
// BLP1 compression: 0=JPEG (not used in WoW), 1=palette/indexed
|
||||
// BLP1 does NOT support DXT — only palette with optional alpha
|
||||
if (header->compression == 1) {
|
||||
if (header.compression == 1) {
|
||||
image.compression = BLPCompression::PALETTE;
|
||||
} else if (header->compression == 0) {
|
||||
} else if (header.compression == 0) {
|
||||
LOG_WARNING("BLP1 JPEG compression not supported");
|
||||
return BLPImage();
|
||||
} else {
|
||||
LOG_WARNING("BLP1 unknown compression: ", header->compression);
|
||||
LOG_WARNING("BLP1 unknown compression: ", header.compression);
|
||||
return BLPImage();
|
||||
}
|
||||
|
||||
LOG_DEBUG("Loading BLP1: ", image.width, "x", image.height, " ",
|
||||
getCompressionName(image.compression), " alpha=", header->alphaBits);
|
||||
getCompressionName(image.compression), " alpha=", header.alphaBits);
|
||||
|
||||
// Get first mipmap (full resolution)
|
||||
uint32_t offset = header->mipOffsets[0];
|
||||
uint32_t mipSize = header->mipSizes[0];
|
||||
uint32_t offset = header.mipOffsets[0];
|
||||
uint32_t mipSize = header.mipSizes[0];
|
||||
|
||||
if (offset + mipSize > size) {
|
||||
LOG_ERROR("BLP1 mipmap data out of bounds (offset=", offset, " size=", mipSize, " fileSize=", size, ")");
|
||||
|
|
@ -70,45 +75,50 @@ BLPImage BLPLoader::loadBLP1(const uint8_t* data, size_t size) {
|
|||
int pixelCount = image.width * image.height;
|
||||
image.data.resize(pixelCount * 4); // RGBA8
|
||||
|
||||
decompressPalette(mipData, image.data.data(), header->palette,
|
||||
image.width, image.height, static_cast<uint8_t>(header->alphaBits));
|
||||
decompressPalette(mipData, image.data.data(), header.palette,
|
||||
image.width, image.height, static_cast<uint8_t>(header.alphaBits));
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
BLPImage BLPLoader::loadBLP2(const uint8_t* data, size_t size) {
|
||||
// BLP2 header has uint8 fields for compression/alpha/encoding
|
||||
const BLP2Header* header = reinterpret_cast<const BLP2Header*>(data);
|
||||
// Copy header to stack to avoid unaligned reinterpret_cast (UB on strict platforms)
|
||||
if (size < sizeof(BLP2Header)) {
|
||||
LOG_ERROR("BLP2 data too small for header");
|
||||
return BLPImage();
|
||||
}
|
||||
BLP2Header header;
|
||||
std::memcpy(&header, data, sizeof(BLP2Header));
|
||||
|
||||
BLPImage image;
|
||||
image.format = BLPFormat::BLP2;
|
||||
image.width = header->width;
|
||||
image.height = header->height;
|
||||
image.width = header.width;
|
||||
image.height = header.height;
|
||||
image.channels = 4;
|
||||
image.mipLevels = header->hasMips ? 16 : 1;
|
||||
image.mipLevels = header.hasMips ? 16 : 1;
|
||||
|
||||
// BLP2 compression types:
|
||||
// 1 = palette/uncompressed
|
||||
// 2 = DXTC (DXT1/DXT3/DXT5 based on alphaDepth + alphaEncoding)
|
||||
// 3 = plain A8R8G8B8
|
||||
if (header->compression == 1) {
|
||||
if (header.compression == 1) {
|
||||
image.compression = BLPCompression::PALETTE;
|
||||
} else if (header->compression == 2) {
|
||||
} else if (header.compression == 2) {
|
||||
// BLP2 DXTC format selection based on alphaDepth + alphaEncoding:
|
||||
// alphaDepth=0 → DXT1 (no alpha)
|
||||
// alphaDepth>0, alphaEncoding=0 → DXT1 (1-bit alpha)
|
||||
// alphaDepth>0, alphaEncoding=1 → DXT3 (explicit 4-bit alpha)
|
||||
// alphaDepth>0, alphaEncoding=7 → DXT5 (interpolated alpha)
|
||||
if (header->alphaDepth == 0 || header->alphaEncoding == 0) {
|
||||
if (header.alphaDepth == 0 || header.alphaEncoding == 0) {
|
||||
image.compression = BLPCompression::DXT1;
|
||||
} else if (header->alphaEncoding == 1) {
|
||||
} else if (header.alphaEncoding == 1) {
|
||||
image.compression = BLPCompression::DXT3;
|
||||
} else if (header->alphaEncoding == 7) {
|
||||
} else if (header.alphaEncoding == 7) {
|
||||
image.compression = BLPCompression::DXT5;
|
||||
} else {
|
||||
image.compression = BLPCompression::DXT1;
|
||||
}
|
||||
} else if (header->compression == 3) {
|
||||
} else if (header.compression == 3) {
|
||||
image.compression = BLPCompression::ARGB8888;
|
||||
} else {
|
||||
image.compression = BLPCompression::ARGB8888;
|
||||
|
|
@ -116,13 +126,13 @@ BLPImage BLPLoader::loadBLP2(const uint8_t* data, size_t size) {
|
|||
|
||||
LOG_DEBUG("Loading BLP2: ", image.width, "x", image.height, " ",
|
||||
getCompressionName(image.compression),
|
||||
" (comp=", (int)header->compression, " alphaDepth=", (int)header->alphaDepth,
|
||||
" alphaEnc=", (int)header->alphaEncoding, " mipOfs=", header->mipOffsets[0],
|
||||
" mipSize=", header->mipSizes[0], ")");
|
||||
" (comp=", (int)header.compression, " alphaDepth=", (int)header.alphaDepth,
|
||||
" alphaEnc=", (int)header.alphaEncoding, " mipOfs=", header.mipOffsets[0],
|
||||
" mipSize=", header.mipSizes[0], ")");
|
||||
|
||||
// Get first mipmap (full resolution)
|
||||
uint32_t offset = header->mipOffsets[0];
|
||||
uint32_t mipSize = header->mipSizes[0];
|
||||
uint32_t offset = header.mipOffsets[0];
|
||||
uint32_t mipSize = header.mipSizes[0];
|
||||
|
||||
if (offset + mipSize > size) {
|
||||
LOG_ERROR("BLP2 mipmap data out of bounds");
|
||||
|
|
@ -149,8 +159,8 @@ BLPImage BLPLoader::loadBLP2(const uint8_t* data, size_t size) {
|
|||
break;
|
||||
|
||||
case BLPCompression::PALETTE:
|
||||
decompressPalette(mipData, image.data.data(), header->palette,
|
||||
image.width, image.height, header->alphaDepth);
|
||||
decompressPalette(mipData, image.data.data(), header.palette,
|
||||
image.width, image.height, header.alphaDepth);
|
||||
break;
|
||||
|
||||
case BLPCompression::ARGB8888:
|
||||
|
|
|
|||
|
|
@ -42,19 +42,20 @@ bool DBCFile::load(const std::vector<uint8_t>& dbcData) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Read header
|
||||
const DBCHeader* header = reinterpret_cast<const DBCHeader*>(dbcData.data());
|
||||
// Read header safely (avoid unaligned reinterpret_cast — UB on strict platforms)
|
||||
DBCHeader header;
|
||||
std::memcpy(&header, dbcData.data(), sizeof(DBCHeader));
|
||||
|
||||
// Verify magic
|
||||
if (std::memcmp(header->magic, "WDBC", 4) != 0) {
|
||||
LOG_ERROR("Invalid DBC magic: ", std::string(header->magic, 4));
|
||||
if (std::memcmp(header.magic, "WDBC", 4) != 0) {
|
||||
LOG_ERROR("Invalid DBC magic: ", std::string(header.magic, 4));
|
||||
return false;
|
||||
}
|
||||
|
||||
recordCount = header->recordCount;
|
||||
fieldCount = header->fieldCount;
|
||||
recordSize = header->recordSize;
|
||||
stringBlockSize = header->stringBlockSize;
|
||||
recordCount = header.recordCount;
|
||||
fieldCount = header.fieldCount;
|
||||
recordSize = header.recordSize;
|
||||
stringBlockSize = header.stringBlockSize;
|
||||
|
||||
// Validate sizes
|
||||
uint32_t expectedSize = sizeof(DBCHeader) + (recordCount * recordSize) + stringBlockSize;
|
||||
|
|
@ -111,8 +112,9 @@ uint32_t DBCFile::getUInt32(uint32_t recordIndex, uint32_t fieldIndex) const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t* field = reinterpret_cast<const uint32_t*>(record + (fieldIndex * 4));
|
||||
return *field;
|
||||
uint32_t value;
|
||||
std::memcpy(&value, record + (fieldIndex * 4), sizeof(uint32_t));
|
||||
return value;
|
||||
}
|
||||
|
||||
int32_t DBCFile::getInt32(uint32_t recordIndex, uint32_t fieldIndex) const {
|
||||
|
|
@ -129,8 +131,9 @@ float DBCFile::getFloat(uint32_t recordIndex, uint32_t fieldIndex) const {
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
const float* field = reinterpret_cast<const float*>(record + (fieldIndex * 4));
|
||||
return *field;
|
||||
float value;
|
||||
std::memcpy(&value, record + (fieldIndex * 4), sizeof(float));
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string DBCFile::getString(uint32_t recordIndex, uint32_t fieldIndex) const {
|
||||
|
|
|
|||
|
|
@ -1456,9 +1456,7 @@ bool M2Loader::loadSkin(const std::vector<uint8_t>& skinData, M2Model& model) {
|
|||
if (header.nSubmeshes > 0 && header.ofsSubmeshes > 0) {
|
||||
submeshes = readArray<M2SkinSubmesh>(skinData, header.ofsSubmeshes, header.nSubmeshes);
|
||||
core::Logger::getInstance().debug(" Submeshes: ", submeshes.size());
|
||||
for (size_t i = 0; i < submeshes.size(); i++) {
|
||||
const auto& sm = submeshes[i];
|
||||
}
|
||||
(void)submeshes;
|
||||
}
|
||||
|
||||
// Read batches with proper submesh references
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue