// end Convert // Datafile private void saveRawDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; saveFileDialog.FileName = node.Text; if (saveFileDialog.ShowDialog() == DialogResult.OK) { Forge.FileEntry entry = forge.GetFileEntry(node.Text); byte[] data = forge.GetRawData(entry); try { File.WriteAllBytes(saveFileDialog.FileName, data); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Done"); } } }
private void extractAllToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; if (forge != null && forge.FileEntries.Length > 0) { using (FolderBrowserDialog dialog = new FolderBrowserDialog()) { if (dialog.ShowDialog() == DialogResult.OK) { BeginMarquee(); Parallel.ForEach(forge.FileEntries, (fe) => { string name = fe.NameTable.Name; byte[] data = forge.GetRawData(fe); File.WriteAllBytes(Path.Combine(dialog.SelectedPath, name), data); }); EndMarquee(); MessageBox.Show($"Extracted all of {forge.Name}.", "Done"); } } } }
// Datafile private void saveRawDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.GetForge(); saveFileDialog.FileName = $"{node.Text}.dat"; saveFileDialog.Filter = "Raw Data|*.dat|All Files|*.*"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { Forge.FileEntry entry = forge.GetFileEntry(node.Text); byte[] data = forge.GetRawData(entry); try { File.WriteAllBytes(saveFileDialog.FileName, data); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Extracted decompressed data.", "Success"); } } }
private void saveDecompressedDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.GetForge(); string text = node.Text; byte[] decompressedData = null; BeginMarquee(); Helpers.DoBackgroundWork(() => { Forge.FileEntry entry = forge.GetFileEntry(text); byte[] rawData = forge.GetRawData(entry); decompressedData = Odyssey.ReadFile(rawData); }, () => { EndMarquee(); // failure if (decompressedData.Length == 0 || decompressedData == null) { MessageBox.Show("Could not decompress data.", "Failure"); return; } saveFileDialog.FileName = string.Concat(node.Text, ".", Helpers.ExtensionForGame(node.Game)); saveFileDialog.Filter = $"{Helpers.NameOfGame(node.Game)} Data|*.{Helpers.ExtensionForGame(node.Game)}|All Files|*.*"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { try { File.WriteAllBytes(saveFileDialog.FileName, decompressedData); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Done"); } } }); }
private List <EntryTreeNode> PopulateEntry(EntryTreeNode node) { // extract the contents from the forge Forge forge = node.GetForge(); byte[] data = forge.GetRawData(node.Offset, node.Size); // decompress string file = $"{node.Text}.{Helpers.ExtensionForGame(node.Game)}"; if (node.Game == Game.ODYSSEY) { Helpers.WriteToFile(file, Odyssey.ReadFile(data), true); } else if (node.Game == Game.ORIGINS) { Helpers.WriteToFile(file, Odyssey.ReadFile(data), true); } else if (node.Game == Game.STEEP) { Helpers.WriteToFile(file, Steep.ReadFile(data), true); } // path will hold the file name node.Path = file; // get resource locations and create nodes List <EntryTreeNode> nodes = new List <EntryTreeNode>(); using (Stream stream = new FileStream(Helpers.GetTempPath(file), FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { Helpers.ResourceLocation[] locations = Helpers.LocateResourceIdentifiers(reader); foreach (Helpers.ResourceLocation location in locations) { nodes.Add(new EntryTreeNode { Game = node.Game, Path = file, ResourceType = location.Type, Text = location.Type.ToString(), Type = EntryTreeNodeType.SUBENTRY }); } } } return(nodes); }
private void saveDecompressedDataAsToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView.SelectedNode == null) { return; } EntryTreeNode node = (EntryTreeNode)treeView.SelectedNode; Forge forge = node.Forge; string text = node.Text; byte[] decompressedData = null; BeginMarquee(); Helpers.DoBackgroundWork(() => { Forge.FileEntry entry = forge.GetFileEntry(text); byte[] rawData = forge.GetRawData(entry); decompressedData = Odyssey.ReadFile(rawData); }, () => { EndMarquee(); saveFileDialog.FileName = $"{node.Text}.dec"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { try { File.WriteAllBytes(saveFileDialog.FileName, decompressedData); } catch (IOException ee) { Console.WriteLine(ee); } finally { MessageBox.Show("Done"); } } }); }
public static bool ExtractTextureMap(string fileName, Forge forge) { using (Stream stream = new FileStream($"{fileName}-combined", FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { // this is omnipresent DatafileHeader header = new DatafileHeader { ResourceType = reader.ReadInt32(), FileSize = reader.ReadInt32(), FileNameSize = reader.ReadInt32() }; header.FileName = reader.ReadChars(header.FileNameSize); // ignore the 2 bytes, file ID, and resource type identifier reader.BaseStream.Seek(14, SeekOrigin.Current); // toppmip 0 TopMip mip0 = new TopMip { Width = reader.ReadInt32(), Height = reader.ReadInt32() }; reader.BaseStream.Seek(8, SeekOrigin.Current); mip0.DXTType = DXTExtensions.GetDXT(reader.ReadInt32()); reader.BaseStream.Seek(4, SeekOrigin.Current); mip0.Mipmaps = reader.ReadInt32(); reader.BaseStream.Seek(81, SeekOrigin.Current); // topmip 1 TopMip mip1 = new TopMip { Width = reader.ReadInt32(), Height = reader.ReadInt32() }; reader.BaseStream.Seek(8, SeekOrigin.Current); mip1.DXTType = DXTExtensions.GetDXT(reader.ReadInt32()); reader.BaseStream.Seek(4, SeekOrigin.Current); mip1.Mipmaps = reader.ReadInt32(); // locate the two topmips, if they exist if (forge.FileEntries.Where(x => x.NameTable.Name.Contains(Path.GetFileName(fileName) + "_TopMip")).Count() == 2) { Forge.FileEntry topMipEntry = forge.FileEntries.Where(x => x.NameTable.Name == Path.GetFileName(fileName) + "_TopMip_0").First(); // extract, read, and create DDS images with the first topmips byte[] rawData = forge.GetRawData(topMipEntry); Helpers.WriteToTempFile(topMipEntry.NameTable.Name, rawData); ReadFile(Helpers.GetTempPath(topMipEntry.NameTable.Name)); ExtractTopMip(Helpers.GetTempPath(topMipEntry.NameTable.Name), mip0); } else // topmips do not exist. fear not! there is still image data found here. let us use that. { reader.BaseStream.Seek(25, SeekOrigin.Current); TextureMap map = new TextureMap { DataSize = reader.ReadInt32() }; byte[] mipmapData = reader.ReadBytes(map.DataSize); Helpers.WriteTempDDS(fileName, mipmapData, mip0.Width, mip0.Height, mip0.Mipmaps, mip0.DXTType); } } } return(true); }
private void treeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode curNode = (EntryTreeNode)e.Node; string text = curNode.Text; string tag = (string)curNode.Tag; // a forge file if (tag.EndsWith(".forge")) { // dump resources used by currentForge if (currentForge != null) { currentForge.Dump(); } currentForge = new Forge(tag); Helpers.DoBackgroundWork(() => { currentForge.Read(); }, () => { // show message if there are over 10000 files in the forge if (currentForge.FileEntries.Length > 10000 && MessageBox.Show("This forge file contains more " + "than 10000 entries (" + currentForge.FileEntries.Length + " exactly). Loading all these " + "entries will take a while and Blacksmith will freeze.\n\nContinue?", "Large forge file!", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } // delete the empty tree node e.Node.Nodes.RemoveAt(0); // show and update the progress bar toolStripProgressBar.Visible = true; toolStripProgressBar.Value = 0; toolStripProgressBar.Maximum = currentForge.FileEntries.Length; // load entries into this forge's tree node for (int i = 0; i < currentForge.FileEntries.Length; i++) { string name = currentForge.FileEntries[i].NameTable.Name; EntryTreeNode node = new EntryTreeNode { Text = name, Tag = string.Format("{0}{1}{2}", curNode.Tag, FORGE_ENTRY_IDENTIFIER, name), // set the tag of this file's tree node Size = currentForge.FileEntries[i].IndexTable.RawDataSize }; node.Nodes.Add(new EntryTreeNode()); // add empty node (for entry's contents) curNode.Nodes.Add(node); toolStripProgressBar.Value++; } // reset and hide the progress bar toolStripProgressBar.Value = toolStripProgressBar.Maximum = 0; toolStripProgressBar.Visible = false; }); } // forge entry else if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && !tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { // extract, if the entry has an empty node or if data as a file does not exist if (curNode.Nodes.Count == 1 && curNode.Nodes[0].Text == "" && !File.Exists(Helpers.GetTempPath(text))) { BeginMarquee(); Helpers.DoBackgroundWork(() => { Forge.FileEntry entry = currentForge.GetFileEntry(text); byte[] rawData = currentForge.GetRawData(entry); Helpers.WriteToTempFile(text, rawData); Odyssey.ReadFile(Helpers.GetTempPath(text)); }, () => { EndMarquee(); // remove nodes curNode.Nodes.Clear(); string combined = $"{Helpers.GetTempPath(text)}-combined"; // look for supported resource types using (Stream stream = new FileStream(combined, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { // create nodes based on located resource types foreach (Helpers.ResourceLocation loc in Helpers.LocateResourceIdentifiers(reader)) { curNode.Nodes.Add(new EntryTreeNode { Text = loc.Type.ToString(), Tag = string.Format("{0}{1}{2}", tag, FORGE_SUBENTRY_IDENTIFIER, loc.Type.ToString()), ResourceType = loc.Type }); } } } }); } } }
private void treeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) { if (e.Node == null || e.Node.Tag == null) { return; } EntryTreeNode node = (EntryTreeNode)e.Node; int levels = LevelsDeep(node.FullPath); Forge forge = levels == 1 ? node.Forge : levels == 2 ? ((EntryTreeNode)node.Parent).Forge: ((EntryTreeNode)node.Parent.Parent).Forge; Console.WriteLine(levels + " deep"); string text = node.Text; string tag = (string)node.Tag; if (string.IsNullOrEmpty(text)) { return; } // a forge file if (tag.EndsWith(".forge")) { // dump resources used by currentForge if (currentForge != null) { currentForge.Dump(); } currentForge = new Forge(tag); Helpers.DoBackgroundWork(() => { currentForge.Read(); }, () => { // show message if there are over 10000 files in the forge if (forge.FileEntries.Length > 10000 && MessageBox.Show("This forge file contains more " + "than 10000 entries (" + forge.FileEntries.Length + " exactly). Loading all these " + "entries will take a while and Blacksmith will freeze.\n\nContinue?", "Large forge file!", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } // delete the empty tree node e.Node.Nodes.RemoveAt(0); // show and update the progress bar toolStripProgressBar.Visible = true; toolStripProgressBar.Value = 0; toolStripProgressBar.Maximum = forge.FileEntries.Length; Helpers.DoBackgroundWork(() => { // load entries into this forge's tree node if (!forge.IsFullyRead()) { return; } for (int i = 0; i < forge.FileEntries.Length; i++) { if (forge.FileEntries[i].NameTable == null) { continue; } string name = forge.FileEntries[i].NameTable.Name; EntryTreeNode n = new EntryTreeNode { Text = name, Forge = forge, Tag = $"{node.Tag}{FORGE_ENTRY_IDENTIFIER}{name}", // set the tag of this file's tree node Offset = forge.FileEntries[i].IndexTable.OffsetToRawDataTable, Size = forge.FileEntries[i].IndexTable.RawDataSize, Game = node.Game }; n.Nodes.Add(new EntryTreeNode()); // add empty node (for entry's contents) Invoke(new Action(() => { if (this != null && toolStripProgressBar.Value < 3001) // I recieved an error stating that the progress bar cannot go above 3001 { node.Nodes.Add(n); toolStripProgressBar.Value++; } })); } }, () => { // reset and hide the progress bar toolStripProgressBar.Value = toolStripProgressBar.Maximum = 0; toolStripProgressBar.Visible = false; }); }); } // forge entry else if (tag.Contains(FORGE_ENTRY_IDENTIFIER) && !tag.Contains(FORGE_SUBENTRY_IDENTIFIER)) { // extract, if the entry has an empty node if (node.Nodes.Count == 1 && node.Nodes[0].Text == "") { BeginMarquee(); Helpers.DoBackgroundWork(() => { byte[] rawData = forge.GetRawData(node.Offset, (int)node.Size); Helpers.WriteToFile($"{text}.ext", rawData, true); if (node.Game == Game.ODYSSEY || node.Game == Game.ORIGINS) // temporary, until this Origins no longer works like Odyssey { Odyssey.ReadFile(Helpers.GetTempPath($"{text}.ext")); } else { Steep.ReadFile(Helpers.GetTempPath($"{text}.ext")); } }, () => { EndMarquee(); // remove nodes node.Nodes.Clear(); // look for supported resource types. steep stays out, for now (because it causes crashes). string combined = $"{Helpers.GetTempPath(text)}.dec"; if (File.Exists(combined)) { using (Stream stream = new FileStream(combined, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (BinaryReader reader = new BinaryReader(stream)) { // create nodes based on located resource types foreach (Helpers.ResourceLocation loc in Helpers.LocateResourceIdentifiers(reader)) { node.Nodes.Add(new EntryTreeNode { Text = loc.Type.ToString(), Tag = $"{tag}{FORGE_SUBENTRY_IDENTIFIER}{loc.Type.ToString()}", ResourceType = loc.Type, Game = node.Game }); } } } } }); } } }