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); }
protected override void ReadHeader(FileStream inStream, long offset) { long currentOffset = offset; ushort chunkTypeId; ushort subChunkCount; // read header size this.HeaderSize = ParseFile.ReadUintLE(inStream, currentOffset + 4) + 8; currentOffset += 8; while (currentOffset < this.HeaderSize) { // read chunk type id chunkTypeId = ParseFile.ReadUshortBE(inStream, currentOffset); // read subchunk count subChunkCount = ParseFile.ReadUshortLE(inStream, currentOffset + 2); switch (chunkTypeId) { // get audio details case MobiclipWiiStream.AudioChunkSignature: this.AudioStreamCount = ParseFile.ReadUintLE(inStream, currentOffset + 4); this.AudioStreamFeatures = new MobiclipAudioStreamFeatures[this.AudioStreamCount]; for (uint i = 0; i < this.AudioStreamCount; i++) { this.AudioStreamFeatures[i] = new MobiclipAudioStreamFeatures(); this.AudioStreamFeatures[i].StreamType = ParseFile.ReadUshortBE(inStream, currentOffset + 8 + (i * 0xA)); this.AudioStreamFeatures[i].Frequency = ParseFile.ReadUintLE(inStream, currentOffset + 8 + (i * 0xA) + 2); this.AudioStreamFeatures[i].Channels = ParseFile.ReadUintLE(inStream, currentOffset + 8 + (i * 0xA) + 6); } break; case MobiclipWiiStream.AudioChunkSignaturePcm: case MobiclipWiiStream.AudioChunkSignatureA3: this.AudioStreamCount = 1; this.AudioStreamFeatures = new MobiclipAudioStreamFeatures[this.AudioStreamCount]; this.AudioStreamFeatures[0] = new MobiclipAudioStreamFeatures(); this.AudioStreamFeatures[0].StreamType = ParseFile.ReadUshortBE(inStream, currentOffset); this.AudioStreamFeatures[0].Frequency = ParseFile.ReadUintLE(inStream, currentOffset + 4); this.AudioStreamFeatures[0].Channels = ParseFile.ReadUintLE(inStream, currentOffset + 8); break; default: break; } currentOffset += (subChunkCount * 4) + 4; } }
protected void ConvertSubtitles(uint streamId, FileStream subtitleStream) { long subsLength = subtitleStream.Length; long currentOffset = 0; byte[] encodedPresentationTimeStamp; ulong decodedTimeStamp; ushort subtitlePacketSize; byte[] PNG_HEADER = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; byte[] PNG_END = new byte[] { 0x49, 0x45, 0x4E, 0x44 }; long pngStartOffset; long pngEndOffset; long pngSize; uint pngCount = 0; string baseDirectory = Path.GetDirectoryName(subtitleStream.Name); baseDirectory = Path.Combine(baseDirectory, String.Format("{0}_PNGs", Path.GetFileNameWithoutExtension(subtitleStream.Name))); string destinationFile; while (currentOffset < subsLength) { // decode time stamp encodedPresentationTimeStamp = ParseFile.ParseSimpleOffset(subtitleStream, currentOffset, 5); decodedTimeStamp = this.DecodePresentationTimeStamp(encodedPresentationTimeStamp); // get subtitle packet size subtitlePacketSize = ParseFile.ReadUshortBE(subtitleStream, currentOffset + 0xC); // extract PNG pngStartOffset = ParseFile.GetNextOffset(subtitleStream, currentOffset + 0x1E, PNG_HEADER); pngEndOffset = ParseFile.GetNextOffset(subtitleStream, pngStartOffset, PNG_END) + 4; pngSize = pngEndOffset - pngStartOffset; if (pngSize > (subtitlePacketSize - 0x14)) { throw new Exception("Warning, PNG size exceeds packet size."); } destinationFile = Path.Combine(baseDirectory, String.Format("{0}.png", pngCount.ToString("D8"))); ParseFile.ExtractChunkToFile(subtitleStream, pngStartOffset, pngSize, destinationFile); pngCount++; // write timestamp and PNG to file // move to next block currentOffset += 0xE + subtitlePacketSize; } }
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 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); }
private ushort getBlockSize(Stream inStream, long hcaOffset) { ushort blockSize = 0; long decChunkOffset; long compChunkOffset; //---------------- // 'dec ' offset //---------------- // get 'dec' chunk offset, if exists (v1.3, maybe others?) decChunkOffset = ParseFile.GetNextOffsetWithLimitMasked(inStream, hcaOffset, hcaOffset + MAX_HEADER_SIZE, DEC_CHUNK_BYTES, MASK_BYTES, true); if (decChunkOffset > -1) { blockSize = ParseFile.ReadUshortBE(inStream, decChunkOffset + 4); } else { //---------------- // 'comp' offset //---------------- // get 'comp' chunk offset, if exists (v1.3, maybe others?) compChunkOffset = ParseFile.GetNextOffsetWithLimitMasked(inStream, hcaOffset, hcaOffset + MAX_HEADER_SIZE, COMP_CHUNK_BYTES, MASK_BYTES, true); if (compChunkOffset > -1) { blockSize = ParseFile.ReadUshortBE(inStream, compChunkOffset + 4); } else { throw new FormatException( String.Format("Cannot find 'dec' or 'comp' chunk to determine block size for HCA starting at 0x{0}", hcaOffset.ToString("X8"))); } } return(blockSize); }
/// <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 void InitializeCueList(FileStream fs) { this.CueNamesToWaveforms = new Dictionary <string, ushort>(); ulong referenceItemsOffset = 0; ulong referenceItemsSize = 0; ulong referenceCorrection = 0; object dummy; byte isStreaming = 0; CriUtfTable cueTableUtf = new CriUtfTable(); cueTableUtf.Initialize(fs, (long)this.CueTableOffset); CriUtfTable waveformTableUtf = new CriUtfTable(); waveformTableUtf.Initialize(fs, (long)this.WaveformTableOffset); CriUtfTable synthTableUtf = new CriUtfTable(); synthTableUtf.Initialize(fs, (long)this.SynthTableOffset); this.CueList = new CriAcbCueRecord[cueTableUtf.NumberOfRows]; for (int i = 0; i < cueTableUtf.NumberOfRows; i++) { this.CueList[i] = new CriAcbCueRecord(); this.CueList[i].IsWaveformIdentified = false; this.CueList[i].CueId = (uint)CriUtfTable.GetUtfFieldForRow(cueTableUtf, i, "CueId"); this.CueList[i].ReferenceType = (byte)CriUtfTable.GetUtfFieldForRow(cueTableUtf, i, "ReferenceType"); this.CueList[i].ReferenceIndex = (ushort)CriUtfTable.GetUtfFieldForRow(cueTableUtf, i, "ReferenceIndex"); switch (this.CueList[i].ReferenceType) { case 2: referenceItemsOffset = (ulong)CriUtfTable.GetOffsetForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); referenceItemsSize = CriUtfTable.GetSizeForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); referenceCorrection = referenceItemsSize + 2; break; case 3: case 8: if (i == 0) { referenceItemsOffset = (ulong)CriUtfTable.GetOffsetForUtfFieldForRow(synthTableUtf, 0, "ReferenceItems"); referenceItemsSize = CriUtfTable.GetSizeForUtfFieldForRow(synthTableUtf, 0, "ReferenceItems"); referenceCorrection = referenceItemsSize - 2; // samples found have only had a '01 00' record => Always Waveform[0]?. } else { referenceCorrection += 4; // relative to previous offset, do not lookup // @TODO: Should this do a referenceItemsSize - 2 for the ReferenceIndex? Need to find // one where size > 4. //referenceItemsOffset = (ulong)CriUtfTable.GetOffsetForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); //referenceItemsSize = CriUtfTable.GetSizeForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); //referenceCorrection = referenceItemsSize - 2; } break; default: throw new FormatException(String.Format(" Unexpected ReferenceType: '{0}' for CueIndex: '{1}.' Please report to VGMToolbox thread at hcs64.com forums, see link in 'Other' menu item.", this.CueList[i].ReferenceType.ToString("D"), i.ToString("D"))); } if (referenceItemsSize != 0) { // get wave form info this.CueList[i].WaveformIndex = ParseFile.ReadUshortBE(fs, (long)(referenceItemsOffset + referenceCorrection)); // get Streaming flag, 0 = in ACB files, 1 = in AWB file dummy = CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "Streaming"); if (dummy != null) // check to see if this Id actually exists in the WaveformIndex { isStreaming = (byte)dummy; this.CueList[i].IsStreaming = isStreaming == 0 ? false : true; // get waveform id and encode type from corresponding waveform var waveformId = CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "Id"); if (waveformId != null) { // early revisions of ACB spec used "Id" this.CueList[i].WaveformId = (ushort)waveformId; } else { // later versions using "MemoryAwbId" and "StreamingAwbId" if (this.CueList[i].IsStreaming) { this.CueList[i].WaveformId = (ushort)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "StreamAwbId"); } else { this.CueList[i].WaveformId = (ushort)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "MemoryAwbId"); } } this.CueList[i].EncodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "EncodeType"); // update flag this.CueList[i].IsWaveformIdentified = true; } // if (dummy != null) } } }
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 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 }