Пример #1
0
        /// <summary>
        /// Writes the contents of the archive to be generated to the stream.
        /// </summary>
        public void Write(Stream writeStream, bool bigEndian)
        {
            using var stream = new ExtendedMemoryStream();
            using EndianMemoryStream endianStream = bigEndian ? (EndianMemoryStream) new BigEndianMemoryStream(stream) : new LittleEndianMemoryStream(stream);

            // Precompute Offsets
            var        fileNameSize = Files.Sum(x => x.Name.Length) + (Files.Count);
            Span <int> offsets      = stackalloc int[Files.Count];

            PrecomputeFileOffsets(offsets, fileNameSize);

            // Texture Count
            endianStream.Write <short>((short)Files.Count);
            endianStream.Write((short)1);

            // Texture Offsets
            for (int x = 0; x < offsets.Length; x++)
            {
                endianStream.Write(offsets[x]);
            }

            // Texture Flags
            for (int x = 0; x < Files.Count; x++)
            {
                endianStream.Write((byte)0x11);
            }

            // Texture Names
            Span <byte> currentString = stackalloc byte[1024];

            foreach (var file in Files)
            {
                int numEncoded = Encoding.ASCII.GetBytes(file.Name, currentString);
                currentString[numEncoded] = 0x00;
                stream.Write(currentString.Slice(0, numEncoded + 1));
            }

            // Texture Data
            stream.AddPadding(FileDataAlignment);
            for (int x = 0; x < Files.Count; x++)
            {
                stream.Write(Files[x].Data);
                stream.AddPadding(FileDataAlignment);
            }

            writeStream.Write(stream.ToArray());
        }
Пример #2
0
        /// <summary>
        /// Writes the contents of the archive to be generated to the stream.
        /// </summary>
        public void Write(Stream writeStream)
        {
            using var stream = new ExtendedMemoryStream();

            // Number of items.
            stream.Write <int>(Groups.Keys.Count);

            // Number of items for each id.
            foreach (var group in Groups)
            {
                stream.Write <byte>((byte)group.Value.Files.Count);
            }

            stream.AddPadding(0x00, 4);

            // Write first item index for each group.
            ushort totalItems = 0;

            foreach (var group in Groups)
            {
                stream.Write <ushort>(totalItems);
                totalItems += (ushort)group.Value.Files.Count;
            }

            // Write ID for each group.
            foreach (var group in Groups)
            {
                stream.Write <ushort>(group.Value.Id);
            }

            // Write offsets for each file and pad.
            int firstWriteOffset = Utilities.Utilities.RoundUp((int)stream.Position + (sizeof(int) * totalItems), 16);
            int fileWriteOffset  = firstWriteOffset;

            foreach (var group in Groups)
            {
                foreach (var file in group.Value.Files)
                {
                    stream.Write <int>(file.Data.Length <= 0 ? 0 : fileWriteOffset);
                    fileWriteOffset += file.Data.Length;
                }
            }

            // Write files.
            stream.Write(new byte[(int)(firstWriteOffset - stream.Position)]); // Alignment
            foreach (var file in Groups.SelectMany(x => x.Value.Files))
            {
                stream.Write(file.Data);
            }

            writeStream.Write(stream.ToArray());
        }
Пример #3
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));
        }