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 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); } } }
/// <summary> /// Creates an RARC virtual folder from data and an archive name. /// </summary> /// <param name="data">The RARC file data</param> /// <param name="name">The name of the RARC archive</param> public RARC(byte[] data, string name) { FileName = name; if (Yay0.IsYay0(data)) { data = Yay0.Decompress(data); } else if (Yaz0.IsYaz0(data)) { data = Yaz0.Decompress(data); } Header = new RARCHeader(data); ReadNodes(data); }
public void Load(string Path) { FullPath = Path; Data = Helpers.LoadBinary(FullPath); Filename = System.IO.Path.GetFileName(FullPath); if (Helpers.ReadString(Data, 0, 4) == "Yaz0") { byte[] DecData = null; DecompressYaz0(Data, 0, ref DecData); Data = DecData; IsCompressed = true; } Header = new RARCHeader(this, Data, ref Root); }
/// <summary> /// Creates an RARC archive from the given directory and settings. /// </summary> /// <param name="directory">The directory to be converted to an RARC archive.</param> /// <param name="archiveType">The type of archive this will be treated as.</param> /// <param name="compressionType">The compression type of the final archive, if one is desired.</param> public RARC(string directory, ArchiveType archiveType = ArchiveType.MemoryArchive, CompressionType compressionType = CompressionType.None) { if (!Directory.Exists(directory)) { throw new ArgumentException("Constructor expects a valid directory!", nameof(directory)); } var archiveName = $"{Path.GetFileName(directory)}.arc"; if (compressionType != CompressionType.None) { archiveName += compressionType == CompressionType.SZP ? ".szp" : ".szs"; } var archiveFileName = Path.Combine(Path.GetDirectoryName(directory), archiveName); using var writer = new BinaryWriterX(File.Create(archiveFileName), ByteOrder.BigEndian); Header = new RARCHeader(); CreateArchive(writer, directory, archiveType, compressionType); writer.Close(); // Compress the archive if requested if (compressionType != CompressionType.None) { var fileData = File.ReadAllBytes(archiveFileName); switch (compressionType) { case CompressionType.SZP: var szpData = Yay0.Compress(fileData); if (szpData.Length < fileData.Length) { File.WriteAllBytes(archiveFileName, szpData); } break; case CompressionType.SZS: var szsData = Yaz0.Compress(fileData); if (szsData.Length < fileData.Length) { File.WriteAllBytes(archiveFileName, szsData); } break; } } }
public RARC(byte[] Data) { EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.BigEndian); try { Header = new RARCHeader(er); ArchiveInfo = new InfoBlock(er); er.BaseStream.Position = ArchiveInfo.FolderTableOffset + Header.HeaderSize; FolderTable = new FolderTableEntry[ArchiveInfo.NrFolderTableEntries]; for (int i = 0; i < ArchiveInfo.NrFolderTableEntries; i++) { FolderTable[i] = new FolderTableEntry(er); } er.BaseStream.Position = ArchiveInfo.FileTableOffset + Header.HeaderSize; FileTable = new FileTableEntry[ArchiveInfo.NrFileTableEntries]; for (int i = 0; i < ArchiveInfo.NrFileTableEntries; i++) { FileTable[i] = new FileTableEntry(er); } for (int i = 0; i < ArchiveInfo.NrFolderTableEntries; i++) { er.BaseStream.Position = ArchiveInfo.StringTableOffset + Header.HeaderSize + FolderTable[i].NameOffset; FolderTable[i].Name = er.ReadStringNT(Encoding.ASCII); } for (int i = 0; i < ArchiveInfo.NrFileTableEntries; i++) { er.BaseStream.Position = ArchiveInfo.StringTableOffset + Header.HeaderSize + FileTable[i].NameOffset; FileTable[i].Name = er.ReadStringNT(Encoding.ASCII); } er.BaseStream.Position = Header.HeaderSize + Header.FileDataOffset; this.Data = er.ReadBytes((int)Header.FileDataLength1); } finally { er.Close(); } }
public RARC(byte[] Data, string Name) { FileName = Name; Header = new RARCHeader(Data); ReadNodes(Data); }
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 void Pack(VirtualFolder root, EndianBinaryWriter writer) { Header = new RARCHeader(); Header.Magic = "RARC"; Header.Unknown1 = 0x20; Header.Unknown6 = 0x20; Nodes = new List<RARCNode>(); Entries = new List<RARCFileEntry>(); StringTable = new List<char>(); Data = new List<byte>(); StringTable.Add('.'); StringTable.Add('\0'); StringTable.Add('.'); StringTable.Add('.'); StringTable.Add('\0'); RARCNode rootNode = new RARCNode(); rootNode.Type = "ROOT"; rootNode.NameOffset = 5; rootNode.NameHash = HashName(root.Name); foreach (char c in root.Name) { StringTable.Add(c); } StringTable.Add('\0'); rootNode.FileEntryCount = (short)(root.Subdirs.Count + root.Files.Count + 2); rootNode.FirstFileEntryIndex = 0; Nodes.Add(rootNode); EntryCount = rootNode.FileEntryCount; string lastFolderNodeName = ""; foreach (VirtualFolder folder in root.Subdirs) { //Node subdirNode = new Node(); //subdirNode.Type = folder.NodeName; //subdirNode.NameOffset = StringTable.Count; //foreach (char c in folder.Name) //{ // StringTable.Add(c); //} //StringTable.Add('\0'); //rootNode.FileEntryCount = (short)(folder.Files.Count + 2); //Nodes.Add(subdirNode); //FileEntry subdirEntry = new FileEntry(); //subdirEntry.FileId = -1; //subdirEntry.NameHash = HashName(folder.Name); //subdirEntry.Type = 2; //subdirEntry.Padding = 0; //subdirEntry.NameOffset = (short)subdirNode.NameOffset; //subdirEntry.DataOffset = Nodes.IndexOf(subdirNode); //subdirEntry.DataSize = 0x10; //subdirEntry.Zero = 0; //Entries.Add(subdirEntry); if (folder.NodeName == lastFolderNodeName) { } RecursiveDir(folder, rootNode); } foreach (FileData file in root.Files) { Entries.Add(AddFileFileEntry(file)); } #region Add first two period entries. Not using the method I created because of course these two have a slightly different format.... RARCFileEntry singlePeriod = new RARCFileEntry(); singlePeriod.FileId = -1; singlePeriod.NameHash = 0x2E; singlePeriod.Type = 2; singlePeriod.Padding = 0; singlePeriod.NameOffset = 0; singlePeriod.DataOffset = 0; singlePeriod.DataSize = 0x10; singlePeriod.Zero = 0; Entries.Add(singlePeriod); RARCFileEntry doublePeriod = new RARCFileEntry(); doublePeriod.FileId = -1; doublePeriod.NameHash = 0xB8; doublePeriod.Type = 2; doublePeriod.Padding = 0; doublePeriod.NameOffset = 2; doublePeriod.DataOffset = -1; doublePeriod.DataSize = 0x10; doublePeriod.Zero = 0; Entries.Add(doublePeriod); #endregion foreach (VirtualFolder folder in root.Subdirs) { RecursiveFile(folder); } Header.NodeCount = Nodes.Count; Header.Unknown2 = Data.Count; Header.Unknown3 = Data.Count; Header.Unknown7 = Entries.Count; Header.FileEntryCount = (short)Entries.Count; Header.UnknownBool1 = 1; int headerLength = 64; int unalignedData = (headerLength + (Nodes.Count * 16) + (Entries.Count * 20) + StringTable.Count); int alignedEntries = ((Entries.Count * 0x14) + 0x1F) & ~0x1F; int alignedNodes = ((Nodes.Count * 0x10) + 0x1F) & ~0x1F; int alignedTable = alignedNodes + alignedEntries + headerLength; int alignedStringTableSize = (StringTable.Count + 0x1F) & ~0x1F; int alignedData = (alignedTable + alignedStringTableSize + 0x1F) & ~0x1F; Header.Unknown8 = alignedStringTableSize; Header.FileEntriesOffset = alignedNodes + 64 - 0x20; Header.StringTableOffset = alignedTable - 0x20; Header.DataOffset = alignedData - 0x20; Header.FileSize = (alignedData + Data.Count + 0x1F) & ~0x1F; Write(writer); }