예제 #1
0
        public void Save(Stream output, bool leaveOpen = false)
        {
            using (var bw = new BinaryWriterX(output, leaveOpen, byteOrder))
            {
                //Header.dataOffset = Files.Aggregate(
                //    0x14 + 0xC + 0x8 + Files.Sum(afi => usesSFNT ? ((afi.FileName.Length + 4) & ~3) + 0x10 : 0x10),
                //    (n, file) => Support.Pad(n, file.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU));

                // SFAT Header
                bw.BaseStream.Position = 0x14;
                bw.WriteStruct(new SFATHeader
                {
                    hashMultiplier = (int)hashMultiplier,
                    nodeCount      = (short)Files.Count
                });

                // SFAT List + nameList
                var nameOffset = 0;
                var dataOffset = 0;
                var sfatEntry  = new SFATEntry();
                foreach (var afi in Files)
                {
                    dataOffset = Support.Pad(dataOffset, afi.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU);

                    // BXLIM Alignment Reading
                    if (afi.FileName.EndsWith("lim"))
                    {
                        using (var br = new BinaryReaderX(afi.FileData, true, byteOrder))
                        {
                            br.BaseStream.Position = br.BaseStream.Length - 0x28;
                            var type      = br.PeekString();
                            var alignment = 0;
                            if (type == "FLIM")
                            {
                                br.BaseStream.Position = br.BaseStream.Length - 0x8;
                                alignment = br.ReadInt16();
                            }
                            else if (type == "CLIM")
                            {
                                br.BaseStream.Position = br.BaseStream.Length - 0x6;
                                alignment = br.ReadInt16();
                            }
                            dataOffset = (sfatEntry.dataEnd + alignment - 1) & -alignment;
                        }
                    }

                    var fileLen = (int)afi.FileData.Length;

                    sfatEntry = new SFATEntry
                    {
                        nameHash       = usesSFNT ? SimpleHash.Create(afi.FileName, hashMultiplier) : Convert.ToUInt32(afi.FileName.Substring(2, 8), 16),
                        SFNTOffsetFlag = (uint)(((usesSFNT ? 0x100 : 0) << 16) | (usesSFNT ? nameOffset / 4 : 0)),
                        dataStart      = dataOffset,
                        dataEnd        = dataOffset + fileLen
                    };
                    bw.WriteStruct(sfatEntry);

                    nameOffset = (nameOffset + afi.FileName.Length + 4) & ~3;
                    dataOffset = sfatEntry.dataEnd;
                }

                // SFNT
                bw.WriteStruct(SFNTHeader);
                if (usesSFNT)
                {
                    foreach (var afi in Files)
                    {
                        bw.WriteASCII(afi.FileName + "\0");
                        bw.BaseStream.Position = (bw.BaseStream.Position + 3) & ~3;
                    }
                }

                // Files
                bw.WriteAlignment(Header.dataOffset);
                foreach (var afi in Files)
                {
                    var alignment = Support.Pad((int)bw.BaseStream.Length, afi.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU);

                    // BXLIM Alignment Reading
                    if (afi.FileName.EndsWith("lim"))
                    {
                        using (var br = new BinaryReaderX(afi.FileData, true, byteOrder))
                        {
                            br.BaseStream.Position = br.BaseStream.Length - 0x28;
                            var type = br.PeekString();
                            if (type == "FLIM")
                            {
                                br.BaseStream.Position = br.BaseStream.Length - 0x8;
                                alignment = br.ReadInt16();
                            }
                            else if (type == "CLIM")
                            {
                                br.BaseStream.Position = br.BaseStream.Length - 0x6;
                                alignment = br.ReadInt16();
                            }
                        }
                    }

                    bw.WriteAlignment(alignment);
                    afi.FileData.CopyTo(bw.BaseStream);
                }

                // Header
                bw.BaseStream.Position = 0;
                Header.fileSize        = (int)bw.BaseStream.Length;
                bw.WriteStruct(Header);
            }
        }
예제 #2
0
파일: SARC.cs 프로젝트: shenhaiyu/Kuriimu
        public void Save(Stream output, bool leaveOpen = false)
        {
            using (var bw = new BinaryWriterX(output, leaveOpen, byteOrder))
            {
                //Create SARCHeader
                var header = new SARCHeader
                {
                    byteOrder  = byteOrder,
                    dataOffset = Files.Aggregate(
                        0x14 + 0xc + 0x8 + Files.Sum(afi => usesSFNT ? ((afi.FileName.Length + 4) & ~3) + 0x10 : 0x10),
                        (n, file) => Support.Pad(n, file.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU))
                };

                //SFATHeader
                bw.BaseStream.Position = 0x14;
                bw.WriteStruct(new SFATHeader
                {
                    hashMultiplier = (int)hashMultiplier,
                    nodeCount      = (short)Files.Count
                });

                //SFAT List + nameList
                int nameOffset = 0;
                int dataOffset = 0;
                foreach (var afi in Files)
                {
                    dataOffset = Support.Pad(dataOffset, afi.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU);
                    var fileLen = (int)afi.FileData.Length;

                    var sfatEntry = new SFATEntry
                    {
                        nameHash       = usesSFNT ? SimpleHash.Create(afi.FileName, hashMultiplier) : Convert.ToUInt32(afi.FileName.Substring(2, 8), 16),
                        SFNTOffsetFlag = (uint)(((usesSFNT ? 0x100 : 0) << 16) | (usesSFNT ? nameOffset / 4 : 0)),
                        dataStart      = dataOffset,
                        dataEnd        = dataOffset + fileLen
                    };
                    bw.WriteStruct(sfatEntry);
                    nameOffset = (nameOffset + afi.FileName.Length + 4) & ~3;
                    dataOffset = sfatEntry.dataEnd;
                }

                //SFNT
                bw.WriteStruct(new SFNTHeader());
                if (usesSFNT)
                {
                    foreach (var afi in Files)
                    {
                        bw.WriteASCII(afi.FileName + "\0");
                        bw.BaseStream.Position = (bw.BaseStream.Position + 3) & ~3;
                    }
                }

                //FileData
                bw.WriteAlignment(header.dataOffset);
                foreach (var afi in Files)
                {
                    bw.WriteAlignment(Support.Pad((int)bw.BaseStream.Length, afi.FileName, (byteOrder == ByteOrder.LittleEndian) ? System.CTR : System.WiiU));    //(unusual) padding scheme through filenames
                    afi.FileData.CopyTo(bw.BaseStream);
                }

                bw.BaseStream.Position = 0;
                header.fileSize        = (int)bw.BaseStream.Length;
                bw.WriteStruct(header);
            }
        }