Пример #1
0
        public static void ExtractRawSectors(Stream cdStream,
                                             string destinationPath, long volumeBaseOffset,
                                             long lba, long sectorCount)
        {
            long offset;
            long lbaCounter = 0;

            byte[] sector;

            // create directory
            string destinationFolder = Path.GetDirectoryName(destinationPath);

            if (!Directory.Exists(destinationFolder))
            {
                Directory.CreateDirectory(destinationFolder);
            }

            using (FileStream outStream = File.OpenWrite(destinationPath))
            {
                while (lbaCounter < sectorCount)
                {
                    offset = volumeBaseOffset + ((lba + lbaCounter) * CdRom.RAW_SECTOR_SIZE);
                    sector = ParseFile.ParseSimpleOffset(cdStream, offset, (int)CdRom.RAW_SECTOR_SIZE);
                    outStream.Write(sector, 0, sector.Length);
                    lbaCounter++;
                }
            }
        }
Пример #2
0
        private uint GetLengthTypeValue(Stream inStream, long offsetToValue, LengthType valueSize, ref uint bytesRead)
        {
            uint lengthTypeValue = 0;

            switch (valueSize)
            {
            case LengthType.Byte:
                lengthTypeValue = (uint)(ParseFile.ParseSimpleOffset(inStream, offsetToValue, 1)[0]);
                bytesRead       = 1;
                break;

            case LengthType.Word:
                lengthTypeValue = (uint)BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(inStream, offsetToValue, 2), 0);
                bytesRead       = 2;
                break;

            case LengthType.Dword:
                lengthTypeValue = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(inStream, offsetToValue, 4), 0);
                bytesRead       = 4;
                break;
            }
            ;

            return(lengthTypeValue);
        }
Пример #3
0
        protected override string GetAudioFileExtension(Stream readStream, long currentOffset)
        {
            string fileExtension;

            byte[] checkBytes, checkBytesAc3;

            int headerSize = this.GetAudioPacketHeaderSize(readStream, currentOffset);

            checkBytes = ParseFile.ParseSimpleOffset(readStream, (currentOffset + 6 + headerSize), 4);

            if (ParseFile.CompareSegment(checkBytes, 0, AixSignatureBytes))
            {
                fileExtension = AixAudioExtension;
            }
            else if (checkBytes[0] == 0x80)
            {
                fileExtension = AdxAudioExtension;
            }
            else
            {
                checkBytesAc3 = ParseFile.ParseSimpleOffset(readStream, (currentOffset + 6 + headerSize), 2);

                if (ParseFile.CompareSegment(checkBytesAc3, 0, Ac3SignatureBytes))
                {
                    fileExtension = Ac3AudioExtension;
                }
                else
                {
                    fileExtension = ".bin";
                }
            }

            return(fileExtension);
        }
Пример #4
0
        private void ValidateIvfcContainer(FileStream fs, long offset) // thanks to neimod's ctrtool
        {
            StringBuilder hashFailures = new StringBuilder();

            ulong blockCount;

            byte[]        blockToHash;
            byte[]        calculatedHash;
            byte[]        testHash;
            HashAlgorithm cryptoHash = SHA256.Create();

            uint badHashCount = 0, goodHashCount = 0;

            // only check level 1 and 2 hash on load, level 3 takes too long and can be performed on extraction
            for (ulong i = 0; i < 3; i++)
            {
                // verify hash block to data size
                blockCount = this.IvfcLevels[i].DataSize / this.IvfcLevels[i].HashBlockSize;

                if ((blockCount * this.IvfcLevels[i].HashBlockSize) != this.IvfcLevels[i].DataSize)
                {
                    throw new Exception("Error, IVFC block mismatch.");
                }

                // calculate hash and compare
                for (ulong j = 0; j < blockCount; j++)
                {
                    testHash = ParseFile.ParseSimpleOffset(fs, offset + (long)this.IvfcLevels[i].HashOffset + (long)(0x20 * j), 0x20);

                    blockToHash    = ParseFile.ParseSimpleOffset(fs, offset + (long)this.IvfcLevels[i].DataOffset + ((long)this.IvfcLevels[i].HashBlockSize * (long)j), (int)this.IvfcLevels[i].HashBlockSize);
                    calculatedHash = cryptoHash.ComputeHash(blockToHash);

                    if (!ParseFile.CompareSegment(calculatedHash, 0, testHash))
                    {
                        badHashCount++;
                    }
                    else
                    {
                        goodHashCount++;
                    }
                }

                if (badHashCount > 0)
                {
                    hashFailures.AppendFormat("IVFC hash failure(s) in Level {0}.  Good Blocks: {1}  Bad Blocks: {2}{3}", i + 1, goodHashCount.ToString(), badHashCount.ToString(), Environment.NewLine);
                }
                else
                {
                    hashFailures.AppendFormat("No IVFC hash failures found in Level {0} check.{1}", i + 1, Environment.NewLine);
                }
            } // for (ulong i = 0;...

            // display warning about hash failures
            if (hashFailures.Length > 0)
            {
                //hashFailures.Insert(0, String.Format("Hash Failures when Validating .3DS file.  This file is corrupted.{0}{0}", Environment.NewLine));
                //MessageBox.Show(hashFailures.ToString(), "Warning: Hash Failures in .3DS file.");
                MessageBox.Show(hashFailures.ToString(), "Hash Validation Results");
            }
        }
Пример #5
0
        public void Initialize(Stream pStream, string pFilePath)
        {
            this.FilePath       = pFilePath;
            this.AsciiSignature = ParseFile.ParseSimpleOffset(pStream, SIG_OFFSET, SIG_LENGTH);
            this.VersionNumber  = ParseFile.ParseSimpleOffset(pStream, VERSION_OFFSET, VERSION_LENGTH);
            this.PalNtscFlag    = ParseFile.ParseSimpleOffset(pStream, PAL_NTSC_OFFSET, PAL_NTSC_LENGTH);
            this.Scanlines      = ParseFile.ParseSimpleOffset(pStream, SCANLINES_OFFSET, SCANLINES_LENGTH);
            this.Reserved1      = ParseFile.ParseSimpleOffset(pStream, RESERVED1_OFFSET, RESERVED1_LENGTH);
            this.StartAddress   = ParseFile.ParseSimpleOffset(pStream, START_ADDRESS_OFFSET, START_ADDRESS_LENGTH);
            this.InitAddress    = ParseFile.ParseSimpleOffset(pStream, INIT_ADDRESS_OFFSET, INIT_ADDRESS_LENGTH);
            this.PlayAddress    = ParseFile.ParseSimpleOffset(pStream, PLAY_ADDRESS_OFFSET, PLAY_ADDRESS_LENGTH);
            this.StackPointer   = ParseFile.ParseSimpleOffset(pStream, STACK_POINTER_OFFSET, STACK_POINTER_LENGTH);
            this.Reserved2      = ParseFile.ParseSimpleOffset(pStream, RESERVED2_OFFSET, RESERVED2_LENGTH);
            this.RstPointers    = ParseFile.ParseSimpleOffset(pStream, RST_POINTERS_OFFSET, RST_POINTERS_LENGTH);
            this.MapperChip     = ParseFile.ParseSimpleOffset(pStream, MAPPER_CHIP_OFFSET, MAPPER_CHIP_LENGTH);
            this.StartingSong   = ParseFile.ParseSimpleOffset(pStream, STARTING_SONG_OFFSET, STARTING_SONG_LENGTH);
            this.TotalSongs     = ParseFile.ParseSimpleOffset(pStream, TOTAL_SONGS_OFFSET, TOTAL_SONGS_LENGTH);
            this.StartingSfx    = ParseFile.ParseSimpleOffset(pStream, STARTING_SFX_OFFSET, STARTING_SFX_LENGTH);
            this.EndingSfx      = ParseFile.ParseSimpleOffset(pStream, ENDING_SFX_OFFSET, ENDING_SFX_LENGTH);
            this.SystemType     = ParseFile.ParseSimpleOffset(pStream, SYSTEM_TYPE_OFFSET, SYSTEM_TYPE_LENGTH);
            this.Reserved3      = ParseFile.ParseSimpleOffset(pStream, RESERVED3_OFFSET, RESERVED3_LENGTH);
            this.SongName       = ParseFile.ParseSimpleOffset(pStream, NAME_OFFSET, NAME_LENGTH);
            this.SongArtist     = ParseFile.ParseSimpleOffset(pStream, ARTIST_OFFSET, ARTIST_LENGTH);
            this.SongCopyright  = ParseFile.ParseSimpleOffset(pStream, COPYRIGHT_OFFSET, COPYRIGHT_LENGTH);
            this.Data           = ParseFile.ParseSimpleOffset(pStream, DATA_OFFSET, (int)(pStream.Length - DATA_OFFSET) + 1);

            this.initializeTagHash();
        }
        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();
        }
Пример #7
0
        public Ps2SqTimingStruct getTimeInSecondsForSequenceNumber(Stream pStream, int pSequenceNumber)
        {
            Ps2SqTimingStruct ret = new Ps2SqTimingStruct();

            if (pSequenceNumber <= this.midiChunk.maxSeqCount &&
                this.midiChunk.subSeqOffsetAddr[pSequenceNumber] != EMPTY_MIDI_OFFSET)
            {
                uint  tempo           = this.getTempoForSequenceNumber(pStream, pSequenceNumber);
                long  eofOffset       = this.getEndOfTrackForSequenceNumber(pStream, pSequenceNumber);
                Int32 midiBlockOffset = MIDI_CHUNK_OFFSET + this.midiChunk.subSeqOffsetAddr[pSequenceNumber];

                MidiDataChunkStruct dataChunkHeader = new MidiDataChunkStruct();
                dataChunkHeader.sequenceOffsetRelativeToChunk = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(pStream, (long)midiBlockOffset, 4), 0);
                dataChunkHeader.resolution = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(pStream, (long)(midiBlockOffset + 4), 2), 0);

                if (dataChunkHeader.sequenceOffsetRelativeToChunk == 6) // uncompressed
                {
                    ret = getTimeInSecondsForChunk(pStream, (long)(midiBlockOffset + dataChunkHeader.sequenceOffsetRelativeToChunk),
                                                   eofOffset, tempo, dataChunkHeader.resolution);
                }
                else
                {
                    throw new Exception("Compressed Sequences Not Supported.");
                }
            }

            return(ret);
        }
Пример #8
0
        private Psf2DirectoryEntry[] getDirectoryEntries(UInt32 pOffset)
        {
            UInt32 numberOfDirectoryEntries;

            Psf2DirectoryEntry[] ret;
            System.Text.Encoding enc = System.Text.Encoding.ASCII;

            using (FileStream fs = File.Open(this.FilePath, FileMode.Open, FileAccess.Read))
            {
                numberOfDirectoryEntries =
                    BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, pOffset, 4), 0);
                ret = new Psf2DirectoryEntry[numberOfDirectoryEntries];

                for (UInt32 i = 0; i < numberOfDirectoryEntries; i++)
                {
                    ret[i].Filename =
                        enc.GetString(FileUtil.ReplaceNullByteWithSpace(ParseFile.ParseSimpleOffset(fs, (pOffset + 4) + (48 * i), 36))).Trim();
                    ret[i].Offset =
                        Xsf.RESERVED_SECTION_OFFSET +
                        BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, (pOffset + 4) + (48 * i) + 36, 4), 0);
                    ret[i].UncompressedSize =
                        BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, (pOffset + 4) + (48 * i) + 40, 4), 0);
                    ret[i].BlockSize =
                        BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, (pOffset + 4) + (48 * i) + 44, 4), 0);
                }
            }
            return(ret);
        }
Пример #9
0
        private static byte[] getGzippedSignatureBytes(Stream pFileStream)
        {
            byte[] ret = null;

            long currentPosition = pFileStream.Position;

            GZipInputStream gZipInputStream = new GZipInputStream(pFileStream);
            string          tempGzipFile    = Path.GetTempFileName();
            FileStream      gZipFileStream  = new FileStream(tempGzipFile, FileMode.Open, FileAccess.ReadWrite);

            int size = 4096;

            byte[] writeData = new byte[size];
            while (true)
            {
                size = gZipInputStream.Read(writeData, 0, size);
                if (size > 0)
                {
                    gZipFileStream.Write(writeData, 0, size);
                }
                else
                {
                    break;
                }
            }

            ret = ParseFile.ParseSimpleOffset(gZipFileStream, HEADER_OFFSET, MAX_SIGNATURE_LENGTH);
            gZipFileStream.Close();
            gZipFileStream.Dispose();

            File.Delete(tempGzipFile);               // delete temp file
            pFileStream.Position = currentPosition;  // return file to position on entry

            return(ret);
        }
Пример #10
0
        ////////////
        // METHODS
        ////////////

        private SdatInfoRec getInfoRec(Stream pStream, int pSectionOffset,
                                       int pInfoRecOffset)
        {
            SdatInfoRec sdatInfoRec = new SdatInfoRec();;

            if (pInfoRecOffset > 0)
            {
                int entryOffsetCount;

                sdatInfoRec.nCount = ParseFile.ParseSimpleOffset(pStream,
                                                                 pSectionOffset + pInfoRecOffset + INFO_RECORD_STRUCT_COUNT_OFFSET,
                                                                 INFO_RECORD_STRUCT_COUNT_LENGTH);

                entryOffsetCount          = BitConverter.ToInt32(sdatInfoRec.nCount, 0);
                sdatInfoRec.nEntryOffsets = new byte[entryOffsetCount][];

                for (int i = 1; i <= entryOffsetCount; i++)
                {
                    sdatInfoRec.nEntryOffsets[i - 1] = ParseFile.ParseSimpleOffset(pStream,
                                                                                   pSectionOffset + pInfoRecOffset + (INFO_RECORD_STRUCT_OFFSETS_OFFSET * i),
                                                                                   INFO_RECORD_STRUCT_OFFSETS_LENGTH);
                }
            }

            return(sdatInfoRec);
        }
Пример #11
0
        private SqHeaderStruct parseSqHeader(Stream pStream)
        {
            SqHeaderStruct ret;

            byte[] temp; // used to reverse from big endian to little endian

            // magic bytes
            ret            = new SqHeaderStruct();
            ret.MagicBytes = ParseFile.ParseSimpleOffset(pStream, 0, 4); // pQES

            // version
            temp = ParseFile.ParseSimpleOffset(pStream, 4, 4);
            Array.Reverse(temp);
            ret.Version = BitConverter.ToUInt32(temp, 0);

            // resolution
            temp = ParseFile.ParseSimpleOffset(pStream, 8, 2);
            Array.Reverse(temp);
            ret.Resolution = BitConverter.ToUInt16(temp, 0);

            // tempo
            temp = new byte[4];
            Array.Copy(ParseFile.ParseSimpleOffset(pStream, 10, 3), 0, temp, 1, 3);
            Array.Reverse(temp);
            ret.InitialTempo = BitConverter.ToUInt32(temp, 0);

            // unknown
            temp = ParseFile.ParseSimpleOffset(pStream, 13, 2);
            Array.Reverse(temp);
            ret.unknown = BitConverter.ToUInt16(temp, 0);

            return(ret);
        }
Пример #12
0
        public void initialize(byte[] pBytes)
        {
            // int _titleLength;
            // int _pdxLength;

            // Title
            this.titleLength = ParseFile.GetSegmentLength(pBytes, 0, TITLE_TERMINATOR);

            if (this.titleLength > 0)
            {
                title = VGMToolbox.util.ByteConversion.GetJapaneseEncodedText(ParseFile.ParseSimpleOffset(pBytes, 0,
                                                                                                          this.titleLength));
            }

            // PDX
            this.pdxOffset = this.titleLength + TITLE_TERMINATOR.Length;
            this.pdxLength = ParseFile.GetSegmentLength(pBytes,
                                                        (this.titleLength + TITLE_TERMINATOR.Length), PDX_TERMINATOR);
            if (this.pdxLength > 0)
            {
                pdxFileName = VGMToolbox.util.ByteConversion.GetJapaneseEncodedText(ParseFile.ParseSimpleOffset(pBytes,
                                                                                                                (this.titleLength + TITLE_TERMINATOR.Length), this.pdxLength));
            }

            this.dataOffset = this.titleLength + TITLE_TERMINATOR.Length +
                              this.pdxLength + PDX_TERMINATOR.Length;
            this.dataLength = (int)(pBytes.Length - this.dataOffset);
        }
Пример #13
0
        public void Initialize(FileStream isoStream, long offset, bool isRawDump)
        {
            byte[] volumeIdentifierBytes;

            this.DiscBaseOffset = offset;
            this.DiscReader     = new NintendoWiiEncryptedDiscReader();

            this.WiiDiscId  = ByteConversion.GetAsciiText(ParseFile.ParseSimpleOffset(isoStream, this.DiscBaseOffset, 1));
            this.GameCode   = ByteConversion.GetAsciiText(ParseFile.ParseSimpleOffset(isoStream, this.DiscBaseOffset + 1, 2));
            this.RegionCode = ByteConversion.GetAsciiText(ParseFile.ParseSimpleOffset(isoStream, this.DiscBaseOffset + 3, 1));
            this.MakerCode  = ParseFile.ParseSimpleOffset(isoStream, this.DiscBaseOffset + 4, 2);

            this.IsRawDump = isRawDump;

            // get identifier
            volumeIdentifierBytes = ParseFile.ParseSimpleOffset(isoStream, this.DiscBaseOffset + 0x20, 64);
            volumeIdentifierBytes = FileUtil.ReplaceNullByteWithSpace(volumeIdentifierBytes);

            // initialize partition info
            this.InitializePartitions(isoStream);

            // initialize volumes
            this.VolumeArrayList = new ArrayList();
            this.LoadVolumes(isoStream);
        }
Пример #14
0
        public Iso9660PathTableRecord(byte[] pathBytes, bool isLittleEndian)
        {
            this.LengthOfDirectoryIdentifier   = ParseFile.ParseSimpleOffset(pathBytes, 0, 1)[0];
            this.ExtendedAttributeRecordLength = ParseFile.ParseSimpleOffset(pathBytes, 1, 1)[0];

            if (isLittleEndian)
            {
                this.LocationOfExtent = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(pathBytes, 2, 4), 0);
            }
            else
            {
                this.LocationOfExtent = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(pathBytes, 2, 4));
            }
            if (isLittleEndian)
            {
                this.DirectoryNumberOfParentDirectory = BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(pathBytes, 6, 2), 0);
            }
            else
            {
                this.DirectoryNumberOfParentDirectory = ByteConversion.GetUInt16BigEndian(ParseFile.ParseSimpleOffset(pathBytes, 6, 2));
            }

            this.DirectoryIdentifierBytes = ParseFile.ParseSimpleOffset(pathBytes, 8, this.LengthOfDirectoryIdentifier);
            this.DirectoryIdentifier      =
                ByteConversion.GetEncodedText(this.DirectoryIdentifierBytes,
                                              ByteConversion.GetPredictedCodePageForTags(this.DirectoryIdentifierBytes));

            if (this.LengthOfDirectoryIdentifier % 2 == 1)
            {
                this.PaddingByte = ParseFile.ParseSimpleOffset(pathBytes, this.LengthOfDirectoryIdentifier + 8, 1)[0];
            }
        }
Пример #15
0
        public void Initialize(Stream pStream, string pFilePath)
        {
            this.filePath = pFilePath;

            this.asciiSignature = ParseFile.ParseSimpleOffset(pStream, SIG_OFFSET, SIG_LENGTH);
            this.versionNumber  = ParseFile.ParseSimpleOffset(pStream, VERSION_OFFSET, VERSION_LENGTH);
            this.startingSong   = ParseFile.ParseSimpleOffset(pStream, STARTING_SONG_OFFSET, STARTING_SONG_LENGTH);
            this.requestAddress = ParseFile.ParseSimpleOffset(pStream, REQUEST_ADDRESS_OFFSET, REQUEST_ADDRESS_LENGTH);
            this.initialMpr0    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR0_OFFSET, INITIAL_MPR0_LENGTH);
            this.initialMpr1    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR1_OFFSET, INITIAL_MPR1_LENGTH);
            this.initialMpr2    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR2_OFFSET, INITIAL_MPR2_LENGTH);
            this.initialMpr3    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR3_OFFSET, INITIAL_MPR3_LENGTH);
            this.initialMpr4    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR4_OFFSET, INITIAL_MPR4_LENGTH);
            this.initialMpr5    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR5_OFFSET, INITIAL_MPR5_LENGTH);
            this.initialMpr6    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR6_OFFSET, INITIAL_MPR6_LENGTH);
            this.initialMpr7    = ParseFile.ParseSimpleOffset(pStream, INITIAL_MPR7_OFFSET, INITIAL_MPR7_LENGTH);

            this.dataSig     = ParseFile.ParseSimpleOffset(pStream, DATA_SIG_OFFSET, DATA_SIG_LENGTH);
            this.dataSize    = ParseFile.ParseSimpleOffset(pStream, DATA_SIZE_OFFSET, DATA_SIZE_LENGTH);
            this.loadAddress = ParseFile.ParseSimpleOffset(pStream, LOAD_ADDRESS_OFFSET, LOAD_ADDRESS_LENGTH);
            this.reserve     = ParseFile.ParseSimpleOffset(pStream, RESERVE_OFFSET, RESERVE_LENGTH);

            int dataLength = BitConverter.ToInt32(this.dataSize, 0);

            this.data = ParseFile.ParseSimpleOffset(pStream, DATA_OFFSET, dataLength);

            this.initializeTagHash();
        }
Пример #16
0
        private void BuildRomFsFile(FileStream isoStream, long ivfcOffset, long fileEntryOffset, long fileBlockOffset, long romFsDataOffset)
        {
            RomFsFileEntry file = new RomFsFileEntry();

            // Nintendo3dsCtrFile tempFile;
            byte[] nameBytes;

            // load dir
            file.ParentDirOffset = ParseFile.ReadUintLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset);
            file.SiblingOffset   = ParseFile.ReadInt32LE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 4);
            file.DataOffset      = ParseFile.ReadUlongLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 8);
            file.DataSize        = ParseFile.ReadUlongLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x10);
            file.WeirdOffset     = ParseFile.ReadUintLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x18);
            file.NameSize        = ParseFile.ReadUintLE(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x1C);

            // build directory name
            if (file.NameSize > 0)
            {
                nameBytes = ParseFile.ParseSimpleOffset(isoStream, ivfcOffset + fileBlockOffset + fileEntryOffset + 0x20, (int)file.NameSize);
                file.Name = ByteConversion.GetUtf16LeText(nameBytes);
            }
            else // this is root
            {
                file.Name = "NO_NAME_FOUND"; // @TODO Make this a constant
            }

            this.FileName = file.Name;
            this.Offset   = ivfcOffset + romFsDataOffset + (long)file.DataOffset;
            this.Size     = (long)file.DataSize;

            // get sibling
            this.SiblingOffset = file.SiblingOffset;
        }
Пример #17
0
        public void Initialize(Stream pStream, string pFilePath)
        {
            this.filePath         = pFilePath;
            this.asciiSignature   = ParseFile.ParseSimpleOffset(pStream, SIG_OFFSET, SIG_LENGTH);
            this.channels         = ParseFile.ParseSimpleOffset(pStream, CHANNELS_OFFSET, CHANNELS_LENGTH);
            this.interleave       = ParseFile.ParseSimpleOffset(pStream, INTERLEAVE_OFFSET, INTERLEAVE_LENGTH);
            this.frequency        = ParseFile.ParseSimpleOffset(pStream, FREQUENCY_OFFSET, FREQUENCY_LENGTH);
            this.loopStart        = ParseFile.ParseSimpleOffset(pStream, LOOP_START_OFFSET, LOOP_START_LENGTH);
            this.loopEnd          = ParseFile.ParseSimpleOffset(pStream, LOOP_END_OFFSET, LOOP_END_LENGTH);
            this.identifier       = ParseFile.ParseSimpleOffset(pStream, IDENTIFIER_OFFSET, IDENTIFIER_LENGTH);
            this.audioStart       = ParseFile.ParseSimpleOffset(pStream, AUDIO_START_OFFSET, AUDIO_START_LENGTH);
            this.headerLength     = ParseFile.ParseSimpleOffset(pStream, HEADER_LENGTH_OFFSET, HEADER_LENGTH_LENGTH);
            this.originalFileName = ParseFile.ParseSimpleOffset(pStream, ORIG_FILENAME_OFFSET, ORIG_FILENAME_LENGTH);
            this.originalFileSize = ParseFile.ParseSimpleOffset(pStream, ORIG_FILESIZE_OFFSET, ORIG_FILESIZE_LENGTH);
            this.versionNumber    = ParseFile.ParseSimpleOffset(pStream, GENH_VERSION_OFFSET, GENH_VERSION_LENGTH);

            this.LeftCoef        = ParseFile.ParseSimpleOffset(pStream, LEFT_COEF_OFFSET, LEFT_COEF_LENGTH);
            this.RightCoef       = ParseFile.ParseSimpleOffset(pStream, RIGHT_COEF_OFFSET, RIGHT_COEF_LENGTH);
            this.DspInterleave   = ParseFile.ParseSimpleOffset(pStream, DSP_INTERLEAVE_OFFSET, DSP_INTERLEAVE_LENGTH);
            this.CoefficientType = ParseFile.ParseSimpleOffset(pStream, COEFFICIENT_TYPE_OFFSET, COEFFICIENT_TYPE_LENGTH);
            this.SplitCoef1      = ParseFile.ParseSimpleOffset(pStream, SPLIT_COEF1_OFFSET, SPLIT_COEF1_LENGTH);
            this.SplitCoef2      = ParseFile.ParseSimpleOffset(pStream, SPLIT_COEF2_OFFSET, SPLIT_COEF2_LENGTH);

            this.TotalSamples     = ParseFile.ParseSimpleOffset(pStream, TOTAL_SAMPLES_OFFSET, TOTAL_SAMPLES_LENGTH);
            this.SkipSamples      = ParseFile.ParseSimpleOffset(pStream, SKIP_SAMPLES_OFFSET, SKIP_SAMPLES_LENGTH);
            this.SkipSamplesMode  = ParseFile.ReadByte(pStream, SKIP_SAMPLES_MODE_OFFSET);
            this.Atrac3StereoMode = ParseFile.ReadByte(pStream, ATRAC3_STEREO_MODE_OFFSET);
            this.XmaStreamMode    = ParseFile.ReadByte(pStream, XMA_STREAM_MODE_OFFSET);
            this.RawStreamSize    = ParseFile.ParseSimpleOffset(pStream, RAW_DATA_SIZE_OFFSET, RAW_DATA_SIZE_LENGTH);

            this.initializeTagHash();
        }
Пример #18
0
        private SdatInfoWaveArc[] getInfoWaveArcEntries(Stream pStream, int pSectionOffset,
                                                        SdatInfoRec pSdatInfoRec)
        {
            int entryCount = BitConverter.ToInt32(pSdatInfoRec.nCount, 0);

            SdatInfoWaveArc[] ret = new SdatInfoWaveArc[entryCount];

            for (int i = 0; i < entryCount; i++)
            {
                ret[i] = new SdatInfoWaveArc();
                int infoOffset = BitConverter.ToInt32(pSdatInfoRec.nEntryOffsets[i], 0);

                if (infoOffset > 0)
                {
                    ret[i].fileId = ParseFile.ParseSimpleOffset(pStream,
                                                                pSectionOffset + infoOffset +
                                                                INFO_ENTRY_WAVARC_FILEID_OFFSET, INFO_ENTRY_WAVARC_FILEID_LENGTH);
                    ret[i].unknown = ParseFile.ParseSimpleOffset(pStream,
                                                                 pSectionOffset + infoOffset +
                                                                 INFO_ENTRY_WAVARC_UNKNOWN_OFFSET, INFO_ENTRY_WAVARC_UNKNOWN_LENGTH);
                }
            }

            return(ret);
        }
Пример #19
0
        public static PphdStruct GetPphdData(FileStream fs, long offset)
        {
            PphdStruct phdObject = new PphdStruct();

            // save off info
            phdObject.startingOffset = offset;

            phdObject.progSectionOffset = offset + BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0x10, 4), 0);
            phdObject.toneSectionOffset = offset + BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0x14, 4), 0);
            phdObject.vagSectionOffset  = offset + BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, offset + 0x18, 4), 0);

            phdObject.maxVagInfoNumber = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, phdObject.vagSectionOffset + 0x14, 4), 0);
            phdObject.vagInfoSize      = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, phdObject.vagSectionOffset + 8, 4), 0);

            phdObject.vagOffsets           = new long[phdObject.maxVagInfoNumber + 1];
            phdObject.vagLengths           = new long[phdObject.maxVagInfoNumber + 1];
            phdObject.expectedPbdLength    = 0;
            phdObject.IsSmallSamplePresent = false;

            for (int i = 0; i <= phdObject.maxVagInfoNumber; i++)
            {
                phdObject.vagOffsets[i]      = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, phdObject.vagSectionOffset + 0x20 + (i * phdObject.vagInfoSize) + 0, 4), 0);
                phdObject.vagLengths[i]      = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, phdObject.vagSectionOffset + 0x20 + (i * phdObject.vagInfoSize) + 8, 4), 0);
                phdObject.expectedPbdLength += phdObject.vagLengths[i];

                if (phdObject.vagLengths[i] < Psf.MIN_ADPCM_ROW_SIZE)
                {
                    phdObject.IsSmallSamplePresent = true;
                }
            }

            phdObject.length = phdObject.vagSectionOffset - offset + 0x20 + ((phdObject.maxVagInfoNumber + 1) * phdObject.vagInfoSize);

            return(phdObject);
        }
Пример #20
0
        private void buildValidSequenceArray(FileStream pFileStream, int pSequenceCount)
        {
            int tempValue;

            this.validSequenceArray = new bool[pSequenceCount];

            tempValue = BitConverter.ToInt32(ParseFile.ParseSimpleOffset(pFileStream,
                                                                         PSF2_CSL_SEQ_OFFSET_BEGIN, 4), 0);

            if (tempValue > 0)
            {
                this.validSequenceArray[0] = true;
            }

            for (int i = 1; i < pSequenceCount; i++)
            {
                tempValue = BitConverter.ToInt32(ParseFile.ParseSimpleOffset(pFileStream,
                                                                             PSF2_CSL_SEQ_OFFSET_BEGIN + (i * 4), 4), 0);

                if (tempValue > 0)
                {
                    this.validSequenceArray[i] = true;
                }
            }
        }
Пример #21
0
        public void Extract(ref Dictionary <string, FileStream> streamCache, string destinationFolder, bool extractAsRaw)
        {
            string destinationFile = Path.Combine(Path.Combine(destinationFolder, this.ParentDirectoryName), this.FileName);

            byte[] magicBytes;

            if (!streamCache.ContainsKey(this.SourceFilePath))
            {
                streamCache[this.SourceFilePath] = File.OpenRead(this.SourceFilePath);
            }

            // check for CRILAYLA signature since file size is not always reliable,
            //    this will be a little slower, but hopefully the stream caching will minimize
            //    the impact
            magicBytes = ParseFile.ParseSimpleOffset(streamCache[this.SourceFilePath], (long)this.Offset, CriCpkArchive.CRILAYLA_SIGNATURE.Length);

            if (ParseFile.CompareSegment(magicBytes, 0, CriCpkArchive.CRILAYLA_SIGNATURE))
            {
                CriCpkArchive.Uncompress(streamCache[this.SourceFilePath], (long)this.Offset, this.Size, destinationFile);
            }
            else
            {
                ParseFile.ExtractChunkToFile64(streamCache[this.SourceFilePath], (ulong)this.Offset, (ulong)this.Size, destinationFile, false, false);
            }
        }
Пример #22
0
        public virtual void LoadDirectories(FileStream isoStream)
        {
            // change name of top level folder
            this.DirectoryRecordForRootDirectory.FileIdentifierString = String.Empty;

            // get first path record
            byte[] rootDirPathBytes = CdRom.GetSectorByLba(isoStream, this.VolumeBaseOffset, this.LocationOfOccurrenceOfTypeMPathTable, this.IsRawDump, this.LogicalBlockSize);
            rootDirPathBytes = CdRom.GetDataChunkFromSector(rootDirPathBytes, this.IsRawDump);

            // grab the directory record
            uint rootDirectoryOffset = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(rootDirPathBytes, 2, 4));

            byte[] rootDirDirectorySector = CdRom.GetSectorByLba(isoStream, this.VolumeBaseOffset, rootDirectoryOffset, this.IsRawDump, this.LogicalBlockSize);
            rootDirDirectorySector = CdRom.GetDataChunkFromSector(rootDirDirectorySector, this.IsRawDump);

            byte rootDirectoryRecordSize = rootDirDirectorySector[0];

            byte[] rootDirectoryRecord = ParseFile.ParseSimpleOffset(rootDirDirectorySector, 0, rootDirectoryRecordSize);
            this.DirectoryRecordForRootDirectory = new GreenBookCdiDirectoryRecord(rootDirectoryRecord);

            // populate this volume's directory structure
            GreenBookCdiDirectoryStructure rootDirectory =
                new GreenBookCdiDirectoryStructure(isoStream, isoStream.Name,
                                                   this.VolumeBaseOffset, this.DirectoryRecordForRootDirectory,
                                                   this.LogicalBlockSize, this.IsRawDump, this.SectorSize, null);

            this.DirectoryStructureArray.Add(rootDirectory);
        }
Пример #23
0
        protected Dictionary <string, string> getTags(byte[] pBytes, int pTagOffset, int pLength)
        {
            Dictionary <string, string> tags =
                new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            if (pTagOffset < pLength)
            {
                string tagsString;
                byte[] tagBytes;

                int tagLength = pLength - pTagOffset;

                if (pTagOffset != 0)
                {
                    tagBytes = ParseFile.ParseSimpleOffset(pBytes, pTagOffset, tagLength);
                }
                else
                {
                    tagBytes = pBytes;
                }

                /* This is a hack for improper tags, see Lost Vikings II SNSF set.  Official spec
                 *   does not allow null values (0x00) */
                tagBytes = FileUtil.ReplaceNullByteWithSpace(tagBytes);

                tagsString = VGMToolbox.util.ByteConversion.GetEncodedText(
                    tagBytes,
                    VGMToolbox.util.ByteConversion.GetPredictedCodePageForTags(tagBytes));

                // check for utf8 tag and reencode bytes if needed
                if (tagsString.IndexOf(TAG_UTF8_INDICATOR) > -1)
                {
                    tagsString = System.Text.Encoding.UTF8.GetString(tagBytes);
                }

                string[] splitTags = tagsString.Trim().Split((char)0x0A);
                string[] tag;

                foreach (string s in splitTags)
                {
                    tag = s.Split((char)0x3D);

                    if (tag.Length >= 2)
                    {
                        if (!tags.ContainsKey(tag[0]))
                        {
                            tags.Add(tag[0].Trim(), tag[1].Trim());
                        }
                        else
                        {
                            string oldTag = tags[tag[0]] + Environment.NewLine;
                            tags.Remove(tag[0]);
                            tags.Add(tag[0], oldTag + tag[1]);
                        }
                    }
                } // foreach (string s in splitTags)
            }
            return(tags);
        }
Пример #24
0
        protected override byte GetStreamId(Stream readStream, long currentOffset)
        {
            byte streamId;

            streamId = ParseFile.ParseSimpleOffset(readStream, currentOffset + 0xC, 1)[0];

            return(streamId);
        }
Пример #25
0
        protected override long GetBlockSize(FileStream inStream, long currentOffset)
        {
            long blockSize = (long)(BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(inStream, currentOffset + 2, 2), 0) * 4);

            blockSize += 4;

            return(blockSize);
        }
Пример #26
0
        public static string[] ExtractSdatsFromFile(string pPath, string pDirectorySuffix)
        {
            ArrayList extractedSdatPaths = new ArrayList();

            string fullPath = Path.GetFullPath(pPath);
            string outputPath;
            string filePrefix = Path.GetFileNameWithoutExtension(fullPath);

            if (!String.IsNullOrEmpty(pDirectorySuffix))
            {
                filePrefix += pDirectorySuffix;
            }

            int  sdatIndex = 0;
            long sdatOffset;
            long previousOffset;

            byte[] sdatSizeBytes;
            int    sdatSize;

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException(String.Format("Cannot find file <{0}>", fullPath));
            }
            else
            {
                using (FileStream fs = File.Open(fullPath, FileMode.Open, FileAccess.Read))
                {
                    previousOffset = 0;

                    while ((sdatOffset = ParseFile.GetNextOffset(fs, previousOffset, Sdat.ASCII_SIGNATURE)) != -1)
                    {
                        sdatSizeBytes = ParseFile.ParseSimpleOffset(fs, sdatOffset + 8, 4);
                        sdatSize      = BitConverter.ToInt32(sdatSizeBytes, 0);

                        outputPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(pPath), Path.Combine(filePrefix,
                                                                                                              String.Format("sound_data_{0}.sdat", sdatIndex++.ToString("X2")))));

                        ParseFile.ExtractChunkToFile(fs, sdatOffset, sdatSize, outputPath);

                        extractedSdatPaths.Add(outputPath);

                        // only increment by one since there can be fake or bad SDATs which will move us past proper ones.
                        previousOffset = sdatOffset + 1;
                    }
                }
            }

            // return paths of extracted SDATs
            if (extractedSdatPaths.Count > 0)
            {
                return((string[])extractedSdatPaths.ToArray(typeof(string)));
            }
            else
            {
                return(null);
            }
        }
Пример #27
0
        private void parseHeader(Stream inStream, long currentOffset)
        {
            Guid  checkGuid;
            ulong checkObjectSize;
            ulong endOfHeaderBlockOffset;

            AsfStreamPropertiesObject tempStreamPropertiesObject;
            ArrayList tempStreamPropertiesArray = new ArrayList();

            AsfHeaderObject tempHeader = new AsfHeaderObject();

            tempHeader.ObjectGuid            = new Guid(ParseFile.ParseSimpleOffset(inStream, currentOffset, 0x10));
            tempHeader.ObjectSize            = BitConverter.ToUInt64(ParseFile.ParseSimpleOffset(inStream, (currentOffset + 0x10), 8), 0);
            tempHeader.NumberOfHeaderObjects = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(inStream, (currentOffset + 0x18), 4), 0);
            tempHeader.Reserved1             = ParseFile.ParseSimpleOffset(inStream, (currentOffset + 0x1C), 1)[0];
            tempHeader.Reserved2             = ParseFile.ParseSimpleOffset(inStream, (currentOffset + 0x1D), 1)[0];
            tempHeader.RawBlock    = ParseFile.ParseSimpleOffset(inStream, currentOffset, (int)tempHeader.ObjectSize);
            endOfHeaderBlockOffset = (ulong)currentOffset + tempHeader.ObjectSize;

            // get additional header objects
            currentOffset += 0x1E;

            for (uint i = 0; i < tempHeader.NumberOfHeaderObjects; i++)
            {
                checkGuid       = new Guid(ParseFile.ParseSimpleOffset(inStream, currentOffset, 0x10));
                checkObjectSize = BitConverter.ToUInt64(ParseFile.ParseSimpleOffset(inStream, (currentOffset + 0x10), 8), 0);

                if (checkGuid.Equals(MicrosoftAsfContainer.ASF_File_Properties_Object))
                {
                    tempHeader.FileProperties = this.parseAsfFilePropertiesObject(inStream, currentOffset);
                }
                else if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Stream_Properties_Object))
                {
                    tempStreamPropertiesObject = this.parseAsfStreamPropertiesObject(inStream, currentOffset);
                    tempStreamPropertiesArray.Add(tempStreamPropertiesObject);
                }
                else if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Header_Extension_Object))
                {
                    // not used at this time
                    tempHeader.HeaderExtension = this.parseAsfHeaderExtensionObject(inStream, currentOffset);
                }
                else if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Codec_List_Object))
                {
                    tempHeader.CodecList = this.parseAsfCodecListObject(inStream, currentOffset);
                }

                currentOffset += (long)checkObjectSize;

                // verify we have not gone past the end of the header
                if ((ulong)currentOffset > endOfHeaderBlockOffset)
                {
                    throw new IndexOutOfRangeException(String.Format("Error parsing header, object ending at 0x{0} exceeds header size.{1}", currentOffset.ToString("X"), Environment.NewLine));
                }
            }

            tempHeader.StreamProperties = (AsfStreamPropertiesObject[])tempStreamPropertiesArray.ToArray(typeof(AsfStreamPropertiesObject));
            this.Header = tempHeader;
        }
Пример #28
0
        public void Initialize(FileStream isoStream, long offset, bool isRawDump)
        {
            this.VolumeBaseOffset        = offset;
            this.IsRawDump               = isRawDump;
            this.VolumeType              = VolumeDataType.Data;
            this.DirectoryStructureArray = new ArrayList();
            this.FormatDescription       = MicrosoftExFatFileSystem.FORMAT_DESCRIPTION_STRING;

            this.JumpBoot   = ParseFile.ReadUint24LE(isoStream, this.VolumeBaseOffset + 0);
            this.MagicBytes = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 3, 8);
            this.ZeroChunk  = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 11, 53);

            this.PartitionOffset           = ParseFile.ReadUlongLE(isoStream, this.VolumeBaseOffset + 64);
            this.VolumeLength              = ParseFile.ReadUlongLE(isoStream, this.VolumeBaseOffset + 72);
            this.FatOffset                 = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 80);
            this.FatLength                 = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 84);
            this.ClusterHeapOffset         = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 88);
            this.ClusterCount              = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 92);
            this.RootDirectoryFirstCluster = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 96);

            this.VolumeSerialNumber = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 100);
            this.VolumeIdentifier   = this.VolumeSerialNumber.ToString("X2");

            this.FileSystemRevision = ParseFile.ReadUshortLE(isoStream, this.VolumeBaseOffset + 104);
            this.VolumeFlags        = ParseFile.ReadUshortLE(isoStream, this.VolumeBaseOffset + 106);

            this.BytesPerSector    = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 108);
            this.SectorsPerCluster = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 109);

            this.NumberOfFats = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 110);

            // caclulate helper values
            this.SectorSizeInBytes  = (uint)(1 << this.BytesPerSector);
            this.ClusterSizeInBytes = (uint)(1 << (this.SectorsPerCluster + this.BytesPerSector));

            this.VolumeLengthInBytes         = this.VolumeLength * this.SectorSizeInBytes;
            this.FatAbsoluteOffset           = (ulong)this.VolumeBaseOffset + (this.FatOffset * this.SectorSizeInBytes);
            this.FatLengthInBytes            = this.FatLength * this.SectorSizeInBytes;
            this.ClusterHeapAbsoluteOffset   = (ulong)this.VolumeBaseOffset + (this.ClusterHeapOffset * this.SectorSizeInBytes);
            this.RootDirectoryAbsoluteOffset =
                MicrosoftExFatFileSystem.GetOffsetForClusterId(this.ClusterHeapAbsoluteOffset, this.ClusterSizeInBytes, this.RootDirectoryFirstCluster); // this.ClusterHeapAbsoluteOffset + ((this.RootDirectoryFirstCluster - MicrosoftExFatFileSystem.CLUSTER_CORRECTION_OFFSET) * this.ClusterSizeInBytes);

            if (this.FileSystemRevision == MicrosoftExFatFileSystem.EXFAT_VERSION_0100)
            {
                // initialize FAT
                this.InitializeAndValidateFat(isoStream);

                // process root directory entry
                this.GetVolumeLabel(isoStream);

                // load directories
                this.LoadDirectories(isoStream);
            }
            else
            {
                MessageBox.Show(String.Format("Unsupported exFAT version: {0}", this.FileSystemRevision.ToString("X8")));
            }
        }
Пример #29
0
        protected override byte GetStreamId(Stream readStream, long currentOffset)
        {
            byte streamId;

            streamId = ParseFile.ParseSimpleOffset(readStream,
                                                   currentOffset + 6 + this.GetAudioPacketHeaderSize(readStream, currentOffset), 1)[0];

            return(streamId);
        }
Пример #30
0
        private void LoadDirectories(FileStream isoStream)
        {
            MicrosoftExFatDirectoryStructure rootDirectory;

            byte[] primaryEntry = new byte[MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE];

            byte  entryType     = 0xFF;
            long  currentOffset = (long)this.RootDirectoryAbsoluteOffset;
            ulong maxDirectoryLength;

            bool rootDirectoryProcessed = false;

            // @TODO: Updated to use max data size and to jump clusters if needed.
            do
            {
                // read primary entry
                primaryEntry = ParseFile.ParseSimpleOffset(isoStream, currentOffset, MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE);

                // process primary entry and subentries if needed
                entryType = primaryEntry[0];

                switch (entryType)
                {
                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_FILE_DIRECTORY:
                    // calculate max size for root directory entries
                    maxDirectoryLength = this.GetMaxDataSizeForFirstCluster(this.RootDirectoryFirstCluster);

                    // build root directory
                    rootDirectory = new MicrosoftExFatDirectoryStructure(isoStream, this.VolumeBaseOffset, (long)this.RootDirectoryAbsoluteOffset, (long)maxDirectoryLength,
                                                                         String.Empty, String.Empty, this.ClusterHeapAbsoluteOffset, this.ClusterSizeInBytes);

                    // add root directory
                    this.DirectoryStructureArray.Add(rootDirectory);

                    // skip the root directory entries, primaryEntry[1] is the FileDirectoryEntry.SecondaryCount value
                    currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE +
                                     (uint)(MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE * primaryEntry[1]);

                    // set flag to indicate directory was processed
                    rootDirectoryProcessed = true;
                    break;

                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_VOLUME_LABEL:
                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP:
                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_UPCASE:
                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_VOLUME_GUID:
                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_TEXFAT_PADDING:
                case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_WINDOWS_CE_ACL:
                    currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE;
                    break;

                default:
                    currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE;
                    break;
                } // switch (entryType)
            }while ((!rootDirectoryProcessed) && (entryType != MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_EMPTY)); // @todo: add max size?
        }