示例#1
0
        /// <summary>
        /// Creates a ONE archive from a set of files.
        /// </summary>
        /// <param name="files">The files to create an archive from.</param>
        /// <param name="version">The version of the archive. Heroes' default is 3.5.0.0. Consider using 3.3.0.0 to support all available prototypes.</param>
        /// <param name="bufferSize">Size of the search buffer used in compression between 0-8191.</param>
        public static byte[] FromFiles(IList <ManagedOneFile> files, RwVersion version, int bufferSize = 255)
        {
            // Compress all files.
            files = files.Select(x => new ManagedOneFile(x.Name, x.GetCompressedData(bufferSize), true)).ToArray();

            // Calculate sizes.
            var numberOfFiles     = files.Count + 2; // Two dummy entries.
            var sizeOfHeaders     = sizeof(OneArchiveHeader) + sizeof(OneNameSectionHeader);
            var sizeOfNameSection = sizeof(OneFileName) * numberOfFiles;
            var sizeOfFileSection = files.Sum(x => x.GetCompressedData().Length + sizeof(OneFileEntry));

            var totalSize = sizeOfHeaders + sizeOfNameSection + sizeOfFileSection;

            // Make file.
            using var memStream = new ExtendedMemoryStream(totalSize);
            memStream.Append(new OneArchiveHeader(totalSize - sizeof(OneArchiveHeader), version));
            memStream.Append(new OneNameSectionHeader(sizeOfNameSection, version));
            memStream.Append(new OneFileName("")); // Dummy entries
            memStream.Append(new OneFileName(""));

            foreach (var file in files)
            {
                memStream.Append(new OneFileName(file.Name));
            }

            int nameSectionIndex = 2;

            foreach (var file in files)
            {
                memStream.Append(new OneFileEntry(nameSectionIndex++, file.GetCompressedData().Length, file.RwVersion));
                memStream.Append(file.GetCompressedData());
            }

            return(memStream.ToArray());
        }
示例#2
0
        /// <summary>
        /// Builds a virtual AFS based upon a supplied base AFS file.
        /// </summary>
        public VirtualAfs Build(string afsFilePath, int alignment = 2048)
        {
            // Get entries from original AFS file.
            var entries = GetEntriesFromFile(afsFilePath);
            var files   = new Dictionary <int, VirtualFile>(entries.Length);

            // Get Original File List and Copy to New Header.
            var maxCustomFileId = _customFiles.Count > 0 ? _customFiles.Max(x => x.Key) + 1 : 0;
            var numFiles        = Math.Max(maxCustomFileId, entries.Length);
            var newEntries      = new AfsFileEntry[numFiles];
            var headerLength    = Utilities.RoundUp(sizeof(AfsHeader) + (sizeof(AfsFileEntry) * entries.Length), alignment);

            // Create new Virtual AFS Header
            for (int x = 0; x < entries.Length; x++)
            {
                var offset = x > 0 ? Utilities.RoundUp(newEntries[x - 1].Offset + newEntries[x - 1].Length, alignment) : entries[0].Offset;
                int length = 0;

                if (_customFiles.ContainsKey(x))
                {
                    length        = _customFiles[x].Length;
                    files[offset] = _customFiles[x];
                }
                else
                {
                    length        = entries[x].Length;
                    files[offset] = new VirtualFile(entries[x], afsFilePath);
                }

                newEntries[x] = new AfsFileEntry(offset, length);
            }

            var lastEntry = newEntries.Last();
            var fileSize  = Utilities.RoundUp(lastEntry.Offset + lastEntry.Length, alignment);

            // Make Header
            using var memStream = new ExtendedMemoryStream(headerLength);
            memStream.Append(AfsHeader.FromNumberOfFiles(newEntries.Length));
            memStream.Append(newEntries);
            memStream.Append(new AfsFileEntry(0, 0));
            memStream.AddPadding(alignment);

            return(new VirtualAfs(memStream.ToArray(), files, alignment, fileSize));
        }