Use the right archive type to load bsa according to their type

depth-refraction
Cédric Mocquillon 1 year ago
parent 974799c011
commit d30deef4b5

@ -48,12 +48,14 @@ std::unique_ptr<VFS::Archive> makeBsaArchive(const std::filesystem::path& path)
case Bsa::BSAVER_UNKNOWN:
std::cerr << '"' << path << "\" is unknown BSA archive" << std::endl;
return nullptr;
case Bsa::BSAVER_UNCOMPRESSED:
return std::make_unique<VFS::BsaArchive>(path);
case Bsa::BSAVER_COMPRESSED:
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_COMPRESSED>::type>(path);
case Bsa::BSAVER_BA2_GNRL:
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_BA2_GNRL>::type>(path);
case Bsa::BSAVER_BA2_DX10:
return std::make_unique<VFS::CompressedBsaArchive>(path);
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_BA2_DX10>::type>(path);
case Bsa::BSAVER_UNCOMPRESSED:
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>::type>(path);
}
std::cerr << '"' << path << "\" is unsupported BSA archive" << std::endl;

@ -1,120 +0,0 @@
#include "bsaarchive.hpp"
#include <algorithm>
#include <memory>
namespace VFS
{
BsaArchive::BsaArchive(const std::filesystem::path& filename)
{
mFile = std::make_unique<Bsa::BSAFile>();
mFile->open(filename);
const Bsa::BSAFile::FileList& filelist = mFile->getList();
for (Bsa::BSAFile::FileList::const_iterator it = filelist.begin(); it != filelist.end(); ++it)
{
mResources.emplace_back(&*it, mFile.get());
}
}
BsaArchive::BsaArchive() {}
BsaArchive::~BsaArchive() {}
void BsaArchive::listResources(std::map<std::string, File*>& out, char (*normalize_function)(char))
{
for (std::vector<BsaArchiveFile>::iterator it = mResources.begin(); it != mResources.end(); ++it)
{
std::string ent = it->mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
out[ent] = &*it;
}
}
bool BsaArchive::contains(const std::string& file, char (*normalize_function)(char)) const
{
for (const auto& it : mResources)
{
std::string ent = it.mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
if (file == ent)
return true;
}
return false;
}
std::string BsaArchive::getDescription() const
{
return std::string{ "BSA: " } + mFile->getFilename();
}
// ------------------------------------------------------------------------------
BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::BSAFile* bsa)
: mInfo(info)
, mFile(bsa)
{
}
Files::IStreamPtr BsaArchiveFile::open()
{
return mFile->getFile(mInfo);
}
CompressedBsaArchive::CompressedBsaArchive(const std::filesystem::path& filename)
: Archive()
{
mCompressedFile = std::make_unique<Bsa::CompressedBSAFile>();
mCompressedFile->open(filename);
const Bsa::BSAFile::FileList& filelist = mCompressedFile->getList();
for (Bsa::BSAFile::FileList::const_iterator it = filelist.begin(); it != filelist.end(); ++it)
{
mCompressedResources.emplace_back(&*it, mCompressedFile.get());
}
}
void CompressedBsaArchive::listResources(std::map<std::string, File*>& out, char (*normalize_function)(char))
{
for (std::vector<CompressedBsaArchiveFile>::iterator it = mCompressedResources.begin();
it != mCompressedResources.end(); ++it)
{
std::string ent = it->mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
out[ent] = &*it;
}
}
bool CompressedBsaArchive::contains(const std::string& file, char (*normalize_function)(char)) const
{
for (const auto& it : mCompressedResources)
{
std::string ent = it.mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
if (file == ent)
return true;
}
return false;
}
std::string CompressedBsaArchive::getDescription() const
{
return std::string{ "BSA: " } + mCompressedFile->getFilename();
}
CompressedBsaArchiveFile::CompressedBsaArchiveFile(
const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa)
: mInfo(info)
, mCompressedFile(bsa)
{
}
Files::IStreamPtr CompressedBsaArchiveFile::open()
{
return mCompressedFile->getFile(mInfo);
}
}

@ -3,66 +3,108 @@
#include "archive.hpp"
#include <components/bsa/ba2dx10file.hpp>
#include <components/bsa/ba2gnrlfile.hpp>
#include <components/bsa/bsa_file.hpp>
#include <components/bsa/compressedbsafile.hpp>
namespace VFS
{
template <typename FileType>
class BsaArchiveFile : public File
{
public:
BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::BSAFile* bsa);
BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, FileType* bsa)
: mInfo(info)
, mFile(bsa)
{
}
Files::IStreamPtr open() override;
Files::IStreamPtr open() override { return mFile->getFile(mInfo); }
std::filesystem::path getPath() override { return mInfo->name(); }
const Bsa::BSAFile::FileStruct* mInfo;
Bsa::BSAFile* mFile;
FileType* mFile;
};
class CompressedBsaArchiveFile : public File
template <typename BSAFileType>
class BsaArchive : public Archive
{
public:
CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa);
Files::IStreamPtr open() override;
BsaArchive(const std::filesystem::path& filename)
: Archive()
{
mFile = std::make_unique<BSAFileType>();
mFile->open(filename);
const Bsa::BSAFile::FileList& filelist = mFile->getList();
for (Bsa::BSAFile::FileList::const_iterator it = filelist.begin(); it != filelist.end(); ++it)
{
mResources.emplace_back(&*it, mFile.get());
}
}
virtual ~BsaArchive() {}
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override
{
for (auto& resource : mResources)
{
std::string ent = resource.mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
out[ent] = &resource;
}
}
bool contains(const std::string& file, char (*normalize_function)(char)) const override
{
for (const auto& it : mResources)
{
std::string ent = it.mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
if (file == ent)
return true;
}
return false;
}
std::string getDescription() const override { return std::string{ "BSA: " } + mFile->getFilename(); }
std::filesystem::path getPath() override { return mInfo->name(); }
private:
std::unique_ptr<BSAFileType> mFile;
std::vector<BsaArchiveFile<BSAFileType>> mResources;
};
const Bsa::BSAFile::FileStruct* mInfo;
Bsa::CompressedBSAFile* mCompressedFile;
template <Bsa::BsaVersion>
struct ArchiveSelector
{
};
class BsaArchive : public Archive
template <>
struct ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>
{
public:
BsaArchive(const std::filesystem::path& filename);
BsaArchive();
virtual ~BsaArchive();
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override;
bool contains(const std::string& file, char (*normalize_function)(char)) const override;
std::string getDescription() const override;
protected:
std::unique_ptr<Bsa::BSAFile> mFile;
std::vector<BsaArchiveFile> mResources;
using type = BsaArchive<Bsa::BSAFile>;
};
class CompressedBsaArchive : public Archive
template <>
struct ArchiveSelector<Bsa::BSAVER_COMPRESSED>
{
public:
CompressedBsaArchive(const std::filesystem::path& filename);
virtual ~CompressedBsaArchive() {}
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override;
bool contains(const std::string& file, char (*normalize_function)(char)) const override;
std::string getDescription() const override;
using type = BsaArchive<Bsa::CompressedBSAFile>;
};
private:
std::unique_ptr<Bsa::CompressedBSAFile> mCompressedFile;
std::vector<CompressedBsaArchiveFile> mCompressedResources;
template <>
struct ArchiveSelector<Bsa::BSAVER_BA2_GNRL>
{
using type = BsaArchive<Bsa::BA2GNRLFile>;
};
template <>
struct ArchiveSelector<Bsa::BSAVER_BA2_DX10>
{
using type = BsaArchive<Bsa::BA2DX10File>;
};
}
#endif

@ -28,9 +28,15 @@ namespace VFS
Bsa::BsaVersion bsaVersion = Bsa::BSAFile::detectVersion(archivePath);
if (bsaVersion == Bsa::BSAVER_COMPRESSED)
vfs->addArchive(std::make_unique<CompressedBsaArchive>(archivePath));
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_COMPRESSED>::type>(archivePath));
else if (bsaVersion == Bsa::BSAVER_BA2_GNRL)
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_BA2_GNRL>::type>(archivePath));
else if (bsaVersion == Bsa::BSAVER_BA2_DX10)
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_BA2_DX10>::type>(archivePath));
else if (bsaVersion == Bsa::BSAVER_UNCOMPRESSED)
vfs->addArchive(std::make_unique<ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>::type>(archivePath));
else
vfs->addArchive(std::make_unique<BsaArchive>(archivePath));
throw std::runtime_error("Unknown archive type '" + *archive + "'");
}
else
{

Loading…
Cancel
Save