Example #1
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("CLM2");
            bw.WriteInt32(0);
            bw.WriteInt16(1);
            bw.WriteInt16(1);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(Meshes.Count);
            bw.WriteInt32(0x28);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0x28);

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

            for (int i = 0; i < Meshes.Count; i++)
            {
                Meshes[i].WriteEntries(bw, i);
            }
        }
Example #2
0
        /// <summary>
        /// Write a DDS file from this header object and given pixel data.
        /// </summary>
        public byte[] Write(byte[] pixelData)
        {
            BinaryWriterEx bw = new BinaryWriterEx(false);

            bw.WriteASCII("DDS ");
            bw.WriteInt32(124);

            bw.WriteUInt32((uint)dwFlags);
            bw.WriteInt32(dwHeight);
            bw.WriteInt32(dwWidth);
            bw.WriteInt32(dwPitchOrLinearSize);
            bw.WriteInt32(dwDepth);
            bw.WriteInt32(dwMipMapCount);

            for (int i = 0; i < 11; i++)
            {
                bw.WriteInt32(0);
            }

            ddspf.Write(bw);
            bw.WriteUInt32((uint)dwCaps);
            bw.WriteUInt32((uint)dwCaps2);

            for (int i = 0; i < 3; i++)
            {
                bw.WriteInt32(0);
            }

            if (ddspf.dwFourCC == "DX10")
            {
                header10.Write(bw);
            }

            bw.WriteBytes(pixelData);
            return(bw.FinishBytes());
        }
Example #3
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);
            }
        }
Example #4
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
        }
Example #5
0
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian  = BigEndian;
            bw.VarintLong = Version == MQBVersion.DarkSouls2Scholar;

            bw.WriteASCII("MQB ");
            bw.WriteSByte((sbyte)(BigEndian ? -1 : 0));
            bw.WriteByte(0);
            bw.WriteSByte((sbyte)(Version == MQBVersion.DarkSouls2Scholar ? -1 : 0));
            bw.WriteByte(0);
            bw.WriteUInt32((uint)Version);
            switch (Version)
            {
            case MQBVersion.DarkSouls2: bw.WriteInt32(0x14); break;

            case MQBVersion.DarkSouls2Scholar: bw.WriteInt32(0x28); break;

            case MQBVersion.Bloodborne: bw.WriteInt32(0x20); break;

            case MQBVersion.DarkSouls3: bw.WriteInt32(0x24); break;

            default:
                throw new NotImplementedException($"Missing header size for version {Version}.");
            }

            bw.ReserveVarint("ResourcePathsOffset");
            if (Version == MQBVersion.DarkSouls2Scholar)
            {
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }
            else if (Version >= MQBVersion.Bloodborne)
            {
                bw.WriteInt32(1);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                if (Version >= MQBVersion.DarkSouls3)
                {
                    bw.WriteInt32(0);
                }
            }

            bw.WriteFixStrW(Name, 0x40, 0x00);
            bw.WriteSingle(Framerate);
            bw.WriteInt32(Resources.Count);
            bw.WriteInt32(Cuts.Count);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);

            var allCustomData          = new List <CustomData>();
            var customDataValueOffsets = new List <long>();

            for (int i = 0; i < Resources.Count; i++)
            {
                Resources[i].Write(bw, i, allCustomData, customDataValueOffsets);
            }

            var offsetsByDispos = new Dictionary <Disposition, long>();

            for (int i = 0; i < Cuts.Count; i++)
            {
                Cuts[i].Write(bw, Version, offsetsByDispos, i, allCustomData, customDataValueOffsets);
            }

            for (int i = 0; i < Cuts.Count; i++)
            {
                Cuts[i].WriteTimelines(bw, Version, i);
            }

            for (int i = 0; i < Cuts.Count; i++)
            {
                Cuts[i].WriteTimelineCustomData(bw, i, allCustomData, customDataValueOffsets);
            }

            for (int i = 0; i < Cuts.Count; i++)
            {
                Cuts[i].WriteDisposOffsets(bw, offsetsByDispos, i);
            }

            bw.FillVarint("ResourcePathsOffset", bw.Position);
            for (int i = 0; i < Resources.Count; i++)
            {
                bw.ReserveVarint($"ResourcePathOffset{i}");
            }

            bw.WriteUTF16(ResourceDirectory, true);
            for (int i = 0; i < Resources.Count; i++)
            {
                if (Resources[i].Path == null)
                {
                    bw.FillVarint($"ResourcePathOffset{i}", 0);
                }
                else
                {
                    bw.FillVarint($"ResourcePathOffset{i}", bw.Position);
                    bw.WriteUTF16(Resources[i].Path, true);
                }
            }

            // I know this is weird, but trust me.
            if (Version >= MQBVersion.Bloodborne)
            {
                bw.WriteInt16(0);
                bw.Pad(4);
            }

            for (int i = 0; i < allCustomData.Count; i++)
            {
                allCustomData[i].WriteSequences(bw, i, customDataValueOffsets[i]);
            }

            for (int i = 0; i < allCustomData.Count; i++)
            {
                allCustomData[i].WriteSequencePoints(bw, i);
            }
        }
Example #6
0
 internal static void WriteBDFHeader(IBXF3 bxf, BinaryWriterEx bw)
 {
     bw.WriteASCII("BDF3");
     bw.WriteFixStr(bxf.Version, 8);
     bw.WriteInt32(0);
 }
Example #7
0
        private static void CompressDCXEDGE(byte[] data, BinaryWriterEx bw)
        {
            int chunkCount = data.Length / 0x10000;

            if (data.Length % 0x10000 > 0)
            {
                chunkCount++;
            }

            bw.WriteASCII("DCX\0");
            bw.WriteInt32(0x10000);
            bw.WriteInt32(0x18);
            bw.WriteInt32(0x24);
            bw.WriteInt32(0x24);
            bw.WriteInt32(0x50 + chunkCount * 0x10);

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

            bw.WriteASCII("DCP\0");
            bw.WriteASCII("EDGE");
            bw.WriteInt32(0x20);
            bw.WriteInt32(0x9000000);
            bw.WriteInt32(0x10000);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0x00100100);

            long dcaStart = bw.Position;

            bw.WriteASCII("DCA\0");
            bw.ReserveInt32("DCASize");
            long egdtStart = bw.Position;

            bw.WriteASCII("EgdT");
            bw.WriteInt32(0x00010100);
            bw.WriteInt32(0x24);
            bw.WriteInt32(0x10);
            bw.WriteInt32(0x10000);
            bw.WriteInt32(data.Length % 0x10000);
            bw.ReserveInt32("EGDTSize");
            bw.WriteInt32(chunkCount);
            bw.WriteInt32(0x100000);

            for (int i = 0; i < chunkCount; i++)
            {
                bw.WriteInt32(0);
                bw.ReserveInt32($"ChunkOffset{i}");
                bw.ReserveInt32($"ChunkSize{i}");
                bw.ReserveInt32($"ChunkCompressed{i}");
            }

            bw.FillInt32("DCASize", (int)(bw.Position - dcaStart));
            bw.FillInt32("EGDTSize", (int)(bw.Position - egdtStart));
            long dataStart = bw.Position;

            int compressedSize = 0;

            for (int i = 0; i < chunkCount; i++)
            {
                int chunkSize = 0x10000;
                if (i == chunkCount - 1)
                {
                    chunkSize = data.Length % 0x10000;
                }

                byte[] chunk;
                using (MemoryStream cmpStream = new MemoryStream())
                    using (MemoryStream dcmpStream = new MemoryStream(data, i * 0x10000, chunkSize))
                    {
                        DeflateStream dfltStream = new DeflateStream(cmpStream, CompressionMode.Compress);
                        dcmpStream.CopyTo(dfltStream);
                        dfltStream.Close();
                        chunk = cmpStream.ToArray();
                    }

                if (chunk.Length < chunkSize)
                {
                    bw.FillInt32($"ChunkCompressed{i}", 1);
                }
                else
                {
                    bw.FillInt32($"ChunkCompressed{i}", 0);
                    chunk = data;
                }

                compressedSize += chunk.Length;
                bw.FillInt32($"ChunkOffset{i}", (int)(bw.Position - dataStart));
                bw.FillInt32($"ChunkSize{i}", chunk.Length);
                bw.WriteBytes(chunk);
                bw.Pad(0x10);
            }

            bw.FillInt32("CompressedSize", compressedSize);
        }
Example #8
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("TAE ");
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0);
            bw.WriteByte(0xFF);
            bw.WriteInt32(0x1000C);
            bw.ReserveInt32("FileSize");
            bw.WriteInt64(0x40);
            bw.WriteInt64(1);
            bw.WriteInt64(0x50);
            bw.WriteInt64(0x80);
            bw.WriteInt64(Unk30);
            bw.WriteInt64(0);
            bw.WriteBytes(Flags);
            bw.WriteInt64(1);
            bw.WriteInt32(ID);
            bw.WriteInt32(Animations.Count);
            bw.ReserveInt64("AnimsOffset");
            bw.ReserveInt64("AnimGroupsOffset");
            bw.WriteInt64(0xA0);
            bw.WriteInt64(Animations.Count);
            bw.ReserveInt64("FirstAnimOffset");
            bw.WriteInt64(1);
            bw.WriteInt64(0x90);
            bw.WriteInt32(ID);
            bw.WriteInt32(ID);
            bw.WriteInt64(0x50);
            bw.WriteInt64(0);
            bw.WriteInt64(0xB0);
            bw.ReserveInt64("SkeletonName");
            bw.ReserveInt64("SibName");
            bw.WriteInt64(0);
            bw.WriteInt64(0);

            bw.FillInt64("SkeletonName", bw.Position);
            bw.WriteUTF16(SkeletonName, true);
            bw.Pad(0x10);

            bw.FillInt64("SibName", bw.Position);
            bw.WriteUTF16(SibName, true);
            bw.Pad(0x10);

            Animations.Sort((a1, a2) => a1.ID.CompareTo(a2.ID));

            bw.FillInt64("AnimsOffset", bw.Position);
            var animOffsets = new List <long>(Animations.Count);

            for (int i = 0; i < Animations.Count; i++)
            {
                animOffsets.Add(bw.Position);
                Animations[i].WriteHeader(bw, i);
            }

            bw.FillInt64("AnimGroupsOffset", bw.Position);
            bw.ReserveInt64("AnimGroupsCount");
            bw.ReserveInt64("AnimGroupsOffset");
            int  groupCount = 0;
            long groupStart = bw.Position;

            for (int i = 0; i < Animations.Count; i++)
            {
                int firstIndex = i;
                bw.WriteInt32((int)Animations[i].ID);
                while (i < Animations.Count - 1 && Animations[i + 1].ID == Animations[i].ID + 1)
                {
                    i++;
                }
                bw.WriteInt32((int)Animations[i].ID);
                bw.WriteInt64(animOffsets[firstIndex]);
                groupCount++;
            }
            bw.FillInt64("AnimGroupsCount", groupCount);
            if (groupCount == 0)
            {
                bw.FillInt64("AnimGroupsOffset", 0);
            }
            else
            {
                bw.FillInt64("AnimGroupsOffset", groupStart);
            }

            bw.FillInt64("FirstAnimOffset", bw.Position);
            for (int i = 0; i < Animations.Count; i++)
            {
                Animations[i].WriteBody(bw, i);
            }

            for (int i = 0; i < Animations.Count; i++)
            {
                Animations[i].WriteAnimFile(bw, i);

                long timeStart = bw.Position;
                Animations[i].WriteTimes(bw, i);

                var eventHeaderOffsets = Animations[i].WriteEventHeaders(bw, i, timeStart);

                Animations[i].WriteEventData(bw, i);

                Animations[i].WriteEventGroupHeaders(bw, i);

                Animations[i].WriteEventGroupData(bw, i, eventHeaderOffsets);
            }

            bw.FillInt32("FileSize", (int)bw.Position);
        }
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            Entries entries;

            entries.Models     = Models.GetEntries();
            entries.Events     = Events.GetEntries();
            entries.Regions    = Regions.GetEntries();
            entries.Routes     = Routes.GetEntries();
            entries.Layers     = Layers.GetEntries();
            entries.Parts      = Parts.GetEntries();
            entries.PartsPoses = PartsPoses.GetEntries();
            entries.BoneNames  = BoneNames.GetEntries();

            foreach (Model model in entries.Models)
            {
                model.CountInstances(entries.Parts);
            }
            foreach (Event evt in entries.Events)
            {
                evt.GetIndices(this, entries);
            }
            foreach (Region region in entries.Regions)
            {
                region.GetIndices(this, entries);
            }
            foreach (Part part in entries.Parts)
            {
                part.GetIndices(this, entries);
            }
            foreach (PartsPose pose in entries.PartsPoses)
            {
                pose.GetIndices(this, entries);
            }

            bw.WriteASCII("MSB ");
            bw.WriteInt32(1);
            bw.WriteInt32(0x10);
            bw.WriteBoolean(false);
            bw.WriteBoolean(false);
            bw.WriteByte(1);
            bw.WriteByte(0xFF);

            Models.Write(bw, entries.Models);
            bw.FillInt64("NextParamOffset", bw.Position);
            Events.Write(bw, entries.Events);
            bw.FillInt64("NextParamOffset", bw.Position);
            Regions.Write(bw, entries.Regions);
            bw.FillInt64("NextParamOffset", bw.Position);
            Routes.Write(bw, entries.Routes);
            bw.FillInt64("NextParamOffset", bw.Position);
            Layers.Write(bw, entries.Layers);
            bw.FillInt64("NextParamOffset", bw.Position);
            Parts.Write(bw, entries.Parts);
            bw.FillInt64("NextParamOffset", bw.Position);
            PartsPoses.Write(bw, entries.PartsPoses);
            bw.FillInt64("NextParamOffset", bw.Position);
            BoneNames.Write(bw, entries.BoneNames);
            bw.FillInt64("NextParamOffset", 0);
        }
Example #10
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);
            }
        }
Example #11
0
 public void Write(BinaryWriterEx bw, uint sectionBaseOffset)
 {
     bw.WriteUInt32(Signature);
     bw.WriteByte(0x09);
     bw.WriteASCII(ClassName, true);
 }
Example #12
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteInt32(0);
            bw.ReserveInt32("FileSize");
            int fileStart = (int)bw.Position;

            bw.WriteInt32(0);
            bw.WriteInt32(3);
            WriteMarker(bw, 0x01);
            bw.WriteInt32(0);
            bw.WriteInt32(0x1C);
            bw.WriteInt32(1);
            bw.WriteInt32(2);
            WriteMarker(bw, 0xB0);
            bw.WriteInt32(4);
            bw.WriteASCII("MTD ");
            WriteMarker(bw, 0x34);
            bw.WriteInt32(0x3E8);
            WriteMarker(bw, 0x01);
            bw.WriteInt32(0);
            bw.ReserveInt32("DataSize");
            bw.WriteInt32(2);
            bw.WriteInt32(4);
            int dataStart = (int)bw.Position;

            WriteMarker(bw, 0xA3);

            bw.WriteShiftJISLengthPrefixed(ShaderPath, 0xA3);
            bw.WriteShiftJISLengthPrefixed(Description, 0x03);

            bw.WriteInt32(1);
            bw.WriteInt32(0);
            bw.ReserveInt32("ParamSize");
            bw.WriteInt32(3);
            bw.WriteInt32(4);
            WriteMarker(bw, 0xA3);
            bw.WriteInt32(0);
            int paramStart = (int)bw.Position;

            WriteMarker(bw, 0x03);

            bw.WriteInt32(Params.Count);
            foreach (Param internalEntry in Params)
            {
                internalEntry.Write(bw);
            }

            WriteMarker(bw, 0x03);

            bw.WriteInt32(Textures.Count);
            foreach (Texture externalEntry in Textures)
            {
                externalEntry.Write(bw);
            }

            WriteMarker(bw, 0x04);
            bw.WriteInt32(0);
            WriteMarker(bw, 0x04);
            bw.WriteInt32(0);
            WriteMarker(bw, 0x04);
            bw.WriteInt32(0);

            int position = (int)bw.Position;

            bw.FillInt32("FileSize", position - fileStart);
            bw.FillInt32("DataSize", position - dataStart);
            bw.FillInt32("ParamSize", position - paramStart);
        }
Example #13
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteASCII("filt");
            bw.WriteInt32(2);
            bw.WriteInt32(0);
            bw.WriteInt32(Groups.Count);
            bw.WriteInt32(Unk1);
            bw.WriteInt32(0x40);

            bw.ReserveInt32("GroupHeadersOffset");
            bw.ReserveInt32("ParamHeaderOffsetsOffset");
            bw.ReserveInt32("ParamHeadersOffset");
            bw.ReserveInt32("ValuesOffset");
            bw.ReserveInt32("UnkBlock1Offset");
            bw.ReserveInt32("UnkBlock2Offset");

            bw.WriteInt32(Unk2);
            bw.ReserveInt32("UnkBlock3Offset");
            bw.ReserveInt32("UnkBlock4Offset");
            bw.WriteInt32(0);

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

            int groupHeadersOffset = (int)bw.Position;

            bw.FillInt32("GroupHeadersOffset", groupHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteHeader(bw, i, groupHeadersOffset);
            }

            int paramHeaderOffsetsOffset = (int)bw.Position;

            bw.FillInt32("ParamHeaderOffsetsOffset", paramHeaderOffsetsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaderOffsets(bw, i, paramHeaderOffsetsOffset);
            }

            int paramHeadersOffset = (int)bw.Position;

            bw.FillInt32("ParamHeadersOffset", paramHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaders(bw, i, paramHeadersOffset);
            }

            int valuesOffset = (int)bw.Position;

            bw.FillInt32("ValuesOffset", valuesOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValues(bw, i, valuesOffset);
            }

            bw.FillInt32("UnkBlock1Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock1);

            bw.FillInt32("UnkBlock2Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock2);

            bw.FillInt32("UnkBlock3Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock3);

            bw.FillInt32("UnkBlock4Offset", (int)bw.Position);
            bw.WriteBytes(UnkBlock4);
        }
Example #14
0
            internal void WriteStrings(BinaryWriterEx bw, PARAMDEF def, int index, Dictionary <string, long> sharedStringOffsets)
            {
                if (def.FormatVersion >= 202)
                {
                    bw.FillInt64($"DisplayNameOffset{index}", bw.Position);
                    bw.WriteUTF16(DisplayName, true);
                }

                long descriptionOffset = 0;

                if (Description != null)
                {
                    descriptionOffset = bw.Position;
                    if (def.Unicode)
                    {
                        bw.WriteUTF16(Description, true);
                    }
                    else
                    {
                        bw.WriteShiftJIS(Description, true);
                    }
                }

                if (def.FormatVersion >= 200)
                {
                    bw.FillInt64($"DescriptionOffset{index}", descriptionOffset);
                }
                else
                {
                    bw.FillInt32($"DescriptionOffset{index}", (int)descriptionOffset);
                }

                if (def.FormatVersion >= 202)
                {
                    bw.FillInt64($"InternalTypeOffset{index}", bw.Position);
                    bw.WriteASCII(InternalType, true);

                    bw.FillInt64($"InternalNameOffset{index}", bw.Position);
                    bw.WriteASCII(MakeInternalName(), true);
                }

                if (def.FormatVersion >= 200)
                {
                    long writeSharedStringMaybe(string str, bool unicode)
                    {
                        if (str == null)
                        {
                            return(0);
                        }

                        if (!sharedStringOffsets.ContainsKey(str))
                        {
                            sharedStringOffsets[str] = bw.Position;
                            if (unicode)
                            {
                                bw.WriteUTF16(str, true);
                            }
                            else
                            {
                                bw.WriteASCII(str, true);
                            }
                        }
                        return(sharedStringOffsets[str]);
                    }

                    bw.FillInt64($"UnkB8Offset{index}", writeSharedStringMaybe(UnkB8, false));
                    bw.FillInt64($"UnkC0Offset{index}", writeSharedStringMaybe(UnkC0, false));
                    bw.FillInt64($"UnkC8Offset{index}", writeSharedStringMaybe(UnkC8, true));
                }
            }
Example #15
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            if (Game == GPGame.DarkSouls2)
            {
                bw.WriteASCII("filt");
            }
            else
            {
                bw.WriteUTF16("filt");
            }
            bw.WriteUInt32((uint)Game);
            bw.WriteByte(0);
            bw.WriteBoolean(Unk0D);
            bw.WriteInt16(0);
            bw.WriteInt32(Groups.Count);
            bw.WriteInt32(Unk14);
            bw.ReserveInt32("HeaderSize");

            bw.ReserveInt32("GroupHeadersOffset");
            bw.ReserveInt32("ParamHeaderOffsetsOffset");
            bw.ReserveInt32("ParamHeadersOffset");
            bw.ReserveInt32("ValuesOffset");
            bw.ReserveInt32("ValueIDsOffset");
            bw.ReserveInt32("UnkOffset2");

            bw.WriteInt32(Unk3s.Count);
            bw.ReserveInt32("UnkOffset3");
            bw.ReserveInt32("Unk3ValuesOffset");
            bw.WriteInt32(0);

            if (Game == GPGame.DarkSouls3 || Game == GPGame.Sekiro)
            {
                bw.ReserveInt32("CommentOffsetsOffsetsOffset");
                bw.ReserveInt32("CommentOffsetsOffset");
                bw.ReserveInt32("CommentsOffset");
            }

            if (Game == GPGame.Sekiro)
            {
                bw.WriteSingle(Unk50);
            }

            bw.FillInt32("HeaderSize", (int)bw.Position);

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

            int groupHeadersOffset = (int)bw.Position;

            bw.FillInt32("GroupHeadersOffset", groupHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteHeader(bw, Game, i, groupHeadersOffset);
            }

            int paramHeaderOffsetsOffset = (int)bw.Position;

            bw.FillInt32("ParamHeaderOffsetsOffset", paramHeaderOffsetsOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaderOffsets(bw, i, paramHeaderOffsetsOffset);
            }

            int paramHeadersOffset = (int)bw.Position;

            bw.FillInt32("ParamHeadersOffset", paramHeadersOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteParamHeaders(bw, Game, i, paramHeadersOffset);
            }

            int valuesOffset = (int)bw.Position;

            bw.FillInt32("ValuesOffset", valuesOffset);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValues(bw, i, valuesOffset);
            }

            int valueIDsOffset = (int)bw.Position;

            bw.FillInt32("ValueIDsOffset", (int)bw.Position);
            for (int i = 0; i < Groups.Count; i++)
            {
                Groups[i].WriteValueIDs(bw, Game, i, valueIDsOffset);
            }

            bw.FillInt32("UnkOffset2", (int)bw.Position);
            bw.WriteBytes(UnkBlock2);

            bw.FillInt32("UnkOffset3", (int)bw.Position);
            for (int i = 0; i < Unk3s.Count; i++)
            {
                Unk3s[i].WriteHeader(bw, Game, i);
            }

            int unk3ValuesOffset = (int)bw.Position;

            bw.FillInt32("Unk3ValuesOffset", unk3ValuesOffset);
            for (int i = 0; i < Unk3s.Count; i++)
            {
                Unk3s[i].WriteValues(bw, Game, i, unk3ValuesOffset);
            }

            if (Game == GPGame.DarkSouls3 || Game == GPGame.Sekiro)
            {
                bw.FillInt32("CommentOffsetsOffsetsOffset", (int)bw.Position);
                for (int i = 0; i < Groups.Count; i++)
                {
                    Groups[i].WriteCommentOffsetsOffset(bw, i);
                }

                int commentOffsetsOffset = (int)bw.Position;
                bw.FillInt32("CommentOffsetsOffset", commentOffsetsOffset);
                for (int i = 0; i < Groups.Count; i++)
                {
                    Groups[i].WriteCommentOffsets(bw, i, commentOffsetsOffset);
                }

                int commentsOffset = (int)bw.Position;
                bw.FillInt32("CommentsOffset", commentsOffset);
                for (int i = 0; i < Groups.Count; i++)
                {
                    Groups[i].WriteComments(bw, i, commentsOffset);
                }
            }
        }
Example #16
0
        protected override void Write(BinaryWriterEx bw)
        {
            bool bigEndian = Format == Game.DarkSouls1BE;
            bool is64Bit   = Format >= Game.Bloodborne;
            bool unk06     = Format >= Game.DarkSouls3;
            bool unk07     = Format >= Game.Sekiro;
            int  version   = Format < Game.DarkSouls3 ? 0xCC : 0xCD;

            var layers = new List <uint>();

            foreach (Event evt in Events)
            {
                foreach (Instruction inst in evt.Instructions)
                {
                    if (inst.Layer.HasValue && !layers.Contains(inst.Layer.Value))
                    {
                        layers.Add(inst.Layer.Value);
                    }
                }
            }

            bw.WriteASCII("EVD\0");
            bw.WriteBoolean(bigEndian);
            bw.WriteSByte((sbyte)(is64Bit ? -1 : 0));
            bw.WriteBoolean(unk06);
            bw.WriteSByte((sbyte)(unk07 ? -1 : 0));
            bw.BigEndian  = bigEndian;
            bw.VarintLong = is64Bit;

            bw.WriteInt32(version);
            bw.ReserveInt32("FileSize");

            Offsets offsets = default;

            bw.WriteVarint(Events.Count);
            bw.ReserveVarint("EventsOffset");
            bw.WriteVarint(Events.Sum(e => e.Instructions.Count));
            bw.ReserveVarint("InstructionsOffset");
            bw.WriteVarint(0);
            bw.ReserveVarint("Offset3");
            bw.WriteVarint(layers.Count);
            bw.ReserveVarint("LayersOffset");
            bw.WriteVarint(Events.Sum(e => e.Parameters.Count));
            bw.ReserveVarint("ParametersOffset");
            bw.WriteVarint(LinkedFileOffsets.Count);
            bw.ReserveVarint("LinkedFilesOffset");
            bw.ReserveVarint("ArgumentsLength");
            bw.ReserveVarint("ArgumentsOffset");
            bw.WriteVarint(StringData.Length);
            bw.ReserveVarint("StringsOffset");
            if (!is64Bit)
            {
                bw.WriteInt32(0);
            }

            offsets.Events = bw.Position;
            bw.FillVarint("EventsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].Write(bw, Format, i);
            }

            offsets.Instructions = bw.Position;
            bw.FillVarint("InstructionsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].WriteInstructions(bw, Format, offsets, i);
            }

            bw.FillVarint("Offset3", bw.Position);

            offsets.Layers = bw.Position;
            bw.FillVarint("LayersOffset", bw.Position);
            var layerOffsets = new Dictionary <uint, long>(layers.Count);

            foreach (uint layer in layers)
            {
                layerOffsets[layer] = bw.Position - offsets.Layers;
                Layer.Write(bw, layer);
            }
            for (int i = 0; i < Events.Count; i++)
            {
                Event evt = Events[i];
                for (int j = 0; j < evt.Instructions.Count; j++)
                {
                    evt.Instructions[j].FillLayerOffset(bw, Format, i, j, layerOffsets);
                }
            }

            offsets.Arguments = bw.Position;
            bw.FillVarint("ArgumentsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Event evt = Events[i];
                for (int j = 0; j < evt.Instructions.Count; j++)
                {
                    evt.Instructions[j].WriteArgs(bw, Format, offsets, i, j);
                }
            }
            if ((bw.Position - offsets.Arguments) % 0x10 > 0)
            {
                bw.WritePattern(0x10 - (int)(bw.Position - offsets.Arguments) % 0x10, 0x00);
            }
            bw.FillVarint("ArgumentsLength", bw.Position - offsets.Arguments);

            offsets.Parameters = bw.Position;
            bw.FillVarint("ParametersOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].WriteParameters(bw, Format, offsets, i);
            }

            offsets.LinkedFiles = bw.Position;
            bw.FillVarint("LinkedFilesOffset", bw.Position);
            foreach (long offset in LinkedFileOffsets)
            {
                bw.WriteVarint((int)offset);
            }

            offsets.Strings = bw.Position;
            bw.FillVarint("StringsOffset", bw.Position);
            bw.WriteBytes(StringData);

            bw.FillInt32("FileSize", (int)bw.Position);
        }
Example #17
0
        /// <summary>
        /// Serializes file data to a stream.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = false;

            bw.WriteASCII(LongFormat ? "fsSL" : "fSSL");
            bw.WriteInt32(1);
            bw.WriteInt32(DarkSoulsCount);
            bw.WriteInt32(DarkSoulsCount);
            bw.WriteInt32(0x54);
            bw.ReserveInt32("DataSize");
            bw.WriteInt32(6);
            bw.WriteInt32(LongFormat ? 0x48 : 0x2C);
            bw.WriteInt32(1);
            bw.WriteInt32(LongFormat ? 0x20 : 0x10);
            bw.WriteInt32(StateGroups.Count);
            int stateSize = LongFormat ? 0x48 : 0x24;

            bw.WriteInt32(stateSize);
            bw.WriteInt32(StateGroups.Values.Sum(sg => sg.Count + (sg.Count == 1 ? 0 : 1)));
            bw.WriteInt32(LongFormat ? 0x38 : 0x1C);
            bw.ReserveInt32("ConditionCount");
            bw.WriteInt32(LongFormat ? 0x18 : 0x10);
            bw.ReserveInt32("CommandCallCount");
            bw.WriteInt32(LongFormat ? 0x10 : 0x8);
            bw.ReserveInt32("CommandArgCount");
            bw.ReserveInt32("ConditionOffsetsOffset");
            bw.ReserveInt32("ConditionOffsetsCount");
            bw.ReserveInt32("NameBlockOffset");
            bw.WriteInt32(Name == null ? 0 : Name.Length + 1);
            bw.ReserveInt32("UnkOffset1");
            bw.WriteInt32(0);
            bw.ReserveInt32("UnkOffset2");
            bw.WriteInt32(0);

            long dataStart = bw.Position;

            bw.WriteInt32(1);
            bw.WriteInt32(Unk70);
            bw.WriteInt32(Unk74);
            bw.WriteInt32(Unk78);
            bw.WriteInt32(Unk7C);
            if (LongFormat)
            {
                bw.WriteInt32(0);
            }

            ReserveVarint(bw, LongFormat, "StateGroupsOffset");
            WriteVarint(bw, LongFormat, StateGroups.Count);
            ReserveVarint(bw, LongFormat, "NameOffset");
            WriteVarint(bw, LongFormat, Name == null ? 0 : Name.Length + 1);
            long unkNull = DarkSoulsCount == 1 ? 0 : -1;

            WriteVarint(bw, LongFormat, unkNull);
            WriteVarint(bw, LongFormat, unkNull);

            // Collect and sort all the IDs so everything is definitely in the same order everywhere
            List <long> stateGroupIDs = StateGroups.Keys.ToList();

            stateGroupIDs.Sort();
            var stateIDs = new Dictionary <long, List <long> >();

            foreach (long groupID in stateGroupIDs)
            {
                stateIDs[groupID] = StateGroups[groupID].Keys.ToList();
                stateIDs[groupID].Sort();
            }

            if (StateGroups.Count == 0)
            {
                FillVarint(bw, LongFormat, "StateGroupsOffset", -1);
            }
            else
            {
                FillVarint(bw, LongFormat, "StateGroupsOffset", bw.Position - dataStart);
                foreach (long groupID in stateGroupIDs)
                {
                    WriteVarint(bw, LongFormat, groupID);
                    ReserveVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset1");
                    WriteVarint(bw, LongFormat, StateGroups[groupID].Count);
                    ReserveVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset2");
                }
            }

            var stateOffsets      = new Dictionary <long, Dictionary <long, long> >();
            var weirdStateOffsets = new List <long[]>();

            foreach (long groupID in stateGroupIDs)
            {
                stateOffsets[groupID] = new Dictionary <long, long>();
                FillVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset1", bw.Position - dataStart);
                FillVarint(bw, LongFormat, $"StateGroup{groupID}:StatesOffset2", bw.Position - dataStart);
                long firstStateOffset = bw.Position;
                foreach (long stateID in stateIDs[groupID])
                {
                    stateOffsets[groupID][stateID] = bw.Position - dataStart;
                    StateGroups[groupID][stateID].WriteHeader(bw, LongFormat, groupID, stateID);
                }
                if (StateGroups[groupID].Count > 1)
                {
                    weirdStateOffsets.Add(new long[] { firstStateOffset, bw.Position });
                    bw.Position += stateSize;
                }
            }

            // Make a list of every unique condition
            var conditions = new Dictionary <long, List <Condition> >();

            foreach (long groupID in stateGroupIDs)
            {
                conditions[groupID] = new List <Condition>();
                void addCondition(Condition cond)
                {
                    if (!conditions[groupID].Any(c => ReferenceEquals(cond, c)))
                    {
                        conditions[groupID].Add(cond);
                        foreach (Condition subCond in cond.Subconditions)
                        {
                            addCondition(subCond);
                        }
                    }
                }

                foreach (State state in StateGroups[groupID].Values)
                {
                    foreach (Condition cond in state.Conditions)
                    {
                        addCondition(cond);
                    }
                }
            }
            bw.FillInt32("ConditionCount", conditions.Values.Sum(group => group.Count));

            // Yes, I do in fact want this to be keyed by reference
            var conditionOffsets = new Dictionary <Condition, long>();

            foreach (long groupID in stateGroupIDs)
            {
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    Condition cond = conditions[groupID][i];
                    conditionOffsets[cond] = bw.Position - dataStart;
                    cond.WriteHeader(bw, LongFormat, groupID, i, stateOffsets[groupID]);
                }
            }

            var commands = new List <CommandCall>();

            foreach (long groupID in stateGroupIDs)
            {
                foreach (long stateID in stateIDs[groupID])
                {
                    StateGroups[groupID][stateID].WriteCommandCalls(bw, LongFormat, groupID, stateID, dataStart, commands);
                }
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditions[groupID][i].WriteCommandCalls(bw, LongFormat, groupID, i, dataStart, commands);
                }
            }
            bw.FillInt32("CommandCallCount", commands.Count);
            bw.FillInt32("CommandArgCount", commands.Sum(command => command.Arguments.Count));

            for (int i = 0; i < commands.Count; i++)
            {
                commands[i].WriteArgs(bw, LongFormat, i, dataStart);
            }

            bw.FillInt32("ConditionOffsetsOffset", (int)(bw.Position - dataStart));
            int conditionOffsetsCount = 0;

            foreach (long groupID in stateGroupIDs)
            {
                foreach (long stateID in stateIDs[groupID])
                {
                    conditionOffsetsCount += StateGroups[groupID][stateID].WriteConditionOffsets(bw, LongFormat, groupID, stateID, dataStart, conditionOffsets);
                }
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditionOffsetsCount += conditions[groupID][i].WriteConditionOffsets(bw, LongFormat, groupID, i, dataStart, conditionOffsets);
                }
            }
            bw.FillInt32("ConditionOffsetsCount", conditionOffsetsCount);

            foreach (long groupID in stateGroupIDs)
            {
                for (int i = 0; i < conditions[groupID].Count; i++)
                {
                    conditions[groupID][i].WriteEvaluator(bw, LongFormat, groupID, i, dataStart);
                }
            }
            for (int i = 0; i < commands.Count; i++)
            {
                commands[i].WriteBytecode(bw, LongFormat, i, dataStart);
            }

            bw.FillInt32("NameBlockOffset", (int)(bw.Position - dataStart));
            if (Name == null)
            {
                FillVarint(bw, LongFormat, "NameOffset", -1);
            }
            else
            {
                bw.Pad(2);
                FillVarint(bw, LongFormat, "NameOffset", bw.Position - dataStart);
                bw.WriteUTF16(Name, true);
            }
            bw.FillInt32("UnkOffset1", (int)(bw.Position - dataStart));
            bw.FillInt32("UnkOffset2", (int)(bw.Position - dataStart));
            bw.FillInt32("DataSize", (int)(bw.Position - dataStart));

            if (DarkSoulsCount == 1)
            {
                bw.Pad(4);
            }
            else if (DarkSoulsCount == 2)
            {
                bw.Pad(0x10);
            }

            foreach (long[] offsets in weirdStateOffsets)
            {
                bw.Position = offsets[0];
                byte[] bytes = new byte[stateSize];
                bw.Stream.Read(bytes, 0, stateSize);
                bw.Position = offsets[1];
                bw.WriteBytes(bytes);
            }
        }
Example #18
0
            // <summary>
            // Convert the internal format to PC tpf format
            // </summary>
            public void ConsoleToPC(TPFPlatform source)
            {
                // Need to create a DDS Header
                BinaryWriterEx bw = new BinaryWriterEx(false);

                bw.WriteASCII("DDS ");
                bw.WriteInt32(124);
                bw.WriteUInt32(659463); // Flags
                bw.WriteUInt32((uint)Header.Height);
                bw.WriteUInt32((uint)Header.Width);
                bw.WriteUInt32(((uint)Header.Width * (uint)Header.Height) / 2); // Dummy pitch size
                bw.WriteUInt32(1);                                              // Depth
                if (source == TPFPlatform.PS3)
                {
                    // DeS sometimes has mipmap count set to 0 :trashcat:
                    if (Mipmaps == 0)
                    {
                        var dim = Math.Max(Header.Width, Header.Height);
                        while (dim >= 1)
                        {
                            Mipmaps++;
                            dim >>= 1;
                        }
                    }
                }
                bw.WriteUInt32(Mipmaps);
                for (int i = 0; i < 11; i++)
                {
                    bw.WriteInt32(0);
                }
                // Pixel format
                bw.WriteInt32(32);
                bw.WriteInt32(4); // Flags (compressed)
                bool writeExtendedHeader = false;

                if (Header.DXGIFormat == 71 || Header.DXGIFormat == 72 || (source == TPFPlatform.PS3 && (Format == 0 || Format == 1)))
                {
                    bw.WriteASCII("DXT1");
                }
                else if (Header.DXGIFormat == 73 || Header.DXGIFormat == 74 || Header.DXGIFormat == 75 || (source == TPFPlatform.PS3 && (Format == 2 || Format == 3)))
                {
                    bw.WriteASCII("DXT3");
                }
                else if (Header.DXGIFormat == 76 || Header.DXGIFormat == 77 || Header.DXGIFormat == 78 || (source == TPFPlatform.PS3 && (Format == 4 || Format == 5)))
                {
                    bw.WriteASCII("DXT5");
                }
                else if (Header.DXGIFormat == 79 || Header.DXGIFormat == 80 || Header.DXGIFormat == 81)
                {
                    bw.WriteASCII("ATI1");
                }
                else if (Header.DXGIFormat == 82 || Header.DXGIFormat == 83 || Header.DXGIFormat == 84)
                {
                    bw.WriteASCII("ATI2");
                }
                else if (source == TPFPlatform.PS3 && (Format == 9 || Format == 10))
                {
                    bw.WriteASCII("DXT1");
                    Console.WriteLine("ARGB");
                }
                else
                {
                    bw.WriteASCII("DX10");
                    writeExtendedHeader = true;
                }
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);

                bw.WriteUInt32(0x401008); // Caps
                if (Cubemap)
                {
                    bw.WriteUInt32(0xFE00);
                }
                else
                {
                    bw.WriteUInt32(0);
                }
                bw.WriteUInt32(0);
                bw.WriteUInt32(0);
                bw.WriteUInt32(0);

                // DX10 extended header
                if (writeExtendedHeader)
                {
                    bw.WriteInt32(Header.DXGIFormat);
                    bw.WriteUInt32(3); // 2D texture
                    if (Cubemap)
                    {
                        bw.WriteUInt32(0x4);
                    }
                    else
                    {
                        bw.WriteUInt32(0);
                    }
                    bw.WriteUInt32(1); // Array Size
                    bw.WriteUInt32(0); // Misc
                }

                // Next attempt to unswizzle the texture
                byte[] unswizzled = new byte[Bytes.Length];
                for (int i = 0; i < unswizzled.Length; i++)
                {
                    unswizzled[i] = Bytes[i];
                }

                if (source == TPFPlatform.PS4)
                {
                    uint blockSize = 16;
                    if (Header.DXGIFormat == 71 || Header.DXGIFormat == 72 || Header.DXGIFormat == 79 || Header.DXGIFormat == 80 || Header.DXGIFormat == 81)
                    {
                        blockSize = 8;
                    }

                    int mipBase    = 0;
                    int mipBaseSrc = 0;
                    for (int miplevel = 0; miplevel < Mipmaps; miplevel++)
                    {
                        uint bytesPerLine = Math.Max((uint)Header.Width >> miplevel, 1) * blockSize / 4;
                        int  heightBlock  = Math.Max((Header.Height / 4) >> miplevel, 1);
                        int  widthBlock   = Math.Max((Header.Width / 4) >> miplevel, 1);
                        // Convert swizzled to linear strided

                        int index = 0;
                        for (int y = 0; y < heightBlock; y++)
                        {
                            for (int x = 0; x < widthBlock; x++)
                            {
                                int mx = x;
                                int my = y;
                                if (widthBlock > 1 && heightBlock > 1)
                                {
                                    MapBlockPosition(x, y, widthBlock, 2, out mx, out my);
                                }

                                if (widthBlock > 2 && heightBlock > 2)
                                {
                                    MapBlockPosition(mx, my, widthBlock, 4, out mx, out my);
                                }

                                if (widthBlock > 4 && heightBlock > 4)
                                {
                                    MapBlockPosition(mx, my, widthBlock, 8, out mx, out my);
                                }

                                int destinationIndex = (int)blockSize * (my * widthBlock + mx);
                                for (int i = 0; i < blockSize; i++)
                                {
                                    unswizzled[mipBase + destinationIndex + i] = Bytes[mipBaseSrc + index];
                                    index += 1;
                                }
                            }
                        }

                        mipBase += index;
                        if (index < 512)
                        {
                            mipBaseSrc += 512;
                        }
                        else
                        {
                            mipBaseSrc += index;
                        }
                    }
                }

                // Append the rest of the original texture and update
                bw.WriteBytes(unswizzled);
                Bytes = bw.FinishBytes();
            }
Example #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;
            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
        }
Example #20
0
        /// <summary>
        /// Writes FLVER data to a BinaryWriterEx.
        /// </summary>
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian = Header.BigEndian;
            bw.WriteASCII("FLVER\0");
            bw.WriteASCII(Header.BigEndian ? "B\0" : "L\0");
            bw.WriteInt32(Header.Version);

            bw.ReserveInt32("DataOffset");
            bw.ReserveInt32("DataSize");
            bw.WriteInt32(Dummies.Count);
            bw.WriteInt32(Materials.Count);
            bw.WriteInt32(Bones.Count);
            bw.WriteInt32(Meshes.Count);
            bw.WriteInt32(Meshes.Sum(m => m.VertexBuffers.Count));
            bw.WriteVector3(Header.BoundingBoxMin);
            bw.WriteVector3(Header.BoundingBoxMax);

            int trueFaceCount  = 0;
            int totalFaceCount = 0;

            foreach (Mesh mesh in Meshes)
            {
                bool allowPrimitiveRestarts = mesh.Vertices.Length < ushort.MaxValue;
                foreach (FaceSet faceSet in mesh.FaceSets)
                {
                    faceSet.AddFaceCounts(allowPrimitiveRestarts, ref trueFaceCount, ref totalFaceCount);
                }
            }
            bw.WriteInt32(trueFaceCount);
            bw.WriteInt32(totalFaceCount);

            byte vertexIndicesSize = 0;

            if (Header.Version < 0x20013)
            {
                vertexIndicesSize = 16;
                foreach (Mesh mesh in Meshes)
                {
                    foreach (FaceSet fs in mesh.FaceSets)
                    {
                        vertexIndicesSize = (byte)Math.Max(vertexIndicesSize, fs.GetVertexIndexSize());
                    }
                }
            }

            bw.WriteByte(vertexIndicesSize);
            bw.WriteBoolean(Header.Unicode);
            bw.WriteBoolean(Header.Unk4A);
            bw.WriteByte(0);

            bw.WriteInt32(Header.Unk4C);

            bw.WriteInt32(Meshes.Sum(m => m.FaceSets.Count));
            bw.WriteInt32(BufferLayouts.Count);
            bw.WriteInt32(Materials.Sum(m => m.Textures.Count));

            bw.WriteByte(Header.Unk5C);
            bw.WriteByte(Header.Unk5D);
            bw.WriteByte(0);
            bw.WriteByte(0);

            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(Header.Unk68);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);
            bw.WriteInt32(0);

            foreach (FLVER.Dummy dummy in Dummies)
            {
                dummy.Write(bw, Header.Version);
            }

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

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

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

            int faceSetIndex = 0;

            foreach (Mesh mesh in Meshes)
            {
                for (int i = 0; i < mesh.FaceSets.Count; i++)
                {
                    int indexSize = vertexIndicesSize;
                    if (indexSize == 0)
                    {
                        indexSize = mesh.FaceSets[i].GetVertexIndexSize();
                    }

                    mesh.FaceSets[i].Write(bw, Header, indexSize, faceSetIndex + i);
                }
                faceSetIndex += mesh.FaceSets.Count;
            }

            int vertexBufferIndex = 0;

            foreach (Mesh mesh in Meshes)
            {
                for (int i = 0; i < mesh.VertexBuffers.Count; i++)
                {
                    mesh.VertexBuffers[i].Write(bw, Header, vertexBufferIndex + i, i, BufferLayouts, mesh.Vertices.Length);
                }
                vertexBufferIndex += mesh.VertexBuffers.Count;
            }

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

            int textureIndex = 0;

            for (int i = 0; i < Materials.Count; i++)
            {
                Materials[i].WriteTextures(bw, i, textureIndex);
                textureIndex += Materials[i].Textures.Count;
            }

            if (Header.Version >= 0x2001A)
            {
                SekiroUnk.Write(bw);
            }

            bw.Pad(0x10);
            for (int i = 0; i < BufferLayouts.Count; i++)
            {
                BufferLayouts[i].WriteMembers(bw, i);
            }

            bw.Pad(0x10);
            for (int i = 0; i < Meshes.Count; i++)
            {
                Meshes[i].WriteBoundingBox(bw, i, Header);
            }

            bw.Pad(0x10);
            int boneIndicesStart = (int)bw.Position;

            for (int i = 0; i < Meshes.Count; i++)
            {
                Meshes[i].WriteBoneIndices(bw, i, boneIndicesStart);
            }

            bw.Pad(0x10);
            faceSetIndex = 0;
            for (int i = 0; i < Meshes.Count; i++)
            {
                bw.FillInt32($"MeshFaceSetIndices{i}", (int)bw.Position);
                for (int j = 0; j < Meshes[i].FaceSets.Count; j++)
                {
                    bw.WriteInt32(faceSetIndex + j);
                }
                faceSetIndex += Meshes[i].FaceSets.Count;
            }

            bw.Pad(0x10);
            vertexBufferIndex = 0;
            for (int i = 0; i < Meshes.Count; i++)
            {
                bw.FillInt32($"MeshVertexBufferIndices{i}", (int)bw.Position);
                for (int j = 0; j < Meshes[i].VertexBuffers.Count; j++)
                {
                    bw.WriteInt32(vertexBufferIndex + j);
                }
                vertexBufferIndex += Meshes[i].VertexBuffers.Count;
            }

            bw.Pad(0x10);
            var gxOffsets = new List <int>();

            foreach (GXList gxList in GXLists)
            {
                gxOffsets.Add((int)bw.Position);
                gxList.Write(bw, Header);
            }
            for (int i = 0; i < Materials.Count; i++)
            {
                Materials[i].FillGXOffset(bw, i, gxOffsets);
            }

            bw.Pad(0x10);
            textureIndex = 0;
            for (int i = 0; i < Materials.Count; i++)
            {
                Material material = Materials[i];
                material.WriteStrings(bw, Header, i);

                for (int j = 0; j < material.Textures.Count; j++)
                {
                    material.Textures[j].WriteStrings(bw, Header, textureIndex + j);
                }
                textureIndex += material.Textures.Count;
            }

            bw.Pad(0x10);
            for (int i = 0; i < Bones.Count; i++)
            {
                Bones[i].WriteStrings(bw, Header.Unicode, i);
            }

            int alignment = Header.Version <= 0x2000E ? 0x20 : 0x10;

            bw.Pad(alignment);
            if (Header.Version == 0x2000F || Header.Version == 0x20010)
            {
                bw.Pad(0x20);
            }

            int dataStart = (int)bw.Position;

            bw.FillInt32("DataOffset", dataStart);

            faceSetIndex      = 0;
            vertexBufferIndex = 0;
            for (int i = 0; i < Meshes.Count; i++)
            {
                Mesh mesh = Meshes[i];
                for (int j = 0; j < mesh.FaceSets.Count; j++)
                {
                    int indexSize = vertexIndicesSize;
                    if (indexSize == 0)
                    {
                        indexSize = mesh.FaceSets[j].GetVertexIndexSize();
                    }

                    bw.Pad(alignment);
                    mesh.FaceSets[j].WriteVertices(bw, indexSize, faceSetIndex + j, dataStart);
                }
                faceSetIndex += mesh.FaceSets.Count;

                foreach (FLVER.Vertex vertex in mesh.Vertices)
                {
                    vertex.PrepareWrite();
                }

                for (int j = 0; j < mesh.VertexBuffers.Count; j++)
                {
                    bw.Pad(alignment);
                    mesh.VertexBuffers[j].WriteBuffer(bw, vertexBufferIndex + j, BufferLayouts, mesh.Vertices, dataStart, Header);
                }

                foreach (FLVER.Vertex vertex in mesh.Vertices)
                {
                    vertex.FinishWrite();
                }

                vertexBufferIndex += mesh.VertexBuffers.Count;
            }

            bw.Pad(alignment);
            bw.FillInt32("DataSize", (int)bw.Position - dataStart);
            if (Header.Version == 0x2000F || Header.Version == 0x20010)
            {
                bw.Pad(0x20);
            }
        }
Example #21
0
        internal override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("EVD\0");

            if (Game == GameType.DS1)
            {
                bw.WriteUInt32(0);
                bw.WriteUInt32(0xCC);
            }
            else if (Game == GameType.BB)
            {
                bw.WriteUInt32(0xFF00);
                bw.WriteUInt32(0xCC);
            }
            else if (Game == GameType.DS3)
            {
                bw.WriteUInt32(0x1FF00);
                bw.WriteUInt32(0xCD);
            }

            void ReserveIntW(string name, bool?isWide = null)
            {
                if (isWide ?? Game != GameType.DS1)
                {
                    bw.ReserveInt64(name);
                }
                else
                {
                    bw.ReserveInt32(name);
                }
            }

            void FillIntW(string name, long value, bool?isWide = null)
            {
                if (isWide ?? Game != GameType.DS1)
                {
                    bw.FillInt64(name, value);
                }
                else
                {
                    bw.FillInt32(name, (int)value);
                }
            }

            void WriteIntW(long value, bool?isWide = null)
            {
                if (isWide ?? Game != GameType.DS1)
                {
                    bw.WriteInt64(value);
                }
                else
                {
                    bw.WriteInt32((int)value);
                }
            }

            if (Game == GameType.BB)
            {
                bw.ReserveInt64("FileLength");
            }
            else
            {
                bw.ReserveInt32("FileLength");
            }

            WriteIntW(Events.Count);
            ReserveIntW("EventsOffset");
            ReserveIntW("InstructionsCount");
            ReserveIntW("InstructionsOffset");

            //Dummy count. Always empty.
            WriteIntW(0);
            // Same as EventLayersOffset because it's always empty.
            ReserveIntW("DummiesOffset");
            ReserveIntW("EventLayersCount");
            ReserveIntW("EventLayersOffset");
            ReserveIntW("ParametersCount");
            ReserveIntW("ParametersOffset");
            WriteIntW(LinkedFileStringIndices.Count);
            ReserveIntW("LinkedFilesOffset");
            ReserveIntW("ArgsBlockSize");
            ReserveIntW("ArgsBlockOffset");
            ReserveIntW("StringsBlockSize");
            ReserveIntW("StringsBlockOffset");

            if (Game == GameType.DS1)
            {
                bw.WriteInt32(0);
            }

            // Events
            FillIntW("EventsOffset", bw.Position);
            for (int i = 0; i < Events.Count; i++)
            {
                Events[i].Write(bw, Game, i);
            }

            // Instructions
            long instructionsOffset = bw.Position;

            FillIntW("InstructionsOffset", instructionsOffset);
            long instructionsCount = 0;

            for (int i = 0; i < Events.Count; i++)
            {
                FillIntW($"EventInstructionsOffset{i}", bw.Position - instructionsOffset);
                for (int j = 0; j < Events[i].Instructions.Count; j++)
                {
                    Events[i].Instructions[j].Write(bw, Game, i, j);
                }
                instructionsCount += Events[i].Instructions.Count;
            }
            FillIntW("InstructionsCount", instructionsCount);

            // Dummies
            FillIntW("DummiesOffset", bw.Position);

            // EventLayers
            long eventLayersOffset = bw.Position;

            FillIntW("EventLayersOffset", eventLayersOffset);
            long eventLayersCount = 0;

            for (int i = 0; i < Events.Count; i++)
            {
                for (int j = 0; j < Events[i].Instructions.Count; j++)
                {
                    if (Events[i].Instructions[j].Layer != null)
                    {
                        if (Game == GameType.DS3)
                        {
                            bw.FillInt64($"InstructionLayerOffset{i}:{j}", bw.Position - eventLayersOffset);
                        }
                        else
                        {
                            bw.FillInt32($"InstructionLayerOffset{i}:{j}", (int)(bw.Position - eventLayersOffset));
                        }
                        Events[i].Instructions[j].Layer.Write(bw, Game);
                        eventLayersCount++;
                    }
                }
            }
            FillIntW("EventLayersCount", eventLayersCount);

            // Args
            long argsBlockOffset = bw.Position;

            FillIntW("ArgsBlockOffset", argsBlockOffset);
            for (int i = 0; i < Events.Count; i++)
            {
                for (int j = 0; j < Events[i].Instructions.Count; j++)
                {
                    if (Events[i].Instructions[j].Args.Length > 0)
                    {
                        bw.FillInt32($"InstructionArgsOffset{i}:{j}", (int)(bw.Position - argsBlockOffset));
                        bw.WriteBytes(Events[i].Instructions[j].Args);
                        //bw.Pad(4);
                    }
                }
            }

            if (Game == GameType.DS1)
            {
                if ((bw.Position - argsBlockOffset) % 16 > 0)
                {
                    bw.WritePattern(16 - (int)(bw.Position - argsBlockOffset) % 16, 0x00);
                }
            }
            else
            {
                bw.Pad(16);
            }

            FillIntW("ArgsBlockSize", bw.Position - argsBlockOffset);

            // Parameters
            long parametersOffset = bw.Position;

            FillIntW("ParametersOffset", parametersOffset);
            long parametersCount = 0;

            for (int i = 0; i < Events.Count; i++)
            {
                if (Events[i].Parameters.Count > 0)
                {
                    if (Game == GameType.DS3)
                    {
                        bw.FillInt64($"EventParametersOffset{i}", bw.Position - parametersOffset);
                    }
                    else
                    {
                        bw.FillInt32($"EventParametersOffset{i}", (int)(bw.Position - parametersOffset));
                    }
                    for (int j = 0; j < Events[i].Parameters.Count; j++)
                    {
                        Events[i].Parameters[j].Write(bw, Game);
                    }
                    parametersCount += Events[i].Parameters.Count;
                }
            }
            FillIntW("ParametersCount", parametersCount);

            // Linked Files
            FillIntW("LinkedFilesOffset", bw.Position);
            for (int i = 0; i < LinkedFileStringIndices.Count; i++)
            {
                ReserveIntW($"LinkedFileStringOffset{i}");
            }

            // Strings
            FillIntW("StringsBlockOffset", bw.Position);
            long        stringsStartOffset = bw.Position;
            List <long> stringTableOffsets = new List <long>();

            for (int i = 0; i < StringTable.Count; i++)
            {
                stringTableOffsets.Add(bw.Position - stringsStartOffset);
                bw.WriteUTF16(StringTable[i], terminate: true);
            }
            FillIntW("StringsBlockSize", bw.Position - stringsStartOffset);

            // Linked Files - Second Pass
            for (int i = 0; i < LinkedFileStringIndices.Count; i++)
            {
                FillIntW($"LinkedFileStringOffset{i}", stringTableOffsets[LinkedFileStringIndices[i]]);
            }

            if (Game == GameType.BB)
            {
                bw.FillInt64("FileLength", bw.Position);
            }
            else
            {
                bw.FillInt32("FileLength", (int)bw.Position);
            }
        }
Example #22
0
        protected override void Write(BinaryWriterEx bw)
        {
            bw.WriteASCII("FXR\0");
            bw.WriteInt16(0);
            bw.WriteUInt16((ushort)Version);
            bw.WriteInt32(1);
            bw.WriteInt32(ID);
            bw.ReserveInt32("Section1Offset");
            bw.WriteInt32(1);
            bw.ReserveInt32("Section2Offset");
            bw.WriteInt32(Section1Tree.Section2s.Count);
            bw.ReserveInt32("Section3Offset");
            bw.ReserveInt32("Section3Count");
            bw.ReserveInt32("Section4Offset");
            bw.ReserveInt32("Section4Count");
            bw.ReserveInt32("Section5Offset");
            bw.ReserveInt32("Section5Count");
            bw.ReserveInt32("Section6Offset");
            bw.ReserveInt32("Section6Count");
            bw.ReserveInt32("Section7Offset");
            bw.ReserveInt32("Section7Count");
            bw.ReserveInt32("Section8Offset");
            bw.ReserveInt32("Section8Count");
            bw.ReserveInt32("Section9Offset");
            bw.ReserveInt32("Section9Count");
            bw.ReserveInt32("Section10Offset");
            bw.ReserveInt32("Section10Count");
            bw.ReserveInt32("Section11Offset");
            bw.ReserveInt32("Section11Count");
            bw.WriteInt32(1);
            bw.WriteInt32(0);

            if (Version == FXRVersion.Sekiro)
            {
                bw.ReserveInt32("Section12Offset");
                bw.WriteInt32(Section12s.Count);
                bw.ReserveInt32("Section13Offset");
                bw.WriteInt32(Section13s.Count);
                bw.ReserveInt32("Section14Offset");
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
            }

            bw.FillInt32("Section1Offset", (int)bw.Position);
            Section1Tree.Write(bw);
            bw.Pad(0x10);

            bw.FillInt32("Section2Offset", (int)bw.Position);
            Section1Tree.WriteSection2s(bw);
            bw.Pad(0x10);

            bw.FillInt32("Section3Offset", (int)bw.Position);
            List <Section2> section2s = Section1Tree.Section2s;
            var             section3s = new List <Section3>();

            for (int i = 0; i < section2s.Count; i++)
            {
                section2s[i].WriteSection3s(bw, i, section3s);
            }
            bw.FillInt32("Section3Count", section3s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section4Offset", (int)bw.Position);
            var section4s = new List <Section4>();

            Section4Tree.Write(bw, section4s);
            Section4Tree.WriteSection4s(bw, section4s);
            bw.FillInt32("Section4Count", section4s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section5Offset", (int)bw.Position);
            int section5Count = 0;

            for (int i = 0; i < section4s.Count; i++)
            {
                section4s[i].WriteSection5s(bw, i, ref section5Count);
            }
            bw.FillInt32("Section5Count", section5Count);
            bw.Pad(0x10);

            bw.FillInt32("Section6Offset", (int)bw.Position);
            section5Count = 0;
            var section6s = new List <FFXDrawEntityHost>();

            for (int i = 0; i < section4s.Count; i++)
            {
                section4s[i].WriteSection6s(bw, i, ref section5Count, section6s);
            }
            bw.FillInt32("Section6Count", section6s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section7Offset", (int)bw.Position);
            var section7s = new List <FFXProperty>();

            for (int i = 0; i < section6s.Count; i++)
            {
                section6s[i].WriteSection7s(bw, i, section7s);
            }
            bw.FillInt32("Section7Count", section7s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section8Offset", (int)bw.Position);
            var section8s = new List <Section8>();

            for (int i = 0; i < section7s.Count; i++)
            {
                section7s[i].WriteSection8s(bw, i, section8s);
            }
            bw.FillInt32("Section8Count", section8s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section9Offset", (int)bw.Position);
            var section9s = new List <Section9>();

            for (int i = 0; i < section8s.Count; i++)
            {
                section8s[i].WriteSection9s(bw, i, section9s);
            }
            bw.FillInt32("Section9Count", section9s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section10Offset", (int)bw.Position);
            var section10s = new List <Section10>();

            for (int i = 0; i < section6s.Count; i++)
            {
                section6s[i].WriteSection10s(bw, i, section10s);
            }
            bw.FillInt32("Section10Count", section10s.Count);
            bw.Pad(0x10);

            bw.FillInt32("Section11Offset", (int)bw.Position);
            int section11Count = 0;

            for (int i = 0; i < section3s.Count; i++)
            {
                section3s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section6s.Count; i++)
            {
                section6s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section7s.Count; i++)
            {
                section7s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section8s.Count; i++)
            {
                section8s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section9s.Count; i++)
            {
                section9s[i].WriteSection11s(bw, i, ref section11Count);
            }
            for (int i = 0; i < section10s.Count; i++)
            {
                section10s[i].WriteSection11s(bw, i, ref section11Count);
            }
            bw.FillInt32("Section11Count", section11Count);
            bw.Pad(0x10);

            if (Version == FXRVersion.Sekiro)
            {
                bw.FillInt32("Section12Offset", (int)bw.Position);
                bw.WriteInt32s(Section12s);
                bw.Pad(0x10);

                bw.FillInt32("Section13Offset", (int)bw.Position);
                bw.WriteInt32s(Section13s);
                bw.Pad(0x10);

                bw.FillInt32("Section14Offset", (int)bw.Position);
            }
        }
Example #23
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);
            }
        }
Example #24
0
        protected override void Write(BinaryWriterEx bw)
        {
            bw.BigEndian  = BigEndian;
            bw.VarintLong = Version == NGPVersion.Scholar;

            bw.WriteASCII("NVG2");
            bw.WriteUInt16((ushort)Version);
            bw.WriteInt16(0);
            bw.WriteInt32(Meshes.Count);
            bw.WriteInt32(StructAs.Count);
            bw.WriteInt32(StructBs.Count);
            bw.WriteInt32(StructCs.Count);
            bw.WriteInt32(StructDs.Count);
            bw.WriteInt32(Unk1C);
            bw.ReserveVarint("OffsetA");
            bw.ReserveVarint("OffsetB");
            bw.ReserveVarint("OffsetC");
            bw.ReserveVarint("OffsetD");
            for (int i = 0; i < Meshes.Count; i++)
            {
                bw.ReserveVarint($"MeshOffset{i}");
            }

            void writeMeshes()
            {
                for (int i = 0; i < Meshes.Count; i++)
                {
                    bw.Pad(bw.VarintSize);
                    bw.FillVarint($"MeshOffset{i}", bw.Position);
                    Meshes[i].Write(bw, Version);
                }
            }

            if (Version == NGPVersion.Vanilla)
            {
                writeMeshes();
            }

            bw.Pad(bw.VarintSize);
            bw.FillVarint("OffsetA", bw.Position);
            foreach (StructA structA in StructAs)
            {
                structA.Write(bw);
            }

            bw.Pad(bw.VarintSize);
            bw.FillVarint("OffsetB", bw.Position);
            foreach (StructB structB in StructBs)
            {
                structB.Write(bw);
            }

            bw.Pad(bw.VarintSize);
            bw.FillVarint("OffsetC", bw.Position);
            bw.WriteInt32s(StructCs);

            bw.Pad(bw.VarintSize);
            bw.FillVarint("OffsetD", bw.Position);
            bw.WriteInt16s(StructDs);

            if (Version == NGPVersion.Scholar)
            {
                writeMeshes();
            }
        }
Example #25
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);
            }
        }
Example #26
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.WriteASCII(Timestamp.PadRight(8, '\0'));
                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 (Util.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);
                    }
                }
            }