From 129bd516721b25b69b4b2e21a7b3a519f91f9c92 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Fri, 23 Oct 2020 14:04:21 +0300 Subject: [PATCH] Add compressed BSA support to bsatool --- apps/bsatool/bsatool.cpp | 53 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp index ed86a3a42..3afbd777f 100644 --- a/apps/bsatool/bsatool.cpp +++ b/apps/bsatool/bsatool.cpp @@ -6,7 +6,8 @@ #include #include -#include +#include +#include #define BSATOOL_VERSION 1.1 @@ -25,16 +26,6 @@ struct Arguments bool fullpath; }; -void replaceAll(std::string& str, const std::string& needle, const std::string& substitute) -{ - size_t pos = str.find(needle); - while(pos != std::string::npos) - { - str.replace(pos, needle.size(), substitute); - pos = str.find(needle); - } -} - bool parseOptions (int argc, char** argv, Arguments &info) { bpo::options_description desc("Inspect and extract files from Bethesda BSA archives\n\n" @@ -144,9 +135,9 @@ bool parseOptions (int argc, char** argv, Arguments &info) return true; } -int list(Bsa::BSAFile& bsa, Arguments& info); -int extract(Bsa::BSAFile& bsa, Arguments& info); -int extractAll(Bsa::BSAFile& bsa, Arguments& info); +int list(std::unique_ptr& bsa, Arguments& info); +int extract(std::unique_ptr& bsa, Arguments& info); +int extractAll(std::unique_ptr& bsa, Arguments& info); int main(int argc, char** argv) { @@ -157,8 +148,16 @@ int main(int argc, char** argv) return 1; // Open file - Bsa::BSAFile bsa; - bsa.open(info.filename); + std::unique_ptr bsa; + + Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(info.filename); + + if (bsaVersion == Bsa::BSAVER_COMPRESSED) + bsa = std::make_unique(Bsa::CompressedBSAFile()); + else + bsa = std::make_unique(Bsa::BSAFile()); + + bsa->open(info.filename); if (info.mode == "list") return list(bsa, info); @@ -179,10 +178,10 @@ int main(int argc, char** argv) } } -int list(Bsa::BSAFile& bsa, Arguments& info) +int list(std::unique_ptr& bsa, Arguments& info) { // List all files - const Bsa::BSAFile::FileList &files = bsa.getList(); + const Bsa::BSAFile::FileList &files = bsa->getList(); for (const auto& file : files) { if(info.longformat) @@ -201,15 +200,15 @@ int list(Bsa::BSAFile& bsa, Arguments& info) return 0; } -int extract(Bsa::BSAFile& bsa, Arguments& info) +int extract(std::unique_ptr& bsa, Arguments& info) { std::string archivePath = info.extractfile; - replaceAll(archivePath, "/", "\\"); + Misc::StringUtils::replaceAll(archivePath, "/", "\\"); std::string extractPath = info.extractfile; - replaceAll(extractPath, "\\", "/"); + Misc::StringUtils::replaceAll(extractPath, "\\", "/"); - if (!bsa.exists(archivePath.c_str())) + if (!bsa->exists(archivePath.c_str())) { std::cout << "ERROR: file '" << archivePath << "' not found\n"; std::cout << "In archive: " << info.filename << std::endl; @@ -237,7 +236,7 @@ int extract(Bsa::BSAFile& bsa, Arguments& info) } // Get a stream for the file to extract - Files::IStreamPtr stream = bsa.getFile(archivePath.c_str()); + Files::IStreamPtr stream = bsa->getFile(archivePath.c_str()); bfs::ofstream out(target, std::ios::binary); @@ -250,12 +249,12 @@ int extract(Bsa::BSAFile& bsa, Arguments& info) return 0; } -int extractAll(Bsa::BSAFile& bsa, Arguments& info) +int extractAll(std::unique_ptr& bsa, Arguments& info) { - for (const auto &file : bsa.getList()) + for (const auto &file : bsa->getList()) { std::string extractPath(file.name); - replaceAll(extractPath, "\\", "/"); + Misc::StringUtils::replaceAll(extractPath, "\\", "/"); // Get the target path (the path the file will be extracted to) bfs::path target (info.outdir); @@ -273,7 +272,7 @@ int extractAll(Bsa::BSAFile& bsa, Arguments& info) // Get a stream for the file to extract // (inefficient because getFile iter on the list again) - Files::IStreamPtr data = bsa.getFile(file.name); + Files::IStreamPtr data = bsa->getFile(file.name); bfs::ofstream out(target, std::ios::binary); // Write the file to disk