Пример #1
0
            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();
            }
Пример #2
0
            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);
                    }
                }
            }
Пример #3
0
        /// <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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        /// <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;
                }
            }
        }
Пример #7
0
        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();
            }
        }
Пример #8
0
 public RARC(byte[] Data, string Name)
 {
     FileName = Name;
     Header   = new RARCHeader(Data);
     ReadNodes(Data);
 }
Пример #9
0
            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);
                }
            }
Пример #10
0
            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);
        }