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(); }
/// <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); } }
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); }
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); }
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."); } }
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); }
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."); } }
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); }
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); }
/// <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)); }
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; } } } }
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++) }
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); } }
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 }