Пример #1
0
        internal override void WriteContent(EndianBinaryWriter writer, IOContext context)
        {
            writer.OffsetPositions.Clear();

            var start = writer.Position;

            // -- header --
            // Write relocation table last (lowest priority)
            writer.PushBaseOffset(start + 0x10);
            writer.ScheduleWriteOffsetAligned(-1, 16, () =>
            {
                // Encode & write relocation table
                var encodedRelocationTable =
                    RelocationTableEncoding.Encode(writer.OffsetPositions.Select(x => ( int )x).ToList(), ( int )writer.BaseOffset);
                writer.WriteBytes(encodedRelocationTable);

                var end = writer.Position;
                writer.SeekBegin(start + 4);
                writer.WriteInt32(encodedRelocationTable.Length);
                writer.SeekBegin(end);
            });

            writer.WriteInt32(0);
            writer.WriteInt16(Group);
            writer.WriteInt16(PlayGroup);
            writer.WriteInt16(FirstMotion);
            writer.WriteInt16(Flags);

            // -- motion data header --
            if (mControllerDefinitions == null)
            {
                mControllerDefinitions = Motions.Where(x => x != null)
                                         .SelectMany(x => x.Controllers)
                                         .Select(x => x.GetDefinition())
                                         .Distinct()
                                         //.OrderBy( x => x.NodeIndex )
                                         .ToList();
            }

            if (mMotionDefinitions == null)
            {
                mMotionDefinitions = BuildMotionDefinitions();
            }

            writer.WriteInt16(( short )Motions.Count);
            writer.WriteInt16(( short )mControllerDefinitions.Count);
            writer.ScheduleWriteOffsetAligned(16, () =>
            {
                writer.ScheduleWriteObjectOffsetsAligned(mMotionDefinitions, 4);
            });

            // -- controller definitions --
            writer.WriteObjects(mControllerDefinitions);

            // write all the things
            writer.PerformScheduledWrites();
            writer.PopBaseOffset();
        }
Пример #2
0
        private void BuildHeaderFinalPass(ref BinaryHeader header)
        {
            header.RelocationTable.Offset = GetAlignedAddress() + BinaryHeader.SIZE;
            header.RelocationTable.Value  =
                RelocationTableEncoding.Encode(mAddressLocations, BinaryHeader.SIZE);
            header.RelocationTableSize = header.RelocationTable.Value.Length;
            mPosition += header.RelocationTableSize;

            header.FileSize = mPosition;
        }
Пример #3
0
        protected override void Write(EndianBinaryWriter writer, IOContext context = null)
        {
            // Skip header
            writer.PushBaseOffset();
            var start = writer.Position;

            writer.Write(( int )ResourceDescriptor.FileType);
            writer.Write(( uint )ResourceDescriptor.Identifier);
            writer.Write(0);   // dummy data size
            writer.ScheduleWriteOffsetAligned(-1, 16, () =>
            {
                // Write data size
                var relocationTableStart = writer.Position;
                writer.SeekBegin(start + 8);
                writer.Write(( int )relocationTableStart - start);

                // Encode & write relocation table
                writer.SeekBegin(relocationTableStart);
                var encodedRelocationTable = RelocationTableEncoding.Encode(writer.OffsetPositions.Select(x => ( int )x).ToList(), ( int )writer.BaseOffset);
                writer.Write(encodedRelocationTable);

                // Write relocation table size
                var relocationTableEnd = writer.Position;
                writer.SeekBegin(start + 16);
                writer.Write(encodedRelocationTable.Length);
                writer.SeekBegin(relocationTableEnd);
            });
            writer.Write(0);   // dummy relocation table size

            // Write resource content
            WriteContent(writer, context);
            writer.PerformScheduledWrites();

            // Seek back to the end and align to 64 bytes
            writer.PopBaseOffset();
        }
Пример #4
0
        internal override void WriteContent(EndianBinaryWriter writer, IOContext context)
        {
            if (!context.IsFieldObject)
            {
                // TODO: implement this properly
                writer.OffsetPositions.Clear();
            }

            var start = writer.Position;

            if (!context.IsFieldObject)
            {
                // Relocation table needs this base offset
                writer.PushBaseOffset(start + 16);

                // Write relocation table last (lowest priority)
                writer.ScheduleWriteOffsetAligned(-1, 16, () =>
                {
                    // Encode & write relocation table
                    var encodedRelocationTable =
                        RelocationTableEncoding.Encode(writer.OffsetPositions.Select(x => ( int )x).ToList(), ( int )writer.BaseOffset);
                    writer.Write(encodedRelocationTable);

                    // Kind of a hack here, but we need to write the relocation table size after the offset
                    // Seeing as we have the offset positions required to encode the relocation table only at the very end
                    // I can't really think of a better solution
                    var end = writer.Position;
                    writer.SeekBegin(start + 4);
                    writer.Write(encodedRelocationTable.Length);
                    writer.SeekBegin(end);
                });
            }
            else
            {
                writer.Write(0);
                writer.Write(0);
            }

            writer.Align(16);

            writer.ScheduleWriteOffsetAligned(16, () =>
            {
                writer.Write(Nodes.Count);
                writer.Align(16);
                for (int i = 0; i < Nodes.Count; i++)
                {
                    writer.WriteObject(Nodes[i], (i, Nodes));
                }
            });

            writer.ScheduleWriteOffsetAligned(16, () =>
            {
                writer.Write(Materials.Count);
                for (int i = 0; i < Materials.Count; i++)
                {
                    writer.WriteObject(Materials[i], i);
                }
            });

            var morpherMeshCount = Nodes.Where(x => x.Geometry != null && x.Geometry.Meshes?.Count > 0)
                                   .Sum(x => x.Geometry.Meshes.Count(y => MeshTypeTraits.HasMorphers(y.Type)));

            writer.Write(morpherMeshCount);

            writer.ScheduleWriteOffsetAligned(16, () =>
            {
                // NDNM is a special case as we stored the data in the nodes themselves.
                bool noNodeNames = Nodes.All(x => x.Name == null);
                if (!noNodeNames)
                {
                    WriteExtension(writer, ModelExtensionIdentifier.NodeName, () =>
                    {
                        for (int i = 0; i < Nodes.Count; i++)
                        {
                            writer.Write(Nodes[i].Name, StringBinaryFormat.NullTerminated);
                            writer.Align(4);
                            writer.Write(i);
                        }
                    });
                }

                foreach (var extension in Extensions)
                {
                    WriteExtension(writer, extension.Identifier, () => writer.WriteObject(extension));
                }

                // Write dummy end extension
                writer.Write(0);
                writer.Write(0);
                writer.Align(16);
            });

            if (!context.IsFieldObject)
            {
                // TODO(TGE): implement this properly
                writer.PerformScheduledWrites();
            }
        }