libeuropa/io: Refactor PakWriter for pakv5 sector alignment support
This really could be classed a "fix", since adding support for it when reading broke writing. Now we do the right thing. This makes sector-alignment a no-op when writing other archive versions. I might make it an error to specify -s with a non-JSF package version.
This commit is contained in:
parent
dc95b3ba9c
commit
05d4b706b4
4 changed files with 38 additions and 14 deletions
|
@ -93,7 +93,7 @@ namespace europa::io {
|
|||
toc = value;
|
||||
}
|
||||
|
||||
void InitAs(structs::PakVersion version) {
|
||||
void InitAs(structs::PakVersion version, bool aligned) {
|
||||
switch(version) {
|
||||
case structs::PakVersion::Ver3:
|
||||
toc = structs::PakHeader_V3::TocEntry {};
|
||||
|
@ -102,6 +102,9 @@ namespace europa::io {
|
|||
toc = structs::PakHeader_V4::TocEntry {};
|
||||
break;
|
||||
case structs::PakVersion::Ver5:
|
||||
if(aligned)
|
||||
toc = structs::PakHeader_V5::TocEntry_SectorAligned {};
|
||||
else
|
||||
toc = structs::PakHeader_V5::TocEntry {};
|
||||
break;
|
||||
default:
|
||||
|
@ -147,6 +150,11 @@ namespace europa::io {
|
|||
return std::get<T>(toc);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
[[nodiscard]] T& GetTOCEntry() {
|
||||
return std::get<T>(toc);
|
||||
}
|
||||
|
||||
std::uint32_t GetCreationUnixTime() const {
|
||||
std::uint32_t time {};
|
||||
|
||||
|
|
|
@ -64,15 +64,21 @@ namespace europa::io {
|
|||
// Leave space for the header
|
||||
os.seekp(sizeof(THeader), std::ostream::beg);
|
||||
|
||||
// Version 5 paks seem to have an additional bit of reserved data
|
||||
// (which is all zeros.)
|
||||
if(THeader::VERSION == structs::PakVersion::Ver5) {
|
||||
os.seekp(6, std::ostream::cur);
|
||||
if constexpr(THeader::VERSION == structs::PakVersion::Ver5) {
|
||||
if(sectorAlignment == SectorAlignment::Align) {
|
||||
pakHeader.sectorAlignment = util::kCDSectorSize;
|
||||
pakHeader.sectorAlignedFlag = 1;
|
||||
} else {
|
||||
pakHeader.sectorAlignment = 0;
|
||||
pakHeader.sectorAlignedFlag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr(THeader::VERSION == structs::PakVersion::Ver5) {
|
||||
// Align the first file to start on the next sector boundary.
|
||||
if(sectorAlignment == SectorAlignment::Align)
|
||||
os.seekp(util::AlignBy(static_cast<std::size_t>(os.tellp()), util::kCDSectorSize), std::istream::beg);
|
||||
}
|
||||
|
||||
// Write all the file data
|
||||
for(auto& [filename, file] : sortedFiles) {
|
||||
|
@ -84,6 +90,14 @@ namespace europa::io {
|
|||
tocEntry.offset = os.tellp();
|
||||
});
|
||||
|
||||
// For sector alignment.
|
||||
if constexpr(THeader::VERSION == structs::PakVersion::Ver5) {
|
||||
if(sectorAlignment == SectorAlignment::Align) {
|
||||
auto& toc = file.GetTOCEntry<structs::PakHeader_V5::TocEntry_SectorAligned>();
|
||||
toc.startLBA = (os.tellp() / util::kCDSectorSize);
|
||||
}
|
||||
}
|
||||
|
||||
auto& fileData = file.GetData();
|
||||
|
||||
// Visit the file data sum type and do the right operation
|
||||
|
@ -109,9 +123,11 @@ namespace europa::io {
|
|||
});
|
||||
// clang-format on
|
||||
|
||||
if constexpr(THeader::VERSION == structs::PakVersion::Ver5) {
|
||||
// Align to the next sector boundary.
|
||||
if(sectorAlignment == SectorAlignment::Align)
|
||||
os.seekp(util::AlignBy(static_cast<std::size_t>(os.tellp()), util::kCDSectorSize), std::istream::beg);
|
||||
}
|
||||
|
||||
sink.OnEvent({ PakProgressReportSink::FileEvent::EventCode::FileWriteEnd,
|
||||
filename });
|
||||
|
|
|
@ -61,7 +61,7 @@ int main(int argc, char** argv) {
|
|||
.metavar("VERSION");
|
||||
|
||||
createParser.add_argument("-s", "--sector-aligned")
|
||||
.help(R"(Aligns all files in this new package to CD-ROM sector boundaries.)")
|
||||
.help(R"(Aligns all files in this new package to CD-ROM sector boundaries. Only valid for -V jedistarfighter.)")
|
||||
.flag();
|
||||
|
||||
createParser.add_argument("output")
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace eupak::tasks {
|
|||
eio::PakFile file;
|
||||
eio::PakFile::DataType pakData = eio::PakFileData::InitAsPath(ent.path());
|
||||
|
||||
file.InitAs(args.pakVersion);
|
||||
file.InitAs(args.pakVersion, args.sectorAligned);
|
||||
|
||||
// Add data
|
||||
file.SetData(std::move(pakData));
|
||||
|
|
Loading…
Reference in a new issue