Пример #1
0
        void extractNEFS()
        {
            NefsProgressInfo _progressInfo = new NefsProgressInfo();

            _progressInfo.Progress = new Progress <NefsProgress>();

            DirectoryInfo di = new DirectoryInfo(PathToCars);

            foreach (FileInfo fi in di.GetFiles("*.nefs"))
            {
                try
                {
                    NefsArchive archive = new NefsArchive(fi.FullName, _progressInfo);
                    NefsItem    item    = archive.GetItem(13);
                    string      car3    = fi.Name.Replace(fi.Extension, "");
                    FileInfo    fi2     = new FileInfo(PathToCars + "\\" + car3 + "\\" + item.Filename + ".bin.xml");
                    item.Extract(fi2.FullName, _progressInfo);
                    string filename = PathToCars + "\\" + car3 + "\\" + item.Filename;
                    ConvertBinXMLToPlainXML(fi2.FullName, filename);
                }
                catch (Exception)
                {
                }
            }
        }
Пример #2
0
        /// <inheritdoc/>
        public async Task <NefsArchive> WriteArchiveAsync(string destFilePath, NefsArchive nefs, NefsProgress p)
        {
            NefsArchive newArchive = null;

            // Check header version
            if (!(nefs.Header is Nefs20Header header))
            {
                throw new NotSupportedException("Can only write v2.0 files right now.");
            }

            // Setup temp working directory
            var workDir = this.PrepareWorkingDirectory(destFilePath);

            // Write to temp file
            var tempFilePath = Path.Combine(workDir, "temp.nefs");

            using (var file = this.FileSystem.File.Open(tempFilePath, FileMode.Create))
            {
                newArchive = await this.WriteArchiveAsync(file, header, nefs.Items, workDir, p);
            }

            // Copy to final destination
            this.FileSystem.File.Copy(tempFilePath, destFilePath, true);

            return(newArchive);
        }
Пример #3
0
        /// <summary>
        /// Saves the specified archive to a location chosen by the user.
        /// </summary>
        /// <param name="archive">The archive to save.</param>
        public async Task <bool> SaveArchiveAsAsync(NefsArchive archive)
        {
            if (archive == null)
            {
                MessageBox.Show("No archive selected to save.");
                return(false);
            }

            /*
             * Open an open file dialog and get file to inject
             */
            var sfd = new SaveFileDialog();

            sfd.OverwritePrompt = true;
            sfd.FileName        = Path.GetFileName(archive.FilePath);
            var result = sfd.ShowDialog();

            if (result == DialogResult.OK)
            {
                var success = await SaveArchiveAsync(archive, sfd.FileName);

                return(success);
            }

            return(false);
        }
Пример #4
0
        private void LoadArchive(NefsArchive archive)
        {
            // Clear current list
            this.itemsListView.Items.Clear();
            this.listItems.Clear();

            if (archive == null)
            {
                return;
            }

            // Load all items in the NeFS archive into the listview
            foreach (var item in archive.Items.EnumerateById())
            {
                var listItem = new ListViewItem();

                // The list item is actually the first column
                listItem.Text = item.Id.Value.ToString("X");

                // Save a reference to the item object
                listItem.Tag = item;

                this.AddSubItem(listItem, "filename", item.FileName);
                this.AddSubItem(listItem, "directoryId", item.DirectoryId.Value.ToString("X"));
                this.AddSubItem(listItem, "compressedSize", item.CompressedSize.ToString("X"));
                this.AddSubItem(listItem, "extractedSize", item.ExtractedSize.ToString("X"));

                var p1 = archive.Header.Part1.EntriesById[item.Id];
                this.AddSubItem(listItem, "pt1.0x00", p1.OffsetToData.ToString("X"));
                this.AddSubItem(listItem, "pt1.0x08", p1.MetadataIndex.ToString("X"));
                this.AddSubItem(listItem, "pt1.0x0c", p1.IndexIntoPart4.ToString("X"));
                this.AddSubItem(listItem, "pt1.0x10", p1.Id.Value.ToString("X"));

                var p2 = archive.Header.Part2.EntriesById[item.Id];
                this.AddSubItem(listItem, "pt2.0x00", p2.DirectoryId.Value.ToString("X"));
                this.AddSubItem(listItem, "pt2.0x04", p2.FirstChildId.Value.ToString("X"));
                this.AddSubItem(listItem, "pt2.0x08", p2.OffsetIntoPart3.ToString("X"));
                this.AddSubItem(listItem, "pt2.0x0c", p2.ExtractedSize.ToString("X"));
                this.AddSubItem(listItem, "pt2.0x10", p2.Id.Value.ToString("X"));

                var p6 = archive.Header.Part6.EntriesById.GetValueOrDefault(item.Id);
                this.AddSubItem(listItem, "pt6.0x00", p6?.Byte0.ToString("X"));
                this.AddSubItem(listItem, "pt6.0x01", p6?.Byte1.ToString("X"));
                this.AddSubItem(listItem, "pt6.0x02", p6?.Byte2.ToString("X"));
                this.AddSubItem(listItem, "pt6.0x03", p6?.Byte3.ToString("X"));

                var p7 = archive.Header.Part7.EntriesById.GetValueOrDefault(item.Id);
                this.AddSubItem(listItem, "pt7.0x00", p7?.SiblingId.Value.ToString("X"));
                this.AddSubItem(listItem, "pt7.0x04", p7?.Id.Value.ToString("X"));

                if (item.Type == NefsItemType.Directory)
                {
                    listItem.BackColor = Color.LightBlue;
                }

                this.listItems.Add(item, listItem);
                this.itemsListView.Items.Add(listItem);
            }
        }
Пример #5
0
        private void setArchive(NefsArchive archive)
        {
            _archive = archive;
            _archivePropertyForm.SetSelectedObject(archive);
            _browseAllForm.LoadArchive(archive);
            _browseTreeForm.LoadArchive(archive);

            updateTitle();
        }
Пример #6
0
        public void LoadArchive(NefsArchive archive)
        {
            if (archive == null)
            {
                return;
            }

            // Clear current list
            itemsListView.Items.Clear();

            // Load all items in the NeFS archive into the listview
            foreach (var item in archive.Items)
            {
                ListViewItem listItem = new ListViewItem();

                // The list item is actually the first column
                listItem.Text = item.Id.ToString("X");

                // Save a reference to the item object
                listItem.Tag = item;

                addSubItem(listItem, "filename", item.Filename);
                addSubItem(listItem, "directoryId", item.DirectoryId.ToString("X"));
                addSubItem(listItem, "compressedSize", item.CompressedSize.ToString("X"));
                addSubItem(listItem, "extractedSize", item.ExtractedSize.ToString("X"));

                addSubItem(listItem, "pt1.0x00", item.Part1Entry.OffsetToData.ToString("X"));
                addSubItem(listItem, "pt1.0x08", item.Part1Entry.OffsetIntoPt2Raw.ToString("X"));
                addSubItem(listItem, "pt1.0x0c", item.Part1Entry.OffsetIntoPt4Raw.ToString("X"));
                addSubItem(listItem, "pt1.0x10", item.Part1Entry.Id.ToString("X"));

                addSubItem(listItem, "pt2.0x00", item.Part2Entry.DirectoryId.ToString("X"));
                addSubItem(listItem, "pt2.0x04", item.Part2Entry.FirstChildId.ToString("X"));
                addSubItem(listItem, "pt2.0x08", item.Part2Entry.FilenameOffset.ToString("X"));
                addSubItem(listItem, "pt2.0x0c", item.Part2Entry.ExtractedSize.ToString("X"));
                addSubItem(listItem, "pt2.0x10", item.Part2Entry.Id.ToString("X"));

                addSubItem(listItem, "pt5.0x00", item.Part5Entry.Byte1.ToString("X"));
                addSubItem(listItem, "pt5.0x01", item.Part5Entry.Byte2.ToString("X"));
                addSubItem(listItem, "pt5.0x02", item.Part5Entry.Byte3.ToString("X"));
                addSubItem(listItem, "pt5.0x03", item.Part5Entry.Byte4.ToString("X"));

                addSubItem(listItem, "pt6.0x00", item.Part6Entry.Off_0x00.ToString("X"));
                addSubItem(listItem, "pt6.0x04", item.Part6Entry.Off_0x04.ToString("X"));

                if (item.Type == NefsItem.NefsItemType.Directory)
                {
                    listItem.BackColor = Color.LightBlue;
                }

                itemsListView.Items.Add(listItem);
            }
        }
Пример #7
0
        private void PrintDebugInfo(NefsItem item, NefsArchive archive)
        {
            this.richTextBox.Text = "";

            if (item == null || archive == null)
            {
                return;
            }

            var p1 = archive.Header.Part1.EntriesById.GetValueOrDefault(item.Id);
            var p2 = archive.Header.Part2.EntriesById.GetValueOrDefault(item.Id);
            var p6 = archive.Header.Part6.EntriesById.GetValueOrDefault(item.Id);
            var p7 = archive.Header.Part7.EntriesById.GetValueOrDefault(item.Id);

            this.richTextBox.Text = $@"Item Info
-----------------------------------------------------------
Item name:                  {item.FileName}
Item path:                  {archive.Items.GetItemFilePath(item.Id)}

Part 1
-----------------------------------------------------------
Offset to data:             {p1?.OffsetToData.ToString("X")}
Index in part 2:            {p1?.MetadataIndex.ToString("X")}
Index in part 4:            {p1?.IndexIntoPart4.ToString("X")}
Id:                         {p1?.Id.Value.ToString("X")}

Part 2
-----------------------------------------------------------
Directory id:               {p2?.DirectoryId.Value.ToString("X")}
First child id:             {p2?.FirstChildId.Value.ToString("X")}
Offset in part 3:           {p2?.OffsetIntoPart3.ToString("X")}
Extracted size:             {p2?.ExtractedSize.ToString("X")}
Id:                         {p2?.Id.Value.ToString("X")}

Part 4
-----------------------------------------------------------
Chunks                      {this.PrintChunkSizesToString(archive.Header.Part4.GetChunkSizesForItem(item))}

Part 6
-----------------------------------------------------------
0x00:                       {p6?.Byte0.ToString("X")}
0x01:                       {p6?.Byte1.ToString("X")}
0x02:                       {p6?.Byte2.ToString("X")}
0x03:                       {p6?.Byte3.ToString("X")}

Part 7
-----------------------------------------------------------
Sibling id:                 {p7?.SiblingId.Value.ToString("X")}
Item id:                    {p7?.Id.Value.ToString("X")}
";
        }
Пример #8
0
        public async Task ReadArchiveAsync_EncrpytedCarArchive()
        {
            var         fs     = new FileSystem();
            var         reader = new NefsReader(fs);
            var         path   = Path.Combine(DirtRally2Path, @"cars\c4r.nefs");
            NefsArchive nefs   = null;

            using (var stream = fs.File.OpenRead(path))
            {
                nefs = await reader.ReadArchiveAsync(path, this.progress);
            }

            Assert.Equal(98, nefs.Items.Count);
        }
Пример #9
0
        private void LoadArchive(NefsArchive archive)
        {
            if (archive == null)
            {
                this.filesListView.Items.Clear();
                this.filesListItems.Clear();
                this.directoryTreeView.Nodes.Clear();
                return;
            }

            this.directoryTreeView.Nodes.Clear();

            var fileName = Path.GetFileName(this.Workspace.ArchiveSource.DataFilePath);
            var root     = this.directoryTreeView.Nodes.Add(fileName);

            foreach (var item in archive.Items.EnumerateDepthFirstByName())
            {
                if (item.Type == NefsItemType.Directory)
                {
                    if (item.Id == item.DirectoryId)
                    {
                        // This directory is at the root level
                        var newNode = root.Nodes.Add(item.FileName);
                        newNode.Tag = item;
                    }
                    else
                    {
                        // Find this directory's parent directory
                        var parent = (from n in root.DescendantNodes()
                                      where n.Tag != null && ((NefsItem)n.Tag).Id == item.DirectoryId
                                      select n).FirstOrDefault();

                        if (parent == null)
                        {
                            // TODO : FIX THIS ?
                            Log.LogDebug("Could not find parent directory.");
                            continue;
                        }

                        var newNode = parent.Nodes.Add(item.FileName);
                        newNode.Tag = item;
                    }
                }
            }

            root.Expand();

            this.OpenDirectory(null);
        }
Пример #10
0
        public async Task ReadArchiveAsync_GameNefsArchive()
        {
            var         fs     = new FileSystem();
            var         reader = new NefsReader(fs);
            var         path   = Path.Combine(DirtRally2Path, @"game\game.nefs");
            NefsArchive nefs   = null;

            using (var stream = fs.File.OpenRead(path))
            {
                nefs = await reader.ReadArchiveAsync(path, this.progress);
            }

            // Not sure if this is the actual count, there are errors when reading game.nefs
            Assert.Equal(0x445, nefs.Items.Count);
        }
Пример #11
0
        public void LoadArchive(NefsArchive archive)
        {
            if (archive == null)
            {
                return;
            }

            _archive = archive;
            directoryTreeView.Nodes.Clear();

            // TODO : Change the root node to the name of the archive?
            var root = directoryTreeView.Nodes.Add("root");

            foreach (var item in archive.Items)
            {
                if (item.Type == NefsItem.NefsItemType.Directory)
                {
                    if (item.Id == item.DirectoryId)
                    {
                        /* This directory is at the root level */
                        var newNode = root.Nodes.Add(item.Filename);
                        newNode.Tag = item;
                    }
                    else
                    {
                        /* Find this directory's parent directory */
                        var parent = (from n in root.DescendantNodes()
                                      where n.Tag != null && ((NefsItem)n.Tag).Id == item.DirectoryId
                                      select n).FirstOrDefault();

                        if (parent == null)
                        {
                            // TODO : FIX THIS
                            MessageBox.Show("LOL");
                        }

                        var newNode = parent.Nodes.Add(item.Filename);
                        newNode.Tag = item;
                    }
                }
            }

            root.Expand();

            OpenDirectory(null);
        }
Пример #12
0
        private async void loadNefsAsync(string filePath)
        {
            /* Create a progress dialog form */
            var progressDialog = new ProgressDialogForm();

            /* Show the loading dialog asnyc */
            var progressDialogTask = progressDialog.ShowDialogAsync();

            /* Load the archive */
            var archive = await NefsArchive.LoadAsync(filePath, progressDialog.ProgressInfo);

            /* Close the progress dialog */
            progressDialog.Close();

            /* After loading activities */
            setArchive(archive);
        }
Пример #13
0
        internal NefsHeader(FileStream file, NefsArchive archive, NefsProgressInfo p)
        {
            _archive = archive;

            p.BeginTask(0.15f, "Reading header intro...");
            _intro = new NefsHeaderIntro(file, p);
            p.EndTask();

            p.BeginTask(0.15f, "Reading header part 1...");
            _part1 = new NefsHeaderPt1(file, _intro.Part1Offset, _intro.Part1Size, p);
            p.EndTask();

            p.BeginTask(0.15f, "Reading header part 2...");
            _part2 = new NefsHeaderPt2(file, _intro.Part2Offset, _intro.Part2Size, p);
            p.EndTask();

            p.BeginTask(0.10f, "Reading header part 3...");
            _part3 = new NefsHeaderPt3(file, _intro.Part3Offset, _intro.Part3Size, p);
            p.EndTask();

            p.BeginTask(0.15f, "Reading header part 4...");
            _part4 = new NefsHeaderPt4(file, _intro.Part4Offset, _intro.Part4Size, p);
            p.EndTask();

            p.BeginTask(0.10f, "Reading header part 5...");
            _part5 = new NefsHeaderPt5(file, _intro.Part5Offset, _intro.Part5Size, p);
            p.EndTask();

            p.BeginTask(0.10f, "Reading header part 6...");
            _part6 = new NefsHeaderPt6(file, _intro.Part6Offset, _intro.Part6Size, p);
            p.EndTask();

            p.BeginTask(0.10f, "Reading header part 7...");
            // Theres a section of data after header part 6 and the first section of compressed data.
            // I'm not sure what it is. Just copying for now.
            var firstItemOffset = _part1.FirstItemDataOffset;

            if (firstItemOffset > 0 && firstItemOffset > _intro.DataOffset)
            {
                _part7 = new NefsHeaderPt7(file, _intro.DataOffset, (uint)firstItemOffset - _intro.DataOffset);
            }
            p.EndTask();
        }
Пример #14
0
        /// <inheritdoc/>
        public async Task <NefsArchive> WriteArchiveAsync(string destFilePath, NefsArchive nefs, NefsProgress p)
        {
            NefsArchive newArchive = null;

            // Setup temp working directory
            var workDir = this.PrepareWorkingDirectory(destFilePath);

            // Write to temp file
            var tempFilePath = Path.Combine(workDir, "temp.nefs");

            using (var file = this.FileSystem.File.Open(tempFilePath, FileMode.Create))
            {
                newArchive = await this.WriteArchiveAsync(file, nefs.Header, nefs.Items, workDir, p);
            }

            // Copy to final destination
            this.FileSystem.File.Copy(tempFilePath, destFilePath, true);

            return(newArchive);
        }
Пример #15
0
        private void PrintDebugInfo(NefsArchive archive, NefsArchiveSource source)
        {
            this.richTextBox.Text = "";

            if (archive == null)
            {
                return;
            }

            if (archive.Header is Nefs20Header h20)
            {
                this.richTextBox.Text = this.GetDebugInfoVersion20(h20, source);
            }
            else if (archive.Header is Nefs16Header h16)
            {
                this.richTextBox.Text = this.GetDebugInfoVersion16(h16, source);
            }
            else
            {
                this.richTextBox.Text = "Unknown header version.";
            }
        }
Пример #16
0
        private void PrintDebugInfo(NefsItem item, NefsArchive archive)
        {
            this.richTextBox.Text = "";

            if (item == null || archive == null)
            {
                return;
            }

            if (archive.Header is Nefs20Header h20)
            {
                this.richTextBox.Text = this.GetDebugInfoVersion20(item, h20, archive.Items);
            }
            else if (archive.Header is Nefs16Header h16)
            {
                this.richTextBox.Text = this.GetDebugInfoVersion16(item, h16, archive.Items);
            }
            else
            {
                this.richTextBox.Text = "Unknown header version.";
            }
        }
Пример #17
0
        /// <summary>
        /// Saves the specified archive to the specified location.
        /// </summary>
        /// <param name="archive">The archive to save.</param>
        /// <param name="filename">Location to save to.</param>
        public async Task <bool> SaveArchiveAsync(NefsArchive archive, string filename)
        {
            var success = false;

            /* Create a progress dialog form */
            var progressDialog = new ProgressDialogForm();

            /* Show the progress dialog asnyc */
            var progressDialogTask = progressDialog.ShowDialogAsync();

            /* Replace the item */
            await Task.Run(() =>
            {
                try
                {
                    log.Info("----------------------------");
                    log.Info(String.Format("Saving archive to {0}...", filename));
                    archive.Save(filename, progressDialog.ProgressInfo);
                    log.Info("Item successfully saved: " + filename);
                    success = true;
                }
                catch (Exception ex)
                {
                    log.Error("Error saving archive.", ex);
                }
            });

            /* Update editor */
            setArchive(archive);
            SelectNefsItem(_selectedItems);
            updateTitle();

            /* Close the progress dialog */
            progressDialog.Close();

            return(success);
        }
Пример #18
0
        private void LoadArchive(NefsArchive archive)
        {
            // Clear current list
            this.itemsListView.Items.Clear();
            this.listItems.Clear();

            if (archive == null)
            {
                return;
            }

            // Load all items in the NeFS archive into the listview
            foreach (var item in archive.Items.EnumerateById())
            {
                var listItem = new ListViewItem();

                // The list item is actually the first column
                listItem.Text = item.Id.Value.ToString("X");

                // Save a reference to the item object
                listItem.Tag = item;

                this.AddSubItem(listItem, "filename", item.FileName);
                this.AddSubItem(listItem, "directoryId", item.DirectoryId.Value.ToString("X"));
                this.AddSubItem(listItem, "compressedSize", item.CompressedSize.ToString("X"));
                this.AddSubItem(listItem, "extractedSize", item.ExtractedSize.ToString("X"));

                if (archive.Header is Nefs20Header h20)
                {
                    var p1 = h20.Part1.EntriesByGuid[item.Guid];
                    this.AddSubItem(listItem, "pt1.0x00", p1.OffsetToData.ToString("X"));
                    this.AddSubItem(listItem, "pt1.0x08", p1.IndexPart2.ToString("X"));
                    this.AddSubItem(listItem, "pt1.0x0c", p1.IndexPart4.ToString("X"));
                    this.AddSubItem(listItem, "pt1.0x10", p1.Id.Value.ToString("X"));

                    var p2 = h20.Part2.EntriesByIndex[(int)p1.IndexPart2];
                    this.AddSubItem(listItem, "pt2.0x00", p2.DirectoryId.Value.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x04", p2.FirstChildId.Value.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x08", p2.OffsetIntoPart3.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x0c", p2.ExtractedSize.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x10", p2.Id.Value.ToString("X"));

                    var p6 = h20.Part6.EntriesByGuid[item.Guid];
                    this.AddSubItem(listItem, "pt6.0x00", p6.Volume.ToString("X"));
                    this.AddSubItem(listItem, "pt6.0x02", ((byte)p6.Flags).ToString("X"));
                    this.AddSubItem(listItem, "pt6.0x03", p6.Unknown0x3.ToString("X"));

                    var p7 = h20.Part7.EntriesByIndex[(int)p1.IndexPart2];
                    this.AddSubItem(listItem, "pt7.0x00", p7.SiblingId.Value.ToString("X"));
                    this.AddSubItem(listItem, "pt7.0x04", p7.Id.Value.ToString("X"));
                }
                else if (archive.Header is Nefs16Header h16)
                {
                    var p1 = h16.Part1.EntriesByGuid[item.Guid];
                    this.AddSubItem(listItem, "pt1.0x00", p1.OffsetToData.ToString("X"));
                    this.AddSubItem(listItem, "pt1.0x08", p1.IndexPart2.ToString("X"));
                    this.AddSubItem(listItem, "pt1.0x0c", p1.IndexPart4.ToString("X"));
                    this.AddSubItem(listItem, "pt1.0x10", p1.Id.Value.ToString("X"));

                    var p2 = h16.Part2.EntriesByIndex[(int)p1.IndexPart2];
                    this.AddSubItem(listItem, "pt2.0x00", p2.DirectoryId.Value.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x04", p2.FirstChildId.Value.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x08", p2.OffsetIntoPart3.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x0c", p2.ExtractedSize.ToString("X"));
                    this.AddSubItem(listItem, "pt2.0x10", p2.Id.Value.ToString("X"));

                    var p6 = h16.Part6.EntriesByGuid[item.Guid];
                    this.AddSubItem(listItem, "pt6.0x00", p6.Volume.ToString("X"));
                    this.AddSubItem(listItem, "pt6.0x02", ((byte)p6.Flags).ToString("X"));
                    this.AddSubItem(listItem, "pt6.0x03", p6.Unknown0x3.ToString("X"));

                    var p7 = h16.Part7.EntriesByIndex[(int)p1.IndexPart2];
                    this.AddSubItem(listItem, "pt7.0x00", p7.SiblingId.Value.ToString("X"));
                    this.AddSubItem(listItem, "pt7.0x04", p7.Id.Value.ToString("X"));
                }

                if (item.Type == NefsItemType.Directory)
                {
                    listItem.BackColor = Color.LightBlue;
                }

                if (item.Attributes.IsDuplicated)
                {
                    listItem.BackColor = Color.LightPink;
                }

                this.listItems.Add(item, listItem);
                this.itemsListView.Items.Add(listItem);
            }
        }
Пример #19
0
        private void PrintDebugInfo(NefsArchive archive, NefsArchiveSource source)
        {
            this.richTextBox.Text = "";

            if (archive == null)
            {
                return;
            }

            var headerPart1String = new StringBuilder();

            foreach (var entry in archive.Header.Part1.EntriesByIndex)
            {
                headerPart1String.Append($"0x{entry.OffsetToData.ToString("X")}".PadRight(20));
                headerPart1String.Append($"0x{entry.MetadataIndex.ToString("X")}".PadRight(20));
                headerPart1String.Append($"0x{entry.IndexIntoPart4.ToString("X")}".PadRight(20));
                headerPart1String.Append($"0x{entry.Id.Value.ToString("X")}".PadRight(20));
                headerPart1String.Append("\n");
            }

            var headerPart2String = new StringBuilder();

            foreach (var entry in archive.Header.Part2.EntriesByIndex)
            {
                headerPart2String.Append($"0x{entry.DirectoryId.Value.ToString("X")}".PadRight(20));
                headerPart2String.Append($"0x{entry.FirstChildId.Value.ToString("X")}".PadRight(20));
                headerPart2String.Append($"0x{entry.OffsetIntoPart3.ToString("X")}".PadRight(20));
                headerPart2String.Append($"0x{entry.ExtractedSize.ToString("X")}".PadRight(20));
                headerPart2String.Append($"0x{entry.Id.Value.ToString("X")}".PadRight(20));
                headerPart2String.Append("\n");
            }

            var headerPart3String = new StringBuilder();

            foreach (var s in archive.Header.Part3.FileNames)
            {
                headerPart3String.AppendLine(s);
            }

            var headerPart6String = new StringBuilder();

            foreach (var entry in archive.Header.Part6.EntriesByIndex)
            {
                headerPart6String.Append($"0x{entry.Byte0.ToString("X")}".PadRight(20));
                headerPart6String.Append($"0x{entry.Byte1.ToString("X")}".PadRight(20));
                headerPart6String.Append($"0x{entry.Byte2.ToString("X")}".PadRight(20));
                headerPart6String.Append($"0x{entry.Byte3.ToString("X")}".PadRight(20));
                headerPart6String.Append("\n");
            }

            var headerPart7String = new StringBuilder();

            foreach (var entry in archive.Header.Part7.EntriesByIndex)
            {
                headerPart7String.Append($"0x{entry.SiblingId.Value.ToString("X")}".PadRight(20));
                headerPart7String.Append($"0x{entry.Id.Value.ToString("X")}".PadRight(20));
                headerPart7String.Append("\n");
            }

            this.richTextBox.Text = $@"Archive Source
-----------------------------------------------------------
Header source file:         {source.HeaderFilePath}
Header offset:              {source.HeaderOffset.ToString("X")}
Data file path:             {source.DataFilePath}
Is header/data separate:    {source.IsHeaderSeparate}

General Info
-----------------------------------------------------------
Archive Size:               {archive.Header.Part5.ArchiveSize.ToString("X")}
Is Header Encrypted?        {archive.Header.Intro.IsEncrypted}

Header size:                {archive.Header.Intro.HeaderSize.ToString("X")}
Intro size:                 {NefsHeaderIntro.Size.ToString("X")}
Toc size:                   {NefsHeaderIntroToc.Size.ToString("X")}
Part 1 size:                {archive.Header.TableOfContents.Part1Size.ToString("X")}
Part 2 size:                {archive.Header.TableOfContents.Part2Size.ToString("X")}
Part 3 size:                {archive.Header.TableOfContents.Part3Size.ToString("X")}
Part 4 size:                {archive.Header.TableOfContents.Part4Size.ToString("X")}
Part 5 size:                {archive.Header.TableOfContents.Part5Size.ToString("X")}
Part 6 size:                {archive.Header.TableOfContents.Part6Size.ToString("X")}
Part 7 size:                {archive.Header.TableOfContents.Part7Size.ToString("X")}
Part 8 size:                {(archive.Header.Intro.HeaderSize - archive.Header.TableOfContents.OffsetToPart8).ToString("X")}

Header Intro
-----------------------------------------------------------
Magic Number:               {archive.Header.Intro.MagicNumber.ToString("X")}
Expected SHA-256 hash:      {StringHelper.ByteArrayToString(archive.Header.Intro.ExpectedHash)}
AES 256 key hex string:     {StringHelper.ByteArrayToString(archive.Header.Intro.AesKeyHexString)}
Header size:                {archive.Header.Intro.HeaderSize.ToString("X")}
Unknown 0x68:               {archive.Header.Intro.Unknown0x68.ToString("X")}
Number of items:            {archive.Header.Intro.NumberOfItems.ToString("X")}
Unknown 0x70:               {archive.Header.Intro.Unknown0x70zlib.ToString("X")}
Unknown 0x78:               {archive.Header.Intro.Unknown0x78.ToString("X")}

Header Table of Contents
-----------------------------------------------------------
Offset to Part 1:           {archive.Header.TableOfContents.OffsetToPart1.ToString("X")}
Offset to Part 2:           {archive.Header.TableOfContents.OffsetToPart2.ToString("X")}
Offset to Part 3:           {archive.Header.TableOfContents.OffsetToPart3.ToString("X")}
Offset to Part 4:           {archive.Header.TableOfContents.OffsetToPart4.ToString("X")}
Offset to Part 5:           {archive.Header.TableOfContents.OffsetToPart5.ToString("X")}
Offset to Part 6:           {archive.Header.TableOfContents.OffsetToPart6.ToString("X")}
Offset to Part 7:           {archive.Header.TableOfContents.OffsetToPart7.ToString("X")}
Offset to Part 8:           {archive.Header.TableOfContents.OffsetToPart8.ToString("X")}
Unknown 0x00:               {archive.Header.TableOfContents.Unknown0x00.ToString("X")}
Unknown 0x24:               {StringHelper.ByteArrayToString(archive.Header.TableOfContents.Unknown0x24)}

Header Part 1
-----------------------------------------------------------
Data Offset         Metadata index      Index to Part 4     Id
{headerPart1String.ToString()}
Header Part 2
-----------------------------------------------------------
Directory Id        First child Id      Part 3 offset       Extracted size      Id
{headerPart2String.ToString()}
Header Part 3
-----------------------------------------------------------
{headerPart3String.ToString()}
Header Part 4
-----------------------------------------------------------
Number of files:            {archive.Header.Part4.EntriesByIndex.Count.ToString("X")}

Header Part 5
-----------------------------------------------------------
Archive size:               {archive.Header.Part5.ArchiveSize.ToString("X")}
First data offset:          {archive.Header.Part5.FirstDataOffset.ToString("X")}
Archive name string offset: {archive.Header.Part5.ArchiveNameStringOffset.ToString("X")}

Header Part 6
-----------------------------------------------------------
{headerPart6String.ToString()}
Header Part 7
-----------------------------------------------------------
{headerPart7String.ToString()}
";
        }