示例#1
0
            internal void Write(BinaryWriterEx bw, PARAMDEF def, int index)
            {
                if (def.Unicode)
                {
                    bw.WriteFixStrW(DisplayName, 0x40, (byte)(def.Version >= 104 ? 0x00 : 0x20));
                }
                else
                {
                    bw.WriteFixStr(DisplayName, 0x40, (byte)(def.Version >= 104 ? 0x00 : 0x20));
                }

                byte padding = (byte)(def.Version >= 201 ? 0x00 : 0x20);

                bw.WriteFixStr(DisplayType.ToString(), 8, padding);
                bw.WriteFixStr(DisplayFormat, 8, padding);
                bw.WriteSingle(Default);
                bw.WriteSingle(Minimum);
                bw.WriteSingle(Maximum);
                bw.WriteSingle(Increment);
                bw.WriteInt32((int)EditFlags);
                bw.WriteInt32(ParamUtil.GetValueSize(DisplayType) * (ParamUtil.IsArrayType(DisplayType) ? ArrayLength : 1));

                if (def.Version >= 201)
                {
                    bw.ReserveInt64($"DescriptionOffset{index}");
                }
                else
                {
                    bw.ReserveInt32($"DescriptionOffset{index}");
                }

                bw.WriteFixStr(InternalType, 0x20, padding);

                if (def.Version >= 102)
                {
                    string internalName = InternalName;
                    // This is accurate except for "hasTarget : 1" in SpEffect
                    if (BitSize != -1)
                    {
                        internalName = $"{internalName}:{BitSize}";
                    }
                    // BB is not consistent about including [1] or not, but PTDE always does
                    else if (ParamUtil.IsArrayType(DisplayType))
                    {
                        internalName = $"{internalName}[{ArrayLength}]";
                    }
                    bw.WriteFixStr(internalName, 0x20, padding);
                }

                if (def.Version >= 104)
                {
                    bw.WriteInt32(SortID);
                }

                if (def.Version >= 201)
                {
                    bw.WritePattern(0x1C, 0x00);
                }
            }
示例#2
0
            internal void Write(BinaryWriterEx bw, PARAMDEF def, int index)
            {
                if (def.Unicode)
                {
                    bw.WriteFixStrW(DisplayName, 0x40, (byte)(def.Version >= 104 ? 0x00 : 0x20));
                }
                else
                {
                    bw.WriteFixStr(DisplayName, 0x40, (byte)(def.Version >= 104 ? 0x00 : 0x20));
                }

                byte padding = (byte)(def.Version >= 201 ? 0x00 : 0x20);

                bw.WriteFixStr(DisplayType.ToString(), 8, padding);
                bw.WriteFixStr(DisplayFormat, 8, padding);
                bw.WriteSingle(Default);
                bw.WriteSingle(Minimum);
                bw.WriteSingle(Maximum);
                bw.WriteSingle(Increment);
                bw.WriteInt32((int)EditFlags);
                bw.WriteInt32(ByteCount);

                if (def.Version >= 201)
                {
                    bw.ReserveInt64($"DescriptionOffset{index}");
                }
                else
                {
                    bw.ReserveInt32($"DescriptionOffset{index}");
                }

                bw.WriteFixStr(InternalType, 0x20, padding);

                if (def.Version >= 102)
                {
                    bw.WriteFixStr(InternalName, 0x20, padding);
                }

                if (def.Version >= 104)
                {
                    bw.WriteInt32(SortID);
                }

                if (def.Version >= 201)
                {
                    bw.WritePattern(0x1C, 0x00);
                }
            }
示例#3
0
        internal static void WriteHeader(IBND3 bnd, BinaryWriterEx bw, List <BinderFileHeader> fileHeaders)
        {
            bw.BigEndian = bnd.BigEndian || Binder.ForceBigEndian(bnd.Format);

            bw.WriteASCII("BND3");
            bw.WriteFixStr(bnd.Version, 8);

            Binder.WriteFormat(bw, bnd.BigEndian, bnd.Format);
            bw.WriteBoolean(bnd.BigEndian);
            bw.WriteBoolean(bnd.BitBigEndian);
            bw.WriteByte(0);

            bw.WriteInt32(fileHeaders.Count);
            bw.ReserveInt32("FileHeadersEnd");
            bw.WriteInt32(bnd.Unk18);
            bw.WriteInt32(0);

            for (int i = 0; i < fileHeaders.Count; i++)
            {
                fileHeaders[i].WriteBinder3FileHeader(bw, bnd.Format, bnd.BitBigEndian, i);
            }

            for (int i = 0; i < fileHeaders.Count; i++)
            {
                fileHeaders[i].WriteFileName(bw, bnd.Format, false, i);
            }

            bw.FillInt32($"FileHeadersEnd", (int)bw.Position);
        }
示例#4
0
        internal static void WriteBHFHeader(IBXF3 bxf, BinaryWriterEx bw, List <BinderFileHeader> fileHeaders)
        {
            bw.BigEndian = bxf.BigEndian || Binder.ForceBigEndian(bxf.Format);

            bw.WriteASCII("BHF3");
            bw.WriteFixStr(bxf.Version, 8);

            Binder.WriteFormat(bw, bxf.BitBigEndian, bxf.Format);
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0);

            bw.WriteInt32(fileHeaders.Count);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);

            for (int i = 0; i < fileHeaders.Count; i++)
            {
                fileHeaders[i].WriteBinder3FileHeader(bw, bxf.Format, bxf.BitBigEndian, i);
            }

            for (int i = 0; i < fileHeaders.Count; i++)
            {
                fileHeaders[i].WriteFileName(bw, bxf.Format, false, i);
            }
        }
示例#5
0
        internal static void WriteHeader(IBND4 bnd, BinaryWriterEx bw, List <BinderFileHeader> fileHeaders)
        {
            bw.BigEndian = bnd.BigEndian;

            bw.WriteASCII("BND4");

            bw.WriteBoolean(bnd.Unk04);
            bw.WriteBoolean(bnd.Unk05);
            bw.WriteByte(0);
            bw.WriteByte(0);

            bw.WriteByte(0);
            bw.WriteBoolean(bnd.BigEndian);
            bw.WriteBoolean(!bnd.BitBigEndian);
            bw.WriteByte(0);

            bw.WriteInt32(fileHeaders.Count);
            bw.WriteInt64(0x40);
            bw.WriteFixStr(bnd.Version, 8);
            bw.WriteInt64(Binder.GetBND4FileHeaderSize(bnd.Format));
            bw.ReserveInt64("HeadersEnd");

            bw.WriteBoolean(bnd.Unicode);
            Binder.WriteFormat(bw, bnd.BitBigEndian, bnd.Format);
            bw.WriteByte(bnd.Extended);
            bw.WriteByte(0);

            bw.WriteInt32(0);
            bw.ReserveInt64("HashTableOffset");

            for (int i = 0; i < fileHeaders.Count; i++)
            {
                fileHeaders[i].WriteBinder4FileHeader(bw, bnd.Format, bnd.BitBigEndian, i);
            }

            for (int i = 0; i < fileHeaders.Count; i++)
            {
                fileHeaders[i].WriteFileName(bw, bnd.Format, bnd.Unicode, i);
            }

            if (bnd.Extended == 4)
            {
                bw.Pad(0x8);
                bw.FillInt64("HashTableOffset", bw.Position);
                BinderHashTable.Write(bw, fileHeaders);
            }
            else
            {
                bw.FillInt64("HashTableOffset", 0);
            }

            bw.FillInt64("HeadersEnd", bw.Position);
        }
示例#6
0
 internal void Write(BinaryWriterEx bw)
 {
     bw.BigEndian = BigEndian;
     bw.WriteASCII("BDF4");
     bw.WriteBoolean(Flag1);
     bw.WriteBoolean(Flag2);
     bw.WriteByte(0);
     bw.WriteByte(0);
     bw.WriteInt32(0x10000);
     bw.WriteInt32(0);
     bw.WriteInt64(Unk1);
     bw.WriteFixStr(Timestamp, 8);
     bw.WriteInt64(0);
     bw.WriteInt64(0);
 }
示例#7
0
        private void Write(BinaryWriterEx bhdWriter, BinaryWriterEx bdtWriter)
        {
            bhdWriter.WriteASCII("BHF3");
            bhdWriter.WriteFixStr(BHDTimestamp, 8);
            bhdWriter.WriteByte((byte)Format);
            bhdWriter.WriteByte(0);
            bhdWriter.WriteByte(0);
            bhdWriter.WriteByte(0);
            bhdWriter.BigEndian = Binder.ForceBigEndian(Format);

            bhdWriter.WriteInt32(Files.Count);
            bhdWriter.WriteInt32(0);
            bhdWriter.WriteInt32(0);
            bhdWriter.WriteInt32(0);

            bdtWriter.WriteASCII("BDF3");
            bdtWriter.WriteFixStr(BDTTimestamp, 8);
            bdtWriter.WriteInt32(0);

            for (int i = 0; i < Files.Count; i++)
            {
                BinderFile file = Files[i];
                bhdWriter.WriteByte(0x40);
                bhdWriter.WriteByte(0);
                bhdWriter.WriteByte(0);
                bhdWriter.WriteByte(0);

                bhdWriter.WriteInt32(file.Bytes.Length);
                bhdWriter.WriteUInt32((uint)bdtWriter.Position);
                bhdWriter.WriteInt32(i);
                bhdWriter.ReserveUInt32($"FileName{i}");

                if (Binder.HasUncompressedSize(Format))
                {
                    bhdWriter.WriteInt32(file.Bytes.Length);
                }

                bdtWriter.WriteBytes(file.Bytes);
                bdtWriter.Pad(0x10);
            }

            for (int i = 0; i < Files.Count; i++)
            {
                BinderFile file = Files[i];
                bhdWriter.FillUInt32($"FileName{i}", (uint)bhdWriter.Position);
                bhdWriter.WriteShiftJIS(file.Name, true);
            }
        }
示例#8
0
        private void Write(BinaryWriterEx bhdWriter, BinaryWriterEx bdtWriter)
        {
            bhdWriter.WriteASCII("BHF3");
            bhdWriter.WriteFixStr(BHDTimestamp, 8);
            bhdWriter.WriteByte(Format);
            bhdWriter.WriteByte(0);
            bhdWriter.WriteByte(0);
            bhdWriter.WriteByte(0);
            bhdWriter.BigEndian = Format == 0xE0;

            bhdWriter.WriteInt32(Files.Count);
            bhdWriter.WriteInt32(0);
            bhdWriter.WriteInt32(0);
            bhdWriter.WriteInt32(0);

            bdtWriter.WriteASCII("BDF3");
            bdtWriter.WriteFixStr(BDTTimestamp, 8);
            bdtWriter.WriteInt32(0);

            for (int i = 0; i < Files.Count; i++)
            {
                File file = Files[i];
                bhdWriter.WriteByte(0x40);
                bhdWriter.WriteByte(0);
                bhdWriter.WriteByte(0);
                bhdWriter.WriteByte(0);

                bhdWriter.WriteInt32(file.Bytes.Length);
                bhdWriter.WriteInt32((int)bdtWriter.Position);
                bhdWriter.WriteInt32(i);
                bhdWriter.ReserveInt32($"FileName{i}");

                if (Format == 0x54 || Format == 0x74)
                {
                    bhdWriter.WriteInt32(file.Bytes.Length);
                }

                bdtWriter.WriteBytes(file.Bytes);
                bdtWriter.Pad(0x10);
            }

            for (int i = 0; i < Files.Count; i++)
            {
                File file = Files[i];
                bhdWriter.FillInt32($"FileName{i}", (int)bhdWriter.Position);
                bhdWriter.WriteShiftJIS(file.Name, true);
            }
        }
示例#9
0
 internal static void WriteBDFHeader(IBXF4 bxf, BinaryWriterEx bw)
 {
     bw.BigEndian = bxf.BigEndian;
     bw.WriteASCII("BDF4");
     bw.WriteBoolean(bxf.Unk04);
     bw.WriteBoolean(bxf.Unk05);
     bw.WriteByte(0);
     bw.WriteByte(0);
     bw.WriteByte(0);
     bw.WriteBoolean(bxf.BigEndian);
     bw.WriteBoolean(!bxf.BitBigEndian);
     bw.WriteByte(0);
     bw.WriteInt32(0);
     bw.WriteInt64(0x30);
     bw.WriteFixStr(bxf.Version, 8);
     bw.WriteInt64(0);
     bw.WriteInt64(0);
 }
 public void WriteHeader(BinaryWriterEx bw, HKX.HKXVariation variation)
 {
     bw.WriteFixStr(SectionTag, 19);
     bw.WriteByte(0xFF);
     bw.ReserveUInt32("absoffset" + SectionID);
     bw.ReserveUInt32("locoffset" + SectionID);
     bw.ReserveUInt32("globoffset" + SectionID);
     bw.ReserveUInt32("virtoffset" + SectionID);
     bw.ReserveUInt32("expoffset" + SectionID);
     bw.ReserveUInt32("impoffset" + SectionID);
     bw.ReserveUInt32("endoffset" + SectionID);
     if (variation == HKX.HKXVariation.HKXBloodBorne || variation == HKX.HKXVariation.HKXDS3)
     {
         bw.WriteUInt32(0xFFFFFFFF);
         bw.WriteUInt32(0xFFFFFFFF);
         bw.WriteUInt32(0xFFFFFFFF);
         bw.WriteUInt32(0xFFFFFFFF);
     }
 }
示例#11
0
 internal void Write(BinaryWriterEx bw, FLVERHeader header)
 {
     if (header.Version <= 0x20010)
     {
         if (int.TryParse(ID, out int id))
         {
             bw.WriteInt32(id);
         }
         else
         {
             throw new FormatException("For Dark Souls 2, GX IDs must be convertible to int.");
         }
     }
     else
     {
         bw.WriteFixStr(ID, 4);
     }
     bw.WriteInt32(Unk04);
     bw.WriteInt32(Data.Length + 0xC);
     bw.WriteBytes(Data);
 }
示例#12
0
文件: HKX.cs 项目: FloorBelow/dstools
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = (Header.Endian == 0) ? true : false;
            bw.WriteUInt32(Header.Magic0);
            bw.WriteUInt32(Header.Magic1);
            bw.WriteInt32(Header.UserTag);
            bw.WriteInt32(Header.Version);
            bw.WriteByte(Header.PointerSize);
            bw.WriteByte(Header.Endian);
            bw.WriteByte(Header.PaddingOption);
            bw.WriteByte(Header.BaseClass);
            bw.WriteInt32(Header.SectionCount);
            bw.WriteInt32(Header.ContentsSectionIndex);
            bw.WriteInt32(Header.ContentsSectionOffset);
            bw.WriteInt32(Header.ContentsClassNameSectionIndex);
            bw.WriteInt32(Header.ContentsClassNameSectionOffset);
            bw.WriteFixStr(Header.ContentsVersionString, 16, 0xFF);
            bw.WriteInt32(Header.Flags);
            if (Header.Version >= 0x0B)
            {
                bw.WriteInt16(Header.Unk3C);
                bw.WriteInt16(Header.SectionOffset);
                bw.WriteUInt32(Header.Unk40);
                bw.WriteUInt32(Header.Unk44);
                bw.WriteUInt32(Header.Unk48);
                bw.WriteUInt32(Header.Unk4C);
            }
            else
            {
                bw.WriteUInt32(0xFFFFFFFF);
            }

            ClassSection.WriteHeader(bw, Variation);
            TypeSection.WriteHeader(bw, Variation);
            DataSection.WriteHeader(bw, Variation);
            ClassSection.WriteData(bw, this, HKXVariation.HKXDS3);
            TypeSection.WriteData(bw, this, HKXVariation.HKXDS3);
            DataSection.WriteData(bw, this, HKXVariation.HKXDS3);
        }
示例#13
0
        /// <summary>
        /// Writes BND3 data to a BinaryWriterEx.
        /// </summary>
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;
            bw.WriteASCII("BND3");
            bw.WriteFixStr(Timestamp, 8);
            bw.WriteByte(Format);
            bw.WriteBoolean(BigEndian);
            bw.WriteBoolean(Unk1);
            bw.WriteByte(0);

            bw.BigEndian = BigEndian || Format == 0xE0 || Format == 0xF0;
            bw.WriteInt32(Files.Count);
            bw.ReserveInt32("HeaderEnd");
            bw.WriteInt32(Unk2);
            bw.WriteInt32(0);

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

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

            bw.FillInt32($"HeaderEnd", (int)bw.Position);

            for (int i = 0; i < Files.Count; i++)
            {
                Files[i].WriteData(bw, i, Format);
            }
        }
示例#14
0
        /// <summary>
        /// Writes BND3 data to a BinaryWriterEx.
        /// </summary>
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;
            bw.WriteASCII("BND3");
            bw.WriteFixStr(Timestamp, 8);
            bw.WriteByte((byte)Format);
            bw.WriteBoolean(BigEndian);
            bw.WriteBoolean(Unk1);
            bw.WriteByte(0);

            bw.BigEndian = BigEndian || Binder.ForceBigEndian(Format);
            bw.WriteInt32(Files.Count);
            bw.ReserveInt32("HeaderEnd");
            bw.WriteInt32(Unk2);
            bw.WriteInt32(0);

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

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

            bw.FillInt32($"HeaderEnd", (int)bw.Position);

            for (int i = 0; i < Files.Count; i++)
            {
                WriteFileData(Files[i], bw, i);
            }
        }
示例#15
0
        internal override void Write(BinaryWriterEx bw)
        {
            if (layout == null)
            {
                throw new InvalidOperationException("Params cannot be written without a layout.");
            }

            Rows.Sort((r1, r2) => r1.ID.CompareTo(r2.ID));

            bw.BigEndian = BigEndian;
            void WriteFormat()
            {
                bw.WriteByte((byte)(BigEndian ? 0xFF : 0x00));
                bw.WriteByte(Format2D);
                bw.WriteByte(Format2E);
                bw.WriteByte(Format2F);
            }

            // DeS, DS1
            if ((Format2D & 0x7F) < 3)
            {
                bw.ReserveUInt32("StringsOffset");
                bw.ReserveUInt16("DataStart");
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteFixStr(ID, 0x20, 0x20);
                WriteFormat();
            }
            // DS2
            else if ((Format2D & 0x7F) == 3)
            {
                bw.ReserveUInt32("StringsOffset");
                bw.WriteInt16(0);
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteFixStr(ID, 0x20, 0x20);
                WriteFormat();
                bw.ReserveUInt32("DataStart");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }
            // SotFS, BB
            else if ((Format2D & 0x7F) == 4)
            {
                bw.ReserveUInt32("StringsOffset");
                bw.WriteInt16(0);
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteFixStr(ID, 0x20, 0x00);
                WriteFormat();
                bw.ReserveInt64("DataStart");
                bw.WriteInt64(0);
            }
            // DS3, SDT
            else
            {
                bw.ReserveUInt32("StringsOffset");
                bw.WriteInt16(0);
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteInt32(0);
                bw.ReserveInt64("IDOffset");
                bw.WritePattern(0x14, 0x00);
                WriteFormat();
                bw.ReserveInt64("DataStart");
                bw.WriteInt64(0);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteHeader(bw, Format2D, i);
            }

            if ((Format2D & 0x7F) < 3)
            {
                bw.FillUInt16("DataStart", (ushort)bw.Position);
            }
            else if ((Format2D & 0x7F) == 3)
            {
                bw.FillUInt32("DataStart", (uint)bw.Position);
            }
            else
            {
                bw.FillInt64("DataStart", bw.Position);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteCells(bw, Format2D, i, layout);
            }

            bw.FillUInt32("StringsOffset", (uint)bw.Position);

            if ((Format2D & 0x7F) > 4)
            {
                bw.FillInt64("IDOffset", bw.Position);
                bw.WriteASCII(ID, true);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteName(bw, Format2D, i);
            }
        }
示例#16
0
            internal void WriteCells(BinaryWriterEx bw, byte format2D, int index)
            {
                if ((format2D & 0x7F) < 4)
                {
                    bw.FillUInt32($"RowOffset{index}", (uint)bw.Position);
                }
                else
                {
                    bw.FillInt64($"RowOffset{index}", bw.Position);
                }

                int bitOffset = -1;

                PARAMDEF.DefType bitType  = PARAMDEF.DefType.u8;
                uint             bitValue = 0;

                for (int i = 0; i < Cells.Count; i++)
                {
                    Cell             cell  = Cells[i];
                    object           value = cell.Value;
                    PARAMDEF.Field   field = cell.Def;
                    PARAMDEF.DefType type  = field.DisplayType;

                    if (type == PARAMDEF.DefType.s8)
                    {
                        bw.WriteSByte((sbyte)value);
                    }
                    else if (type == PARAMDEF.DefType.s16)
                    {
                        bw.WriteInt16((short)value);
                    }
                    else if (type == PARAMDEF.DefType.s32)
                    {
                        bw.WriteInt32((int)value);
                    }
                    else if (type == PARAMDEF.DefType.f32)
                    {
                        bw.WriteSingle((float)value);
                    }
                    else if (type == PARAMDEF.DefType.fixstr)
                    {
                        bw.WriteFixStr((string)value, field.ArrayLength);
                    }
                    else if (type == PARAMDEF.DefType.fixstrW)
                    {
                        bw.WriteFixStrW((string)value, field.ArrayLength * 2);
                    }
                    else if (ParamUtil.IsBitType(type))
                    {
                        if (field.BitSize == -1)
                        {
                            if (type == PARAMDEF.DefType.u8)
                            {
                                bw.WriteByte((byte)value);
                            }
                            else if (type == PARAMDEF.DefType.u16)
                            {
                                bw.WriteUInt16((ushort)value);
                            }
                            else if (type == PARAMDEF.DefType.u32)
                            {
                                bw.WriteUInt32((uint)value);
                            }
                            else if (type == PARAMDEF.DefType.dummy8)
                            {
                                bw.WriteBytes((byte[])value);
                            }
                        }
                        else
                        {
                            if (bitOffset == -1)
                            {
                                bitOffset = 0;
                                bitType   = type == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : type;
                                bitValue  = 0;
                            }

                            uint shifted = 0;
                            if (bitType == PARAMDEF.DefType.u8)
                            {
                                shifted = (byte)value;
                            }
                            else if (bitType == PARAMDEF.DefType.u16)
                            {
                                shifted = (ushort)value;
                            }
                            else if (bitType == PARAMDEF.DefType.u32)
                            {
                                shifted = (uint)value;
                            }
                            // Shift left first to clear any out-of-range bits
                            shifted    = shifted << (32 - field.BitSize) >> (32 - field.BitSize - bitOffset);
                            bitValue  |= shifted;
                            bitOffset += field.BitSize;

                            bool write = false;
                            if (i == Cells.Count - 1)
                            {
                                write = true;
                            }
                            else
                            {
                                PARAMDEF.Field   nextField = Cells[i + 1].Def;
                                PARAMDEF.DefType nextType  = nextField.DisplayType;
                                int bitLimit = ParamUtil.GetBitLimit(bitType);
                                if (!ParamUtil.IsBitType(nextType) || nextField.BitSize == -1 || bitOffset + nextField.BitSize > bitLimit ||
                                    (nextType == PARAMDEF.DefType.dummy8 ? PARAMDEF.DefType.u8 : nextType) != bitType)
                                {
                                    write = true;
                                }
                            }

                            if (write)
                            {
                                bitOffset = -1;
                                if (bitType == PARAMDEF.DefType.u8)
                                {
                                    bw.WriteByte((byte)bitValue);
                                }
                                else if (bitType == PARAMDEF.DefType.u16)
                                {
                                    bw.WriteUInt16((ushort)bitValue);
                                }
                                else if (bitType == PARAMDEF.DefType.u32)
                                {
                                    bw.WriteUInt32(bitValue);
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported field type: {type}");
                    }
                }
            }
示例#17
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            if (AppliedParamdef == null)
            {
                throw new InvalidOperationException("Params cannot be written without applying a paramdef.");
            }

            bw.BigEndian = BigEndian;
            void WriteFormat()
            {
                bw.WriteByte((byte)(BigEndian ? 0xFF : 0x00));
                bw.WriteByte(Format2D);
                bw.WriteByte(Format2E);
                bw.WriteByte(Format2F);
            }

            // DeS, DS1
            if ((Format2D & 0x7F) < 3)
            {
                bw.ReserveUInt32("StringsOffset");
                bw.ReserveUInt16("DataStart");
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteFixStr(ParamType, 0x20, (byte)((Format2D & 0x7F) < 2 ? 0x20 : 0x00));
                WriteFormat();
            }
            // DS2
            else if ((Format2D & 0x7F) == 3)
            {
                bw.ReserveUInt32("StringsOffset");
                bw.WriteInt16(0);
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteFixStr(ParamType, 0x20, 0x20);
                WriteFormat();
                bw.ReserveUInt32("DataStart");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }
            // SotFS, BB
            else if ((Format2D & 0x7F) == 4)
            {
                bw.ReserveUInt32("StringsOffset");
                bw.WriteInt16(0);
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteFixStr(ParamType, 0x20, 0x00);
                WriteFormat();
                bw.ReserveInt64("DataStart");
                bw.WriteInt64(0);
            }
            // DS3, SDT
            else
            {
                bw.ReserveUInt32("StringsOffset");
                bw.WriteInt16(0);
                bw.WriteInt16(Unk06);
                bw.WriteInt16(Unk08);
                bw.WriteUInt16((ushort)Rows.Count);
                bw.WriteInt32(0);
                bw.ReserveInt64("IDOffset");
                bw.WritePattern(0x14, 0x00);
                WriteFormat();
                bw.ReserveInt64("DataStart");
                bw.WriteInt64(0);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteHeader(bw, Format2D, i);
            }

            if ((Format2D & 0x7F) < 2)
            {
                bw.WritePattern(0x20, 0x00);
            }
            if ((Format2D & 0x7F) < 3)
            {
                bw.FillUInt16("DataStart", (ushort)bw.Position);
            }
            else if ((Format2D & 0x7F) == 3)
            {
                bw.FillUInt32("DataStart", (uint)bw.Position);
            }
            else
            {
                bw.FillInt64("DataStart", bw.Position);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteCells(bw, Format2D, i);
            }

            bw.FillUInt32("StringsOffset", (uint)bw.Position);

            if ((Format2D & 0x7F) > 4)
            {
                bw.FillInt64("IDOffset", bw.Position);
                bw.WriteASCII(ParamType, true);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteName(bw, Format2D, Format2E, i);
            }
            // DeS and BB sometimes (but not always) include some useless padding here
        }
示例#18
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);
            }
        }
示例#19
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            if (AppliedParamdef == null)
            {
                throw new InvalidOperationException("Params cannot be written without applying a paramdef.");
            }

            bw.BigEndian = BigEndian;

            bw.ReserveUInt32("StringsOffset");
            if (Format2D.HasFlag(FormatFlags1.Flag01) && Format2D.HasFlag(FormatFlags1.IntDataOffset) || Format2D.HasFlag(FormatFlags1.LongDataOffset))
            {
                bw.WriteInt16(0);
            }
            else
            {
                bw.ReserveUInt16("DataStart");
            }
            bw.WriteInt16(Unk06);
            bw.WriteInt16(ParamdefDataVersion);
            bw.WriteUInt16((ushort)Rows.Count);
            if (Format2D.HasFlag(FormatFlags1.OffsetParamType))
            {
                bw.WriteInt32(0);
                bw.ReserveInt64("ParamTypeOffset");
                bw.WritePattern(0x14, 0x00);
            }
            else
            {
                // This padding heuristic isn't completely accurate, not that it matters
                bw.WriteFixStr(ParamType, 0x20, (byte)(Format2D.HasFlag(FormatFlags1.Flag01) ? 0x20 : 0x00));
            }
            bw.WriteByte((byte)(BigEndian ? 0xFF : 0x00));
            bw.WriteByte((byte)Format2D);
            bw.WriteByte((byte)Format2E);
            bw.WriteByte(ParamdefFormatVersion);
            if (Format2D.HasFlag(FormatFlags1.Flag01) && Format2D.HasFlag(FormatFlags1.IntDataOffset))
            {
                bw.ReserveUInt32("DataStart");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }
            else if (Format2D.HasFlag(FormatFlags1.LongDataOffset))
            {
                bw.ReserveInt64("DataStart");
                bw.WriteInt64(0);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteHeader(bw, this, i);
            }

            // This is probably pretty stupid
            if (Format2D == FormatFlags1.Flag01)
            {
                bw.WritePattern(0x20, 0x00);
            }

            if (Format2D.HasFlag(FormatFlags1.Flag01) && Format2D.HasFlag(FormatFlags1.IntDataOffset))
            {
                bw.FillUInt32("DataStart", (uint)bw.Position);
            }
            else if (Format2D.HasFlag(FormatFlags1.LongDataOffset))
            {
                bw.FillInt64("DataStart", bw.Position);
            }
            else
            {
                bw.FillUInt16("DataStart", (ushort)bw.Position);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteCells(bw, this, i);
            }

            bw.FillUInt32("StringsOffset", (uint)bw.Position);

            if (Format2D.HasFlag(FormatFlags1.OffsetParamType))
            {
                bw.FillInt64("ParamTypeOffset", bw.Position);
                bw.WriteASCII(ParamType, true);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteName(bw, this, i);
            }
            // DeS and BB sometimes (but not always) include some useless padding here
        }
示例#20
0
            internal void Write(BinaryWriterEx bw, List <File> files)
            {
                bw.BigEndian = BigEndian;
                bw.WriteASCII("BHF4");
                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 || Format == 0x30)
                {
                    bw.WriteInt64(0x18);
                }
                else if (Format == 0x2E || Format == 0x74)
                {
                    bw.WriteInt64(0x24);
                }
                else if (Format == 0x3E)
                {
                    bw.WriteInt64(0x28);
                }
                bw.WriteInt64(0);

                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++)
                {
                    FileHeader.Write(bw, files[i], 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 BXF4.");
                    }

                    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);
                    }
                }
            }
示例#21
0
            internal void Write(BinaryWriterEx bw, PARAMDEF def, int index)
            {
                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"DisplayNameOffset{index}");
                }
                else if (def.Unicode)
                {
                    bw.WriteFixStrW(DisplayName, 0x40, (byte)(def.FormatVersion >= 104 ? 0x00 : 0x20));
                }
                else
                {
                    bw.WriteFixStr(DisplayName, 0x40, (byte)(def.FormatVersion >= 104 ? 0x00 : 0x20));
                }

                byte padding = (byte)(def.FormatVersion >= 200 ? 0x00 : 0x20);

                bw.WriteFixStr(DisplayType.ToString(), 8, padding);
                bw.WriteFixStr(DisplayFormat, 8, padding);
                bw.WriteSingle(Default);
                bw.WriteSingle(Minimum);
                bw.WriteSingle(Maximum);
                bw.WriteSingle(Increment);
                bw.WriteInt32((int)EditFlags);
                bw.WriteInt32(ParamUtil.GetValueSize(DisplayType) * (ParamUtil.IsArrayType(DisplayType) ? ArrayLength : 1));

                if (def.FormatVersion >= 200)
                {
                    bw.ReserveInt64($"DescriptionOffset{index}");
                }
                else
                {
                    bw.ReserveInt32($"DescriptionOffset{index}");
                }

                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"InternalTypeOffset{index}");
                }
                else
                {
                    bw.WriteFixStr(InternalType, 0x20, padding);
                }

                if (def.FormatVersion >= 202)
                {
                    bw.ReserveInt64($"InternalNameOffset{index}");
                }
                else if (def.FormatVersion >= 102)
                {
                    bw.WriteFixStr(MakeInternalName(), 0x20, padding);
                }

                if (def.FormatVersion >= 104)
                {
                    bw.WriteInt32(SortID);
                }

                if (def.FormatVersion >= 200)
                {
                    bw.WriteInt32(0);
                    bw.ReserveInt64($"UnkB8Offset{index}");
                    bw.ReserveInt64($"UnkC0Offset{index}");
                    bw.ReserveInt64($"UnkC8Offset{index}");
                }
            }
示例#22
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.ReserveInt32("FileSize");
            bw.WriteInt16((short)(Version >= 201 ? 0xFF : 0x30));
            bw.WriteInt16(Unk06);
            bw.WriteInt16((short)Fields.Count);

            if (Version == 101)
            {
                bw.WriteInt16(0x8C);
            }
            else if (Version == 102)
            {
                bw.WriteInt16(0xAC);
            }
            else if (Version == 103)
            {
                bw.WriteInt16(0x6C);
            }
            else if (Version == 104)
            {
                bw.WriteInt16(0xB0);
            }
            else if (Version == 201)
            {
                bw.WriteInt16(0xD0);
            }

            bw.WriteFixStr(ParamType, 0x20, (byte)(Version >= 201 ? 0x00 : 0x20));
            bw.WriteSByte((sbyte)(BigEndian ? -1 : 0));
            bw.WriteBoolean(Unicode);
            bw.WriteInt16(Version);
            if (Version >= 201)
            {
                bw.WriteInt64(0x38);
            }

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

            long descriptionsStart = bw.Position;

            for (int i = 0; i < Fields.Count; i++)
            {
                Fields[i].WriteDescription(bw, this, i);
            }

            if (Version >= 104)
            {
                long descriptionsLength = bw.Position - descriptionsStart;
                if (descriptionsLength % 0x10 != 0)
                {
                    bw.WritePattern((int)(0x10 - descriptionsLength % 0x10), 0x00);
                }
            }
            else
            {
                bw.Pad(0x10);
            }
            bw.FillInt32("FileSize", (int)bw.Position);
        }
示例#23
0
 internal static void WriteBDFHeader(IBXF3 bxf, BinaryWriterEx bw)
 {
     bw.WriteASCII("BDF3");
     bw.WriteFixStr(bxf.Version, 8);
     bw.WriteInt32(0);
 }
示例#24
0
        internal override void Write(BinaryWriterEx bw)
        {
            if (layout == null)
            {
                throw new InvalidOperationException("Params cannot be written without a layout.");
            }

            Rows.Sort((r1, r2) => r1.ID.CompareTo(r2.ID));

            bw.BigEndian = false;

            bw.ReserveInt32("NameOffset");
            bw.WriteInt16(0);
            bw.WriteInt16(Unk1);
            bw.WriteInt16(Unk2);
            bw.WriteUInt16((ushort)Rows.Count);

            if (FixStrID)
            {
                bw.WriteFixStr(ID, 0x20);
            }
            else
            {
                bw.WriteInt32(0);
                bw.ReserveInt32("IDOffset");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }

            bw.WriteByte(0);
            bw.WriteByte(Unk3);
            bw.WriteByte(Unk4);
            bw.WriteByte(0);

            bw.ReserveInt64("DataStart");
            bw.WriteInt32(0);
            bw.WriteInt32(0);

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteHeader(bw, i);
            }

            bw.FillInt64("DataStart", bw.Position);

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteCells(bw, i, layout);
            }

            bw.FillInt32("NameOffset", (int)bw.Position);
            if (FixStrID)
            {
                if (Unk4 == 6)
                {
                    bw.WriteShiftJIS(Name, true);
                }
                else if (Unk4 == 7)
                {
                    bw.WriteUTF16(Name, true);
                }
            }
            else
            {
                bw.WriteShiftJIS(Name, true);
                bw.FillInt32("IDOffset", (int)bw.Position);
                bw.WriteASCII(ID, true);
            }

            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].WriteName(bw, i, Unk4);
            }
        }
示例#25
0
            internal void WriteCells(BinaryWriterEx bw, int i, Layout layout)
            {
                bw.FillInt64($"RowOffset{i}", bw.Position);
                for (int j = 0; j < layout.Count; j++)
                {
                    Cell         cell  = Cells[j];
                    Layout.Entry entry = layout[j];
                    CellType     type  = entry.Type;
                    object       value = cell.Value;

                    if (entry.Name != cell.Name || type != cell.Type)
                    {
                        throw new FormatException("Layout does not match cells.");
                    }

                    if (type == CellType.s8)
                    {
                        bw.WriteSByte((sbyte)value);
                    }
                    else if (type == CellType.u8 || type == CellType.x8)
                    {
                        bw.WriteByte((byte)value);
                    }
                    else if (type == CellType.s16)
                    {
                        bw.WriteInt16((short)value);
                    }
                    else if (type == CellType.u16 || type == CellType.x16)
                    {
                        bw.WriteUInt16((ushort)value);
                    }
                    else if (type == CellType.s32)
                    {
                        bw.WriteInt32((int)value);
                    }
                    else if (type == CellType.u32 || type == CellType.x32)
                    {
                        bw.WriteUInt32((uint)value);
                    }
                    else if (type == CellType.f32)
                    {
                        bw.WriteSingle((float)value);
                    }
                    else if (type == CellType.dummy8)
                    {
                        bw.WriteBytes((byte[])value);
                    }
                    else if (type == CellType.fixstr)
                    {
                        bw.WriteFixStr((string)value, entry.Size);
                    }
                    else if (type == CellType.fixstrW)
                    {
                        bw.WriteFixStrW((string)value, entry.Size);
                    }
                    else if (type == CellType.b8)
                    {
                        byte b = 0;
                        int  k;
                        for (k = 0; k < 8; k++)
                        {
                            if (j + k >= layout.Count || layout[j + k].Type != CellType.b8)
                            {
                                break;
                            }

                            if ((bool)Cells[j + k].Value)
                            {
                                b |= (byte)(1 << k);
                            }
                        }
                        j += k - 1;
                        bw.WriteByte(b);
                    }
                    else if (type == CellType.b32)
                    {
                        byte[] b = new byte[4];
                        int    k;
                        for (k = 0; k < 32; k++)
                        {
                            if (j + k >= layout.Count || layout[j + k].Type != CellType.b32)
                            {
                                break;
                            }

                            if ((bool)Cells[j + k].Value)
                            {
                                b[k / 8] |= (byte)(1 << (k % 8));
                            }
                        }
                        j += k - 1;
                        bw.WriteBytes(b);
                    }
                }
            }
示例#26
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = BigEndian;

            bw.ReserveInt32("FileSize");
            bw.WriteInt16((short)(FormatVersion >= 200 ? 0xFF : 0x30));
            bw.WriteInt16(DataVersion);
            bw.WriteInt16((short)Fields.Count);

            if (FormatVersion == 101)
            {
                bw.WriteInt16(0x8C);
            }
            else if (FormatVersion == 102)
            {
                bw.WriteInt16(0xAC);
            }
            else if (FormatVersion == 103)
            {
                bw.WriteInt16(0x6C);
            }
            else if (FormatVersion == 104)
            {
                bw.WriteInt16(0xB0);
            }
            else if (FormatVersion == 201)
            {
                bw.WriteInt16(0xD0);
            }
            else if (FormatVersion == 202)
            {
                bw.WriteInt16(0x68);
            }

            if (FormatVersion >= 202)
            {
                bw.WriteInt32(0);
                bw.ReserveInt64("ParamTypeOffset");
                bw.WriteInt64(0);
                bw.WriteInt64(0);
                bw.WriteInt32(0);
            }
            else
            {
                bw.WriteFixStr(ParamType, 0x20, (byte)(FormatVersion >= 200 ? 0x00 : 0x20));
            }

            bw.WriteSByte((sbyte)(BigEndian ? -1 : 0));
            bw.WriteBoolean(Unicode);
            bw.WriteInt16(FormatVersion);
            if (FormatVersion >= 200)
            {
                bw.WriteInt64(0x38);
            }

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

            if (FormatVersion >= 202)
            {
                bw.FillInt64("ParamTypeOffset", bw.Position);
                bw.WriteShiftJIS(ParamType, true);
            }

            long fieldStringsStart   = bw.Position;
            var  sharedStringOffsets = new Dictionary <string, long>();

            for (int i = 0; i < Fields.Count; i++)
            {
                Fields[i].WriteStrings(bw, this, i, sharedStringOffsets);
            }

            if (FormatVersion >= 104 && FormatVersion < 202)
            {
                long fieldStringsLength = bw.Position - fieldStringsStart;
                if (fieldStringsLength % 0x10 != 0)
                {
                    bw.WritePattern((int)(0x10 - fieldStringsLength % 0x10), 0x00);
                }
            }
            else
            {
                if (FormatVersion >= 202 && bw.Position % 0x10 == 0)
                {
                    bw.WritePattern(0x10, 0x00);
                }
                bw.Pad(0x10);
            }
            bw.FillInt32("FileSize", (int)bw.Position);
        }