public IList <IArchiveFileInfo> Load(Stream input) { using var br = new BinaryReaderX(input, true); // Read CPK header table _header = CpkTable.Create(input, 0); var headerRow = _header.Rows[0]; _align = headerRow.Get <int>("Align"); // Retrieve the offsets for the other tables. var contentOffset = headerRow.Get <long>("ContentOffset"); var tocOffset = headerRow.Get <long>("TocOffset"); var itocOffset = headerRow.Get <long>("ItocOffset"); var etocOffset = headerRow.Get <long>("EtocOffset"); // Read tables if (etocOffset > 0) { ReadEtocTable(br, etocOffset); } if (tocOffset > 0) { return(ReadTocTable(br, tocOffset, contentOffset).ToList()); } if (itocOffset > 0) { return(ReadItocTable(br, itocOffset).ToList()); } return(Array.Empty <IArchiveFileInfo>()); }
private IEnumerable <IArchiveFileInfo> ReadTocTable(BinaryReaderX br, long tocOffset, long contentOffset) { // Read toc table _tocTable = CpkTable.Create(br.BaseStream, tocOffset); // Determine file offset var fileOffset = tocOffset; if (contentOffset >= 0) { fileOffset = tocOffset < 0 ? contentOffset : Math.Min(contentOffset, tocOffset); } // Populate files foreach (var row in _tocTable.Rows) { var dir = row.Get <string>("DirName"); var name = row.Get <string>("FileName"); var offset = fileOffset + row.Get <long>("FileOffset"); var compSize = row.Get <int>("FileSize"); var decompSize = row.Get <int>("ExtractSize"); var subStream = new SubStream(br.BaseStream, offset, compSize); if (compSize == decompSize) { yield return(new CpkArchiveFileInfo(subStream, UPath.Combine(dir, name).FullName, row)); } else { yield return(new CpkArchiveFileInfo(subStream, UPath.Combine(dir, name).FullName, row, Kompression.Implementations.Compressions.Crilayla, decompSize)); } } }
private IEnumerable <IArchiveFileInfo> ReadItocTable(BinaryReaderX br, long itocOffset) { // Read toc table _itocTable = CpkTable.Create(br.BaseStream, itocOffset); // Read data tables var itocRow = _itocTable.Rows[0]; _dataLTable = CpkTable.Create(new MemoryStream(itocRow.Get <byte[]>("DataL")), "DataL"); _dataHTable = CpkTable.Create(new MemoryStream(itocRow.Get <byte[]>("DataH")), "DataH"); var fileOffset = _header.Rows[0].Get <long>("ContentOffset"); // Populate files foreach (var row in _dataLTable.Rows.Concat(_dataHTable.Rows).OrderBy(x => x.Get <long>("ID"))) { var id = row.Get <long>("ID"); var compSize = row.Get <int>("FileSize"); var decompSize = row.Get <int>("ExtractSize"); var subStream = new SubStream(br.BaseStream, fileOffset, compSize); if (compSize == decompSize) { yield return(new CpkArchiveFileInfo(subStream, $"{id:00000}.bin", row)); } else { yield return(new CpkArchiveFileInfo(subStream, $"{id:00000}.bin", row, Kompression.Implementations.Compressions.Crilayla, decompSize)); } fileOffset = (fileOffset + compSize + (_align - 1)) & ~(_align - 1); } }
private void ReadGtocTable(BinaryReaderX br, long gtocOffset) { _gtocTable = CpkTable.Create(br.BaseStream, gtocOffset); }
private void ReadEtocTable(BinaryReaderX br, long etocOffset) { _etocTable = CpkTable.Create(br.BaseStream, etocOffset); }