Exemple #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);
        }
Exemple #2
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";
        }
        /// <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);
        }
        /// <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");
        }
        /// <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";
        }
        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);
            }
        }
Exemple #7
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);
        }