From 1877374a92c50cfbb410e7b183d7ce8770d281ba Mon Sep 17 00:00:00 2001 From: PikalaxALT Date: Tue, 16 Jun 2020 17:03:56 -0400 Subject: KNARC: Add handling of .knarcignore, .knarckeep; fix up cli --- tools/knarc/Narc.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'tools/knarc/Narc.cpp') diff --git a/tools/knarc/Narc.cpp b/tools/knarc/Narc.cpp index 506e050f..00a9d0ed 100644 --- a/tools/knarc/Narc.cpp +++ b/tools/knarc/Narc.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #if __GNUC__ <= 7 #include @@ -24,6 +26,9 @@ namespace fs = std::filesystem; using namespace std; +extern bool debug; +extern bool pack_no_fnt; + void Narc::AlignDword(ofstream& ofs, uint8_t paddingChar) { if ((ofs.tellp() % 4) != 0) @@ -104,6 +109,26 @@ NarcError Narc::GetError() const return error; } +class WildcardVector : public vector { +public: + WildcardVector(fs::path fp) { + fstream infile; + if (!fs::exists(fp)) return; + infile.open(fp, ios_base::in); + string line; + while (getline(infile, line)) { + push_back(line); + } + } + bool matches(string fp) { + for (string& pattern : *this) { + if (fnmatch(pattern.c_str(), fp.c_str(), FNM_PERIOD) == 0) + return true; + } + return false; + } +}; + bool Narc::Pack(const fs::path& fileName, const fs::path& directory) { ofstream ofs(fileName, ios::binary); @@ -113,14 +138,22 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) vector fatEntries; uint16_t directoryCounter = 1; + WildcardVector ignore_patterns(directory / ".knarcignore"); + ignore_patterns.push_back(".*ignore"); + ignore_patterns.push_back(".*keep"); + WildcardVector keep_patterns(directory / ".knarckeep"); + for (const auto& de : OrderedDirectoryIterator(directory, true)) { if (is_directory(de)) { ++directoryCounter; } - else + else if (keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename())) { + if (debug) { + cerr << "DEBUG: adding file " << de.path() << endl; + } fatEntries.push_back(FileAllocationTableEntry { .Start = 0x0, @@ -143,7 +176,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) FileAllocationTable fat { - .Id = 0x46415442, + .Id = 0x46415442, // BTAF .ChunkSize = sizeof(FileAllocationTable) + ((uint32_t)fatEntries.size() * sizeof(FileAllocationTableEntry)), .FileCount = static_cast(fatEntries.size()), .Reserved = 0x0 @@ -156,7 +189,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) for (const auto& de : OrderedDirectoryIterator(directory, true)) { - if (!subTables.count(de.path().parent_path())) + if (!subTables.count(de.path().parent_path()) && (keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename()))) { subTables.insert({ de.path().parent_path(), "" }); paths.push_back(de.path().parent_path()); @@ -171,7 +204,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) subTables[de.path().parent_path()] += (0xF000 + directoryCounter) & 0xFF; subTables[de.path().parent_path()] += (0xF000 + directoryCounter) >> 8; } - else + else if (keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename())) { subTables[de.path().parent_path()] += static_cast(de.path().filename().string().size()); subTables[de.path().parent_path()] += de.path().filename().string(); @@ -185,7 +218,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) vector fntEntries; - if (!regex_match(fs::directory_iterator(directory)->path().string(), regex(".*_\\d{4,8}\\.bin"))) + if (!pack_no_fnt) { fntEntries.push_back( { @@ -231,11 +264,11 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) FileNameTable fnt { - .Id = 0x464E5442, + .Id = 0x464E5442, // BTNF .ChunkSize = sizeof(FileNameTable) + (fntEntries.size() * sizeof(FileNameTableEntry)) }; - if (!regex_match(fs::directory_iterator(directory)->path().string(), regex(".*_\\d{4,8}\\.bin"))) + if (!pack_no_fnt) { for (const auto& subTable : subTables) { @@ -250,7 +283,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) FileImages fi { - .Id = 0x46494D47, + .Id = 0x46494D47, // GMIF .ChunkSize = sizeof(FileImages) + fatEntries.back().End }; @@ -261,7 +294,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) Header header { - .Id = 0x4352414E, + .Id = 0x4352414E, // NARC .ByteOrderMark = 0xFFFE, .Version = 0x100, .FileSize = sizeof(Header) + fat.ChunkSize + fnt.ChunkSize + fi.ChunkSize, @@ -284,7 +317,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) ofs.write(reinterpret_cast(&entry), sizeof(FileNameTableEntry)); } - if (!regex_match(fs::directory_iterator(directory)->path().string(), regex(".*_\\d{4,8}\\.bin"))) + if (!pack_no_fnt) { for (const auto& path : paths) { @@ -303,6 +336,11 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) continue; } + if (!(keep_patterns.matches(de.path().filename()) || !ignore_patterns.matches(de.path().filename()))) + { + continue; + } + ifstream ifs(de.path(), ios::binary | ios::ate); if (!ifs.good()) -- cgit v1.2.3 From 6580c05decb34d3c3faaa266fd411d0a1a7e8e0b Mon Sep 17 00:00:00 2001 From: PikalaxALT Date: Tue, 16 Jun 2020 17:11:00 -0400 Subject: KNARC: Fix typo in help string; suppress narrowing warnings --- tools/knarc/Narc.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tools/knarc/Narc.cpp') diff --git a/tools/knarc/Narc.cpp b/tools/knarc/Narc.cpp index 00a9d0ed..7ccdcf0e 100644 --- a/tools/knarc/Narc.cpp +++ b/tools/knarc/Narc.cpp @@ -177,7 +177,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) FileAllocationTable fat { .Id = 0x46415442, // BTAF - .ChunkSize = sizeof(FileAllocationTable) + ((uint32_t)fatEntries.size() * sizeof(FileAllocationTableEntry)), + .ChunkSize = static_cast(sizeof(FileAllocationTable) + ((uint32_t)fatEntries.size() * sizeof(FileAllocationTableEntry))), .FileCount = static_cast(fatEntries.size()), .Reserved = 0x0 }; @@ -222,7 +222,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) { fntEntries.push_back( { - .Offset = (directoryCounter + 1) * sizeof(FileNameTableEntry), + .Offset = static_cast((directoryCounter + 1) * sizeof(FileNameTableEntry)), .FirstFileId = 0x0, .Utility = static_cast(directoryCounter + 1) }); @@ -231,7 +231,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) { fntEntries.push_back( { - .Offset = fntEntries.back().Offset + subTables[paths[i]].size(), + .Offset = static_cast(fntEntries.back().Offset + subTables[paths[i]].size()), .FirstFileId = fntEntries.back().FirstFileId, .Utility = 0x0 }); @@ -265,7 +265,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) FileNameTable fnt { .Id = 0x464E5442, // BTNF - .ChunkSize = sizeof(FileNameTable) + (fntEntries.size() * sizeof(FileNameTableEntry)) + .ChunkSize = static_cast(sizeof(FileNameTable) + (fntEntries.size() * sizeof(FileNameTableEntry))) }; if (!pack_no_fnt) @@ -284,7 +284,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) FileImages fi { .Id = 0x46494D47, // GMIF - .ChunkSize = sizeof(FileImages) + fatEntries.back().End + .ChunkSize = static_cast(sizeof(FileImages) + fatEntries.back().End) }; if ((fi.ChunkSize % 4) != 0) @@ -297,7 +297,7 @@ bool Narc::Pack(const fs::path& fileName, const fs::path& directory) .Id = 0x4352414E, // NARC .ByteOrderMark = 0xFFFE, .Version = 0x100, - .FileSize = sizeof(Header) + fat.ChunkSize + fnt.ChunkSize + fi.ChunkSize, + .FileSize = static_cast(sizeof(Header) + fat.ChunkSize + fnt.ChunkSize + fi.ChunkSize), .ChunkSize = sizeof(Header), .ChunkCount = 0x3 }; -- cgit v1.2.3