コード例 #1
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            // Set correct position for data section
            long offset = this.tableOffset;

            int[] tableItemStart = new int[this.numFiles];
            for (int i = 0; i < this.numFiles; i++)
            {
                tableItemStart[i] = StreamUtility.ReadIntFromStream(this.container, offset, false);
                offset           += 4;
            }

            long listOffset = offset;

            this.fileTable = new List <FileItem>();
            for (int i = 0; i < this.numFiles; i++)
            {
                offset = listOffset + tableItemStart[i];
                FileItem item = new FileItem(this.container);
                item.FileOffset = StreamUtility.ReadUIntFromStream(this.container, offset, false) + this.dataOffset;
                item.FileSize   = StreamUtility.ReadUIntFromStream(this.container, offset + 4, false);
                item.FileName   = StreamUtility.ReadStringFromStream(this.container, offset + 8, -1, 0x00);
                item.FileName   = item.FileName.Replace('\\', '+');
                this.fileTable.Add(item);
            }

            return(fileTable.Count);
        }
コード例 #2
0
        /// <summary>
        /// Construct a UNI2 file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public Uni2Container(FileStream file) : base(file)
        {
            long offset = 0;

            // Confirm 'UNI2' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (identifier != 0x554e4932) // If file identifier is not UNI2
            {
                throw new FormatException(container.Name + ": File is not UNI2 format!");
            }

            // Get the next value
            uint unknown = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;

            // Get number of files
            this.numFiles = StreamUtility.ReadUIntFromStream(this.container, offset);
            offset       += 4;

            // Get file table position
            this.tableCluster = StreamUtility.ReadUIntFromStream(this.container, offset);
            offset           += 4;

            this.containerType = "Union 2";
        }
コード例 #3
0
        /// <summary>
        /// Construct a AXCS file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public AxcsContainer(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Confirm 'AXCS' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (identifier != 0x53435841) // If file identifier is not AXCS
            {
                throw new FormatException(container.Name + ": File is not AXCS format!");
            }

            // Get the next value
            this.dataOffset = StreamUtility.ReadIntFromStream(this.container, offset, false);
            offset         += 4;

            // Get number of files
            this.numFiles = StreamUtility.ReadUIntFromStream(this.container, offset, false);
            offset       += 4;

            // Get file table position
            this.tableOffset = offset;

            this.containerType = "AXCS archive container";
        }
コード例 #4
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            // Set correct position for data section
            this.dataCluster = this.tableCluster +
                               ((this.numFiles * 16) / this.clusterSize);
            if ((this.numFiles * 16) % this.clusterSize != 0)
            {
                this.dataCluster++;
            }

            long offset = this.clusterSize * this.tableCluster;

            this.fileTable = new List <FileItem>();

            string fileNameBase;

            { // Get file name base
                int fileNameStart = this.container.Name.LastIndexOf('\\') + 1;
                int fileNameEnd   = this.container.Name.LastIndexOf('.');
                if (fileNameEnd == -1)
                {
                    fileNameEnd = this.container.Name.Length;
                }
                fileNameBase = this.container.Name.Substring(fileNameStart, fileNameEnd - fileNameStart);
            }

            while (true)
            {
                Uni2FileItem item = new Uni2FileItem();
                item.fileId        = StreamUtility.ReadUIntFromStream(this.container, offset);
                item.startCluster  = StreamUtility.ReadUIntFromStream(this.container, offset + 4);
                item.lengthCluster = StreamUtility.ReadUIntFromStream(this.container, offset + 8);
                item.lengthByte    = StreamUtility.ReadUIntFromStream(this.container, offset + 12);
                offset            += 16;

                if (item.isValid())
                {
                    FileItem FileItem       = ConvertUni2ToGeneral(item, fileNameBase + "-" + Convert.ToSingle(item.fileId));
                    uint     fileIdentifier = StreamUtility.ReadUIntFromStream(this.container, FileItem.FileOffset);
                    string   fileExt        = StreamUtility.GetFileExtension(fileIdentifier);
                    FileItem.FileName += "." + fileExt;
                    fileTable.Add(FileItem);
                }
                else
                {
                    break;
                }
            }

            if (fileTable.Count != this.numFiles)
            {
                throw new FormatException(this.container.Name + ": The real number of files doesn't match the header value!" + System.Environment.NewLine +
                                          "The header indicated: " + Convert.ToString(this.numFiles) + System.Environment.NewLine +
                                          "The real number of files: " + Convert.ToString(fileTable.Count));
            }

            return(fileTable.Count);
        }
コード例 #5
0
        /// <summary>
        /// Construct a MAAB file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public PakContainer(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Get number of files
            this.numFiles = StreamUtility.ReadUIntFromStream(this.container, offset);
            offset       += 4;

            this.tableOffset   = offset;
            this.containerType = "Pak Container";
        }
コード例 #6
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            this.fileTable = new List <FileItem>();

            // Extract TOC
            {
                uint identifier = StreamUtility.ReadUIntFromStream(this.container, this.tableOffset);
                if (identifier != 0x544f4320) // TOC
                {
                    throw new FormatException(container.Name + ": Checking TOC identified failed!");
                }

                // Get UTF length
                int tocLength = StreamUtility.ReadIntFromStream(this.container, this.tableOffset + 0x8, false);

                byte[] tocBytes = StreamUtility.ReadBytesFromStream(this.container, this.tableOffset + 0x10, tocLength);
                this.toc = CriPack_UTF.ByteUnpack(tocBytes);
            }

            // Extract E-TOC (Extended TOC)
            try
            {
                long etocOffset = (long)(ulong)this.header.GetPropertyValue(0, "EtocOffset");
                uint identifier = StreamUtility.ReadUIntFromStream(this.container, etocOffset);
                if (identifier != 0x45544f43) // ETOC
                {
                    throw new FormatException(container.Name + ": Checking E-TOC identified failed!");
                }

                // Get UTF length
                int etocLength = StreamUtility.ReadIntFromStream(this.container, etocOffset + 0x8, false);

                byte[] etocBytes = StreamUtility.ReadBytesFromStream(this.container, etocOffset + 0x10, etocLength);
                this.etoc = CriPack_UTF.ByteUnpack(etocBytes);
            }
            catch (KeyNotFoundException e) { } // No E-TOC

            for (int i = 0; i < toc.properties.Length; i++)
            {
                CriPackFileItem item = new CriPackFileItem(this.container);
                item.AssignTocProperties(toc.properties[i], this.tableOffset);
                if (this.etoc != null)
                {
                    item.AssignEtocProperties(etoc.properties[i]);
                }
                fileTable.Add(item);
            }

            return(fileTable.Count);
        }
コード例 #7
0
        /// <summary>
        /// Construct a CriPack file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public CriPack_Container(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Confirm 'CriPack' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (identifier != 0x43504b20) // If file identifier is not CriPack
            {
                throw new FormatException(container.Name + ": File is not CriPack format!");
            }

            // Get UTF length
            offset += 4;
            int headerLength = StreamUtility.ReadIntFromStream(this.container, offset, false);

            offset += 4;

            // Zero padding, ignore
            offset += 4;


            this.containerType = "CRI Pack Container";

            //byte[] utfHeader = StreamUtility.ReadBytesFromStream(this.container, offset, (int)this.utfLength);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0xedb88320, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0x04C11DB7, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //utfHeader = StreamUtility.ReadBytesFromStream(this.container, offset + 8, (int)this.utfLength - 8);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0xedb88320, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0x04C11DB7, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //utfHeader = StreamUtility.ReadBytesFromStream(this.container, offset - 8, (int)this.utfLength + 8);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0xedb88320, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0x04C11DB7, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //utfHeader = StreamUtility.ReadBytesFromStream(this.container, offset - 16, (int)this.utfLength + 16);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0xedb88320, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0x04C11DB7, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //utfHeader = StreamUtility.ReadBytesFromStream(this.container, offset + 4, (int)this.utfLength - 4);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0xedb88320, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);
            //MessageBox.Show("CRC32 of UTF: " + String.Format("0x{0:X4}", Crc32.Compute(0x04C11DB7, 0xffffffff, utfHeader)), "Info", MessageBoxButtons.OK);



            byte[] headerBytes = StreamUtility.ReadBytesFromStream(this.container, offset, headerLength);
            this.header      = CriPack_UTF.ByteUnpack(headerBytes);
            this.tableOffset = (long)(ulong)this.header.GetPropertyValue(0, "TocOffset");
        }
コード例 #8
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            long offset = 8;
            uint fid    = 0;

            this.fileTable = new List <FileItem>();

            string fileNameBase;

            { // Get file name base
                int fileNameStart = this.container.Name.LastIndexOf('\\') + 1;
                int fileNameEnd   = this.container.Name.LastIndexOf('.');
                if (fileNameEnd == -1)
                {
                    fileNameEnd = this.container.Name.Length;
                }
                fileNameBase = this.container.Name.Substring(fileNameStart, fileNameEnd - fileNameStart);
            }

            while (true)
            {
                Lnk4FileItem item = new Lnk4FileItem();
                item.fileId      = fid;
                item.startOffset = StreamUtility.ReadUIntFromStream(this.container, offset, false) << 11;
                offset          += 4;
                item.length      = StreamUtility.ReadUIntFromStream(this.container, offset, false) << 10;
                offset          += 4;

                if (item.isValid())
                {
                    FileItem FileItem       = ConvertLnk4ToGeneral(item, fileNameBase + "-" + Convert.ToSingle(item.fileId));
                    uint     fileIdentifier = StreamUtility.ReadUIntFromStream(this.container, FileItem.FileOffset);
                    string   fileExt        = StreamUtility.GetFileExtension(fileIdentifier);
                    FileItem.FileName += "." + fileExt;
                    fileTable.Add(FileItem);
                }
                else
                {
                    break;
                }

                fid++;
            }

            return(fileTable.Count);
        }
コード例 #9
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            long offset = this.tableOffset;

            uint[] fileOffset = new uint[numFiles + 1];

            this.fileTable = new List <FileItem>();

            // Read file offsets
            for (int i = 0; i < numFiles; i++)
            {
                fileOffset[i] = StreamUtility.ReadUIntFromStream(this.container, offset);
                offset       += 4;
            }
            fileOffset[numFiles] = (uint)this.container.Length;

            string fileNameBase;

            { // Get file name base
                int fileNameStart = this.container.Name.LastIndexOf('\\') + 1;
                int fileNameEnd   = this.container.Name.LastIndexOf('.');
                if (fileNameEnd == -1)
                {
                    fileNameEnd = this.container.Name.Length;
                }
                fileNameBase = this.container.Name.Substring(fileNameStart, fileNameEnd - fileNameStart);
            }

            for (int i = 0; i < numFiles; i++)
            {
                FileItem item = new FileItem(this.container);
                item.FileName   = fileNameBase + "-" + Convert.ToSingle(i);
                item.FileSize   = fileOffset[i + 1] - fileOffset[i];
                item.FileOffset = fileOffset[i];

                uint   fileIdentifier = StreamUtility.ReadUIntFromStream(this.container, item.FileOffset);
                string fileExt        = StreamUtility.GetFileExtension(fileIdentifier);
                item.FileName += "." + fileExt;
                fileTable.Add(item);
            }

            return(fileTable.Count);
        }
コード例 #10
0
        /// <summary>
        /// Construct a Lnk4 file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public Lnk4Container(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Confirm 'Lnk4' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (identifier != 0x4c4e4b34) // If file identifier is not Lnk4
            {
                throw new FormatException(container.Name + ": File is not Lnk4 format!");
            }

            // Get file address
            this.dataOffset = StreamUtility.ReadUIntFromStream(this.container, offset, false);
            offset         += 4;

            this.containerType = "Link 4";
        }
コード例 #11
0
        /// <summary>
        /// Construct a Afs file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public AfsContainer(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Confirm 'Afs' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (!StreamUtility.GetFileExtension(identifier).Equals("afs")) // If file identifier is not Afs
            {
                throw new FormatException(container.Name + ": File is not Afs format!");
            }

            // Get file address
            this.numFiles = StreamUtility.ReadUIntFromStream(this.container, offset, false);
            offset       += 4;

            this.containerType = "Sega AFS";
        }
コード例 #12
0
        /// <summary>
        /// Construct a MAAB file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public MaabContainer(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Confirm 'MAAB' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (identifier != 0x4d414142) // If file identifier is not MAAB
            {
                throw new FormatException(container.Name + ": File is not MAAB format!");
            }

            // Get number of files
            this.numFiles = StreamUtility.ReadUIntFromStream(this.container, offset);
            offset       += 4;

            this.tableOffset   = offset;
            this.containerType = "MAAB Container";
        }
コード例 #13
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            long offset      = this.tableOffset;
            int  tableLength = this.numFiles * this.tableItemSize;
            long fileOffset  = this.tableOffset + tableLength;

            this.fileTable = new List <FileItem>();

            for (int i = 0; i < this.numFiles; i++)
            {
                FileItem item = new FileItem(this.container);
                item.FileSize   = StreamUtility.ReadUIntFromStream(this.container, offset);
                item.FileName   = StreamUtility.ReadStringFromStream(this.container, offset + 4, -1);
                item.FileOffset = fileOffset;
                offset         += this.tableItemSize;
                fileOffset     += item.FileSize;

                fileTable.Add(item);
            }

            return(fileTable.Count);
        }
コード例 #14
0
        /// <summary>
        /// Construct a Cwab file.
        /// </summary>
        /// <param name="file">File stream.</param>
        public CwabContainer(FileStream file)
            : base(file)
        {
            long offset = 0;

            // Confirm 'CWAB' identifier
            uint identifier = StreamUtility.ReadUIntFromStream(this.container, offset);

            offset += 4;
            if (identifier != 0x43574142) // If file identifier is not CWAB
            {
                throw new FormatException(container.Name + ": File is not CWAB format!");
            }

            // Get number of files
            this.numFiles = StreamUtility.ReadIntFromStream(this.container, offset);
            offset       += 4;

            // Set file table position
            this.tableOffset = offset;

            this.containerType = "CWAB Animation Package";
        }
コード例 #15
0
        public long DecompressToFile(FileStream toFile)
        {
            long offset = this.fileOffset;

            // Check identifier
            ulong identifier = StreamUtility.ReadULongFromStream(this.file, offset);

            if (identifier != 0 && identifier != 0x4352494c41594c41)
            {
                throw new FormatException("File is not compressed by CRILAYLA!");
            }

            int  decompSize         = StreamUtility.ReadIntFromStream(this.file, offset + 0x8);
            long decompHeaderOffset = StreamUtility.ReadUIntFromStream(this.file, offset + 0xC) + offset + 0x10;

            if (decompHeaderOffset + 0x100 != offset + this.fileSize)
            {
                throw new FormatException("Size mismatch!");
            }

            // Extract real header
            StreamUtility.CopyBlock(this.file, toFile, decompHeaderOffset, 0x100);

            //const long input_end = offset + input_size - 0x100 - 1;
            //long input_offset = input_end;
            //const long output_end = 0x100 + uncompressed_size - 1;
            //uint8_t bit_pool = 0;
            //int bits_left = 0;
            //long bytes_output = 0;

            //while ( bytes_output < uncompressed_size )
            //{
            //    if (GET_NEXT_BITS(1))
            //    {
            //        long backreference_offset =
            //            output_end-bytes_output+GET_NEXT_BITS(13)+3;
            //        long backreference_length = 3;

            //        // decode variable length coding for length
            //        enum { vle_levels = 4 };
            //        int vle_lens[vle_levels] = { 2, 3, 5, 8 };
            //        int vle_level;
            //        for (vle_level = 0; vle_level < vle_levels; vle_level++)
            //        {
            //            int this_level = GET_NEXT_BITS(vle_lens[vle_level]);
            //            backreference_length += this_level;
            //            if (this_level != ((1 << vle_lens[vle_level])-1)) break;
            //        }
            //        if (vle_level == vle_levels)
            //        {
            //            int this_level;
            //            do
            //            {
            //                this_level = GET_NEXT_BITS(8);
            //                backreference_length += this_level;
            //            } while (this_level == 255);
            //        }

            //        //printf("0x%08lx backreference to 0x%lx, length 0x%lx\n", output_end-bytes_output, backreference_offset, backreference_length);
            //        for (int i=0;i<backreference_length;i++)
            //        {
            //            output_buffer[output_end-bytes_output] = output_buffer[backreference_offset--];
            //            bytes_output++;
            //        }
            //    }
            //    else
            //    {
            //        // verbatim byte
            //        output_buffer[output_end-bytes_output] = GET_NEXT_BITS(8);
            //        //printf("0x%08lx verbatim byte\n", output_end-bytes_output);
            //        bytes_output++;
            //    }
            //}

            //put_bytes_seek(0, outfile, output_buffer, 0x100 + uncompressed_size);
            //free(output_buffer);

            return(0x100 + decompSize);
        }
コード例 #16
0
        public static CriPack_UTF ByteUnpack(byte[] stream)
        {
            if (stream == null || stream.Length < 4)
            {
                return(null);
            }

            if (stream[0] != 0x40 || // @
                stream[1] != 0x55 || // U
                stream[2] != 0x54 || // T
                stream[3] != 0x46)   // F
            {
                stream = CriPack_UTF.Decrypt(stream);
            }

            using (MemoryStream buffer = new MemoryStream(stream))
            {
                CriPack_UTF utf = new CriPack_UTF();

                long offset = 4;

                utf.payloadSize = StreamUtility.ReadUIntFromStream(buffer, offset);
                offset         += 4;

                utf.dataBankOffset = StreamUtility.ReadUIntFromStream(buffer, offset) + 8;
                offset            += 4;

                utf.stringBankOffset = StreamUtility.ReadUIntFromStream(buffer, offset) + 8;
                offset += 4;

                utf.endOfPayloadOffset = StreamUtility.ReadUIntFromStream(buffer, offset) + 8;
                offset += 4;

                // Optional check
                if (utf.endOfPayloadOffset != (utf.payloadSize + 8))
                {
                    MessageBox.Show("End of UTF Payload (" + String.Format("0x{0:X4}", utf.endOfPayloadOffset) + ") " +
                                    "does not match UTF Payload Size (" + String.Format("0x{0:X4}", utf.payloadSize + 8) + ")", "Warning", MessageBoxButtons.OK);
                }

                int nameOffset = StreamUtility.ReadIntFromStream(buffer, offset);
                offset += 4;

                uint temp = StreamUtility.ReadUIntFromStream(buffer, offset);
                offset += 4;
                int numProperties = (int)((temp >> 16) & 0xff);
                utf.itemDataLength = (int)(temp & 0xff);

                utf.numItem = StreamUtility.ReadIntFromStream(buffer, offset);
                offset     += 4;

                // Optional check
                if ((utf.itemDataLength * utf.numItem) != (utf.stringBankOffset - utf.dataBankOffset))
                {
                    MessageBox.Show(
                        String.Format("Calculated data bank size (0x{0:X4}) does not match specified size (0x{1:X4})",
                                      utf.stringBankOffset - utf.dataBankOffset, utf.itemDataLength * utf.numItem),
                        "Warning", MessageBoxButtons.OK);
                }

                { // Extract string bank
                    int address = (int)utf.stringBankOffset;
                    utf.stringBank = new Dictionary <int, string>();
                    while (address < utf.endOfPayloadOffset)
                    {
                        string value = StreamUtility.ReadStringFromStream(buffer, address, 0);
                        utf.stringBank.Add((address - (int)utf.stringBankOffset), value);
                        address += value.Length + 1;
                    }
                }

                // Get name of this UTF
                utf.name = utf.GetStringFromBank(nameOffset);

                // Extract items
                utf.properties = new CriPack_UTFProperty[utf.numItem][];
                for (int i = 0; i < utf.numItem; i++)
                {
                    // Extract properties
                    utf.properties[i] = new CriPack_UTFProperty[numProperties];
                    long itemOffset     = offset;
                    int  dataBankCursor = (int)utf.dataBankOffset + utf.itemDataLength * i;
                    for (int p = 0; p < numProperties; p++)
                    {
                        // Read flag
                        byte[] bytes = StreamUtility.ReadBytesFromStream(buffer, itemOffset, 1);
                        itemOffset += 1;
                        byte flag = bytes[0];

                        // Determine storage and type
                        CriPack_UTFProperty property = new CriPack_UTFProperty();
                        property.storage = (CriPack_DataStorage)(flag & (byte)CriPack_DataStorage.MASK);
                        property.type    = (CriPack_DataType)(flag & (byte)CriPack_DataType.MASK);

                        if (property.storage == CriPack_DataStorage.UNDEFINED)
                        {
                            throw new NotSupportedException(String.Format("Unrecognized storage location: 0x{0:X4}", (byte)property.storage));
                        }

                        // Extract name of the property
                        {
                            int address = StreamUtility.ReadIntFromStream(buffer, itemOffset);
                            itemOffset   += 4;
                            property.name = utf.GetStringFromBank(address);
                        }

                        // Extract value
                        if (property.storage == CriPack_DataStorage.NONE)
                        {
                            // No value associated
                        }
                        else if (property.storage == CriPack_DataStorage.STRING)
                        {
                            // String value
                            int address = StreamUtility.ReadIntFromStream(buffer, itemOffset);
                            itemOffset    += 4;
                            property.value = utf.GetStringFromBank(address);
                        }
                        else if (property.storage == CriPack_DataStorage.DATA)
                        {
                            int address;
                            // Data value specified by 'type'
                            switch (property.type)
                            {
                            case CriPack_DataType.UNSIGNED_BYTE:
                            case CriPack_DataType.SIGNED_BYTE:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 1);
                                dataBankCursor += 1;
                                property.value  = bytes[0];
                                break;

                            case CriPack_DataType.UNSIGNED_SHORT:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 2);
                                dataBankCursor += 2;
                                Array.Reverse(bytes);     // Change endian
                                property.value = BitConverter.ToUInt16(bytes, 0);
                                break;

                            case CriPack_DataType.SIGNED_SHORT:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 2);
                                dataBankCursor += 2;
                                Array.Reverse(bytes);     // Change endian
                                property.value = BitConverter.ToInt16(bytes, 0);
                                break;

                            case CriPack_DataType.UNSIGNED_INT:
                                property.value  = StreamUtility.ReadUIntFromStream(buffer, dataBankCursor);
                                dataBankCursor += 4;
                                break;

                            case CriPack_DataType.SIGNED_INT:
                                property.value  = StreamUtility.ReadIntFromStream(buffer, dataBankCursor);
                                dataBankCursor += 4;
                                break;

                            case CriPack_DataType.UNSIGNED_LONG:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 8);
                                dataBankCursor += 8;
                                Array.Reverse(bytes);     // Change endian
                                property.value = BitConverter.ToUInt64(bytes, 0);
                                break;

                            case CriPack_DataType.SIGNED_LONG:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 8);
                                dataBankCursor += 8;
                                Array.Reverse(bytes);     // Change endian
                                property.value = BitConverter.ToInt64(bytes, 0);
                                break;

                            case CriPack_DataType.FLOAT:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 4);
                                dataBankCursor += 4;
                                Array.Reverse(bytes);     // Change endian
                                property.value = BitConverter.ToSingle(bytes, 0);
                                break;

                            case CriPack_DataType.DOUBLE:
                                bytes           = StreamUtility.ReadBytesFromStream(buffer, dataBankCursor, 8);
                                dataBankCursor += 8;
                                Array.Reverse(bytes);     // Change endian
                                property.value = BitConverter.ToDouble(bytes, 0);
                                break;

                            case CriPack_DataType.STRING:
                                address         = StreamUtility.ReadIntFromStream(buffer, dataBankCursor);
                                dataBankCursor += 4;
                                property.value  = utf.GetStringFromBank(address);
                                break;

                            case CriPack_DataType.DATA:
                                address         = StreamUtility.ReadIntFromStream(buffer, dataBankCursor);
                                dataBankCursor += 4;
                                int size = StreamUtility.ReadIntFromStream(buffer, dataBankCursor);
                                dataBankCursor += 4;
                                // Assume this is another table
                                bytes          = StreamUtility.ReadBytesFromStream(buffer, address, size);
                                property.value = CriPack_UTF.ByteUnpack(bytes);
                                break;

                            default:
                                property.value = null;
                                break;
                            }
                        }

                        utf.properties[i][p] = property;
                    }
                }

                return(utf);
            }
        }
コード例 #17
0
        /// <summary>
        /// Parse the file table.
        /// </summary>
        /// <returns>Number of files found.</returns>
        public override int ParseFileTable()
        {
            long offset = 8;
            uint fid    = 0;

            this.fileTable = new List <FileItem>();

            string fileNameBase;

            { // Get file name base
                int fileNameStart = this.container.Name.LastIndexOf('\\') + 1;
                int fileNameEnd   = this.container.Name.LastIndexOf('.');
                if (fileNameEnd == -1)
                {
                    fileNameEnd = this.container.Name.Length;
                }
                fileNameBase = this.container.Name.Substring(fileNameStart, fileNameEnd - fileNameStart);
            }

            while (true)
            {
                AfsFileItem item = new AfsFileItem();
                item.fileId      = fid;
                item.startOffset = StreamUtility.ReadUIntFromStream(this.container, offset, false);
                offset          += 4;
                item.length      = StreamUtility.ReadUIntFromStream(this.container, offset, false);
                offset          += 4;

                if (item.isValid())
                {
                    FileItem fileItem       = ConvertAfsToGeneral(item, fileNameBase + "-" + Convert.ToSingle(item.fileId));
                    uint     fileIdentifier = StreamUtility.ReadUIntFromStream(this.container, fileItem.FileOffset);
                    string   fileExt        = StreamUtility.GetFileExtension(fileIdentifier);
                    fileItem.FileName += "." + fileExt;
                    fileTable.Add(fileItem);
                }
                else
                {
                    break;
                }

                fid++;
            }

            if (fileTable.Count == this.numFiles + 1)
            {
                // The last one is the file property table.
                FileItem fileItem = fileTable[fileTable.Count - 1];
                offset = fileItem.FileOffset;
                // Retrieve file names
                for (int i = 0; i < this.numFiles; i++)
                {
                    fileTable[i].FileName = StreamUtility.ReadStringFromStream(this.container, offset, -1);
                    offset += 0x30;
                }
                // Remove the file property table
                fileTable.RemoveAt(fileTable.Count - 1);
            }

            if (fileTable.Count != this.numFiles)
            {
                throw new FormatException(this.container.Name + ": The real number of files doesn't match the header value!" + System.Environment.NewLine +
                                          "The header indicated: " + Convert.ToString(this.numFiles) + System.Environment.NewLine +
                                          "The real number of files: " + Convert.ToString(fileTable.Count));
            }

            return(fileTable.Count);
        }