/// <summary> /// /// </summary> /// <param name="input"></param> /// <returns></returns> public List <IArchiveFileInfo> Load(Stream input) { using var br = new BinaryReaderX(input, true, ByteOrder.BigEndian); Header = br.ReadType <Header>(); // Determine BlockLength uint blockIterator = 256; do { blockIterator *= 256; BlockLength = (ushort)(BlockLength + 1); } while (blockIterator < Header.BlockSize); // Manifest //var manifestEntry = br.ReadType<Entry>(); var manifestEntry = ReadEntry(br); // Entries //var fileEntries = br.ReadMultiple<Entry>(Header.TocEntryCount - 1); var fileEntries = new List <Entry>(); for (var i = 1; i < Header.TocEntryCount; i++) { fileEntries.Add(ReadEntry(br)); } // Blocks var numBlocks = (Header.TocSize - (int)br.BaseStream.Position) / BlockLength; for (var i = 0; i < numBlocks; i++) { CompressedBlockSizes.Add(br.ReadBytes(BlockLength).Reverse().Select((x, j) => x << 8 * j).Sum()); } // Check for SDAT Encryption if (Header.TocEntryCount > 0) { br.BaseStream.Position = manifestEntry.Offset; var compression = br.ReadUInt16(); br.BaseStream.Position -= 2; AllStarsEncryptedArchive = compression == AllStarsEncryptionA || compression == AllStarsEncryptionB; } // Load Filenames var filenames = new List <string>(); if (!AllStarsEncryptedArchive) { var manifestStream = new PsarcBlockStream(input, manifestEntry, Header.BlockSize, CompressedBlockSizes); using var brNames = new BinaryReaderX(manifestStream, Encoding.UTF8); for (var i = 1; i < Header.TocEntryCount; i++) { filenames.Add(Encoding.UTF8.GetString(brNames.ReadBytesUntil(0x0, (byte)'\n'))); } } else { // Temporary until we can decrypt AllStars PSARCs. for (var i = 1; i < Header.TocEntryCount; i++) { filenames.Add($"/{i:00000000}.bin"); } } // Files var _files = new List <IArchiveFileInfo>(); if (!AllStarsEncryptedArchive) { for (int i = 0; i < fileEntries.Count; i++) { _files.Add(new PsarcFileInfo(new PsarcBlockStream(input, fileEntries[i], Header.BlockSize, CompressedBlockSizes), filenames[i])); } } else { for (int i = 0; i < fileEntries.Count; i++) { var entry = fileEntries[i]; var compressedSize = 0L; for (var j = entry.FirstBlockIndex; j < entry.FirstBlockIndex + Math.Ceiling((double)entry.UncompressedSize / Header.BlockSize); j++) { compressedSize += CompressedBlockSizes[j] == 0 ? Header.BlockSize : CompressedBlockSizes[j]; } _files.Add(new ArchiveFileInfo(new SubStream(input, entry.Offset, compressedSize), filenames[i])); } } return(_files); }
/// <summary> /// /// </summary> /// <param name="fileData"></param> /// <param name="filePath"></param> public PsarcFileInfo(PsarcBlockStream fileData, string filePath) : base(fileData, filePath) { }