diff --git a/components/bsa/ba2dx10file.cpp b/components/bsa/ba2dx10file.cpp index 82a5ee84735..502ca043ab7 100644 --- a/components/bsa/ba2dx10file.cpp +++ b/components/bsa/ba2dx10file.cpp @@ -113,19 +113,29 @@ namespace Bsa input.read(reinterpret_cast(header), 16); input.read(reinterpret_cast(&fileTableOffset), 8); - if (header[0] == 0x00415342) /*"BSA\x00"*/ - fail("Unrecognized compressed BSA format"); + if (header[0] != ESM::fourCC("BTDX")) + fail("Unrecognized BA2 signature"); mVersion = header[1]; - if (mVersion != 0x01 /*FO4*/ && mVersion != 0x02 /*Starfield*/) - fail("Unrecognized compressed BSA version"); + switch (static_cast(mVersion)) + { + case BA2Version::Fallout4: + case BA2Version::Fallout4NextGen_v7: + case BA2Version::Fallout4NextGen_v8: + break; + case BA2Version::StarfieldDDS: + uint64_t dummy; + input.read(reinterpret_cast(&dummy), 8); + uint32_t compressionMethod; + input.read(reinterpret_cast(&compressionMethod), 4); + if (compressionMethod == 3) + fail("Unsupported LZ4-compressed DDS BA2"); + break; + default: + fail("Unrecognized DDS BA2 version"); + } type = header[2]; fileCount = header[3]; - if (mVersion == 0x02) - { - uint64_t dummy; - input.read(reinterpret_cast(&dummy), 8); - } } if (type == ESM::fourCC("DX10")) diff --git a/components/bsa/ba2file.hpp b/components/bsa/ba2file.hpp index 75a2ce8d614..9a68d3afd06 100644 --- a/components/bsa/ba2file.hpp +++ b/components/bsa/ba2file.hpp @@ -8,6 +8,15 @@ namespace Bsa { uint32_t generateHash(const std::string& name); uint32_t generateExtensionHash(std::string_view extension); + + enum class BA2Version : std::uint32_t + { + Fallout4 = 1, + StarfieldGeneral = 2, + StarfieldDDS = 3, + Fallout4NextGen_v7 = 7, + Fallout4NextGen_v8 = 8, + }; } #endif diff --git a/components/bsa/ba2gnrlfile.cpp b/components/bsa/ba2gnrlfile.cpp index da5ad470299..63dd3d1d508 100644 --- a/components/bsa/ba2gnrlfile.cpp +++ b/components/bsa/ba2gnrlfile.cpp @@ -107,19 +107,25 @@ namespace Bsa input.read(reinterpret_cast(header), 16); input.read(reinterpret_cast(&fileTableOffset), 8); - if (header[0] == 0x00415342) /*"BSA\x00"*/ - fail("Unrecognized compressed BSA format"); + if (header[0] != ESM::fourCC("BTDX")) + fail("Unrecognized BA2 signature"); mVersion = header[1]; - if (mVersion != 0x01 /*FO4*/ && mVersion != 0x02 /*Starfield*/) - fail("Unrecognized compressed BSA version"); + switch (static_cast(mVersion)) + { + case BA2Version::Fallout4: + case BA2Version::Fallout4NextGen_v7: + case BA2Version::Fallout4NextGen_v8: + break; + case BA2Version::StarfieldGeneral: + uint64_t dummy; + input.read(reinterpret_cast(&dummy), 8); + break; + default: + fail("Unrecognized general BA2 version"); + } type = header[2]; fileCount = header[3]; - if (mVersion == 0x02) - { - uint64_t dummy; - input.read(reinterpret_cast(&dummy), 8); - } } if (type == ESM::fourCC("GNRL")) diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index 4704e6e7e0a..46639a729e5 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -340,18 +340,18 @@ BsaVersion Bsa::BSAFile::detectVersion(const std::filesystem::path& filePath) return BsaVersion::Uncompressed; } - if (head[0] == static_cast(BsaVersion::Compressed) || head[0] == ESM::fourCC("BTDX")) + if (head[0] == static_cast(BsaVersion::Compressed)) { - if (head[1] == static_cast(0x01)) - { - if (head[2] == ESM::fourCC("GNRL")) - return BsaVersion::BA2GNRL; - if (head[2] == ESM::fourCC("DX10")) - return BsaVersion::BA2DX10; - return BsaVersion::Unknown; - } return BsaVersion::Compressed; } + if (head[0] == ESM::fourCC("BTDX")) + { + if (head[2] == ESM::fourCC("GNRL")) + return BsaVersion::BA2GNRL; + if (head[2] == ESM::fourCC("DX10")) + return BsaVersion::BA2DX10; + } + return BsaVersion::Unknown; }