Beispiel #1
0
        public void Save(Stream output, bool leaveOpen = false)
        {
            using (var bw = new BinaryWriterX(output, leaveOpen))
            {
                //SARCHeader
                var header = new SARCHeader {
                    dataOffset = Files.Aggregate(40 + Files.Sum(afi => usesSFNT ? afi.FileName.Length / 4 * 4 + 20 : 16), (n, afi) => Pad(n, afi.FileName))
                };
                bw.WriteStruct(header); // filesize is added later

                //SFATHeader
                bw.WriteStruct(new SFATHeader {
                    nodeCount = (short)Files.Count
                });

                //SFAT List + nameList
                int nameOffset = 0;
                int dataOffset = 0;
                foreach (var afi in Files)
                {
                    dataOffset = Pad(dataOffset, afi.FileName);
                    var fileLen   = (int)afi.FileData.Length;
                    var sfatEntry = new SFATEntry
                    {
                        nameHash      = usesSFNT ? SimpleHash.Create(afi.FileName, 0x65) : Convert.ToUInt32(afi.FileName.Substring(2, 8), 16),
                        SFNTOffset    = (short)(usesSFNT ? nameOffset : 0),
                        filenameFlags = (short)(usesSFNT ? 0x100 : 0),
                        dataStart     = dataOffset,
                        dataEnd       = dataOffset + fileLen
                    };
                    bw.WriteStruct(sfatEntry);
                    nameOffset += afi.FileName.Length / 4 + 1;
                    dataOffset  = sfatEntry.dataEnd;
                }

                bw.WriteStruct(new SFNTHeader());
                if (usesSFNT)
                {
                    foreach (var afi in Files)
                    {
                        bw.WriteASCII(afi.FileName.PadRight(afi.FileName.Length / 4 * 4 + 4, '\0'));
                    }
                }

                bw.WriteAlignment(header.dataOffset);
                foreach (var afi in Files)
                {
                    bw.Write(new byte[Pad((int)bw.BaseStream.Length, afi.FileName) - (int)bw.BaseStream.Length]); // padding
                    afi.FileData.CopyTo(bw.BaseStream);
                }

                bw.BaseStream.Position = 0;
                header.fileSize        = (int)bw.BaseStream.Length;
                bw.WriteStruct(header);
            }
        }
        public SARC(byte[] Data)
        {
            EndianBinaryReaderEx er = new EndianBinaryReaderEx(new MemoryStream(Data), Endianness.LittleEndian);

            try
            {
                Header = new SARCHeader(er);
                SFat   = new SFAT(er);
                SFnt   = new SFNT(er);
                er.BaseStream.Position = Header.FileDataOffset;
                this.Data = er.ReadBytes((int)(Header.FileSize - Header.FileDataOffset));
            }
            finally
            {
                er.Close();
            }
        }
Beispiel #3
0
        public SARC(Stream inputStream)
        {
            EndianBinaryReader er = new EndianBinaryReader(inputStream, Endian.Big);

            try
            {
                Header     = new SARCHeader(er);
                SfatHeader = new SFATHeader(er);

                SfatNodes = new SFATNode[SfatHeader.NodeCount];
                for (int i = 0; i < SfatHeader.NodeCount; i++)
                {
                    SfatNodes[i] = new SFATNode(er);
                }

                // Just skip the SFNT_HEADER because it's useless for now ?
                er.ReadBytes(8);

                SfatStringTable = new string[SfatHeader.NodeCount];
                for (int i = 0; i < SfatHeader.NodeCount; i++)
                {
                    // These are padded strings, so skip the null bytes padding them
                    while (er.PeekReadByte() == 0)
                    {
                        er.ReadByte();
                    }

                    SfatStringTable[i]       = Encoding.UTF8.GetString(er.ReadBytesUntil(0));
                    SfatNodes[i].copied_name = SfatStringTable[i];
                }

                // TODO: Maybe we have to pad here too?
                SfatDataTable = new byte[SfatHeader.NodeCount][];
                for (int i = 0; i < SfatHeader.NodeCount; i++)
                {
                    uint dataLength = SfatNodes[i].NodeDataEndOffset - SfatNodes[i].NodeDataBeginOffset;

                    SfatDataTable[i]         = er.ReadBytesAt(Header.DataOffset + SfatNodes[i].NodeDataBeginOffset, (int)dataLength);
                    SfatNodes[i].copied_data = SfatDataTable[i];
                }
            }
            finally
            {
                er.Close();
            }
        }
        public void FromFileSystem(SFSDirectory Root)
        {
            Header         = new SARCHeader();
            SFat           = new SFAT();
            SFat.NrEntries = (ushort)Root.Files.Count;
            uint DataStart = 0;

            foreach (var v in Root.Files)
            {
                while ((DataStart % 128) != 0)
                {
                    DataStart++;
                }
                uint hash;
                if (v.FileName == string.Format("0x{0:X8}", v.FileID))
                {
                    hash = (uint)v.FileID;
                }
                else
                {
                    hash = GetHashFromName(v.FileName);
                }
                SFat.Entries.Add(new SFAT.SFATEntry()
                {
                    FileDataStart = DataStart, FileDataEnd = (uint)(DataStart + v.Data.Length), FileNameHash = hash, FileNameOffset = 0
                });
                DataStart += (uint)v.Data.Length;
            }
            Data = new byte[DataStart];
            int i = 0;

            foreach (var v in Root.Files)
            {
                Array.Copy(v.Data, 0, Data, SFat.Entries[i].FileDataStart, v.Data.Length);
                i++;
            }
            SFnt            = new SFNT();
            Header.FileSize = (uint)(0x14 + 0xC + SFat.NrEntries * 0x10 + 0x8);
            while ((Header.FileSize % 128) != 0)
            {
                Header.FileSize++;
            }
            Header.FileDataOffset = Header.FileSize;
            Header.FileSize      += (uint)Data.Length;
        }
        public void FromFileSystem(SFSDirectory Root)
        {
            Header         = new SARCHeader();
            SFat           = new SFAT();
            SFat.NrEntries = (ushort)Root.Files.Count;
            uint DataStart = 0;

            Root.Files.Sort(delegate(SFSFile a, SFSFile b) {
                uint hasha = (uint)a.FileID;
                uint hashb = (uint)b.FileID;
                return(hasha.CompareTo(hashb));
            });
            foreach (var v in Root.Files)
            {
                while ((DataStart % 128) != 0)
                {
                    DataStart++;
                }
                uint hash = (uint)v.FileID;
                SFat.Entries.Add(new SFAT.SFATEntry()
                {
                    FileDataStart = DataStart, FileDataEnd = (uint)(DataStart + v.Data.Length), FileNameHash = hash, FileNameOffset = 0
                });
                DataStart += (uint)v.Data.Length;
            }
            Data = new byte[DataStart];
            int i = 0;

            foreach (var v in Root.Files)
            {
                Array.Copy(v.Data, 0, Data, SFat.Entries[i].FileDataStart, v.Data.Length);
                i++;
            }
            SFnt            = new SFNT();
            Header.FileSize = (uint)(0x14 + 0xC + SFat.NrEntries * 0x10 + 0x8);
            while ((Header.FileSize % 128) != 0)
            {
                Header.FileSize++;
            }
            Header.FileDataOffset = Header.FileSize;
            Header.FileSize      += (uint)Data.Length;
        }