private static Romfs_InfoHeader GetRomfsInfoHeaderFromBytes(byte[] headerBytes, uint bodyOffset)
        {
            Romfs_InfoHeader infoHeader = new Romfs_InfoHeader();

            infoHeader.HeaderLength = BitConverter.ToUInt32(headerBytes, 0x00);
            infoHeader.Sections     = new Romfs_SectionHeader[4];
            for (int i = 0; i < 4; i++)
            {
                infoHeader.Sections[i]        = new Romfs_SectionHeader();
                infoHeader.Sections[i].Offset = BitConverter.ToUInt32(headerBytes, 0x04 + (i * 0x08)) + bodyOffset;
                infoHeader.Sections[i].Size   = BitConverter.ToUInt32(headerBytes, 0x08 + (i * 0x08));
            }
            infoHeader.DataOffset = BitConverter.ToUInt32(headerBytes, 0x24) + bodyOffset;
            return(infoHeader);
        }
        public void ExtractRomFS(string outputDirectory, RichTextBox TB_Progress = null, ProgressBar PB_Show = null)
        {
            byte[] ivfcHeaderBytes = new byte[0x5C];
            using (FileStream file = new FileStream(FileName, FileMode.Open, FileAccess.Read))
            {
                file.Read(ivfcHeaderBytes, 0, ivfcHeaderBytes.Length);
            }
            IVFCInfo ivfc = GetIVFCInfoFromBytes(ivfcHeaderBytes);

            ulong romfsDataOffset = Align(ivfc.Levels[0].HashOffset + ivfc.MasterHashSize, ivfc.Levels[2].BlockSize);

            byte[] romfsInfoHeaderBytes = new byte[0x28];
            using (FileStream file = new FileStream(FileName, FileMode.Open, FileAccess.Read))
            {
                file.Seek(Convert.ToInt64(romfsDataOffset), SeekOrigin.Begin);
                file.Read(romfsInfoHeaderBytes, 0, romfsInfoHeaderBytes.Length);
            }
            Romfs_InfoHeader infoHeader = GetRomfsInfoHeaderFromBytes(romfsInfoHeaderBytes, Convert.ToUInt32(romfsDataOffset));

            byte[] directoryMetadataBlock = new byte[infoHeader.Sections[1].Size];
            byte[] fileMetadataBlock      = new byte[infoHeader.Sections[3].Size];
            using (FileStream file = new FileStream(FileName, FileMode.Open, FileAccess.Read))
            {
                file.Seek(Convert.ToInt64(infoHeader.Sections[1].Offset), SeekOrigin.Begin);
                file.Read(directoryMetadataBlock, 0, directoryMetadataBlock.Length);

                file.Seek(Convert.ToInt64(infoHeader.Sections[3].Offset), SeekOrigin.Begin);
                file.Read(fileMetadataBlock, 0, fileMetadataBlock.Length);
            }

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

            VisitDirectory(0, outputDirectory, directoryMetadataBlock, fileMetadataBlock, infoHeader.DataOffset, TB_Progress, PB_Show);
        }