Esempio n. 1
0
 internal static void Compress(byte[] data, BinaryWriterEx bw, Type type)
 {
     bw.BigEndian = true;
     if (type == Type.Zlib)
     {
         SFUtil.WriteZlib(bw, 0xDA, data);
     }
     else if (type == Type.DCP_DFLT)
     {
         CompressDCPDFLT(data, bw);
     }
     else if (type == Type.DCX_EDGE)
     {
         CompressDCXEDGE(data, bw);
     }
     else if (type == Type.DCX_DFLT_10000_24_9 || type == Type.DCX_DFLT_10000_44_9 || type == Type.DCX_DFLT_11000_44_8 || type == Type.DCX_DFLT_11000_44_9)
     {
         CompressDCXDFLT(data, bw, type);
     }
     else if (type == Type.DCX_KRAK)
     {
         CompressDCXKRAK(data, bw);
     }
     else if (type == Type.Unknown)
     {
         throw new ArgumentException("You cannot compress a DCX with an unknown type.");
     }
     else
     {
         throw new NotImplementedException("Compression for the given type is not implemented.");
     }
 }
Esempio n. 2
0
        private static void CompressDCXDFLT(byte[] data, BinaryWriterEx bw, Type type)
        {
            bw.WriteASCII("DCX\0");

            if (type == Type.DCX_DFLT_10000_24_9 || type == Type.DCX_DFLT_10000_44_9)
            {
                bw.WriteInt32(0x10000);
            }
            else if (type == Type.DCX_DFLT_11000_44_8 || type == Type.DCX_DFLT_11000_44_9)
            {
                bw.WriteInt32(0x11000);
            }

            bw.WriteInt32(0x18);
            bw.WriteInt32(0x24);

            if (type == Type.DCX_DFLT_10000_24_9)
            {
                bw.WriteInt32(0x24);
                bw.WriteInt32(0x2C);
            }
            else if (type == Type.DCX_DFLT_10000_44_9 || type == Type.DCX_DFLT_11000_44_8 || type == Type.DCX_DFLT_11000_44_9)
            {
                bw.WriteInt32(0x44);
                bw.WriteInt32(0x4C);
            }

            bw.WriteASCII("DCS\0");
            bw.WriteInt32(data.Length);
            bw.ReserveInt32("CompressedSize");
            bw.WriteASCII("DCP\0");
            bw.WriteASCII("DFLT");
            bw.WriteInt32(0x20);

            if (type == Type.DCX_DFLT_10000_24_9 || type == Type.DCX_DFLT_10000_44_9 || type == Type.DCX_DFLT_11000_44_9)
            {
                bw.WriteInt32(0x9000000);
            }
            else if (type == Type.DCX_DFLT_11000_44_8)
            {
                bw.WriteInt32(0x8000000);
            }

            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0x00010100);
            bw.WriteASCII("DCA\0");
            bw.WriteInt32(8);

            long compressedStart = bw.Position;

            SFUtil.WriteZlib(bw, 0xDA, data);
            bw.FillInt32("CompressedSize", (int)(bw.Position - compressedStart));
        }
Esempio n. 3
0
        private static void CompressDCPDFLT(byte[] data, BinaryWriterEx bw)
        {
            bw.WriteASCII("DCP\0");
            bw.WriteASCII("DFLT");
            bw.WriteInt32(0x20);
            bw.WriteInt32(0x9000000);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0x00010100);

            bw.WriteASCII("DCS\0");
            bw.WriteInt32(data.Length);
            bw.ReserveInt32("CompressedSize");

            int compressedSize = SFUtil.WriteZlib(bw, 0xDA, data);

            bw.FillInt32("CompressedSize", compressedSize);

            bw.WriteASCII("DCA\0");
            bw.WriteInt32(8);
        }
Esempio n. 4
0
        private static void WriteFileData(BinderFile file, BinaryWriterEx bw, int index)
        {
            if (file.Bytes.Length > 0)
            {
                bw.Pad(0x10);
            }

            bw.FillUInt32($"FileData{index}", (uint)bw.Position);

            int compressedSize = file.Bytes.Length;

            if (Binder.IsCompressed(file.Flags))
            {
                compressedSize = SFUtil.WriteZlib(bw, 0x9C, file.Bytes);
            }
            else
            {
                bw.WriteBytes(file.Bytes);
            }

            bw.FillInt32($"CompressedSize{index}", compressedSize);
        }
Esempio n. 5
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            BinaryWriterEx bwData = new BinaryWriterEx(false);

            bwData.WriteInt32(0);
            bwData.WriteInt32(Struct1s.Count);
            bwData.WriteInt32(Struct2s.Count);
            bwData.WriteInt32(0);

            foreach (Struct1 struct1 in Struct1s)
            {
                struct1.Write(bwData);
            }
            bwData.Pad(0x10);

            foreach (Struct2 struct2 in Struct2s)
            {
                struct2.Write(bwData);
            }
            bwData.Pad(0x10);

            bwData.WriteInt16(0);
            foreach (string str in Strings)
            {
                bwData.WriteUTF16(str, true);
            }
            bwData.Pad(0x10);

            byte[] data = bwData.FinishBytes();

            bw.WriteASCII("ENFL");
            bw.WriteInt32(0x10415);
            bw.ReserveInt32("CompressedSize");
            bw.WriteInt32(data.Length);
            int compressedSize = SFUtil.WriteZlib(bw, 0xDA, data);

            bw.FillInt32("CompressedSize", compressedSize);
        }
Esempio n. 6
0
            internal void WriteData(BinaryWriterEx bw, int index, byte format)
            {
                if (Bytes.Length > 0)
                {
                    bw.Pad(0x10);
                }

                bw.FillInt32($"FileData{index}", (int)bw.Position);

                byte[] bytes          = Bytes;
                int    compressedSize = bytes.Length;

                if (Flags == 0xC0)
                {
                    compressedSize = SFUtil.WriteZlib(bw, 0x9C, bytes);
                }
                else
                {
                    bw.WriteBytes(bytes);
                }

                bw.FillInt32($"CompressedSize{index}", bytes.Length);
            }
Esempio n. 7
0
        /// <summary>
        /// Writes BND4 data to a BinaryWriterEx.
        /// </summary>
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.WriteASCII("BND4");
            bw.WriteBoolean(Flag1);
            bw.WriteBoolean(Flag2);
            bw.WriteByte(0);
            bw.WriteByte(0);

            bw.WriteInt32(0x10000);
            bw.WriteInt32(Files.Count);
            bw.WriteInt64(0x40);
            bw.WriteFixStr(Timestamp, 8);
            if (Format == 0x0C)
            {
                bw.WriteInt64(0x18);
            }
            else if (Format == 0x70)
            {
                bw.WriteInt64(0x1C);
            }
            else
            {
                bw.WriteInt64(0x24);
            }
            bw.ReserveInt64("DataStart");

            bw.WriteBoolean(Unicode);
            bw.WriteByte(Format);
            bw.WriteByte(Extended);
            bw.WriteByte(0);

            bw.WriteInt32(0);
            if (Extended == 4)
            {
                bw.ReserveInt64("HashGroups");
            }
            else
            {
                bw.WriteInt64(0);
            }

            for (int i = 0; i < Files.Count; i++)
            {
                Files[i].Write(bw, i, Format);
            }

            for (int i = 0; i < Files.Count; i++)
            {
                File file = Files[i];
                bw.FillInt32($"FileName{i}", (int)bw.Position);
                if (Unicode)
                {
                    bw.WriteUTF16(file.Name, true);
                }
                else
                {
                    bw.WriteShiftJIS(file.Name, true);
                }
            }

            if (Extended == 4)
            {
                uint groupCount = 0;
                for (uint p = (uint)Files.Count / 7; p <= 100000; p++)
                {
                    if (SFUtil.IsPrime(p))
                    {
                        groupCount = p;
                        break;
                    }
                }

                if (groupCount == 0)
                {
                    throw new InvalidOperationException("Hash group count not determined in BND4.");
                }

                var hashLists = new List <PathHash> [groupCount];
                for (int i = 0; i < groupCount; i++)
                {
                    hashLists[i] = new List <PathHash>();
                }

                for (int i = 0; i < Files.Count; i++)
                {
                    var  pathHash = new PathHash(i, Files[i].Name);
                    uint group    = pathHash.Hash % groupCount;
                    hashLists[group].Add(pathHash);
                }

                for (int i = 0; i < groupCount; i++)
                {
                    hashLists[i].Sort((ph1, ph2) => ph1.Hash.CompareTo(ph2.Hash));
                }

                var hashGroups = new List <HashGroup>();
                var pathHashes = new List <PathHash>();

                int count = 0;
                foreach (List <PathHash> hashList in hashLists)
                {
                    int index = count;
                    foreach (PathHash pathHash in hashList)
                    {
                        pathHashes.Add(pathHash);
                        count++;
                    }

                    hashGroups.Add(new HashGroup(index, count - index));
                }

                bw.Pad(0x8);
                bw.FillInt64("HashGroups", bw.Position);
                bw.ReserveInt64("PathHashes");
                bw.WriteUInt32(groupCount);
                bw.WriteInt32(0x00080810);

                foreach (HashGroup hashGroup in hashGroups)
                {
                    hashGroup.Write(bw);
                }

                // No padding after section 1
                bw.FillInt64("PathHashes", bw.Position);
                foreach (PathHash pathHash in pathHashes)
                {
                    pathHash.Write(bw);
                }
            }

            bw.FillInt64("DataStart", bw.Position);
            for (int i = 0; i < Files.Count; i++)
            {
                File file = Files[i];
                if (file.Bytes.LongLength > 0)
                {
                    bw.Pad(0x10);
                }

                bw.FillInt32($"FileData{i}", (int)bw.Position);

                byte[] bytes          = file.Bytes;
                int    compressedSize = bytes.Length;

                if (file.Flags == 0x03 || file.Flags == 0xC0)
                {
                    compressedSize = SFUtil.WriteZlib(bw, 0x9C, bytes);
                }
                else
                {
                    bw.WriteBytes(bytes);
                }

                bw.FillInt64($"CompressedSize{i}", bytes.Length);
            }
        }