From c847d40d3f2585648b8c2318136d82d16ff6499a Mon Sep 17 00:00:00 2001 From: KillzXGaming Date: Sun, 28 Nov 2021 14:28:18 -0500 Subject: [PATCH] RARC : Add rewritten code ported from reborn project --- File_Format_Library.zip | Bin 0 -> 11532 bytes .../FileFormats/Archives/RARC/RARC.cs | 122 +++++ .../Archives/{RARC.cs => RARC/RARC_Parser.cs} | 416 +++++------------- .../File_Format_Library.csproj | 3 +- 4 files changed, 233 insertions(+), 308 deletions(-) create mode 100644 File_Format_Library.zip create mode 100644 File_Format_Library/FileFormats/Archives/RARC/RARC.cs rename File_Format_Library/FileFormats/Archives/{RARC.cs => RARC/RARC_Parser.cs} (57%) diff --git a/File_Format_Library.zip b/File_Format_Library.zip new file mode 100644 index 0000000000000000000000000000000000000000..b0125d7cc55cd2b218f7119b79558b37faa4e76b GIT binary patch literal 11532 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%0AV01i@ejOuUWjB{tO0tkN!dnrvQ{VTE?8 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 literal 0 HcmV?d00001 diff --git a/File_Format_Library/FileFormats/Archives/RARC/RARC.cs b/File_Format_Library/FileFormats/Archives/RARC/RARC.cs new file mode 100644 index 00000000..a597ecd3 --- /dev/null +++ b/File_Format_Library/FileFormats/Archives/RARC/RARC.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox; +using System.Windows.Forms; +using System.IO; +using Toolbox.Library.Forms; +using Toolbox.Library; +using Toolbox.Library.IO; + +namespace FirstPlugin +{ + public class RARC : IArchiveFile, IFileFormat, IContextMenuNode + { + public FileType FileType { get; set; } = FileType.Archive; + + public bool CanSave { get; set; } + public string[] Description { get; set; } = new string[] { "RARC" }; + public string[] Extension { get; set; } = new string[] { "*.rarc", "*.arc", "*.crar", "*.yaz0" }; + public string FileName { get; set; } + public string FilePath { get; set; } + public IFileInfo IFileInfo { get; set; } + + public bool CanAddFiles { get; set; } + public bool CanRenameFiles { get; set; } = true; + public bool CanReplaceFiles { get; set; } + public bool CanDeleteFiles { get; set; } + + public bool Identify(System.IO.Stream stream) + { + using (var reader = new Toolbox.Library.IO.FileReader(stream, true)) + { + return reader.CheckSignature(4, "RARC") || reader.CheckSignature(4, "CRAR"); + } + } + + public Type[] Types + { + get + { + List types = new List(); + return types.ToArray(); + } + } + + RARC_Parser RarcFileData; + + public IEnumerable Files => RarcFileData.Files; + + public void ClearFiles() { RarcFileData.Files.Clear(); } + + public ToolStripItem[] GetContextMenuItems() + { + List Items = new List(); + Items.Add(new ToolStripMenuItem("Save", null, SaveAction, Keys.Control | Keys.S)); + Items.Add(new ToolStripMenuItem("Batch Rename Galaxy (Mario Galaxy)", null, BatchRenameGalaxy, Keys.Control | Keys.S)); + return Items.ToArray(); + } + + private void BatchRenameGalaxy(object sender, EventArgs args) + { + string ActorName = Path.GetFileNameWithoutExtension(FileName); + + RenameDialog dialog = new RenameDialog(); + dialog.SetString(ActorName); + + if (dialog.ShowDialog() == DialogResult.OK) + { + string NewActorName = dialog.textBox1.Text; + FileName = NewActorName + ".arc"; + + foreach (var file in RarcFileData.Files) + { + file.FileName = file.FileName.Replace(ActorName, NewActorName); + file.UpdateWrapper(); + } + } + } + + private void SaveAction(object sender, EventArgs args) + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.Filter = Utils.GetAllFilters(this); + sfd.FileName = FileName; + + if (sfd.ShowDialog() == DialogResult.OK) + { + STFileSaver.SaveFileFormat(this, sfd.FileName); + } + } + + public bool IsLittleEndian { get; set; } = false; + + public void Load(System.IO.Stream stream) + { + CanSave = true; + CanRenameFiles = true; + CanReplaceFiles = true; + + RarcFileData= new RARC_Parser(stream); + } + + public void Save(System.IO.Stream stream) + { + RarcFileData.Save(stream); + } + + public void Unload() { } + + public bool AddFile(ArchiveFileInfo archiveFileInfo) + { + return false; + } + + public bool DeleteFile(ArchiveFileInfo archiveFileInfo) + { + return false; + } + } +} diff --git a/File_Format_Library/FileFormats/Archives/RARC.cs b/File_Format_Library/FileFormats/Archives/RARC/RARC_Parser.cs similarity index 57% rename from File_Format_Library/FileFormats/Archives/RARC.cs rename to File_Format_Library/FileFormats/Archives/RARC/RARC_Parser.cs index cee54d30..7a2eae6f 100644 --- a/File_Format_Library/FileFormats/Archives/RARC.cs +++ b/File_Format_Library/FileFormats/Archives/RARC/RARC_Parser.cs @@ -1,150 +1,40 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; -using System.Threading.Tasks; -using Toolbox; -using System.Windows.Forms; -using System.IO; -using Toolbox.Library.Forms; using Toolbox.Library; using Toolbox.Library.IO; namespace FirstPlugin { - public class RARC : IArchiveFile, IFileFormat, IDirectoryContainer, IContextMenuNode + public class RARC_Parser { - public FileType FileType { get; set; } = FileType.Archive; - - public bool CanSave { get; set; } - public string[] Description { get; set; } = new string[] { "RARC" }; - public string[] Extension { get; set; } = new string[] { "*.rarc", "*.arc", "*.crar", "*.yaz0" }; - public string FileName { get; set; } - public string FilePath { get; set; } - public IFileInfo IFileInfo { get; set; } - - public bool CanAddFiles { get; set; } - public bool CanRenameFiles { get; set; } = true; - public bool CanReplaceFiles { get; set; } - public bool CanDeleteFiles { get; set; } - - public bool Identify(System.IO.Stream stream) - { - using (var reader = new Toolbox.Library.IO.FileReader(stream, true)) - { - return reader.CheckSignature(4, "RARC") || reader.CheckSignature(4, "CRAR"); - } - } - - public Type[] Types - { - get - { - List types = new List(); - return types.ToArray(); - } - } - - public List files = new List(); - public List nodes = new List(); - - public IEnumerable Files => files; - public IEnumerable Nodes => nodes; - - public void ClearFiles() { files.Clear(); } - - public string Name - { - get { return FileName; } - set { FileName = value; } - } + public List Files = new List(); private DirectoryEntry[] Directories; + public bool IsLittleEndian = false; + private uint HeaderSize = 32; private uint Unknown = 256; - public RamAllocation RamType = RamAllocation.MRAM; - - public enum RamAllocation + public RARC_Parser(Stream stream) { - None, - ARAM, - MRAM, - } - - public ToolStripItem[] GetContextMenuItems() - { - List Items = new List(); - Items.Add(new ToolStripMenuItem("Save", null, SaveAction, Keys.Control | Keys.S)); - Items.Add(new ToolStripMenuItem("Batch Rename Galaxy (Mario Galaxy)", null, BatchRenameGalaxy, Keys.Control | Keys.S)); - return Items.ToArray(); - } - - private void BatchRenameGalaxy(object sender, EventArgs args) - { - string ActorName = Path.GetFileNameWithoutExtension(FileName); - - RenameDialog dialog = new RenameDialog(); - dialog.SetString(ActorName); - - if (dialog.ShowDialog() == DialogResult.OK) - { - string NewActorName = dialog.textBox1.Text; - FileName = NewActorName + ".arc"; - - foreach (var file in files) - { - file.FileName = file.FileName.Replace(ActorName, NewActorName); - file.UpdateWrapper(); - } - } - } - - private void SaveAction(object sender, EventArgs args) - { - SaveFileDialog sfd = new SaveFileDialog(); - sfd.Filter = Utils.GetAllFilters(this); - sfd.FileName = FileName; - - if (sfd.ShowDialog() == DialogResult.OK) - { - STFileSaver.SaveFileFormat(this, sfd.FileName); - } - } - - public bool IsLittleEndian { get; set; } = false; - - public void Load(System.IO.Stream stream) - { - CanSave = true; - CanRenameFiles = true; - CanReplaceFiles = true; - - files.Clear(); - - using (var reader = new FileReader(stream)) - { - _savedDirectories.Clear(); - - reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian; + using (var reader = new FileReader(stream)) { + reader.SetByteOrder(true); string signature = reader.ReadString(4, Encoding.ASCII); if (signature == "CRAR") { IsLittleEndian = true; - reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian; + reader.SetByteOrder(false); } + uint FileSize = reader.ReadUInt32(); HeaderSize = reader.ReadUInt32(); uint DataOffset = reader.ReadUInt32(); uint FileDataSize = reader.ReadUInt32(); - uint MRamSize = reader.ReadUInt32(); - uint ARamSize = reader.ReadUInt32(); - byte[] Padding = reader.ReadBytes(4); - - if (MRamSize != 0) - RamType |= RamAllocation.MRAM; - else if (ARamSize != 0) - RamType |= RamAllocation.ARAM; + uint EndOfFileOffset = reader.ReadUInt32(); + byte[] Padding = reader.ReadBytes(8); //Info Block long pos = reader.Position; @@ -159,79 +49,72 @@ namespace FirstPlugin Unknown = reader.ReadUInt16(); byte[] Padding2 = reader.ReadBytes(4); + reader.SeekBegin(DirectoryOffset); Directories = new DirectoryEntry[DirectoryCount]; - for (int dir = 0; dir < DirectoryCount; dir++) - Directories[dir] = new DirectoryEntry(this); - - Console.WriteLine($"DirectoryCount {DirectoryCount}"); - Console.WriteLine($"StringTablOffset {StringTablOffset}"); - - reader.SeekBegin(DirectoryOffset); for (int dir = 0; dir < DirectoryCount; dir++) { - Directories[dir].Read(reader); + Directories[dir] = new DirectoryEntry(); + Directories[dir].Identifier = reader.ReadUInt32(); + Directories[dir].NameOffset = reader.ReadUInt32(); + Directories[dir].Hash = reader.ReadUInt16(); + Directories[dir].NodeCount = reader.ReadUInt16(); + Directories[dir].FirstNodeIndex = reader.ReadUInt32(); + } + + for (int dir = 0; dir < DirectoryCount; dir++) { + uint NamePointer = StringTablOffset + Directories[dir].NameOffset; + Directories[dir].Name = ReadStringAtTable(reader, NamePointer); } for (int dir = 0; dir < DirectoryCount; dir++) { - uint NamePointer = StringTablOffset + Directories[dir].NameOffset; - Directories[dir].Name = ReadStringAtTable(reader, NamePointer); - - Console.WriteLine($"{ Directories[dir].Name } {dir}"); - for (int n = 0; n < Directories[dir].NodeCount; n++) { + //Seek to the child entry reader.SeekBegin(NodeOffset + ((n + Directories[dir].FirstNodeIndex) * 0x14)); FileEntry entry = new FileEntry(); entry.Read(reader, IsLittleEndian); - NamePointer = StringTablOffset + entry.NameOffset; + var NamePointer = StringTablOffset + entry.NameOffset; entry.Name = ReadStringAtTable(reader, NamePointer); - //Root and parent strings. Skip these unecessary nodes. + //Skip root strings if (entry.Name == "." || entry.Name == "..") continue; if (entry.IsDirectory) { - // Directories[entry.Offset].ID = entry.FileId; //0xFFFF or 0 Directories[dir].AddNode(Directories[entry.Offset]); _savedDirectories.Add(entry); } else { - using (reader.TemporarySeek(pos + DataOffset + entry.Offset, System.IO.SeekOrigin.Begin)) - { - entry.FileData = reader.ReadBytes((int)entry.Size); - } - entry.FileName = entry.Name; - files.Add(entry); + long dataPos = pos + DataOffset + entry.Offset; + entry.FileData = reader.getSection((int)dataPos, (int)entry.Size); + Files.Add(entry); Directories[dir].AddNode(entry); + + entry.FileName = GetFullDirectory(entry); + if (Utils.GetExtension(entry.FileName) == ".key") + entry.OpenFileFormatOnLoad = true; } } } - - this.Name = Directories[0].Name; - nodes.AddRange(Directories[0].Nodes); } } - private void LoadAllDirectoriesAndFiles(DirectoryEntry parentDir) + private string GetFullDirectory(INode file) { - for (int i = 0; i < parentDir.Children.Count; i++) - { - if (parentDir.Children[i] is DirectoryEntry) - { - //_savedDirectories.Add((DirectoryEntry)parentDir.nodes[i]); - } - else - _savedFiles.Add((FileEntry)parentDir.Children[i]); - } + if (file.Parent != null) + return GetFullDirectory(file.Parent) + "/" + file.Name; + else + return file.Name; + } - for (int i = 0; i < parentDir.Children.Count; i++) - { - if (parentDir.Children[i] is DirectoryEntry) - LoadAllDirectoriesAndFiles((DirectoryEntry)parentDir.Children[i]); + public void Save(Stream stream) + { + using (var writer = new FileWriter(stream)) { + SaveFile(writer); } } @@ -260,14 +143,12 @@ namespace FirstPlugin writer.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian; writer.WriteSignature(IsLittleEndian ? "CRAR" : "RARC"); - writer.Write(uint.MaxValue); //FileSize writer.Write(HeaderSize); writer.Write(uint.MaxValue); //DataOffset writer.Write(uint.MaxValue); //File Size - writer.Write(0); //MRAM (saved later if used) - writer.Write(0); //ARAM (saved later if used) - writer.Seek(4); //padding + writer.Write(uint.MaxValue); //End of file + writer.Seek(8); //padding writer.SeekBegin(HeaderSize); long InfoPos = writer.Position; @@ -300,7 +181,7 @@ namespace FirstPlugin foreach (FileEntry entry in Files) entry.SaveFileFormat(); - writer.Align(32); + writer.Align(32); Console.WriteLine("Directories"); @@ -316,20 +197,11 @@ namespace FirstPlugin var dirEntry = (DirectoryEntry)_savedNodes[dir].Children[n]; int index = Directories.ToList().IndexOf(dirEntry); - writer.Write(dirEntry.ID); + writer.Write((ushort)0); writer.Write(dirEntry.Hash); - if (IsLittleEndian) - { - writer.Write((ushort)dirEntry.NameOffset); - writer.Write((byte)0); - writer.Write((byte)0x2); - } - else - { - writer.Write((byte)0x2); - writer.Write((byte)0); - writer.Write((ushort)dirEntry.NameOffset); - } + writer.Write((byte)0x2); + writer.Write((byte)0); + writer.Write((ushort)dirEntry.NameOffset); writer.Write((int)index); writer.Write((int)16); writer.Write((int)0); @@ -339,21 +211,12 @@ namespace FirstPlugin var fileEntry = (FileEntry)entry; writer.Write(fileEntry.FileId); writer.Write(fileEntry.Hash); - if (IsLittleEndian) - { - writer.Write((ushort)fileEntry.NameOffset); - writer.Write((byte)0); //Padding - writer.Write(fileEntry.Flags); - } - else - { - writer.Write(fileEntry.Flags); - writer.Write((byte)0); //Padding - writer.Write((ushort)fileEntry.NameOffset); - } + writer.Write(fileEntry.Flags); + writer.Write((byte)0); //Padding + writer.Write((ushort)fileEntry.NameOffset); fileEntry._dataOffsetPos = writer.Position; - writer.Write(0); + writer.Write(0); writer.Write((uint)fileEntry.FileData.Length); _savedFileData.Add(fileEntry.FileData); writer.Write(0); @@ -363,18 +226,9 @@ namespace FirstPlugin //Save parent and root nodes at end writer.Write((ushort)0); writer.Write((ushort)46); - if (IsLittleEndian) - { - writer.Write((ushort)0); - writer.Write((byte)0); - writer.Write((byte)2); - } - else - { - writer.Write((byte)2); - writer.Write((byte)0); - writer.Write((ushort)0); - } + writer.Write((byte)2); + writer.Write((byte)0); + writer.Write((ushort)0); writer.Write(dir); writer.Write(16); writer.Write(0); @@ -383,18 +237,9 @@ namespace FirstPlugin writer.Write((ushort)0); writer.Write((ushort)184); - if (IsLittleEndian) - { - writer.Write((ushort)2); - writer.Write((byte)0); - writer.Write((byte)2); - } - else - { - writer.Write((byte)2); - writer.Write((byte)0); - writer.Write((ushort)2); - } + writer.Write((byte)2); + writer.Write((byte)0); + writer.Write((ushort)2); writer.Write(rootIndex); writer.Write(16); writer.Write(0); @@ -404,21 +249,19 @@ namespace FirstPlugin long stringTablePos = writer.Position; WriteOffset(writer, 20, InfoPos); - foreach (var str in stringTable) - { + foreach (var str in stringTable) { writer.WriteString(str); } writer.Align(32); long stringTableSize = writer.Position - stringTablePos; var dataPos = writer.Position; - using (writer.TemporarySeek(pos + 12, System.IO.SeekOrigin.Begin)) - { + using (writer.TemporarySeek(pos + 12, System.IO.SeekOrigin.Begin)) { writer.Write((uint)(dataPos - InfoPos)); } uint dataOffset = 0; - SaveFileData(writer, ref dataOffset, Directories[0]); + SaveFileData(writer,ref dataOffset, Directories[0]); uint DataSize = (uint)(writer.Position - dataPos); writer.Align(32); @@ -426,28 +269,22 @@ namespace FirstPlugin uint EndFileSize = (uint)(writer.Position - dataPos); //Write data size - using (writer.TemporarySeek(pos + 16, System.IO.SeekOrigin.Begin)) - { + using (writer.TemporarySeek(pos + 16, System.IO.SeekOrigin.Begin)) { writer.Write((uint)DataSize); } - //Write ram size - if (RamType != RamAllocation.None) - { - using (writer.TemporarySeek(pos + (RamType.HasFlag(RamAllocation.MRAM) ? 20 : 24), System.IO.SeekOrigin.Begin)) { - writer.Write((uint)EndFileSize); - } + //Write end of file size + using (writer.TemporarySeek(pos + 20, System.IO.SeekOrigin.Begin)) { + writer.Write((uint)EndFileSize); } //Write file size - using (writer.TemporarySeek(pos + 0x4, System.IO.SeekOrigin.Begin)) - { + using (writer.TemporarySeek(pos + 0x4, System.IO.SeekOrigin.Begin)) { writer.Write((uint)writer.BaseStream.Length); } //Write string table size - using (writer.TemporarySeek(InfoPos + 16, System.IO.SeekOrigin.Begin)) - { + using (writer.TemporarySeek(InfoPos + 16, System.IO.SeekOrigin.Begin)) { writer.Write((uint)stringTableSize); } } @@ -468,10 +305,9 @@ namespace FirstPlugin } private void CreateStringTable(List stringList, - ref uint stringPos, DirectoryEntry parentDir) + ref uint stringPos, DirectoryEntry parentDir) { - if (!stringList.Contains(parentDir.Name)) - { + if (!stringList.Contains(parentDir.Name)) { parentDir.NameOffset = stringPos; stringList.Add(parentDir.Name); stringPos += (uint)parentDir.Name.Length + 1; @@ -479,15 +315,9 @@ namespace FirstPlugin for (int i = 0; i < parentDir.Children.Count; i++) { if (parentDir.Children[i] is FileEntry) - { ((FileEntry)parentDir.Children[i]).NameOffset = (ushort)stringPos; - ((FileEntry)parentDir.Children[i]).UpdateHash(); - } else - { ((DirectoryEntry)parentDir.Children[i]).NameOffset = (ushort)stringPos; - ((DirectoryEntry)parentDir.Children[i]).UpdateHash(); - } Console.WriteLine($"{parentDir.Children[i].Name} {stringPos}"); @@ -500,16 +330,14 @@ namespace FirstPlugin } //Saves data in recusive order - private void SaveFileData(FileWriter writer, ref uint dataPos, DirectoryEntry parentDir) + private void SaveFileData(FileWriter writer, ref uint dataPos, DirectoryEntry parentDir) { for (int i = 0; i < parentDir.Children.Count; i++) { - if (parentDir.Children[i] is FileEntry) - { + if (parentDir.Children[i] is FileEntry) { var entry = (FileEntry)parentDir.Children[i]; long pos = writer.Position; - using (writer.TemporarySeek(entry._dataOffsetPos, System.IO.SeekOrigin.Begin)) - { + using (writer.TemporarySeek(entry._dataOffsetPos, SeekOrigin.Begin)) { writer.Write((uint)dataPos); } writer.Write(entry.FileData); @@ -522,6 +350,25 @@ namespace FirstPlugin } } + private void LoadAllDirectoriesAndFiles(DirectoryEntry parentDir) + { + for (int i = 0; i < parentDir.Children.Count; i++) + { + if (parentDir.Children[i] is DirectoryEntry) + { + //_savedDirectories.Add((DirectoryEntry)parentDir.nodes[i]); + } + else + _savedFiles.Add((FileEntry)parentDir.Children[i]); + } + + for (int i = 0; i < parentDir.Children.Count; i++) + { + if (parentDir.Children[i] is DirectoryEntry) + LoadAllDirectoriesAndFiles((DirectoryEntry)parentDir.Children[i]); + } + } + private void WriteOffset(FileWriter writer, long Target, long RelativePosition) { long Position = writer.Position; @@ -531,10 +378,8 @@ namespace FirstPlugin } } - private string ReadStringAtTable(FileReader reader, uint NameOffset) - { - using (reader.TemporarySeek(NameOffset, System.IO.SeekOrigin.Begin)) - { + private static string ReadStringAtTable(FileReader reader, uint NameOffset) { + using (reader.TemporarySeek(NameOffset, System.IO.SeekOrigin.Begin)) { return reader.ReadZeroTerminatedString(); } } @@ -550,79 +395,36 @@ namespace FirstPlugin return Hash; } - private void CreateDirectoryEntry() + class DirectoryEntry : INode { - - } - - public class DirectoryEntry : IDirectoryContainer - { - public RARC ParentArchive { get; } - public string Name { get; set; } + public uint Identifier; internal uint NameOffset; //Relative to string table public ushort Hash { get; set; } public ushort NodeCount; public uint FirstNodeIndex { get; set; } - public ushort ID { get; set; } = 0xFFFF; - - public DirectoryEntry(RARC rarc) { ParentArchive = rarc; } - - public IEnumerable Nodes { get { return Children; } } public List Children = new List(); - public INode Parent { get; set; } public void AddNode(INode node) { - if (node is FileEntry) - ((FileEntry)node).Parent = this; - else - ((DirectoryEntry)node).Parent = this; - + node.Parent = this; Children.Add(node); } - public void Read(FileReader reader) - { - Identifier = reader.ReadUInt32(); - NameOffset = reader.ReadUInt32(); - Hash = reader.ReadUInt16(); - NodeCount = reader.ReadUInt16(); - FirstNodeIndex = reader.ReadUInt32(); - } - public void UpdateHash() { Hash = CalculateHash(Name); } } - public void Unload() + public class FileEntry : ArchiveFileInfo, INode { + public string Name { get; set; } - } + public INode Parent { get; set; } - public void Save(System.IO.Stream stream) - { - SaveFile(new FileWriter(stream)); - } - - public bool AddFile(ArchiveFileInfo archiveFileInfo) - { - return false; - } - - public bool DeleteFile(ArchiveFileInfo archiveFileInfo) - { - return false; - } - - public class FileEntry : ArchiveFileInfo - { - //According to this to determine directory or not - //https://github.com/LordNed/WArchive-Tools/blob/3c7fdefe54b4c7634a042847b7455de61705033f/ArchiveToolsLib/Archive/Archive.cs#L44 public bool IsDirectory { get { return (Flags & 2) >> 1 == 1; } } public ushort FileId { get; set; } @@ -635,13 +437,11 @@ namespace FirstPlugin internal long _dataOffsetPos; - public INode Parent { get; set; } - - public void Read(FileReader reader, bool IsLittleEndian) + public void Read(FileReader reader, bool isLittleEndian) { FileId = reader.ReadUInt16(); Hash = reader.ReadUInt16(); - if (IsLittleEndian) + if (isLittleEndian) { NameOffset = reader.ReadUInt16(); reader.Seek(1); //Padding @@ -657,10 +457,12 @@ namespace FirstPlugin Offset = reader.ReadUInt32(); Size = reader.ReadUInt32(); } + } - public void UpdateHash() { - Hash = CalculateHash(Name); - } + public interface INode + { + string Name { get; set; } + INode Parent { get; set; } } } } diff --git a/File_Format_Library/File_Format_Library.csproj b/File_Format_Library/File_Format_Library.csproj index ce36ab82..ad80efb1 100644 --- a/File_Format_Library/File_Format_Library.csproj +++ b/File_Format_Library/File_Format_Library.csproj @@ -225,6 +225,7 @@ + @@ -367,7 +368,7 @@ - +