Exemple #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);
            }
        }
Exemple #2
0
        public Archive(Stream stream)
        {
            byte[] header = new byte[4];
            stream.Read(header, 0, 4);
            stream.Seek(-4, SeekOrigin.Current);

            if (header[0] == 'Y')
            {
                archiveFileStream = new Yaz0Stream(stream);
            }
            else
            {
                archiveFileStream = stream;
            }

            using (EndianBinaryReader er = new EndianBinaryReader(archiveFileStream, Encoding.ASCII, true, Endian.Big))
            {
                archiveHeader = new ArchiveHeader(er);
                sfatHeader    = new SFATHeader(er);

                sfatEntries = new SFATEntry[sfatHeader.NodeCount];
                for (int i = 0; i < sfatHeader.NodeCount; i++)
                {
                    sfatEntries[i] = new SFATEntry(er);
                }

                er.Skip(8); // SFNT, 0x00, 0x08, 0x00, 0x00

                sfatStringTable = new string[sfatHeader.NodeCount];
                for (int i = 0; i < sfatHeader.NodeCount; i++)
                {
                    // These strings are aligned to 4 bytes.
                    //while (er.PeekReadByte() == 0)
                    //    er.ReadByte();

                    sfatStringTable[i] = Encoding.ASCII.GetString(er.ReadBytesUntil(0));
                }
            }

            for (int i = 0; i < sfatEntries.Length; i++)
            {
                sfatEntries[i].FileName = sfatStringTable[sfatEntries[i].FileNameTableOffset / 4];
            }

            fileDictionary = new Dictionary <string, ArchiveEntry>(sfatEntries.Length);

            for (int i = 0; i < sfatEntries.Length; i++)
            {
                string name = sfatStringTable[sfatEntries[i].FileNameTableOffset / 4];
                uint   size = sfatEntries[i].DataOffsetEnd - sfatEntries[i].DataOffsetStart;

                fileDictionary.Add(name, new ArchiveEntry(name, sfatEntries[i].DataOffsetStart + archiveHeader.DataOffset, size, sfatEntries[i].FileType));
            }
        }