Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="fileData"></param>
 /// <param name="filePath"></param>
 public PsarcFileInfo(PsarcBlockStream fileData, string filePath) : base(fileData, filePath)
 {
 }