public FileNode(RARC BR, byte[] Data, UInt32 Offset, RARCHeader Header) { BaseRARC = BR; Offset = RARCHeader.Size + (Offset * Size); Tag = Helpers.ReadString(Data, (int)Offset, 4); FilenameOffset = Helpers.Read32(Data, (int)Offset + 4); NumFileEntries = Helpers.Read16(Data, (int)Offset + 10); FirstFileEntryOffset = Helpers.Read32(Data, (int)Offset + 12); NodeName = Helpers.ReadString(Data, (int)(FilenameOffset + Header.StringTableOffset + 32)); Console.WriteLine("Reading node: " + NodeName); for (int i = 0; i < NumFileEntries; ++i) { UInt32 ReadOffset = (UInt32)(Header.FileEntriesOffset + (FirstFileEntryOffset * FileEntry.Size) + (i * FileEntry.Size) + 32); FileEntry CurrentFile = new FileEntry(BaseRARC, Data, ReadOffset, Header); Console.WriteLine("Found fileEntry: " + CurrentFile.FileName); if (CurrentFile.ID == 0xFFFF || CurrentFile.Unknown2 == 0x0200) // 0x2000 correct??? { if (CurrentFile.FilenameOffset != 0 && CurrentFile.FilenameOffset != 2) { ChildNodes.Add(new FileNode(BaseRARC, Data, CurrentFile.DataOffset, Header)); } } else { Files.Add(CurrentFile); } } }
public FileEntry(RARC BR, byte[] Data, UInt32 Offset, RARCHeader Head) { BaseRARC = BR; ID = Helpers.Read16(Data, (int)Offset); Unknown1 = Helpers.Read16(Data, (int)Offset + 2); Unknown2 = Helpers.Read16(Data, (int)Offset + 4); FilenameOffset = Helpers.Read16(Data, (int)Offset + 6); DataOffset = Helpers.Read32(Data, (int)Offset + 8); DataSize = Helpers.Read32(Data, (int)Offset + 12); FileName = Helpers.ReadString(Data, (int)(FilenameOffset + Head.StringTableOffset + 32)); if (Helpers.ReadString(Head.FileData, (int)(Head.DataStartOffset + DataOffset + 32), 4) == "Yaz0") { IsCompressed = true; } else { IsCompressed = false; } Header = Head; fileData = GetFileData_OLD(); }
public RARCHeader(RARC BR, byte[] Data, ref FileNode Root) { BaseRARC = BR; Tag = Helpers.ReadString(Data, 0, 4); FileSize = Helpers.Read32(Data, 4); DataStartOffset = Helpers.Read32(Data, 12); NumNodes = Helpers.Read32(Data, 32); FileEntriesOffset = Helpers.Read32(Data, 44); StringTableOffset = Helpers.Read32(Data, 52); FileData = Data; Root = new FileNode(BaseRARC, Data, 0, this); }
public ZeldaArc(string File, TreeView TV, bool IgnoreModels = false) { Archive = new RARC(File); DZRs = new List<DZx>(); DZSs = new List<DZx>(); DZBs = new List<DZB>(); J3Dxs = new List<J3Dx>(); TreeNode NewNode = Helpers.CreateTreeNode(Archive.Filename, null); PopulateFileList(NewNode, Archive.Root, IgnoreModels); //TV.Nodes[TV.Nodes.Count - 1].Expand(); //TV.SelectedNode = TV.Nodes[TV.Nodes.Count - 1]; TV.Nodes.Add(NewNode); Filename = File; }
public FileNode(RARC BR, byte[] Data, UInt32 Offset, RARCHeader Header) { BaseRARC = BR; Offset = RARCHeader.Size + (Offset * Size); Tag = Helpers.ReadString(Data, (int)Offset, 4); FilenameOffset = Helpers.Read32(Data, (int)Offset + 4); NumFileEntries = Helpers.Read16(Data, (int)Offset + 10); FirstFileEntryOffset = Helpers.Read32(Data, (int)Offset + 12); NodeName = Helpers.ReadString(Data, (int)(FilenameOffset + Header.StringTableOffset + 32)); Console.WriteLine("Reading node: " + NodeName); for (int i = 0; i < NumFileEntries; ++i) { UInt32 ReadOffset = (UInt32)(Header.FileEntriesOffset + (FirstFileEntryOffset * FileEntry.Size) + (i * FileEntry.Size) + 32); FileEntry CurrentFile = new FileEntry(BaseRARC, Data, ReadOffset, Header); Console.WriteLine("Found fileEntry: " + CurrentFile.FileName); if (CurrentFile.ID == 0xFFFF || CurrentFile.Unknown2 == 0x0200) // 0x2000 correct??? { if (CurrentFile.FilenameOffset != 0 && CurrentFile.FilenameOffset != 2) ChildNodes.Add(new FileNode(BaseRARC, Data, CurrentFile.DataOffset, Header)); } else Files.Add(CurrentFile); } }
public FileEntry(RARC BR, byte[] Data, UInt32 Offset, RARCHeader Head) { BaseRARC = BR; ID = Helpers.Read16(Data, (int)Offset); Unknown1 = Helpers.Read16(Data, (int)Offset + 2); Unknown2 = Helpers.Read16(Data, (int)Offset + 4); FilenameOffset = Helpers.Read16(Data, (int)Offset + 6); DataOffset = Helpers.Read32(Data, (int)Offset + 8); DataSize = Helpers.Read32(Data, (int)Offset + 12); FileName = Helpers.ReadString(Data, (int)(FilenameOffset + Head.StringTableOffset + 32)); if (Helpers.ReadString(Head.FileData, (int)(Head.DataStartOffset + DataOffset + 32), 4) == "Yaz0") IsCompressed = true; else IsCompressed = false; Header = Head; fileData = GetFileData_OLD(); }
private void PopulateFileList(TreeNode TN, RARC.FileNode ParentFN, bool IgnoreModels) { foreach (RARC.FileNode ChildFN in ParentFN.ChildNodes) PopulateFileList(TN, ChildFN, IgnoreModels); foreach (RARC.FileEntry FE in ParentFN.Files) { if (J3Dx.ValidExtensions.Contains(Path.GetExtension(FE.FileName)) && IgnoreModels == false) J3Dxs.Add(new J3Dx(FE, TN)); else if (Path.GetExtension(FE.FileName) == ".dzr") DZRs.Add(new DZx(FE, TN, this)); else if (Path.GetExtension(FE.FileName) == ".dzs") DZSs.Add(new DZx(FE, TN, this)); else if (Path.GetExtension(FE.FileName) == ".dzb") DZBs.Add(new DZB(FE, TN)); } }
public static void CreateNodes(RARC.FileNode n) { Console.WriteLine("Creating Node for " + n.NodeName); string dirName = n.NodeName; dirName = dirName.ToUpper(); for (int c = 0; c < dirName.Length; c++) { if (c == 4) break; nodes[numNodesDone].type = nodes[numNodesDone].type + dirName[c]; } nodes[numNodesDone].filenameOffset = (uint)stringTable.Length; stringTable = stringTable + dirName.ToLower() + (char)0x00; int numFiles = n.Files.Count; nodes[numNodesDone].numFileEntries = (ushort)(numFiles + 2); nodes[numNodesDone].firstFileEntryOffset = (uint)totalNumFilesAdded; dirName = n.NodeName; nodes[numNodesDone].foldernameHash = Hash(dirName); numNodesDone++; }
public static void CreateNodeEntries(RARC.FileNode Root) { foreach (RARC.FileNode n in Root.ChildNodes) { Console.WriteLine("Creating fileEntry for node " + n.NodeName); fileEntries[totalNumFilesAdded].id = 0xFFFF; fileEntries[totalNumFilesAdded].unknown2 = 0x0200; fileEntries[totalNumFilesAdded].filenameOffset = (ushort)0xFFFE; string fileName = n.NodeName; fileEntries[totalNumFilesAdded].filenameHash = Hash(fileName); fileEntries[totalNumFilesAdded].dataOffset = (uint)0xFFFE; fileEntries[totalNumFilesAdded].dataSize = 0x10; totalNumFilesAdded++; } }
public static void CreateFileEntries(RARC.FileNode Root) { foreach (RARC.FileEntry f in Root.Files) { Console.WriteLine("Creating fileEntry for " + f.FileName); fileEntries[totalNumFilesAdded].id = (ushort)totalNumFilesAdded; if (f.FileName.EndsWith(".szs"))//Check if szs file and use right.. marker? fileEntries[totalNumFilesAdded].unknown2 = 0x9500; else fileEntries[totalNumFilesAdded].unknown2 = 0x1100; fileEntries[totalNumFilesAdded].filenameOffset = (ushort)stringTable.Length; string fileName = f.FileName; stringTable = stringTable + fileName + (char)0x00; fileEntries[totalNumFilesAdded].filenameHash = Hash(fileName); fileEntries[totalNumFilesAdded].dataOffset = lengthOfDataTable; lengthOfDataTable += (uint)f.fileData.Length; //Pad the data table out so new files start at a 0-based address while ((lengthOfDataTable % 16) != 0) lengthOfDataTable++; if ((lengthOfDataTable % 32) != 0)//Check the new address is a multiple of 32 and add 16 if not lengthOfDataTable += 16; filesData[numFilesWithData] = f.fileData; fileEntries[totalNumFilesAdded].dataSize = (uint)f.fileData.Length; numFilesWithData++; totalNumFilesAdded++; } }
public static void CreateEntries(RARC.FileNode Root) { CreateFileEntries(Root); CreateNodeEntries(Root); CreateDummyFiles(); foreach (RARC.FileNode n in Root.ChildNodes) { CreateNodes(n); CreateEntries(n); } }
public static int countRARCFiles(RARC.FileNode Root) { int count = 0; foreach (RARC.FileEntry f in Root.Files) { Console.WriteLine("File: " + f.FileName); count++; } foreach (RARC.FileNode n in Root.ChildNodes) { count += countRARCFiles (n); } return count; }
public static int countRARCDirs(RARC.FileNode Root) { int count = 0; foreach (RARC.FileNode n in Root.ChildNodes) { Console.WriteLine("Node: " + n.NodeName); count++; count += countRARCDirs (n); } return count; }
public static void CompressRARC(string FullPath, RARC.FileNode Root) { Console.WriteLine("\n>> Compressing " + Root.NodeName + " to " + FullPath); string newFile = Root.NodeName; stringTable = CreateStringTable();//Setup the string table int directoriesCount = countRARCDirs(Root); nodes = new Node[directoriesCount + 1]; //Add 1 for the ROOT node numNodesDone = 0; numFilesWithData = 0; lengthOfDataTable = 0; //Fill out the ROOT node nodes[0].type = "ROOT"; nodes[0].filenameOffset = (uint)stringTable.Length; String rootDirName = newFile; stringTable = stringTable + rootDirName + (char)0x00; nodes[0].foldernameHash = Hash(rootDirName); int filesCount = countRARCFiles (Root); nodes[0].numFileEntries = (ushort)(filesCount + 2); nodes[0].firstFileEntryOffset = 0; numNodesDone++; //One node is complete //Get the total number of subdirectories and files //string[] allFiles = Directory.GetFiles(args[0], "*", SearchOption.AllDirectories); //int numOfFilesAndDirs = allFiles.Length + directoriesCount; int numOfFilesAndDirs = filesCount + directoriesCount; //Now set up an array of FileEntrys(Taking into account the "." and ".." file entries for each folder fileEntries = new FileEntry[numOfFilesAndDirs + (directoriesCount * 2) + 2]; Console.WriteLine("# fileEntries " + (numOfFilesAndDirs + (directoriesCount * 2) + 2)); filesData = new byte[filesCount][]; //Setup an array to store all the file data paths in totalNumFilesAdded = 0; //How many file entries have been done CreateEntries(Root); //Fill out the filename & data offsets for the folder entries with the offset from the appropriate Node for (int n = 0; n < totalNumFilesAdded; n++) { if (fileEntries[n].filenameOffset == 0xFFFE) { uint nodeNum = 0; foreach (Node node in nodes) { if (node.foldernameHash == fileEntries[n].filenameHash) { fileEntries[n].filenameOffset = (ushort)node.filenameOffset; fileEntries[n].dataOffset = nodeNum; } nodeNum++; } } } //Make the data table a mutiple of 16 int numOfPaddingBytes = 0; while ((lengthOfDataTable % 16) != 0) { lengthOfDataTable++; numOfPaddingBytes++; } //Fill out Header information RarcHeader header = new RarcHeader(); header.type = "RARC"; header.numFiles1 = (uint)totalNumFilesAdded; header.numFiles2 = (ushort)totalNumFilesAdded; header.sizeOfDataTable1 = lengthOfDataTable; header.sizeOfDataTable2 = lengthOfDataTable; header.unknown1 = 0x20; header.unknown6 = 0x20; header.unknown8 = 0x100; header.fileEntriesOffset = (numNodesDone * 16) + 0x20; if ((header.fileEntriesOffset % 32) != 0)//Check if it's a multiple of 32 and make it one if it's not header.fileEntriesOffset += 16; Console.WriteLine("fileEntriesOffset is: " + header.fileEntriesOffset); Console.WriteLine("totalNumFilesAdded: " + (totalNumFilesAdded+1)); header.numNodes = numNodesDone; int numFileEntries = (numOfFilesAndDirs + (directoriesCount * 2) + 2); int x = 0; while (0 != (((numFileEntries) * 20) + x) % 16) x++; header.stringTableOffset = header.fileEntriesOffset + (uint)((numFileEntries * 20) + x); if ((header.stringTableOffset % 32) != 0)//Check if it's a multiple of 32 and make it one if it's not header.stringTableOffset += 16; Console.WriteLine("stringTableOffset is: " + header.stringTableOffset); while (0 != (stringTable.Length) % 16)//Pad out the string table so the data table starts at a 0based address stringTable = stringTable + (char)0x00; header.dataStartOffset = (uint)(header.stringTableOffset + stringTable.Length); if ((header.dataStartOffset % 32) != 0)//Check if it's a multiple of 32 and make it one if it's not header.dataStartOffset += 16; Console.WriteLine("dataStartOffset is: " + header.dataStartOffset); header.sizeOfStringTable = (uint)stringTable.Length; header.size = lengthOfDataTable + header.dataStartOffset + 0x20; //Let's write it out // Uncomment while testing //FullPath += ".new.arc"; FileStream filestreamWriter = new FileStream(FullPath, FileMode.Create); BinaryWriter binWriter = new BinaryWriter(filestreamWriter); Console.WriteLine("Writing to file: " + FullPath); Console.WriteLine("Writing header..."); //First the Header is written binWriter.Write(header.type[0]); binWriter.Write(header.type[1]); binWriter.Write(header.type[2]); binWriter.Write(header.type[3]); byte[] buffer = BitConverter.GetBytes(header.size); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.unknown1); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.dataStartOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.sizeOfDataTable1); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.sizeOfDataTable2); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.unknown4); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.unknown5); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.numNodes); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.unknown6); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.numFiles1); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.fileEntriesOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.sizeOfStringTable); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.stringTableOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.numFiles2); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.unknown8); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(header.unknown9); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); Console.WriteLine("Writing nodes..."); //Write each of the nodes foreach (Node currentNode in nodes) { Console.WriteLine("Writing " + currentNode.type); binWriter.Write(currentNode.type[0]); if (currentNode.type.Length > 1) //Incase the dirname is only 1 char long binWriter.Write(currentNode.type[1]); else filestreamWriter.WriteByte(0x20); if (currentNode.type.Length > 2) //Incase the dirname is only 2 char long binWriter.Write(currentNode.type[2]); else filestreamWriter.WriteByte(0x20); if (currentNode.type.Length == 4) //Incase the dirname is only 3 char long binWriter.Write(currentNode.type[3]); else filestreamWriter.WriteByte(0x20); buffer = BitConverter.GetBytes(currentNode.filenameOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(currentNode.foldernameHash); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(currentNode.numFileEntries); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(currentNode.firstFileEntryOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); } //Pad out the file to get the file entries at their correct offset while (filestreamWriter.Position < (header.fileEntriesOffset + 32)) { filestreamWriter.WriteByte(0x00); } //Write all the file entries foreach (FileEntry entry in fileEntries) { Console.WriteLine(String.Format("Writing fileEntry {0:X6}",entry.filenameOffset)); buffer = BitConverter.GetBytes(entry.id); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(entry.filenameHash); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(entry.unknown2); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(entry.filenameOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(entry.dataOffset); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(entry.dataSize); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); buffer = BitConverter.GetBytes(entry.zero); Array.Reverse(buffer); filestreamWriter.Write(buffer, 0, buffer.Length); } //Pad out the file to get the string table at its correct offset while (filestreamWriter.Position < (header.stringTableOffset + 32)) { filestreamWriter.WriteByte(0x00); } //Write string table Encoding enc = Encoding.UTF8; binWriter.Write(enc.GetBytes(stringTable)); //Pad out the file to get the data table at its correct offset while (filestreamWriter.Position < (header.dataStartOffset + 32)) { filestreamWriter.WriteByte(0x00); } //Write files data foreach (byte[] file in filesData) { Console.WriteLine("Dumping file data..."); buffer = file; filestreamWriter.Write(buffer, 0, buffer.Length); while ((filestreamWriter.Position % 32) != 0)//Pad out the data so the next file begins on a 0-based multiple of 32 filestreamWriter.WriteByte(0x00); } for (int pad = 0; pad < numOfPaddingBytes; pad++)//Write the bytes neccessary to make the entire file divisble by 32 filestreamWriter.WriteByte(0x00); binWriter.Close(); filestreamWriter.Close(); Console.WriteLine("Packed and good to go!"); }