Esempio n. 1
0
        public void CharStringWrites()
        {
            var expect = new byte[] {
                0x33, 0x34, 0x34, 0x02, 0x35, 0x35, 0x06, 0x36,
                0x00, 0x36, 0x00, 0x00, 0x00, 0x03, 0x37, 0x37,
                0x00, 0x38, 0x38, 0x00, 0x02, 0x38, 0x38, 0x38,
                0x38
            };
            var ms = new MemoryStream();

            using (var bw = new BinaryWriterX(ms))
            {
                bw.Write('3');
                bw.Write(new char[] { '4', '4' });

                bw.Write("55");
                bw.WriteString("66", Encoding.Unicode);
                bw.WriteString("77", Encoding.GetEncoding("SJIS"));

                bw.WriteString("88", Encoding.ASCII, false, true);
                bw.WriteString("88", Encoding.ASCII, true, false);
                bw.WriteString("88", Encoding.ASCII, false, false);

                Assert.IsTrue(ms.ToArray().SequenceEqual(expect));
            }
        }
Esempio n. 2
0
        private void WriteStrings(Stream output, IList <IArchiveFileInfo> afis)
        {
            var directories = new HashSet <string>();
            var files       = new List <string>(afis.Count);

            foreach (var file in OrderFiles(afis))
            {
                directories.Add(file.FilePath.GetDirectory().ToRelative().FullName + "/");
                files.Add(file.FilePath.GetName());
            }

            var strings = new MemoryStream();

            using var bw = new BinaryWriterX(strings, true);
            foreach (var s in directories)
            {
                bw.WriteString(s, Encoding.ASCII, false);
            }
            foreach (var s in files)
            {
                bw.WriteString(s, Encoding.ASCII, false);
            }

            var compStrings = new MemoryStream();

            XfsaSupport.Compress(strings, compStrings, Level5CompressionMethod.Lz10);

            compStrings.CopyTo(output);

            while (output.Position % 4 > 0)
            {
                output.WriteByte(0);
            }
        }
Esempio n. 3
0
        public void Save(Stream output, ImageInfo imageInfo)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var texOffset = HeaderSize + imageInfo.ImageData.Length;

            // Write image data
            bw.WriteType(new ImgHeader {
                magic = "IMG0", size = imageInfo.ImageData.Length
            });
            bw.Write(imageInfo.ImageData);

            // Write tex header
            bw.WriteType(new ImgHeader {
                magic = "TEXR", size = 0x10
            });
            bw.WriteType(new ImgEntry {
                width = imageInfo.ImageSize.Width, height = imageInfo.ImageSize.Height
            });

            // Write end header
            bw.WriteString("!END", Encoding.ASCII, false, false);
            bw.WritePadding(3);
        }
Esempio n. 4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="output"></param>
 /// <returns></returns>
 public bool Save(Stream output)
 {
     using (var bw = new BinaryWriterX(output, true))
     {
         bw.WriteType(_header);
         bw.BaseStream.Position = 0x40;
         bw.WriteMultiple(_padding);
         var offsetTablePos = bw.BaseStream.Position;
         bw.BaseStream.Position += (0x14 * _header.FileCount);
         foreach (var b in Bitmaps)
         {
             bw.WriteString(b.Name, System.Text.Encoding.ASCII, false, true);
         }
         var newOffsets = new List <OffsetEntry>();
         foreach (var b in Bitmaps)
         {
             var kbi = b as KsltBitmapInfo;
             newOffsets.Add(new OffsetEntry()
             {
                 Offset = (int)bw.BaseStream.Position
             });
             kbi.Header.Width    = (short)kbi.Image.Width;
             kbi.Header.Height   = (short)kbi.Image.Height;
             kbi.Header.DataSize = kbi.ImageData.Length;
             bw.WriteType(kbi.Header);
             bw.Write(kbi.ImageData);
         }
         bw.BaseStream.Position = offsetTablePos;
         bw.WriteMultiple(newOffsets);
     }
     return(true);
 }
Esempio n. 5
0
        public void Save(Stream output, TextEntry textEntry)
        {
            using (var bw = new BinaryWriterX(output, true))
            {
                _content.CharacterCount    = (short)textEntry.EditedText.Trim().Length;
                _content.CharacterDataSize = (short)Encoding.UTF8.GetByteCount(textEntry.EditedText);
                bw.WriteType(_content);
                bw.WriteType(_drawingFrames[0]);

                short  newFrame   = _drawingFrames[0].FrameCounter;
                string TextLength = textEntry.EditedText.Trim();
                TextLength = TextLength.Replace("\r", "").Replace("\n", "");
                for (var i = 1; i < TextLength.Length; i++)
                {
                    bw.WriteType(_drawingFrames[0].Indicator);
                    newFrame += 0x0C;
                    bw.Write(newFrame);
                }

                for (var i = 0; i < TextLength.Length; i++)
                {
                    bw.WriteType(_colorStructs[0]);
                }

                bw.WriteString(textEntry.EditedText, Encoding.UTF8, false);
            }
        }
Esempio n. 6
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            // Wrap encryption
            output = new XorStream(output, _selectedKey);

            using var bw = new BinaryWriterX(output, ByteOrder.BigEndian);

            // Calculate offsets
            var sizeOffset = 2 + files.Sum(x => Encoding.UTF8.GetByteCount(x.FilePath.ToRelative().FullName)) + files.Count * 2;
            var dataOffset = sizeOffset + 2 + files.Count * 4;

            // Write files
            output.Position = dataOffset;
            foreach (var file in files.Cast <ArchiveFileInfo>())
            {
                file.SaveFileData(output);
            }

            // Write sizes
            output.Position = sizeOffset;
            bw.Write((short)files.Count);
            bw.WriteMultiple(files.Select(x => (int)x.FileSize));

            // Write names
            output.Position = 0;
            bw.Write((short)files.Count);
            foreach (var file in files)
            {
                var name = file.FilePath.ToRelative().FullName;

                bw.Write((short)Encoding.UTF8.GetByteCount(name));
                bw.WriteString(name, Encoding.UTF8, false, false);
            }
        }
Esempio n. 7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="output"></param>
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output, true))
            {
                // Updates
                Header.Width  = (short)Texture.Width;
                Header.Height = (short)Texture.Height;

                // Header
                bw.WriteType(Header);
                bw.WriteAlignment();
                bw.WriteString(FileName, Encoding.ASCII, false);
                bw.WriteAlignment();

                // Setup
                if (Header.Format == ImageFormat.Palette_8)
                {
                    var settings = new PaletteImageSettings(Formats[ImageFormat.RGBA8888], PaletteFormats[ImageFormat.Palette_8], Header.Width, Header.Height);
                    var data     = Common.Save(Texture, Palette, settings);

                    bw.Write(data.indexData);
                    bw.Write(data.paletteData);
                }
                else
                {
                    var settings = new ImageSettings(Formats[ImageFormat.RGBA8888], Header.Width, Header.Height);
                    var data     = Common.Save(Texture, settings);

                    bw.Write(data);
                }
            }
        }
Esempio n. 8
0
        public void Save(Stream binOutput, Stream arcOutput, IList <IArchiveFileInfo> files)
        {
            using var binBw = new BinaryWriterX(binOutput);
            using var arcBw = new BinaryWriterX(arcOutput);

            // Calculate offsets
            var fileOffset    = 0x10;
            var entryOffset   = 0x20;
            var offsetsOffset = entryOffset + files.Count * EntrySize;
            var stringOffset  = offsetsOffset + ((files.Count * 4 + 0xF) & ~0xF);

            // Write files
            var offsets = new List <int>();
            var entries = new List <PaaEntry>();

            var filePosition   = fileOffset;
            var stringPosition = stringOffset;

            foreach (var file in files.Cast <PaaArchiveFileInfo>())
            {
                arcOutput.Position = filePosition;
                var writtenSize = file.SaveFileData(arcOutput);
                arcBw.WriteAlignment();

                file.Entry.size       = (int)writtenSize;
                file.Entry.nameOffset = stringPosition;

                offsets.Add(filePosition);
                entries.Add(file.Entry);

                filePosition   += ((int)writtenSize + 0xF) & ~0xF;
                stringPosition += (file.FilePath.ToRelative().FullName.Length + 1 + 0xF) & ~0xF;
            }

            // Write strings
            binOutput.Position = stringOffset;
            foreach (var file in files)
            {
                binBw.WriteString(file.FilePath.ToRelative().FullName, Encoding.ASCII, false);
                binBw.WriteAlignment();
            }

            // Write offsets
            binOutput.Position = offsetsOffset;
            binBw.WriteMultiple(offsets);

            // Write entries
            binOutput.Position = entryOffset;
            binBw.WriteMultiple(entries);

            // Write header
            binOutput.Position = 0;

            _header.fileCount     = files.Count;
            _header.entryOffset   = entryOffset;
            _header.offsetsOffset = offsetsOffset;
            _header.unk2          = _header.fileCount / 2;
            binBw.WriteType(_header);
        }
Esempio n. 9
0
        private long WriteEntries(BinaryWriterX bw, DirectoryEntry entry, Stream imgStream)
        {
            // Collect offsets
            var entryOffset    = bw.BaseStream.Position;
            var stringOffset   = entryOffset + (entry.Directories.Count + entry.Files.Count) * EntrySize;
            var entryEndOffset = stringOffset +
                                 entry.Directories.Sum(x => EucJpEncoding.GetByteCount(x.Name) + 1) +
                                 entry.Files.Sum(x => EucJpEncoding.GetByteCount(x.FilePath.GetName()) + 1);

            entryEndOffset = (entryEndOffset + 0x3) & ~0x3;

            // Create holder entries
            var entries = entry.Directories.Select(x => new DdtInfoHolder(x))
                          .Concat(entry.Files.Select(x => new DdtInfoHolder(x)))
                          .OrderBy(x => x.Name, StringComparer.Ordinal)
                          .ToArray();

            // Write files
            foreach (var file in entries.Where(x => x.IsFile))
            {
                file.Entry.entryOffset = (uint)(imgStream.Position / Alignment_);
                file.Entry.entrySize   = (int)file.File.FileSize;

                (file.File as ArchiveFileInfo).SaveFileData(imgStream);
                while (imgStream.Position % Alignment_ != 0)
                {
                    imgStream.WriteByte(0);
                }
            }

            // Write deeper directory entries
            foreach (var directory in entries.Where(x => !x.IsFile))
            {
                directory.Entry.entryOffset = (uint)entryEndOffset;
                directory.Entry.entrySize   = -(directory.Directory.Directories.Count + directory.Directory.Files.Count);

                bw.BaseStream.Position = entryEndOffset;
                entryEndOffset         = (uint)WriteEntries(bw, directory.Directory, imgStream);
            }

            // Write strings
            bw.BaseStream.Position = stringOffset;
            foreach (var infoHolder in entries)
            {
                infoHolder.Entry.nameOffset = (uint)bw.BaseStream.Position;
                bw.WriteString(infoHolder.Name, EucJpEncoding, false);
            }

            // Write current entries
            bw.BaseStream.Position = entryOffset;
            foreach (var infoHolder in entries)
            {
                bw.WriteType(infoHolder.Entry);
            }

            return(entryEndOffset);
        }
Esempio n. 10
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output);

            var fileEntryStartOffset = _headerSize;
            var nameStartOffset      = _headerSize + files.Count * _fileEntrySize;

            // Write names
            var fileOffset  = 0;
            var nameOffset  = 0;
            var fileEntries = new List <Lpc2FileEntry>();

            foreach (var file in files)
            {
                fileEntries.Add(new Lpc2FileEntry
                {
                    fileOffset = fileOffset,
                    fileSize   = (int)file.FileSize,
                    nameOffset = nameOffset
                });

                bw.BaseStream.Position = nameStartOffset + nameOffset;
                bw.WriteString(file.FilePath.FullName, Encoding.ASCII, false);
                nameOffset = (int)bw.BaseStream.Position - nameStartOffset;

                fileOffset += (int)file.FileSize;
            }

            // Write file data
            var dataOffset = (int)bw.BaseStream.Position;

            foreach (var file in files.Cast <ArchiveFileInfo>())
            {
                file.SaveFileData(bw.BaseStream, null);
            }

            // Write file entries
            bw.BaseStream.Position = fileEntryStartOffset;
            foreach (var fileEntry in fileEntries)
            {
                bw.WriteType(fileEntry);
            }

            // Write header
            bw.BaseStream.Position = 0;
            bw.WriteType(new Lpc2Header
            {
                fileEntryOffset = fileEntryStartOffset,
                nameOffset      = nameStartOffset,
                dataOffset      = dataOffset,

                fileCount = files.Count,

                headerSize = _headerSize,
                fileSize   = (int)bw.BaseStream.Length
            });
        }
Esempio n. 11
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output, _header.byteOrder);

            // Calculate offsets
            var sizeOffset         = HeaderSize;
            var unknownValueOffset = sizeOffset + files.Count * 4;
            var dataOffset         = unknownValueOffset + files.Count * 8;

            // Write files
            var offsets = new List <int>();

            foreach (var file in files.Cast <PackArchiveFileInfo>())
            {
                offsets.Add(dataOffset);

                // Write file name
                output.Position = dataOffset + 8;
                bw.WriteString(file.FilePath.GetName(), Encoding.ASCII, false);

                // Pad to file start
                var alignment = PackSupport.GetAlignment(file.FilePath.GetExtensionWithDot());
                output.Position = dataOffset + 0x28;
                bw.WriteAlignment(alignment);
                file.Entry.fileStart = (short)(output.Position - dataOffset);

                // Write file data
                output.Position = dataOffset + file.Entry.fileStart;
                var writtenSize = file.SaveFileData(output);
                var nextOffset  = output.Position;

                // Write file entry
                file.Entry.fileSize = (uint)writtenSize;
                output.Position     = dataOffset;
                bw.WriteType(file.Entry);

                dataOffset = (int)nextOffset;
            }

            // Write unknown values
            output.Position = unknownValueOffset;
            bw.WriteMultiple(_unknownValues);

            // Write offsets
            output.Position = sizeOffset;
            bw.WriteMultiple(offsets);

            // Write header
            _header.fileCount = (short)files.Count;
            _header.size      = (int)output.Length;

            output.Position = 0;
            bw.WriteType(_header);
        }
Esempio n. 12
0
        public void Write(BinaryWriterX bw)
        {
            var startPosition = bw.BaseStream.Position;

            bw.BaseStream.Position += _headerLength;

            // Write child nodes and data
            if (Data != null)
            {
                Data.Position = 0;
                Data.CopyTo(bw.BaseStream);

                // Update header
                _header.size = (int)(bw.BaseStream.Position - startPosition - 8);

                bw.WriteAlignment(2);
            }
            else
            {
                foreach (var node in Nodes)
                {
                    node.Write(bw);
                }

                // Update header
                _header.size = (int)(bw.BaseStream.Position - startPosition - 8);
            }

            var currentPosition = bw.BaseStream.Position;

            // Write header
            bw.BaseStream.Position = startPosition;
            bw.WriteString(_header.magic, Encoding.ASCII, false, false);
            bw.Write(_header.size);
            if (_headerLength > 8)
            {
                bw.WriteString(_header.description, Encoding.ASCII, false, false);
            }

            bw.BaseStream.Position = currentPosition;
        }
Esempio n. 13
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            var crc32 = Crc32.Default;

            using var bw = new BinaryWriterX(output, true);

            // Calculate offsets
            var entryOffset = HeaderSize;
            var nameOffset  = entryOffset + files.Count * EntrySize;
            var dataOffset  = (nameOffset + 0x7F) & ~0x7F;

            // Write files
            var namePosition = nameOffset;
            var dataPosition = dataOffset;

            var entries = new List <JarcEntry>();

            foreach (var file in files.Cast <JarcArchiveFileInfo>())
            {
                output.Position = dataPosition;
                file.SaveFileData(output);

                entries.Add(new JarcEntry
                {
                    fileOffset = dataPosition,
                    nameOffset = namePosition,
                    fileSize   = (int)file.FileSize,
                    hash       = crc32.ComputeValue(file.FilePath.ToRelative().FullName),
                    unk1       = file.Entry.unk1
                });

                dataPosition += (int)((file.FileSize + 0x7F) & ~0x7F);
                namePosition += Encoding.ASCII.GetByteCount(file.FilePath.ToRelative().FullName) + 1;
            }

            // Write names
            output.Position = nameOffset;
            foreach (var file in files)
            {
                bw.WriteString(file.FilePath.ToRelative().FullName, Encoding.ASCII, false);
            }

            // Write entries
            output.Position = entryOffset;
            bw.WriteMultiple(entries);

            // Write header
            _header.fileCount = files.Count;
            _header.fileSize  = (int)output.Length;

            output.Position = 0;
            bw.WriteType(_header);
        }
Esempio n. 14
0
        private static void WriteFnt(BinaryWriterX bw, int baseOffset, ref int fntOffset, ref int contentOffset, ref int fileId, ref int dirId, int parentDirId, DirectoryEntry entry)
        {
            // Write dir entry
            bw.BaseStream.Position = fntOffset;
            bw.WriteType(new MainFntEntry
            {
                subTableOffset  = contentOffset - baseOffset,
                firstFileId     = (short)fileId,
                parentDirectory = (ushort)(0xF000 + parentDirId)
            });
            fntOffset += 8;

            // Write file names
            bw.BaseStream.Position = contentOffset;
            foreach (var file in entry.Files.Cast <IFileIdArchiveFileInfo>())
            {
                bw.WriteString(file.FilePath.GetName(), Encoding.ASCII, true, false);
                file.FileId = fileId++;
            }
            contentOffset = (int)bw.BaseStream.Position;

            // Write directory entries
            var nextContentOffset = (int)(bw.BaseStream.Position + entry.Directories.Sum(x => x.Name.Length + 3) + 1);
            var currentDirId      = dirId;

            foreach (var dir in entry.Directories)
            {
                bw.BaseStream.Position = contentOffset;

                bw.Write((byte)(dir.Name.Length + 0x80));
                bw.WriteString(dir.Name, Encoding.ASCII, false, false);
                bw.Write((ushort)(0xF000 + ++dirId));

                contentOffset = (int)bw.BaseStream.Position;

                WriteFnt(bw, baseOffset, ref fntOffset, ref nextContentOffset, ref fileId, ref dirId, currentDirId, dir);
            }

            contentOffset = nextContentOffset;
        }
Esempio n. 15
0
        private void WriteTypeString(BinaryWriterX bw, string writeValue, MemberAttributeInfo fieldAttributes, ValueStorage storage)
        {
            var attributeValues = GetLengthAttributeValues(fieldAttributes, storage);

            if (!attributeValues.HasValue)
            {
                return;
            }

            var(length, encoding) = attributeValues.Value;
            if (encoding.GetByteCount(writeValue) != length)
            {
                throw new FieldLengthMismatchException(encoding.GetByteCount(writeValue), length);
            }

            bw.WriteString(writeValue, encoding, false, false);
        }
Esempio n. 16
0
        public async void Save(IFileSystem fileSystem, UPath savePath)
        {
            using var archiveBw = new BinaryWriterX(await fileSystem.OpenFileAsync(savePath, FileMode.Create, FileAccess.ReadWrite));
            using var indexBw   = new BinaryWriterX(await fileSystem.OpenFileAsync("index.bin", FileMode.Create, FileAccess.ReadWrite));

            archiveBw.WriteString("ARC0", Encoding.UTF8, false, false);
            indexBw.WriteString("IDX0", Encoding.UTF8, false, false);

            indexBw.Write(_files.Count);
            archiveBw.Write(new byte[0xC]);

            foreach (var file in _files)
            {
                indexBw.Write((int)archiveBw.BaseStream.Position);
                indexBw.Write((int)file.FileSize);

                file.SaveFileData(archiveBw.BaseStream, null);
            }
        }
Esempio n. 17
0
        public void Save(Stream output, ImageInfo imageInfo)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var nameOffset    = HeaderSize;
            var dataOffset    = (nameOffset + imageInfo.Name.Length + 0x10) & ~0xF; // 0x10 = 0x1 + 0xF
            var paletteOffset = (dataOffset + imageInfo.ImageData.Length + (imageInfo.MipMapData?.Sum(x => x.Length) ?? 0) + 0x3F) & ~0x3F;

            // Write name
            output.Position = nameOffset;
            bw.WriteString(imageInfo.Name, Encoding.ASCII, false);

            // Write image data
            output.Position = dataOffset;
            bw.Write(imageInfo.ImageData);

            // Write mip levels
            foreach (var mipData in imageInfo.MipMapData)
            {
                bw.Write(mipData);
            }

            // Write palette data
            if (imageInfo.HasPaletteInformation)
            {
                output.Position = paletteOffset;
                bw.Write(imageInfo.PaletteData);
            }

            // Update header
            _header.nameOffset    = nameOffset;
            _header.dataOffset    = dataOffset;
            _header.paletteOffset = paletteOffset;
            _header.mipLevels     = (byte)imageInfo.MipMapCount;
            _header.format        = (byte)imageInfo.ImageFormat;
            _header.width         = (short)imageInfo.ImageSize.Width;
            _header.height        = (short)imageInfo.ImageSize.Height;

            // Write header
            output.Position = 0;
            bw.WriteType(_header);
        }
Esempio n. 18
0
        public void Save(Stream output, ImageInfo imageInfo)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var commentOffset = HeaderSize;
            var paletteOffset = commentOffset + 0x1C;
            var dataOffset    = paletteOffset + (imageInfo.HasPaletteInformation ? GetPaletteDataSize((int)_header.paletteFormat, _header.imageFormat) : 0);

            // Write image data
            output.Position = dataOffset;
            output.Write(imageInfo.ImageData);

            if (imageInfo.MipMapCount > 0)
            {
                foreach (var mipData in imageInfo.MipMapData)
                {
                    output.Write(mipData);
                }
            }

            // Write palette data
            if (imageInfo.HasPaletteInformation)
            {
                output.Position = paletteOffset;
                output.Write(imageInfo.PaletteData);
            }

            // Write comment
            output.Position = commentOffset;
            bw.WriteString(_comment, Encoding.ASCII, false);

            // Write header
            _header.imageFormat   = (TMXPixelFormat)imageInfo.ImageFormat;
            _header.paletteFormat = (TMXPixelFormat)(imageInfo.HasPaletteInformation ? imageInfo.PaletteFormat : 0);
            _header.width         = (short)imageInfo.ImageSize.Width;
            _header.height        = (short)imageInfo.ImageSize.Height;
            _header.fileSize      = (int)output.Length;
            _header.mipmapCount   = (byte)imageInfo.MipMapCount;

            output.Position = 0;
            bw.WriteType(_header);
        }
Esempio n. 19
0
        public static void WriteStringTable(Stream input, IList <string> strings)
        {
            using var bw = new BinaryWriterX(input, true);

            var position = input.Position;

            // Write strings
            var stringPosition = (position + 0x20 + strings.Count * 4 + 0xF) & ~0xF;

            input.Position = stringPosition;

            var offsets = new List <int>();

            foreach (var s in strings)
            {
                offsets.Add((int)(input.Position - stringPosition));
                bw.WriteString(s, Encoding.ASCII, false);
            }
            bw.WriteAlignment();

            var endPosition = input.Position;

            // Write offsets
            input.Position = position + 0x20;
            bw.WriteMultiple(offsets);

            // Write header
            input.Position = position + 0x10;
            bw.WriteType(new ApkStringHeader
            {
                sectionSize = (int)(endPosition - position - 0x10),
                stringCount = strings.Count,
                dataOffset  = (int)(stringPosition - position - 0x10)
            });

            // Write section header
            input.Position = position;
            bw.WriteType(new ApkSectionHeader {
                magic = ApkSection.StringTable, sectionSize = (int)(endPosition - position - 0x10)
            });

            input.Position = endPosition;
        }
Esempio n. 20
0
        public override long SaveFileData(Stream output, bool compress, IProgressContext progress = null)
        {
            var position = output.Position;

            var offset = 0;

            if (UsesCompression)
            {
                offset = 0x20;
            }

            output.Position += offset;
            var writtenSize = base.SaveFileData(output, compress, progress);

            // Padding
            while (output.Position % 4 != 0)
            {
                output.WriteByte(0);
            }

            if (!UsesCompression)
            {
                return(writtenSize + offset);
            }

            var bkPos = output.Position;

            using var bw = new BinaryWriterX(output, true);

            output.Position = position;
            bw.WriteString("ACMP", Encoding.ASCII, false, false);
            bw.Write((int)writtenSize);
            bw.Write(0x20);
            bw.Write(0);
            bw.Write((int)FileSize);
            bw.Write(0x01234567);
            bw.Write(0x01234567);
            bw.Write(0x01234567);

            output.Position = bkPos;
            return(writtenSize + offset);
        }
Esempio n. 21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="output"></param>
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output, true))
            {
                // Updates
                Header.Width  = (short)Texture.Width;
                Header.Height = (short)Texture.Height;

                // Header
                bw.WriteType(Header);
                bw.WriteAlignment();
                bw.WriteString(FileName, Encoding.ASCII, false);
                bw.WriteAlignment();

                // Setup
                if (Header.Format == ImageFormat.Palette_8)
                {
                    var settings = new IndexedImageSettings(IndexEncodings[(int)Header.Format], PaletteEncodings[(int)Header.Format], Header.Width, Header.Height)
                    {
                        QuantizationSettings = new QuantizationSettings(new WuColorQuantizer(6, 3), Header.Width, Header.Height)
                        {
                            ColorCount    = 256,
                            ParallelCount = 8
                        }
                    };
                    var data = Kolors.Save(Texture, settings);

                    bw.Write(data.indexData);
                    bw.Write(data.paletteData);
                }
                else
                {
                    var settings = new ImageSettings(Encodings[(int)Header.Format], Header.Width, Header.Height);
                    var data     = Kolors.Save(Texture, settings);

                    bw.Write(data);
                }
            }
        }
Esempio n. 22
0
        public void Save(Stream output, ImageInfo imageInfo)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var entryOffset = HeaderSize;
            var nameOffset  = entryOffset + EntrySize;
            var dataOffset  = (nameOffset + Encoding.ASCII.GetByteCount(imageInfo.Name) + 1 + 0x7F) & ~0x7F;

            // Write image data
            output.Position = dataOffset;
            output.Write(imageInfo.ImageData);

            // Write name
            output.Position = nameOffset;
            bw.WriteString(imageInfo.Name, Encoding.ASCII, false);

            // Write entry
            output.Position = entryOffset;
            bw.WriteType(new StexEntry
            {
                offset = dataOffset,
                unk1   = (imageInfo as StexImageInfo).Entry.unk1
            });

            // Write header
            var header = new StexHeader
            {
                width       = imageInfo.ImageSize.Width,
                height      = imageInfo.ImageSize.Height,
                dataSize    = (int)(output.Length - dataOffset),
                dataType    = (uint)((imageInfo.ImageFormat >> 16) & 0xFFFF),
                imageFormat = (uint)(imageInfo.ImageFormat & 0xFFFF)
            };

            output.Position = 0;
            bw.WriteType(header);
        }
Esempio n. 23
0
        public void Save(Stream output, IList <ArchiveFileInfo> files)
        {
            // Since this is a pointerless archive, we need to keep the original offsets in tact as much as possible

            using var bw = new BinaryWriterX(output);

            for (var i = 0; i < files.Count; i++)
            {
                var offset = output.Position;

                bw.WriteString("3DS-LZ\r\n", Encoding.ASCII, false, false);

                var writtenSize = files[i].SaveFileData(output);
                var paddedSize  = (writtenSize + 0x3F) & ~0x3F;
                var finalSize   = paddedSize - 8;
                if (i + 1 < files.Count && finalSize > _sizes[i])
                {
                    throw new InvalidOperationException("Plugin can not save larger files than their original.");
                }

                output.Position = offset + _sizes[i] + 8;
            }
        }
Esempio n. 24
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output);

            var fileOffsetsPosition  = _headerSize;
            var fileHashesPosition   = fileOffsetsPosition + files.Count * (_offsetSize + _lengthSize);
            var unkIdsPosition       = fileHashesPosition + files.Count * _hashSize;
            var stringOffsetPosition = (unkIdsPosition + _unkIdsSize + 3) & ~3;
            var stringPosition       = (stringOffsetPosition + _stringOffsetSize + 3) & ~3;

            // Write strings
            var crc32 = Crc32.Default;

            bw.BaseStream.Position = stringOffsetPosition;
            var fileHashes           = new List <uint>();
            var relativeStringOffset = stringPosition - stringOffsetPosition;

            for (var i = 0; i < files.Count; i++)
            {
                // Write string offset
                bw.BaseStream.Position = stringOffsetPosition + i * _stringOffsetSize;
                bw.Write((short)relativeStringOffset);

                // Add hash
                fileHashes.Add(crc32.ComputeValue(files[i].FilePath.ToRelative().FullName));

                // Write string
                bw.BaseStream.Position = stringOffsetPosition + relativeStringOffset;
                bw.WriteString(files[i].FilePath.ToRelative().FullName, Encoding.ASCII, false);

                relativeStringOffset = (int)(bw.BaseStream.Position - stringOffsetPosition);
            }

            var fileDataPosition = (bw.BaseStream.Position + 3) & ~3;

            // Write file data
            bw.BaseStream.Position = fileDataPosition;
            var fileOffset = new List <int>();
            var fileSizes  = new List <int>();

            foreach (var file in files.Cast <ArchiveFileInfo>())
            {
                fileOffset.Add((int)((bw.BaseStream.Position - _headerSize) >> 2));

                var writtenSize = file.SaveFileData(bw.BaseStream, null);
                bw.WriteAlignment(0x20);

                fileSizes.Add((int)writtenSize);
            }

            // Write file information
            bw.BaseStream.Position = fileOffsetsPosition;
            bw.WriteMultiple(fileOffset);
            bw.WriteMultiple(fileSizes);
            bw.WriteMultiple(fileHashes);

            // Write unknown information
            bw.WriteMultiple(_unkIds);

            // Write header
            bw.BaseStream.Position = 0;

            _header.fileCount        = files.Count;
            _header.contentSize      = (int)(bw.BaseStream.Length - _headerSize);
            _header.table2EntryCount = (short)fileHashes.Count;

            bw.WriteType(_header);
        }
Esempio n. 25
0
        private void BuildTables(IEnumerable <XfsaArchiveFileInfo <Xfsa1FileEntry> > files,
                                 out IList <Xfsa1DirectoryEntry> directoryEntries, out IList <uint> directoryHashes,
                                 out IList <XfsaArchiveFileInfo <Xfsa1FileEntry> > fileEntries, out Stream nameStream)
        {
            var groupedFiles = files.OrderBy(x => x.FilePath.GetDirectory())
                               .GroupBy(x => x.FilePath.GetDirectory())
                               .ToArray();

            var crc32 = Crc32.Default;
            var sjis  = Encoding.GetEncoding("SJIS");

            nameStream       = new MemoryStream();
            using var nameBw = new BinaryWriterX(nameStream, true);

            var fileInfos = new List <XfsaArchiveFileInfo <Xfsa1FileEntry> >();

            directoryEntries = new List <Xfsa1DirectoryEntry>();
            directoryHashes  = new List <uint>();
            var fileOffset = 0;

            foreach (var fileGroup in groupedFiles)
            {
                var fileIndex        = fileInfos.Count;
                var fileGroupEntries = fileGroup.ToArray();

                // Add directory entry first
                var directoryNameOffset = (int)nameBw.BaseStream.Position;
                var directoryName       = fileGroup.Key.ToRelative().FullName;
                if (!string.IsNullOrEmpty(directoryName))
                {
                    directoryName += "/";
                }
                nameBw.WriteString(directoryName, sjis, false);

                var hash = BinaryPrimitives.ReadUInt32BigEndian(crc32.Compute(sjis.GetBytes(directoryName.ToLower())));
                var newDirectoryEntry = new Xfsa1DirectoryEntry
                {
                    crc32 = string.IsNullOrEmpty(fileGroup.Key.ToRelative().FullName) ? 0xFFFFFFFF : hash,

                    DirectoryCount = (short)groupedFiles.Count(gf => fileGroup.Key != gf.Key && gf.Key.IsInDirectory(fileGroup.Key, false)),

                    FileCount      = (short)fileGroupEntries.Length,
                    firstFileIndex = (ushort)fileIndex,

                    DirectoryNameOffset = directoryNameOffset,
                    FileNameStartOffset = (int)nameBw.BaseStream.Position
                };
                if (newDirectoryEntry.crc32 != 0xFFFFFFFF)
                {
                    directoryHashes.Add(newDirectoryEntry.crc32);
                }
                directoryEntries.Add(newDirectoryEntry);

                // Write file names in alphabetic order
                foreach (var fileEntry in fileGroupEntries)
                {
                    fileEntry.Entry.NameOffset = (int)(nameBw.BaseStream.Position - newDirectoryEntry.FileNameStartOffset);
                    fileEntry.Entry.crc32      = BinaryPrimitives.ReadUInt32BigEndian(crc32.Compute(sjis.GetBytes(fileEntry.FilePath.GetName().ToLower())));
                    fileEntry.Entry.FileOffset = fileOffset;
                    fileEntry.Entry.FileSize   = (int)fileEntry.FileSize;

                    fileOffset = (int)((fileOffset + fileEntry.FileSize + 15) & ~15);

                    nameBw.WriteString(fileEntry.FilePath.GetName(), sjis, false);
                }

                // Add file entries in order of ascending hash
                fileInfos.AddRange(fileGroupEntries.OrderBy(x => x.Entry.crc32));
            }

            fileEntries = fileInfos;

            // Order directory entries by hash and set directoryIndex accordingly
            var directoryIndex = 0;

            directoryEntries = directoryEntries.OrderBy(x => x.crc32).Select(x =>
            {
                x.firstDirectoryIndex = (ushort)directoryIndex;
                directoryIndex       += x.DirectoryCount;
                return(x);
            }).ToList();
        }
Esempio n. 26
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            var crc16 = Crc16.X25;

            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var fileInfoOffset = HeaderSize;
            var nameOffset     = fileInfoOffset + files.Count * EntrySize;
            var dataOffset     = (nameOffset + files.Sum(x => Encoding.ASCII.GetByteCount(x.FilePath.GetName()) + 1) + 3) & ~3;

            // Write files
            var fileInfos = new List <GfspFileInfo>();

            var fileOffset   = 0;
            var stringOffset = 0;

            foreach (var file in files.Cast <ArchiveFileInfo>())
            {
                output.Position = dataOffset + fileOffset;

                var writtenSize = file.SaveFileData(output);
                bw.WriteAlignment(4);

                fileInfos.Add(new GfspFileInfo
                {
                    hash       = crc16.ComputeValue(file.FilePath.GetName()),
                    FileOffset = fileOffset,
                    NameOffset = stringOffset,
                    size       = (ushort)writtenSize
                });

                fileOffset   += (int)file.FileSize;
                stringOffset += Encoding.ASCII.GetByteCount(file.FilePath.GetName()) + 1;
            }

            // Write names
            output.Position = nameOffset;
            foreach (var name in files.Select(x => x.FilePath.GetName()))
            {
                bw.WriteString(name, Encoding.ASCII, false);
            }

            // Write entries
            output.Position = fileInfoOffset;
            bw.WriteMultiple(fileInfos);

            // Write header
            var header = new GfspHeader
            {
                FileCount = (ushort)files.Count,

                FileInfoOffset      = (ushort)fileInfoOffset,
                FilenameTableOffset = (ushort)nameOffset,
                DataOffset          = (ushort)dataOffset,

                FileInfoSize      = (ushort)(nameOffset - fileInfoOffset),
                FilenameTableSize = (ushort)(dataOffset - nameOffset),
                DataSize          = (uint)(output.Length - dataOffset)
            };

            output.Position = 0;
            bw.WriteType(header);
        }
Esempio n. 27
0
        public void Save(StreamInfo output)
        {
            using (var bw = new BinaryWriterX(output.FileData, ByteOrder, BitOrder))
            {
                // Header
                Header.Magic          = ByteOrder == ByteOrder.LittleEndian ? "GFD\0" : "\0DFG";
                Header.CharacterCount = Characters.Count;
                Header.FontTexCount   = Textures.Count;
                bw.WriteType(Header);
                foreach (var f in HeaderF)
                {
                    bw.Write(f);
                }

                // Name
                bw.Write(Name.Length);
                bw.WriteString(Name, Encoding.ASCII, false, false);
                bw.Write((byte)0);

                // Characters
                bw.WriteMultiple(Characters.Select(ci => new CharacterInfo
                {
                    Character = ci.Character,

                    Block1 = new Block1
                    {
                        GlyphY       = ci.GlyphY,
                        GlyphX       = ci.GlyphX,
                        TextureIndex = ci.TextureID
                    },

                    Block2 = new Block2
                    {
                        GlyphHeight = ci.GlyphHeight,
                        GlyphWidth  = ci.GlyphWidth,
                        XAdjust     = ci.XAdjust
                    },

                    Block3 = new Block3
                    {
                        IsSpace        = ci.IsSpace ? 1 : 0,
                        Superscript    = ci.Superscript ? 1 : 0,
                        CharacterWidth = ci.CharacterWidth
                    }
                }));

                // Textures
                for (var i = 0; i < Header.FontTexCount; i++)
                {
                    IMtFrameworkTextureAdapter texAdapter = _texAdapters.Where(adapter => adapter is IIdentifyFiles).
                                                            FirstOrDefault(adapter => ((IIdentifyFiles)adapter).
                                                                           Identify(new StreamInfo(File.OpenRead(GetTexName(_sourceFile, i)), GetTexName(_sourceFile, i)), null));
                    if (texAdapter == null)
                    {
                        continue;
                    }
                    ((ILoadFiles)texAdapter).Load(new StreamInfo(File.OpenRead(GetTexName(_sourceFile, i)), GetTexName(_sourceFile, i)), null);
                    ((IImageAdapter)texAdapter).BitmapInfos[0].Image = Textures[i];
                    ((ISaveFiles)texAdapter).Save(new StreamInfo(File.OpenRead(GetTexName(_sourceFile, i)), GetTexName(_sourceFile, i)), null);
                }

                _sourceFile = output.FileName;
            }
        }
Esempio n. 28
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var fatOffset = NarcHeaderSize;
            var fntOffset = fatOffset + FatHeaderSize + files.Count * FatEntrySize;

            // Write FNT
            int fntSize;

            if (!_hasNames)
            {
                output.Position = fntOffset + 8;
                bw.Write(4);
                bw.Write(0x10000);
                fntSize = 0x10;
            }
            else
            {
                NdsSupport.WriteFnt(bw, fntOffset + 8, files);
                fntSize = (int)(bw.BaseStream.Position - fntOffset);
            }

            output.Position = fntOffset;
            bw.WriteType(new NarcFntHeader
            {
                chunkSize = fntSize
            });

            // Write GMIF
            var fatEntries = new List <FatEntry>();

            var gmifOffset = fntOffset + fntSize;

            output.Position = gmifOffset + 8;
            foreach (var file in files.Cast <FileIdArchiveFileInfo>().OrderBy(x => x.FileId))
            {
                var filePosition = output.Position;
                var writtenSize  = file.SaveFileData(output);

                fatEntries.Add(new FatEntry
                {
                    offset    = (int)filePosition - gmifOffset - 8,
                    endOffset = (int)(filePosition - gmifOffset - 8 + writtenSize)
                });
            }

            output.Position = gmifOffset;
            bw.WriteString("GMIF", Encoding.ASCII, false, false);
            bw.Write((int)(output.Length - gmifOffset));

            // Write FAT
            output.Position = fatOffset;
            bw.WriteType(new NarcFatHeader
            {
                chunkSize = FatHeaderSize + files.Count * FatEntrySize,
                fileCount = (short)files.Count
            });
            bw.WriteMultiple(fatEntries);

            // Write header
            output.Position = 0;
            bw.WriteType(new NarcHeader
            {
                fileSize = (int)output.Length
            });
        }
Esempio n. 29
0
        public void Save(Stream output, IList <IArchiveFileInfo> files, bool isCompressed)
        {
            var simpleHash = new SimpleHash(_sfatHeader.hashMultiplier);

            using var bw = new BinaryWriterX(output, true, _byteOrder);

            var sortedFiles = files.Cast <SarcArchiveFileInfo>().OrderBy(x => _sfntHeader == null ? x.Entry.nameHash : simpleHash.ComputeValue(x.FilePath.ToRelative().FullName)).ToArray();

            // Calculate offsets
            var sfatOffset = HeaderSize;
            var sfntOffset = sfatOffset + SfatHeaderSize + files.Count * SfatEntrySize;
            var dataOffset = _sfntHeader == null
                ? sfntOffset + SfntHeaderSize
                : sfntOffset + SfntHeaderSize + files.Sum(x => (x.FilePath.ToRelative().FullName.Length + 4) & ~3);

            var alignment         = sortedFiles.Max(x => SarcSupport.DetermineAlignment(x, _byteOrder, isCompressed));
            var alignedDataOffset = (dataOffset + alignment - 1) & ~(alignment - 1);

            // Write files
            var entries = new List <SfatEntry>();
            var strings = new List <string>();

            var stringPosition = 0;
            var dataPosition   = alignedDataOffset;

            foreach (var file in sortedFiles)
            {
                // Write file data
                alignment = SarcSupport.DetermineAlignment(file, _byteOrder, isCompressed);
                var alignedDataPosition = (dataPosition + alignment - 1) & ~(alignment - 1);

                output.Position = alignedDataPosition;
                var writtenSize = file.SaveFileData(output);

                // Add entry
                entries.Add(new SfatEntry
                {
                    startOffset = alignedDataPosition - alignedDataOffset,
                    endOffset   = (int)(alignedDataPosition + writtenSize - alignedDataOffset),
                    Flags       = (short)(_sfntHeader == null ? 0 : 0x100),
                    FntOffset   = (short)(_sfntHeader == null ? 0 : stringPosition),
                    nameHash    = _sfntHeader == null ? file.Entry.nameHash : simpleHash.ComputeValue(file.FilePath.ToRelative().FullName)
                });

                // Add string
                strings.Add(file.FilePath.ToRelative().FullName);

                dataPosition    = (int)(alignedDataPosition + writtenSize);
                stringPosition += (file.FilePath.ToRelative().FullName.Length + 4) & ~3;
            }

            // Write SFNT
            output.Position = sfntOffset;
            bw.WriteType(new SfntHeader());

            if (_sfntHeader != null)
            {
                foreach (var s in strings)
                {
                    bw.WriteString(s, Encoding.ASCII, false);
                    bw.WriteAlignment(4);
                }
            }

            // Write SFAT
            output.Position = sfatOffset;
            bw.WriteType(new SfatHeader {
                entryCount = (short)files.Count, hashMultiplier = _sfatHeader.hashMultiplier
            });
            bw.WriteMultiple(entries);

            // Write header
            output.Position = 0;
            bw.WriteType(new SarcHeader {
                byteOrder = _byteOrder, dataOffset = alignedDataOffset, fileSize = (int)output.Length, unk1 = _header.unk1
            });
        }
Esempio n. 30
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var nameOffset = 8;

            // Build string tree
            var fileNames = files.Select(x => x.FilePath.ToRelative().FullName).ToArray();

            var rootNode = new StringNode();

            rootNode.AddRange(fileNames);

            // Assign offsets to nodes
            var nodeOffsetMap   = new Dictionary <StringNode, int>();
            var nameTableOffset = AssignOffsets(rootNode, nameOffset, nodeOffsetMap);

            nameTableOffset = (nameTableOffset + 1) & ~1;

            // Write node tree
            output.Position = nameTableOffset;
            var fileId = 0;

            WriteNodes(rootNode, bw, nodeOffsetMap, ref fileId);

            var entryOffset = bw.BaseStream.Length;
            var fileOffset  = entryOffset + files.Count * EntrySize;

            // Write files
            var entries = new List <PakEntry>();

            var filePosition = fileOffset;

            foreach (var file in files.Cast <ArchiveFileInfo>())
            {
                output.Position = filePosition;
                var writtenSize = file.SaveFileData(output);

                entries.Add(new PakEntry
                {
                    offset = (int)filePosition,
                    size   = (int)writtenSize
                });

                filePosition += writtenSize;
            }

            // Write entries
            output.Position = entryOffset;
            bw.WriteMultiple(entries);

            // Write strings
            foreach (var pair in nodeOffsetMap)
            {
                output.Position = pair.Value;
                bw.WriteString(pair.Key.Text, Encoding.ASCII, false);
            }

            // Write header
            output.Position = 0;
            bw.WriteType(new PakHeader
            {
                fileCount   = (short)files.Count,
                entryOffset = (int)entryOffset,
                nameTable   = (short)nameTableOffset
            });
        }