예제 #1
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            var darcTreeBuilder = new U8TreeBuilder(Encoding.ASCII);

            darcTreeBuilder.Build(files.Select(x => ("/." + x.FilePath.FullName, x)).ToArray());

            var entries    = darcTreeBuilder.Entries;
            var nameStream = darcTreeBuilder.NameStream;

            var namePosition = _headerSize + entries.Count * _entrySize;
            var dataOffset   = (namePosition + (int)nameStream.Length + 0x1F) & ~0x1F;

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

            // Write names
            bw.BaseStream.Position = namePosition;
            nameStream.Position    = 0;
            nameStream.CopyTo(bw.BaseStream);
            bw.WriteAlignment(0x20);

            // Write files
            foreach (var(u8Entry, afi) in entries.Where(x => x.Item2 != null))
            {
                bw.WriteAlignment(0x20);
                var fileOffset = (int)bw.BaseStream.Position;

                var writtenSize = (afi as ArchiveFileInfo).SaveFileData(bw.BaseStream);

                u8Entry.offset = fileOffset;
                u8Entry.size   = (int)writtenSize;
            }

            // Write entries
            bw.BaseStream.Position = _headerSize;
            bw.WriteMultiple(entries.Select(x => x.Item1));

            // Write header
            bw.BaseStream.Position = 0;
            bw.WriteType(new U8Header
            {
                entryDataOffset = _headerSize,
                entryDataSize   = entries.Count * _entrySize + (int)nameStream.Length,
                dataOffset      = dataOffset
            });
            bw.WritePadding(0x10, 0xCC);
        }
예제 #2
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output, ByteOrder.BigEndian);

            // Get system files
            var bi2File       = files.First(x => x.FilePath.ToRelative() == "sys/bi2.bin");
            var appLoaderFile = files.First(x => x.FilePath.ToRelative() == "sys/appldr.bin");
            var execFile      = files.First(x => x.FilePath.ToRelative() == "sys/main.dol");

            // Calculate offsets
            var bi2Offset       = 0x440;
            var appLoaderOffset = bi2Offset + bi2File.FileSize;
            var execOffset      = appLoaderOffset + ((appLoaderFile.FileSize + 0x1F) & ~0x1F) + 0x20;
            var fstOffset       = (execOffset + execFile.FileSize + 0x1F) & ~0x1F;

            // Build U8 entry list
            var treeBuilder = new U8TreeBuilder(Encoding.ASCII);

            treeBuilder.Build(files.Where(x => !x.FilePath.IsInDirectory("/sys", false)).Select(x => (x.FilePath.FullName, x)).ToArray());

            var nameStream = treeBuilder.NameStream;
            var entries    = treeBuilder.Entries;

            nameStream.Position = 0;

            // Write names
            var nameOffset = output.Position = fstOffset + treeBuilder.Entries.Count * Tools.MeasureType(typeof(U8Entry));

            nameStream.CopyTo(output);
            bw.WriteAlignment(0x20);

            // Write files
            foreach (var(u8Entry, afi) in entries.Where(x => x.Item2 != null))
            {
                bw.WriteAlignment(0x20);
                var fileOffset = (int)bw.BaseStream.Position;

                var writtenSize = (afi as ArchiveFileInfo).SaveFileData(bw.BaseStream);

                u8Entry.offset = fileOffset;
                u8Entry.size   = (int)writtenSize;
            }

            // Write FST
            output.Position = fstOffset;
            bw.WriteMultiple(entries.Select(x => x.Item1));

            // Write system files
            output.Position = bi2Offset;
            (bi2File as ArchiveFileInfo).SaveFileData(output);

            output.Position = appLoaderOffset;
            (appLoaderFile as ArchiveFileInfo).SaveFileData(output);

            output.Position = execOffset;
            (execFile as ArchiveFileInfo).SaveFileData(output);

            // Write header
            _header.execOffset = (int)execOffset;
            _header.fstOffset  = (int)fstOffset;
            _header.fstSize    = (int)(nameStream.Length + (nameOffset - fstOffset));
            _header.fstMaxSize = _header.fstSize;

            output.Position = 0;
            bw.WriteType(_header);
        }