Example #1
0
 public void ParseFrameHeader(Stream inStream, long currentOffset, ref FrameHeader fHeader)
 {
     fHeader.Clear();
     fHeader.FrameId1  = ParseFile.ReadUshortBE(inStream, currentOffset);
     fHeader.FrameId2  = ParseFile.ReadUshortBE(inStream, currentOffset + 2);
     fHeader.FrameSize = ParseFile.ReadUintBE(inStream, currentOffset + 4);
 }
        public void Initialize(FileStream isoStream, long offset, bool isRawDump)
        {
            byte[] volumeIdentifierBytes;

            this.SourceFileName    = isoStream.Name;
            this.FormatDescription = MicrosoftSTFS.FORMAT_DESCRIPTION_STRING;

            this.VolumeBaseOffset        = offset;
            this.IsRawDump               = isRawDump;
            this.VolumeType              = VolumeDataType.Data;
            this.FileTableEntryArray     = new ArrayList();
            this.DirectoryStructureArray = new ArrayList();

            // get identifier
            volumeIdentifierBytes = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 0x1691, 0x80);
            this.VolumeIdentifier = Encoding.BigEndianUnicode.GetString(volumeIdentifierBytes);
            this.VolumeIdentifier = this.VolumeIdentifier.Substring(0, this.VolumeIdentifier.IndexOf('\0'));

            // get header size
            this.HeaderSize = ParseFile.ReadUintBE(isoStream, this.VolumeBaseOffset + 0x340);

            // get file table info
            this.BlockSeparation     = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 0x37B);
            this.FileTableBlockCount = ParseFile.ReadInt16LE(isoStream, this.VolumeBaseOffset + 0x37C);

            // not sure about endianess, always zero in my samples so far
            this.FileTableBlockNumber = ParseFile.ReadInt24LE(isoStream, this.VolumeBaseOffset + 0x37E);

            // parse file table
            this.ParseFileTable(isoStream);

            // build directory tree
            this.BuildDirectoryTree();
        }
Example #3
0
        /// <summary>
        /// Parse directory/file nodes.
        /// </summary>
        /// <param name="fs">Filestream of U8 file.</param>
        public void ParseNodes(FileStream fs)
        {
            u8Node node = new u8Node();
            uint   maxNodeId;

            // read first node
            node.NodeType   = ParseFile.ReadByte(fs, this.RootNodeOffset);
            node.NameOffset = ParseFile.ReadUint24BE(fs, this.RootNodeOffset + 1);
            node.DataOffset = ParseFile.ReadUintBE(fs, this.RootNodeOffset + 4);
            node.DataSize   = ParseFile.ReadUintBE(fs, this.RootNodeOffset + 8);
            this.NodeArray.Add(node);

            maxNodeId = node.DataSize;

            // parse each node
            for (int i = 1; i < maxNodeId; i++)
            {
                node            = new u8Node();
                node.NodeType   = ParseFile.ReadByte(fs, this.RootNodeOffset + (i * 0xC));
                node.NameOffset = ParseFile.ReadUint24BE(fs, this.RootNodeOffset + (i * 0xC) + 1);
                node.DataOffset = ParseFile.ReadUintBE(fs, this.RootNodeOffset + (i * 0xC) + 4);
                node.DataSize   = ParseFile.ReadUintBE(fs, this.RootNodeOffset + (i * 0xC) + 8);
                this.NodeArray.Add(node);
            }
        }
Example #4
0
        private void ParseIvfcHeader(FileStream fs, long offset)
        {
            this.MagicBytes = ParseFile.ReadUintBE(fs, offset);

            // verify magic bytes
            if (this.MagicBytes != 0x49564643)
            {
                throw new FormatException(String.Format("IVFC bytes not found."));
            }

            this.VersionNumber  = ParseFile.ReadUintLE(fs, offset + 0x04);
            this.MasterHashSize = ParseFile.ReadUintLE(fs, offset + 0x08);

            this.Level1Offset       = ParseFile.ReadUlongLE(fs, offset + 0x0C);
            this.Level1HashDataSize = ParseFile.ReadUlongLE(fs, offset + 0x14);
            this.Level1BlockSize    = ParseFile.ReadUintLE(fs, offset + 0x1C);
            this.Reserved01         = ParseFile.ReadUintLE(fs, offset + 0x20);

            this.Level2Offset       = ParseFile.ReadUlongLE(fs, offset + 0x24);
            this.Level2HashDataSize = ParseFile.ReadUlongLE(fs, offset + 0x2C);
            this.Level2BlockSize    = ParseFile.ReadUintLE(fs, offset + 0x34);
            this.Reserved02         = ParseFile.ReadUintLE(fs, offset + 0x38);

            this.Level3Offset       = ParseFile.ReadUlongLE(fs, offset + 0x3C);
            this.Level3HashDataSize = ParseFile.ReadUlongLE(fs, offset + 0x44);
            this.Level3BlockSize    = ParseFile.ReadUintLE(fs, offset + 0x4C);
            this.Reserved03         = ParseFile.ReadUintLE(fs, offset + 0x50);

            this.Reserved04       = ParseFile.ReadUintLE(fs, offset + 0x54);
            this.OptionalInfoSize = ParseFile.ReadUintLE(fs, offset + 0x58);
        }
Example #5
0
 public void ParseBlockHeader(Stream inStream, long currentOffset, ref BlockHeader bHeader)
 {
     bHeader.Clear();
     bHeader.BlockSize       = ParseFile.ReadUintBE(inStream, currentOffset);
     bHeader.AudioFrameCount = ParseFile.ReadUintBE(inStream, currentOffset + 4);
     bHeader.VideoFrameCount = ParseFile.ReadUintBE(inStream, currentOffset + 8);
     bHeader.Unknown         = ParseFile.ReadUintBE(inStream, currentOffset + 0xC);
 }
Example #6
0
        public NintendoWad(string sourceFile)
        {
            // check magic bytes
            if (NintendoWad.IsWadFile(sourceFile))
            {
                // read header
                using (FileStream fs = File.OpenRead(sourceFile))
                {
                    // set source file
                    this.SourceFileName = sourceFile;

                    // parse header
                    this.HeaderSize           = ParseFile.ReadUintBE(fs, 0);
                    this.WadType              = ParseFile.ReadUintBE(fs, 4);
                    this.CertificateChainSize = ParseFile.ReadUintBE(fs, 8);
                    this.Reserved             = ParseFile.ReadUintBE(fs, 0xC);
                    this.TicketSize           = ParseFile.ReadUintBE(fs, 0x10);
                    this.TitleMetaDataSize    = ParseFile.ReadUintBE(fs, 0x14);
                    this.DataSize             = ParseFile.ReadUintBE(fs, 0x18);
                    this.FooterSize           = ParseFile.ReadUintBE(fs, 0x1C);

                    // offsets
                    this.CertificateChainOffset = (uint)this.PadValue(this.HeaderSize, "Certificate Chain Offset");
                    this.TicketOffset           = (uint)this.PadValue(this.CertificateChainOffset + this.CertificateChainSize, "Ticket Offset");
                    this.TitleMetaDataOffset    = (uint)this.PadValue(this.TicketOffset + this.TicketSize, "Title Meta Data Offset");
                    this.DataOffset             = (uint)this.PadValue(this.TitleMetaDataOffset + this.TitleMetaDataSize, "Data Offset");
                    this.FooterOffset           = (uint)this.PadValue(this.DataOffset + this.DataSize, "Footer Offset");

                    // get important values
                    this.TicketId          = ParseFile.ReadUlongBE(fs, this.TicketOffset + 0x1D0);
                    this.TitleId           = ParseFile.ReadUlongBE(fs, this.TicketOffset + 0x1DC);
                    this.TitleIdBytes      = ParseFile.ParseSimpleOffset(fs, this.TicketOffset + 0x1DC, 8);
                    this.EncryptedTitleKey = ParseFile.ParseSimpleOffset(fs, this.TicketOffset + 0x1BF, 0x10);
                    this.CommonKeyIndex    = ParseFile.ReadByte(fs, this.TicketOffset + 0x1F1);

                    // decrypt title key
                    this.DecryptTitleKey();

                    // get TMD content entries
                    this.NumberOfContents = ParseFile.ReadUshortBE(fs, this.TitleMetaDataOffset + 0x1DE);
                    this.ParseTmdContentEntries(fs);
                } // using (FileStream fs = File.OpenRead(sourceFile))
            }
            else
            {
                throw new FormatException("Nintendo WAD magic bytes not found at offset 0x03.");
            }
        }
Example #7
0
        private void ParseNcsdHeader(FileStream fs, long offset)
        {
            // parse NCSD header
            this.NcsdHash                 = ParseFile.ParseSimpleOffset(fs, offset, 0x100);
            this.MagicBytes               = ParseFile.ReadUintBE(fs, offset + 0x100);
            this.ImageSize                = ParseFile.ReadUintLE(fs, offset + 0x104);
            this.MediaId                  = ParseFile.ReadUlongLE(fs, offset + 0x108);
            this.PartitionsFsType         = ParseFile.ReadUlongLE(fs, offset + 0x110);
            this.PartitionsEncryptionType = ParseFile.ReadUlongLE(fs, offset + 0x118);

            this.NcchOffsetInfo = new SimpleOffset[8];
            for (int i = 0; i < 8; i++)
            {
                this.NcchOffsetInfo[i] = new SimpleOffset(
                    ParseFile.ReadUintLE(fs, offset + 0x120 + (8 * i)),
                    ParseFile.ReadUintLE(fs, offset + 0x120 + ((8 * i) + 4)));
            }

            // parse Exheader
            this.ExHeaderHash         = ParseFile.ParseSimpleOffset(fs, offset + 0x160, 0x20);
            this.AdditionalHeaderSize = ParseFile.ReadUintLE(fs, offset + 0x180);
            this.SectorZeroOffset     = ParseFile.ReadUintLE(fs, offset + 0x184);
            this.PartitionFlags       = ParseFile.ReadUlongLE(fs, offset + 0x188);

            this.PartitionIds = new ulong[8];
            for (int i = 0; i < 8; i++)
            {
                this.PartitionIds[i] = ParseFile.ReadUlongLE(fs, offset + 0x190 + (8 * i));
            }


            this.Reserved01 = ParseFile.ParseSimpleOffset(fs, offset + 0x1D0, 0x20);
            this.Reserved02 = ParseFile.ParseSimpleOffset(fs, offset + 0x1F0, 0xE);
            this.Unknown01  = ParseFile.ReadByte(fs, 0x1FE);
            this.Unknown02  = ParseFile.ReadByte(fs, 0x1FF);

            // parse Card Info
            this.CardInfoWritableAddress = ParseFile.ReadInt32LE(fs, offset + 0x200);
            this.CardInfoBitmask         = ParseFile.ReadUintLE(fs, offset + 0x204);
            this.CardInfoReserved01      = ParseFile.ParseSimpleOffset(fs, offset + 0x208, 0xDF8);
            this.CardInfoMediaId         = ParseFile.ReadUlongLE(fs, offset + 0x1000);
            this.CardInfoReserved02      = ParseFile.ReadUlongLE(fs, offset + 0x1008);
            this.CardInfoInitialData     = ParseFile.ParseSimpleOffset(fs, offset + 0x1010, 0x30);
            this.CardInfoReserved03      = ParseFile.ParseSimpleOffset(fs, offset + 0x1040, 0xC0);
            this.CardInfoNcchHeaderCopy  = ParseFile.ParseSimpleOffset(fs, offset + 0x1011, 0x100);
        }
Example #8
0
        private void initializeUtfHeader(FileStream UtfTableFs)
        {
            this.TableSize = ParseFile.ReadUintBE(UtfTableFs, 4);

            this.Unknown1 = ParseFile.ReadUshortBE(UtfTableFs, 8);

            this.RowOffset         = (uint)ParseFile.ReadUshortBE(UtfTableFs, 0xA) + 8;
            this.StringTableOffset = ParseFile.ReadUintBE(UtfTableFs, 0xC) + 8;
            this.DataOffset        = ParseFile.ReadUintBE(UtfTableFs, 0x10) + 8;

            this.TableNameOffset = ParseFile.ReadUintBE(UtfTableFs, 0x14);
            this.TableName       = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + this.TableNameOffset);

            this.NumberOfFields = ParseFile.ReadUshortBE(UtfTableFs, 0x18);

            this.RowSize      = ParseFile.ReadUshortBE(UtfTableFs, 0x1A);
            this.NumberOfRows = ParseFile.ReadUintBE(UtfTableFs, 0x1C);
        }
        public void ParseFileTable(FileStream isoStream)
        {
            FileTableEntry tableEntry = new FileTableEntry();
            long           fileTableMinOffset;
            long           fileTableMaxOffset;

            long fileSize = isoStream.Length;

            // get offset for blocks
            fileTableMinOffset = ComputeBlockNumberAndGetOffset(this.FileTableBlockNumber, this.HeaderSize, this.BlockSeparation);
            fileTableMaxOffset = ComputeBlockNumberAndGetOffset(this.FileTableBlockNumber + this.FileTableBlockCount, this.HeaderSize, this.BlockSeparation);

            // check offsets
            if ((fileTableMinOffset >= MicrosoftSTFS.FIRST_BLOCK_OFFSET) &&
                (fileTableMinOffset < fileTableMaxOffset) &&
                (fileTableMaxOffset < fileSize))
            {
                for (long i = fileTableMinOffset; i < fileTableMaxOffset; i += 0x40)
                {
                    tableEntry.FileName = ParseFile.ReadAsciiString(isoStream, i);

                    if (!String.IsNullOrEmpty(tableEntry.FileName))
                    {
                        tableEntry.Flags                  = ParseFile.ReadByte(isoStream, i + 0x28);
                        tableEntry.BlocksForFileLE1       = ParseFile.ReadInt24LE(isoStream, i + 0x29);
                        tableEntry.BlocksForFileLE2       = ParseFile.ReadInt24LE(isoStream, i + 0x2C);
                        tableEntry.StartingBlockForFileLE = ParseFile.ReadInt24LE(isoStream, i + 0x2F);
                        tableEntry.PathIndicator          = ParseFile.ReadInt16BE(isoStream, i + 0x32);
                        tableEntry.FileSize               = ParseFile.ReadUintBE(isoStream, i + 0x34);
                        tableEntry.UpdateDateTime         = ParseFile.ReadInt32BE(isoStream, i + 0x38);
                        tableEntry.AccessDateTime         = ParseFile.ReadInt32BE(isoStream, i + 0x3C);

                        FileTableEntryArray.Add(tableEntry);
                    }
                }
            }
            else
            {
                throw new IndexOutOfRangeException("File Table block IDs do not make sense.");
            }
        }
Example #10
0
        private void ParseNcchHeader(FileStream fs, long offset)
        {
            this.NcsdHash    = ParseFile.ParseSimpleOffset(fs, offset, 0x100);
            this.MagicBytes  = ParseFile.ReadUintBE(fs, offset + 0x100);
            this.ContentSize = ParseFile.ReadUintLE(fs, offset + 0x104);
            this.PartitionId = ParseFile.ReadUlongLE(fs, offset + 0x108);

            this.MakerCode      = ParseFile.ReadUshortLE(fs, offset + 0x110);
            this.Version        = ParseFile.ReadUshortLE(fs, offset + 0x112);
            this.Reserved01     = ParseFile.ReadUintLE(fs, offset + 0x114);
            this.ProgramId      = ParseFile.ReadUlongLE(fs, offset + 0x118);
            this.Reserved02     = ParseFile.ParseSimpleOffset(fs, offset + 0x120, 0x10);
            this.LogoRegionHash = ParseFile.ParseSimpleOffset(fs, offset + 0x130, 0x20);
            this.ProductCode    = ParseFile.ReadAsciiString(fs, offset + 0x150);

            this.ExtendedHeaderHash = ParseFile.ParseSimpleOffset(fs, offset + 0x160, 0x10);
            this.ExtendedHeaderSize = ParseFile.ReadUintLE(fs, offset + 0x180);

            this.Reserved03 = ParseFile.ReadUintLE(fs, offset + 0x184);
            this.Flags      = ParseFile.ReadUlongLE(fs, offset + 0x188);

            this.PlainRegionOffset = ParseFile.ReadUintLE(fs, offset + 0x190);
            this.PlainRegionSize   = ParseFile.ReadUintLE(fs, offset + 0x194);

            this.LogoRegionOffset = ParseFile.ReadUintLE(fs, offset + 0x198);
            this.LogoRegionSize   = ParseFile.ReadUintLE(fs, offset + 0x19C);

            this.ExeFsOffset   = ParseFile.ReadUintLE(fs, offset + 0x1A0);
            this.ExeFsSize     = ParseFile.ReadUintLE(fs, offset + 0x1A4);
            this.ExeFsHashSize = ParseFile.ReadUintLE(fs, offset + 0x1A8);
            this.Reserved04    = ParseFile.ReadUintLE(fs, offset + 0x1AC);

            this.RomFsOffset   = ParseFile.ReadUintLE(fs, offset + 0x1B0);
            this.RomFsSize     = ParseFile.ReadUintLE(fs, offset + 0x1B4);
            this.RomFsHashSize = ParseFile.ReadUintLE(fs, offset + 0x1B8);
            this.Reserved05    = ParseFile.ReadUintLE(fs, offset + 0x1BC);

            this.ExeSuperblockHash   = ParseFile.ParseSimpleOffset(fs, offset + 0x1C0, 0x20);
            this.RomFsSuperblockHash = ParseFile.ParseSimpleOffset(fs, offset + 0x1E0, 0x20);
        }
Example #11
0
        public void Initialize(FileStream fs, long offset, bool isRawDump)
        {
            this.FormatDescription = NintendoU8Archive.FORMAT_DESCRIPTION_STRING;

            this.VolumeBaseOffset        = offset;
            this.IsRawDump               = isRawDump;
            this.VolumeType              = VolumeDataType.Data;
            this.DirectoryStructureArray = new ArrayList();

            // parse header
            this.RootNodeOffset = ParseFile.ReadUintBE(fs, 4);
            this.HeaderOffset   = ParseFile.ReadUintBE(fs, 8);
            this.DataOffset     = ParseFile.ReadUintBE(fs, 0xC);

            // parse nodes
            this.NodeArray = new ArrayList();
            this.ParseNodes(fs);
            this.NameTableOffset = this.RootNodeOffset + ((uint)this.NodeList.Length * 0xC);

            // build directory structure
            this.BuildDirectoryTree(fs);
        }
Example #12
0
        /// <summary>
        /// Parse the Content Entries in the Title Meta Data section.
        /// </summary>
        /// <param name="fs">File Stream of WAD.</param>
        private void ParseTmdContentEntries(FileStream fs)
        {
            ulong            nextOffset = this.DataOffset;
            TmdContentStruct contentEntry;
            ArrayList        contentEntryList = new ArrayList();

            for (ushort i = 0; i < this.NumberOfContents; i++)
            {
                contentEntry               = new TmdContentStruct();
                contentEntry.ContentId     = ParseFile.ReadUintBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 0);
                contentEntry.ContentIndex  = ParseFile.ReadUshortBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 4);
                contentEntry.ContentType   = ParseFile.ReadUshortBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 6);
                contentEntry.ContentSize   = ParseFile.ReadUlongBE(fs, this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 8);
                contentEntry.Sha1Hash      = ParseFile.ParseSimpleOffset(fs, (this.TitleMetaDataOffset + 0x1E4 + (i * 0x24) + 0x10), 20);
                contentEntry.ContentOffset = nextOffset;
                contentEntryList.Add(contentEntry);

                nextOffset = this.PadValue((contentEntry.ContentOffset + contentEntry.ContentSize),
                                           String.Format("Next Offset for ContentId: 0x{0}", contentEntry.ContentId.ToString("X8")));
            }

            this.TmdContentEntries = (TmdContentStruct[])contentEntryList.ToArray(typeof(TmdContentStruct));
        }
Example #13
0
        protected override void DoTaskForFile(string pPath, IVgmtWorkerStruct pExtractAdxStruct, DoWorkEventArgs e)
        {
            ExtractHcaStruct extractAdxStruct = (ExtractHcaStruct)pExtractAdxStruct;

            long offset = 0;

            byte   revisionMajor;
            byte   revisionMinor;
            ushort dataOffset;

            long fmtChunkOffset;

            uint   blockCount;
            ushort blockSize;

            long fileSize;

            int    fileCount  = 0;
            string outputPath = Path.Combine(Path.GetDirectoryName(pPath), "_cri_hca_ext");
            string outputFileName;
            string outputFilePath;

            FileInfo fi = new FileInfo(pPath);

            using (FileStream fs = File.Open(pPath, FileMode.Open, FileAccess.Read))
            {
                outputPath = Path.Combine(Path.GetDirectoryName(pPath), String.Format("{0}_HCAs", Path.GetFileNameWithoutExtension(pPath)));

                while ((offset = ParseFile.GetNextOffsetMasked(fs, offset, HCA_SIG_BYTES, MASK_BYTES)) > -1)
                {
                    if (!this.CancellationPending)
                    {
                        // get version
                        revisionMajor = ParseFile.ReadByte(fs, offset + 4);
                        revisionMinor = ParseFile.ReadByte(fs, offset + 5);

                        // get data offset
                        dataOffset = ParseFile.ReadUshortBE(fs, offset + 6);

                        // get 'fmt' chunk offset
                        fmtChunkOffset = ParseFile.GetNextOffsetMasked(fs, offset, FMT_CHUNK_BYTES, MASK_BYTES);

                        if (fmtChunkOffset > -1)
                        {
                            // get block count
                            blockCount = ParseFile.ReadUintBE(fs, fmtChunkOffset + 8);


                            // get block size
                            blockSize = this.getBlockSize(fs, offset);


                            // calculate file size
                            fileSize = dataOffset + (blockCount * blockSize);

                            // extract file
                            outputFileName = String.Format("{0}_{1}.hca", Path.GetFileNameWithoutExtension(pPath), fileCount.ToString("X8"));
                            outputFilePath = Path.Combine(outputPath, outputFileName);

                            this.progressStruct.Clear();
                            this.progressStruct.GenericMessage = String.Format("{0} - offset: 0x{1} size: 0x{2}{3}", outputFileName, offset.ToString("X8"), fileSize.ToString("X8"), Environment.NewLine);
                            ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                            ParseFile.ExtractChunkToFile(fs, offset, fileSize, outputFilePath, true, true);

                            // increment counter
                            fileCount++;

                            // move pointer
                            offset += fileSize;
                        }
                        else
                        {
                            throw new FormatException(String.Format("'fmt' chunk not found for HCA starting at 0x{0}", offset.ToString("X8")));
                        }
                    }
                    else
                    {
                        e.Cancel = true;
                        return;
                    }
                }
            }
        }
Example #14
0
        private void initializeUtfSchema(FileStream SourceFs, FileStream UtfTableFs, long schemaOffset)
        {
            long nameOffset;

            long constantOffset;

            long dataOffset;
            long dataSize;

            long rowDataOffset;
            long rowDataSize;

            long currentOffset = schemaOffset;
            long currentRowBase;
            long currentRowOffset = 0;

            CriField field;

            for (uint i = 0; i < this.NumberOfRows; i++)
            {
                //if (i == 0x1a2a)
                //{
                //    int yuuuu = 1;
                //}
                //try
                //{
                currentOffset    = schemaOffset;
                currentRowBase   = this.RowOffset + (this.RowSize * i);
                currentRowOffset = 0;
                this.Rows[i]     = new Dictionary <string, CriField>();

                // parse fields
                for (ushort j = 0; j < this.NumberOfFields; j++)
                {
                    field = new CriField();

                    field.Type = ParseFile.ReadByte(UtfTableFs, currentOffset);
                    nameOffset = ParseFile.ReadUintBE(UtfTableFs, currentOffset + 1);
                    field.Name = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + nameOffset);

                    // each row will have a constant
                    if (((field.Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT) ||
                        ((field.Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT2))
                    {
                        // capture offset of constant
                        constantOffset = currentOffset + 5;

                        // read the constant depending on the type
                        switch (field.Type & COLUMN_TYPE_MASK)
                        {
                        case COLUMN_TYPE_STRING:
                            dataOffset     = ParseFile.ReadUintBE(UtfTableFs, constantOffset);
                            field.Value    = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + dataOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_8BYTE:
                            field.Value    = ParseFile.ReadUlongBE(UtfTableFs, constantOffset);
                            currentOffset += 8;
                            break;

                        case COLUMN_TYPE_DATA:
                            dataOffset   = ParseFile.ReadUintBE(UtfTableFs, constantOffset);
                            dataSize     = ParseFile.ReadUintBE(UtfTableFs, constantOffset + 4);
                            field.Offset = (ulong)(this.BaseOffset + this.DataOffset + dataOffset);
                            field.Size   = (ulong)dataSize;

                            // don't think this is encrypted, need to check
                            field.Value    = ParseFile.ParseSimpleOffset(SourceFs, (long)field.Offset, (int)dataSize);
                            currentOffset += 8;
                            break;

                        case COLUMN_TYPE_FLOAT:
                            field.Value    = ParseFile.ReadFloatBE(UtfTableFs, constantOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE2:
                            field.Value    = ParseFile.ReadInt32BE(UtfTableFs, constantOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE:
                            field.Value    = ParseFile.ReadUintBE(UtfTableFs, constantOffset);
                            currentOffset += 4;
                            break;

                        case COLUMN_TYPE_2BYTE2:
                            field.Value    = ParseFile.ReadInt16BE(UtfTableFs, constantOffset);
                            currentOffset += 2;
                            break;

                        case COLUMN_TYPE_2BYTE:
                            field.Value    = ParseFile.ReadUshortBE(UtfTableFs, constantOffset);
                            currentOffset += 2;
                            break;

                        case COLUMN_TYPE_1BYTE2:
                            field.Value    = ParseFile.ReadSByte(UtfTableFs, constantOffset);
                            currentOffset += 1;
                            break;

                        case COLUMN_TYPE_1BYTE:
                            field.Value    = ParseFile.ReadByte(UtfTableFs, constantOffset);
                            currentOffset += 1;
                            break;

                        default:
                            throw new FormatException(String.Format("Unknown COLUMN TYPE at offset: 0x{0}", currentOffset.ToString("X8")));
                        }     // switch (field.Type & COLUMN_TYPE_MASK)
                    }
                    else if ((field.Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_PERROW)
                    {
                        // read the constant depending on the type
                        switch (field.Type & COLUMN_TYPE_MASK)
                        {
                        case COLUMN_TYPE_STRING:
                            rowDataOffset     = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset);
                            field.Value       = ParseFile.ReadAsciiString(UtfTableFs, this.StringTableOffset + rowDataOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_8BYTE:
                            field.Value       = ParseFile.ReadUlongBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 8;
                            break;

                        case COLUMN_TYPE_DATA:
                            rowDataOffset = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset);
                            rowDataSize   = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset + 4);
                            field.Offset  = (ulong)(this.BaseOffset + this.DataOffset + rowDataOffset);
                            field.Size    = (ulong)rowDataSize;

                            // don't think this is encrypted
                            field.Value       = ParseFile.ParseSimpleOffset(SourceFs, (long)field.Offset, (int)rowDataSize);
                            currentRowOffset += 8;
                            break;

                        case COLUMN_TYPE_FLOAT:
                            field.Value       = ParseFile.ReadFloatBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE2:
                            field.Value       = ParseFile.ReadInt32BE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_4BYTE:
                            field.Value       = ParseFile.ReadUintBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 4;
                            break;

                        case COLUMN_TYPE_2BYTE2:
                            field.Value       = ParseFile.ReadInt16BE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 2;
                            break;

                        case COLUMN_TYPE_2BYTE:
                            field.Value       = ParseFile.ReadUshortBE(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 2;
                            break;

                        case COLUMN_TYPE_1BYTE2:
                            field.Value       = ParseFile.ReadSByte(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 1;
                            break;

                        case COLUMN_TYPE_1BYTE:
                            field.Value       = ParseFile.ReadByte(UtfTableFs, currentRowBase + currentRowOffset);
                            currentRowOffset += 1;
                            break;

                        default:
                            throw new FormatException(String.Format("Unknown COLUMN TYPE at offset: 0x{0}", currentOffset.ToString("X8")));
                        } // switch (field.Type & COLUMN_TYPE_MASK)
                    }     // if ((fields[i].Type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT)

                    // add field to dictionary
                    this.Rows[i].Add(field.Name, field);

                    // move to next field
                    currentOffset += 5; //  sizeof(CriField.Type + CriField.NameOffset)
                }                       // for (ushort j = 0; j < this.NumberOfFields; j++)
                //}
                //catch (Exception ex)
                //{
                //    int xxxx = 1;
                //}
            } // for (uint i = 0; i < this.NumberOfRows; i++)
        }
Example #15
0
        public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = -1;
            long fileSize;

            byte[] dummy;

            uint blocksProcessed        = 0;
            uint audioFramesProcessed   = 0;
            uint videoFramesProcessed   = 0;
            uint bytesProcessed         = 0;
            uint expectedBytesProcessed = 0;

            BlockHeader blockHeader = new BlockHeader();
            FrameHeader frameHeader = new FrameHeader();

            bool isFirstVideoFrame = true;
            bool isFirstAudioFrame = true;

            byte[] fullChunk;

            uint audioChunkSize;
            uint audioChunkSamples;

            long blockStart;
            long frameStart;

            Dictionary <string, FileStream> streamWriters = new Dictionary <string, FileStream>();

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    fileSize = fs.Length;

                    #region HEADER CHECK
                    // check header
                    dummy = ParseFile.ParseSimpleOffset(fs, 0, 0x10);

                    if (ParseFile.CompareSegment(dummy, 0, HVQM4_13_SIGNATURE))
                    {
                        this.FileRevision = VersionType.HVQM4_13;
                        currentOffset     = 0;
                    }
                    else if (ParseFile.CompareSegment(dummy, 0, HVQM4_15_SIGNATURE))
                    {
                        this.FileRevision = VersionType.HVQM4_15;
                        currentOffset     = 0;
                    }
                    else
                    {
                        throw new Exception("HVQM4 signature not found at offset 0x00");
                    }
                    #endregion

                    // parse file
                    if (currentOffset >= 0)
                    {
                        // get header
                        this.ParseHeader(fs, 0);
                        currentOffset = this.HeaderSize + 4;

                        // process file
                        while ((currentOffset < fileSize) &&
                               (blocksProcessed < this.Blocks))
                        {
                            // reset flags
                            isFirstVideoFrame = true;
                            isFirstAudioFrame = true;

                            audioFramesProcessed = 0;
                            videoFramesProcessed = 0;

                            //--------------
                            // parse block
                            //--------------
                            blockStart = currentOffset;
                            blocksProcessed++;

                            // parse block header
                            this.ParseBlockHeader(fs, currentOffset, ref blockHeader);
                            currentOffset += blockHeader.GetSize();
                            bytesProcessed = 0;

                            while (bytesProcessed < blockHeader.BlockSize)
                            {
                                frameStart = currentOffset;

                                // verify we haven't processed too much
                                if (audioFramesProcessed > blockHeader.AudioFrameCount)
                                {
                                    throw new Exception(String.Format("Processed more audio frames than expected for block starting at 0x{0}", blockStart.ToString("X8")));
                                }
                                else if (videoFramesProcessed > blockHeader.VideoFrameCount)
                                {
                                    throw new Exception(String.Format("Processed more video frames than expected for block starting at 0x{0}", blockStart.ToString("X8")));
                                }

                                // parse frame header
                                this.ParseFrameHeader(fs, currentOffset, ref frameHeader);
                                currentOffset  += frameHeader.GetSize();
                                bytesProcessed += (uint)frameHeader.GetSize();

                                //---------------
                                // process frame
                                //---------------
                                // audio chunk
                                if (demuxOptions.ExtractAudio && frameHeader.IsAudioFrame(isFirstAudioFrame))
                                {
                                    audioChunkSamples = ParseFile.ReadUintBE(fs, currentOffset);
                                    audioChunkSize    = (audioChunkSamples * this.AudioChannels) / 2;

                                    // get full frame for now
                                    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)frameHeader.FrameSize);

                                    // different frames have different IMA info
                                    //if (isFirstAudioFrame)
                                    //{
                                    //    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset + 6, (int)audioChunkSize);
                                    //}
                                    //else
                                    //{
                                    //    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset + 4, (int)audioChunkSize);
                                    //}

                                    this.writeChunkToStream(fullChunk, "audio", streamWriters, this.FileExtensionAudio);

                                    isFirstAudioFrame = false;
                                    audioFramesProcessed++;
                                }

                                // video chunk
                                else if (demuxOptions.ExtractVideo && frameHeader.IsVideoFrame(isFirstVideoFrame, this.FileRevision))
                                {
                                    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)frameHeader.FrameSize);
                                    this.writeChunkToStream(fullChunk, "video", streamWriters, this.FileExtensionVideo);

                                    isFirstVideoFrame = false;
                                    videoFramesProcessed++;
                                }

                                //unknown
                                else
                                {
                                    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)frameHeader.FrameSize);
                                    this.writeChunkToStream(fullChunk, "unknown", streamWriters, ".bin");
                                }

                                // update number of bytes processed
                                bytesProcessed += frameHeader.FrameSize;

                                // move to next frame
                                currentOffset += frameHeader.FrameSize;
                            } // while (bytesProcessed < blockHeader.BlockSize)

                            // verify proper number of bytes processed
                            if (blocksProcessed < this.Blocks)
                            {
                                bytesProcessed         = bytesProcessed + (uint)(blockHeader.GetSize() + 4);
                                expectedBytesProcessed = ParseFile.ReadUintBE(fs, currentOffset);

                                if (expectedBytesProcessed != bytesProcessed)
                                {
                                    throw new Exception(String.Format(
                                                            "Bytes processed 0x{0}does not match expected bytes processed {1} for block starting at 0x{2}.",
                                                            bytesProcessed.ToString("X8"),
                                                            expectedBytesProcessed.ToString("X8"),
                                                            blockStart.ToString("X8")));
                                }
                                else
                                {
                                    currentOffset += 4;
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new Exception(String.Format("Cannot find MVHD header.{0}", Environment.NewLine));
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                this.DoFinalTasks(streamWriters);
            }
        }
Example #16
0
        public void ParseHeader(Stream inStream, long currentOffset)
        {
            this.HeaderSize      = ParseFile.ReadUintBE(inStream, currentOffset + 0x10);   // 0x10-0x13
            this.BodySize        = ParseFile.ReadUintBE(inStream, currentOffset + 0x14);   // 0x14-0x17
            this.Blocks          = ParseFile.ReadUintBE(inStream, currentOffset + 0x18);   // 0x18-0x1B
            this.AudioFrames     = ParseFile.ReadUintBE(inStream, currentOffset + 0x1C);   // 0x1C-0x1F
            this.VideoFrames     = ParseFile.ReadUintBE(inStream, currentOffset + 0x20);   // 0x20-0x23
            this.Unk24           = ParseFile.ReadUintBE(inStream, currentOffset + 0x24);   // 0x24-0x27 (0x8257,0x8256)
            this.Duration        = ParseFile.ReadUintBE(inStream, currentOffset + 0x28);   // 0x28-0x2B
            this.Unk2C           = ParseFile.ReadUintBE(inStream, currentOffset + 0x2C);   // 0x2C-0x2F (0)
            this.AudioFrameSize  = ParseFile.ReadUintBE(inStream, currentOffset + 0x30);   // 0x30-0x33
            this.Hres            = ParseFile.ReadUshortBE(inStream, currentOffset + 0x34); // 0x34-0x35
            this.Vres            = ParseFile.ReadUshortBE(inStream, currentOffset + 0x36); // 0x36-0x37
            this.Unk38           = ParseFile.ReadUshortBE(inStream, currentOffset + 0x38); // 0x38-0x3B (0x0202)
            this.Unk3A           = ParseFile.ReadByte(inStream, currentOffset + 0x3A);     // 0x3A (0 or 0x12)
            this.Unk3B           = ParseFile.ReadByte(inStream, currentOffset + 0x3B);     // 0x3B (0)
            this.AudioChannels   = ParseFile.ReadByte(inStream, currentOffset + 0x3C);     // 0x3C
            this.AudioBitdepth   = ParseFile.ReadByte(inStream, currentOffset + 0x3D);     // 0x3D
            this.Pad             = ParseFile.ReadUshortBE(inStream, currentOffset + 0x3E); // 0x3E-0x3F (0)
            this.AudioSampleRate = ParseFile.ReadUintBE(inStream, currentOffset + 0x40);   // 0x40-0x43

            // save off original header
            this.FullHeader = ParseFile.ParseSimpleOffset(inStream, currentOffset, (int)this.HeaderSize);

            #region AUDIO/VIDEO features checks
            // set video present flags
            if (this.VideoFrames == 0)
            {
                if (this.Hres == 0)
                {
                    throw new Exception("Video frame count greater than 0, but horizontal resolution equals zero.");
                }
                else if (this.Vres == 0)
                {
                    throw new Exception("Video frame count greater than 0, but vertical resolution equals zero.");
                }
                else
                {
                    this.IsVideoPresent = true;
                }
            }

            // set audio present flags
            if (this.AudioFrames > 0)
            {
                if (this.AudioFrameSize == 0)
                {
                    throw new Exception("Audio frame count greater than 0, but audio frame size equals zero.");
                }
                else if (this.AudioChannels == 0)
                {
                    throw new Exception("Audio frame count greater than 0, but audio channel count equals zero.");
                }
                else if (this.AudioBitdepth == 0)
                {
                    throw new Exception("Audio frame count greater than 0, but audio bit depth equals zero.");
                }
                else if (this.AudioSampleRate == 0)
                {
                    throw new Exception("Audio frame count greater than 0, but audio sample rate equals zero.");
                }
                else
                {
                    this.IsAudioPresent = true;
                }
            }
            #endregion
        }