예제 #1
0
파일: Cpk.cs 프로젝트: obluda3/Kuriimu2
        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>());
        }
예제 #2
0
        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));
                }
            }
        }
예제 #3
0
파일: Cpk.cs 프로젝트: obluda3/Kuriimu2
        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);
            }
        }
예제 #4
0
 private void ReadGtocTable(BinaryReaderX br, long gtocOffset)
 {
     _gtocTable = CpkTable.Create(br.BaseStream, gtocOffset);
 }
예제 #5
0
 private void ReadEtocTable(BinaryReaderX br, long etocOffset)
 {
     _etocTable = CpkTable.Create(br.BaseStream, etocOffset);
 }