Beispiel #1
0
        void IBinarySerializable.Read(EndianBinaryReader reader, object context)
        {
            var vertexCount = ( short )context;

            Positions = reader.ReadVector3Array(vertexCount);
            reader.Align(16);
            Normals = reader.ReadVector3Array(vertexCount);
            reader.Align(16);
        }
        internal override void ReadContent(EndianBinaryReader reader, IOContext context)
        {
            var  textureCount      = reader.ReadInt32();
            long nextTextureOffset = 0;

            for (int i = 0; i < textureCount; i++)
            {
                // Some files have broken offsets (f021_aljira.PB), so we must calculate them ourselves
                var offset     = reader.ReadInt32();
                var nextOffset = reader.Position;

                if (i == 0)
                {
                    reader.SeekBegin(offset + reader.BaseOffset);
                }
                else
                {
                    reader.SeekBegin(nextTextureOffset);
                }

                Textures.Add(reader.ReadObject <Texture>());
                reader.Align(64);

                if ((i + 1) != textureCount)
                {
                    nextTextureOffset = reader.Position;
                    reader.SeekBegin(nextOffset);
                }
            }

            // Make sure we end at the end of the last texture
        }
        protected override void Read(EndianBinaryReader reader)
        {
            var vifCodeStreamSize = reader.ReadInt16();

            MaterialIndex = reader.ReadInt16();
            var vifCodeStreamOffset = reader.ReadInt32();
            var usedNodeCount       = reader.ReadInt16();
            var field0A             = reader.ReadInt16Expects(0, "Field0A is not 0");
            var usedNodes           = reader.ReadInt16Array(usedNodeCount);

            Trace.Assert(usedNodeCount > 0 && usedNodeCount <= 4);
            reader.ReadAtOffset(vifCodeStreamOffset, () =>
            {
                var vifCodeStreamEnd = reader.Position + (vifCodeStreamSize * 16);
                while (reader.Position < vifCodeStreamEnd)
                {
                    var vifTag = reader.ReadObject <VifTag>();
                    if (vifTag.Command == 0 && AlignmentHelper.Align(reader.Position, 16) == vifCodeStreamEnd)
                    {
                        // Stream padding, stop reading
                        break;
                    }

                    reader.SeekCurrent(-VifTag.SIZE);
                    Batches.Add(reader.ReadObject <MeshType2Batch>(usedNodes));
                }
            });
            reader.Align(16);
        }
 void IBinarySerializable.Read(EndianBinaryReader reader, object context)
 {
     (short vertexCount, short nodeIndex) = ((short, short))context;
     NodeIndex = nodeIndex;
     Positions = reader.ReadVector4Array(vertexCount);
     Normals   = reader.ReadVector3Array(vertexCount);
     reader.Align(16);
 }
Beispiel #5
0
        protected void Load()
        {
            using (var stream = new MemoryStream(RawData))
                using (var reader = new EndianBinaryReader(stream, Endian))
                {
                    var nameLength = reader.ReadInt32();
                    Name = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(nameLength));
                    reader.Align(4);
                    Id = reader.ReadUInt32();

                    Load(reader);
                }
        }
Beispiel #6
0
        private List <KeyValuePair <NodeType, dynamic> > ReadArrayNode(EndianBinaryReader reader, int length)
        {
            List <KeyValuePair <NodeType, dynamic> > array = new List <KeyValuePair <NodeType, dynamic> >(length);

            byte[] nodeTypes = reader.ReadBytes(length);
            reader.Align(4);
            for (int i = 0; i < length; i++)
            {
                array.Add(new KeyValuePair <NodeType, dynamic>((NodeType)nodeTypes[i], ReadNode(reader, (NodeType)nodeTypes[i])));
            }

            return(array);
        }
        private void ReadOld(EndianBinaryReader reader)
        {
            while (true)
            {
                var tag = reader.ReadObject <VifTag>();

                if ((tag.Command > 0x20 && tag.Command < 0x60) || tag.Command > 0x70)
                {
                    Debug.WriteLine($"Hit invalid vif cmd: {tag.Command}");
                    reader.SeekCurrent(-VifTag.SIZE);
                    reader.Align(16);
                    break;
                }

                if (( VifCommand )(tag.Command & 0xF0) == VifCommand.Unpack)
                {
                    var packet = reader.ReadObject <VifPacket>(tag);

                    // TODO: use flags for this
                    if (packet.ElementFormat == VifUnpackElementFormat.Float && packet.ElementCount == 4)
                    {
                        Positions = packet.Vector4Array;
                    }
                    else if (packet.ElementFormat == VifUnpackElementFormat.Float && packet.ElementCount == 3)
                    {
                        Normals = packet.Vector3Array;
                    }
                    else
                    {
                        throw new InvalidDataException("Unexpected VIF packet");
                    }
                }
                else
                {
                    var command = ( VifCommand )tag.Command;
                    if (command != VifCommand.ActMicro && command != VifCommand.CntMicro)
                    {
                        throw new InvalidDataException("Unexpected VIF tag command");
                    }

                    break;
                }
            }
        }
Beispiel #8
0
        public void Read(EndianBinaryReader r)
        {
            r.AssertMagicText("shp" + AsciiUtil.GetChar(0x20));

            this.chunkSize = r.ReadUInt32();
            this.shapes    = new Sepd[r.ReadUInt32()];
            this.flags     = r.ReadUInt32();

            for (var i = 0; i < this.shapes.Length; ++i)
            {
                r.ReadInt16(); // ShapeOffset(s)
            }

            r.Align(4);

            for (var i = 0; i < this.shapes.Length; ++i)
            {
                var shape = new Sepd();
                shape.Read(r);
                this.shapes[i] = shape;
            }
        }
Beispiel #9
0
        void IBinarySerializable.Read(EndianBinaryReader reader, object context)
        {
            var flags = ( MeshFlags )context;

            var headerPacket = reader.ReadObject <VifPacket>();

            VifValidationHelper.Ensure(headerPacket, 0xFF, true, false, 1, VifUnpackElementFormat.Short, 2);

            var vertexCount = headerPacket.Int16Arrays[0][0];

            if (headerPacket.Int16Arrays[0][1] != 0)
            {
                throw new InvalidDataException("Header packet second short is not 0");
            }

            var positionsPacket = reader.ReadObject <VifPacket>();

            VifValidationHelper.Ensure(positionsPacket, 0, true, false, vertexCount, VifUnpackElementFormat.Float, 3);
            Positions = positionsPacket.Vector3Array;

            var normalsPacket = reader.ReadObject <VifPacket>();

            VifValidationHelper.Ensure(normalsPacket, 0x18, true, false, vertexCount, VifUnpackElementFormat.Float, 3);
            Normals = normalsPacket.Vector3Array;

            var texCoordPacket = reader.ReadObject <VifPacket>();

            VifValidationHelper.Ensure(texCoordPacket, 0x30, true, false, vertexCount, VifUnpackElementFormat.Float, 2);
            TexCoords = texCoordPacket.Vector2Array;

            var activateTag = reader.ReadObject <VifCode>();

            VifValidationHelper.Ensure(activateTag, 0x16, 0, VifCommand.ActMicro);

            var flushTag = reader.ReadObject <VifCode>();

            VifValidationHelper.Ensure(flushTag, 0, 0, VifCommand.FlushEnd);
            reader.Align(16);
        }
Beispiel #10
0
        protected override void Read(EndianBinaryReader reader)
        {
            var vifCodeStreamSize = reader.ReadInt16();

            MaterialIndex = reader.ReadInt16();
            reader.ReadOffset(() =>
            {
                var vifCodeStreamEnd = reader.Position + (vifCodeStreamSize * 16);
                while (reader.Position < vifCodeStreamEnd)
                {
                    var vifTag = reader.ReadObject <VifTag>();
                    if (vifTag.Command == 0 && AlignmentHelper.Align(reader.Position, 16) == vifCodeStreamEnd)
                    {
                        // Stream padding, stop reading
                        break;
                    }

                    reader.SeekCurrent(-VifTag.SIZE);
                    Batches.Add(reader.ReadObject <MeshType1Batch>());
                }
            });
            reader.Align(16);
        }
        void IBinarySerializable.Read(EndianBinaryReader reader, object context)
        {
            (short[] usedNodeIds, MeshFlags flags) = ((short[], MeshFlags))context;

            var headerPacket = reader.ReadObject <VifPacket>();

            VifValidationHelper.Ensure(headerPacket, 0xFF, true, false, 1, VifUnpackElementFormat.Short, 2);

            var usedNodeCount = headerPacket.Int16Arrays[0][0];
            var vertexCount   = headerPacket.Int16Arrays[0][1];

            if (usedNodeCount + 1 != usedNodeIds.Length)
            {
                throw new InvalidDataException("Used node count + 1 is not equal to the number of used node ids.");
            }

            foreach (short nodeId in usedNodeIds)
            {
                NodeBatches.Add(reader.ReadObject <MeshType7NodeBatch>(nodeId));
            }

            // @NOTE(TGE): Not a single mesh type 7 mesh does not have this flag set so I don't know if it should be checked for.
            var texCoordsPacket = reader.ReadObject <VifPacket>();

            VifValidationHelper.Ensure(texCoordsPacket, null, true, false, vertexCount, VifUnpackElementFormat.Float, 2);
            TexCoords = texCoordsPacket.Vector2Array;

            var texCoordsKickTag = reader.ReadObject <VifCode>();

            VifValidationHelper.Ensure(texCoordsKickTag, 0, 0, VifCommand.CntMicro);

            var flushTag = reader.ReadObject <VifCode>();

            VifValidationHelper.Ensure(flushTag, 0, 0, VifCommand.FlushEnd);
            reader.Align(16);
        }
Beispiel #12
0
        internal override void ReadContent(EndianBinaryReader reader, IOContext context)
        {
            reader.SeekCurrent(8);

            for (int i = 0; i < 2; i++)
            {
                reader.ReadUInt32Expects(0, "Model header padding is not 0");
            }

            // Hacky fix for field models
            if (!context.IsFieldObject)
            {
                reader.PushBaseOffset();
            }

            reader.ReadOffset(() =>
            {
                var nodeCount = reader.ReadInt32();
                reader.Align(16);

                for (int i = 0; i < nodeCount; i++)
                {
                    Nodes.Add(reader.ReadObject <Node>(Nodes));
                }
            });
            reader.ReadOffset(() =>
            {
                var materialCount = reader.ReadInt32();
                Materials         = reader.ReadObjects <Material>(materialCount);
            });
            var morpherMeshCount = reader.ReadInt32();

            reader.ReadOffset(() =>
            {
                while (true)
                {
                    var extensionStart  = reader.Position;
                    var extensionHeader = reader.ReadObject <ModelExtensionHeader>();
                    if (extensionHeader.Identifier == 0)
                    {
                        break;
                    }

                    var extensionEnd = extensionStart + extensionHeader.Size;

                    switch (extensionHeader.Identifier)
                    {
                    case ModelExtensionIdentifier.NodeName:
                        // Special case as we move the data into the nodes themselves
                        for (int i = 0; i < Nodes.Count; i++)
                        {
                            var nodeName = reader.ReadString(StringBinaryFormat.NullTerminated);
                            reader.Align(4);
                            var nodeId         = reader.ReadInt32();
                            Nodes[nodeId].Name = nodeName;
                        }
                        break;

                    default:
                        Extensions.Add(reader.ReadObject <ModelBinaryExtension>(extensionHeader));
                        break;
                    }

                    reader.SeekBegin(extensionEnd);
                }
            });

            if (!context.IsFieldObject)
            {
                reader.PopBaseOffset();
            }
        }
Beispiel #13
0
        internal void Read(EndianBinaryReader reader, bool isModern)
        {
            if (Type == KeySetType.Static)
            {
                Keys.Add(new Key {
                    Value = reader.ReadSingle()
                });
            }

            else if (Type != KeySetType.None)
            {
                HasTangents = Type == KeySetType.Tangent;

                if (isModern)
                {
                    ReadModern();
                }
                else
                {
                    ReadClassic();
                }

                void ReadClassic()
                {
                    ushort keyCount = reader.ReadUInt16();

                    Keys.Capacity = keyCount;
                    for (int i = 0; i < keyCount; i++)
                    {
                        Keys.Add(new Key {
                            Frame = reader.ReadUInt16()
                        });
                    }

                    reader.Align(4);

                    foreach (var key in Keys)
                    {
                        key.Value = reader.ReadSingle();
                        if (HasTangents)
                        {
                            key.Tangent = reader.ReadSingle();
                        }
                    }
                }

                void ReadModern()
                {
                    ushort keyCount = reader.ReadUInt16();
                    ushort type     = reader.ReadUInt16();

                    Keys.Capacity = keyCount;
                    for (int i = 0; i < keyCount; i++)
                    {
                        Keys.Add(new Key());
                    }

                    if (HasTangents)
                    {
                        foreach (var key in Keys)
                        {
                            key.Tangent = reader.ReadSingle();
                        }
                    }

                    reader.Align(4);
                    foreach (var key in Keys)
                    {
                        key.Value = type == 1
                            ? reader.ReadHalf()
                            : reader.ReadSingle();
                    }

                    reader.Align(4);
                    foreach (var key in Keys)
                    {
                        key.Frame = reader.ReadUInt16();
                    }

                    reader.Align(4);
                }
            }
        }
Beispiel #14
0
        public void Read(EndianBinaryReader r)
        {
            bool isConstant = false;

            if (this.parent_.Version > 4)
            {
                isConstant     = r.ReadByte() != 0;
                this.Type      = (AnimationTrackType)r.ReadByte();
                this.Keyframes = new CsabKeyframe[r.ReadUInt16()];
            }
            else
            {
                this.Type      = (AnimationTrackType)r.ReadUInt32();
                this.Keyframes = new CsabKeyframe[r.ReadUInt32()];
                var unk1 = r.ReadUInt32();
                this.Duration = r.ReadUInt32();
            }

            if (isConstant)
            {
                var scale = r.ReadSingle();
                var bias  = r.ReadSingle();

                for (var i = 0; i < this.Keyframes.Count; ++i)
                {
                    var value = r.ReadUInt32();

                    this.Keyframes[i] = new CsabKeyframe {
                        Time  = (uint)i,
                        Value = value * scale - bias,
                    };
                }
            }

            float trackScale = -1;
            float trackBias  = -1;

            if (this.parent_.Version > 4 && this.Type == AnimationTrackType.LINEAR)
            {
                trackScale = r.ReadSingle();
                trackBias  = r.ReadSingle();
            }

            switch (this.Type)
            {
            case AnimationTrackType.LINEAR: {
                for (var i = 0; i < this.Keyframes.Count; ++i)
                {
                    if (!this.AreRotationsShort)
                    {
                        if (this.parent_.Version > 4)
                        {
                            // TODO: Is this right????
                            var raw = this.ValueType switch {
                                TrackType.POSITION => (int)r.ReadUInt16(),
                                TrackType.SCALE => (int)r.ReadInt16(),
                                _ => throw new NotSupportedException(),
                            };
                            var value = raw * trackScale - trackBias;
                            this.Keyframes[i] = new CsabKeyframe {
                                Time  = (uint)i,
                                Value = value,
                            };
                        }
                        else
                        {
                            this.Keyframes[i] = new CsabKeyframe {
                                Time  = r.ReadUInt32(),
                                Value = r.ReadSingle(),
                            };
                        }
                    }
                    else
                    {
                        if (this.parent_.Version > 4)
                        {
                            var value = r.ReadInt16() * trackScale + trackBias;
                            this.Keyframes[i] = new CsabKeyframe {
                                Time  = (uint)i,
                                Value = value,
                            };
                        }
                        else
                        {
                            this.Keyframes[i] = new CsabKeyframe {
                                Time  = r.ReadUInt16(),
                                Value = r.ReadSn16(),
                            };
                        }
                    }
                }
                break;
            }

            case AnimationTrackType.HERMITE: {
                for (var i = 0; i < this.Keyframes.Count; ++i)
                {
                    if (!this.AreRotationsShort)
                    {
                        this.Keyframes[i] = new CsabKeyframe {
                            Time            = r.ReadUInt32(),
                            Value           = r.ReadSingle(),
                            IncomingTangent = Optional <float> .Of(r.ReadSingle()),
                            OutgoingTangent = Optional <float> .Of(r.ReadSingle()),
                        };
                    }
                    else
                    {
                        this.Keyframes[i] = new CsabKeyframe {
                            Time            = r.ReadUInt16(),
                            Value           = r.ReadSn16(),
                            IncomingTangent = Optional <float> .Of(r.ReadSn16()),
                            OutgoingTangent = Optional <float> .Of(r.ReadSn16()),
                        };
                    }
                }
                break;
            }

            default: throw new ArgumentOutOfRangeException();
            }
            r.Align(4);
        }
Beispiel #15
0
        void IBinarySerializable.Read(EndianBinaryReader reader, object context)
        {
            reader.SeekCurrent(4);
            var keyframeCount   = reader.ReadInt16();
            var keyframeSize    = reader.ReadInt16();
            var keyframeTimings = reader.ReadInt16Array(keyframeCount);

            reader.Align(4);

            var controllerType = ( ControllerType )context;

            for (int i = 0; i < keyframeCount; i++)
            {
                IKey key;

                switch (controllerType)
                {
                case ControllerType.Position:
                    switch (keyframeSize)
                    {
                    case 4:
                        key = reader.ReadObject <UInt32Key>();
                        break;

                    case 8:
                        key = reader.ReadObject <PositionKeySize8>();
                        break;

                    case 12:
                        key = reader.ReadObject <Vector3Key>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case ControllerType.Type1:
                    switch (keyframeSize)
                    {
                    case 4:
                        key = reader.ReadObject <UInt32Key>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case ControllerType.Scale:
                    switch (keyframeSize)
                    {
                    case 12:
                        key = reader.ReadObject <Vector3Key>();
                        break;

                    case 20:
                        key = reader.ReadObject <Single5Key>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case ControllerType.Rotation:
                    switch (keyframeSize)
                    {
                    case 8:
                        key = reader.ReadObject <QuaternionKey>();
                        break;

                    case 20:
                        key = reader.ReadObject <Single5Key>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case ControllerType.Morph:
                    switch (keyframeSize)
                    {
                    case 1:
                        key = reader.ReadObject <ByteKey>();
                        break;

                    case 4:
                        key = reader.ReadObject <UInt32Key>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case ControllerType.Type5:
                    switch (keyframeSize)
                    {
                    case 4:
                        key = reader.ReadObject <SingleKey>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case ControllerType.Type8:
                    switch (keyframeSize)
                    {
                    case 4:
                        key = reader.ReadObject <UInt32Key>();
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }

                key.Time = keyframeTimings[i];
                Keyframes.Add(key);
            }

            reader.Align(4);
        }
Beispiel #16
0
        public static AnimationBank[] Read(EndianBinaryReader reader, Pointer offset, uint index, uint num_banks, bool append = false)
        {
            MapLoader l = MapLoader.Loader;

            AnimationBank[] banks = new AnimationBank[num_banks];

            for (int i = 0; i < num_banks; i++)
            {
                // In R3, each animation bank is of size 0x104 = 13 times a stack description of 5 uint32s.
                banks[i]                 = new AnimationBank(Pointer.Current(reader));
                banks[i].a3d_general     = AnimationStack.Read(reader);
                banks[i].vectors         = AnimationStack.Read(reader);
                banks[i].quaternions     = AnimationStack.Read(reader);
                banks[i].hierarchies     = AnimationStack.Read(reader);
                banks[i].NTTO            = AnimationStack.Read(reader);
                banks[i].onlyFrames      = AnimationStack.Read(reader);
                banks[i].channels        = AnimationStack.Read(reader);
                banks[i].framesNumOfNTTO = AnimationStack.Read(reader);
                banks[i].framesKFIndex   = AnimationStack.Read(reader);
                banks[i].keyframes       = AnimationStack.Read(reader);
                banks[i].events          = AnimationStack.Read(reader);
                banks[i].morphData       = AnimationStack.Read(reader);
                if (l.mode != MapLoader.Mode.Rayman2PC)
                {
                    banks[i].deformations = AnimationStack.Read(reader);
                }
                else
                {
                    banks[i].deformations = null;
                }
                banks[i].animations = new AnimA3DGeneral[banks[i].a3d_general.count];
            }
            if (l.mode == MapLoader.Mode.Rayman3PC || (l.mode == MapLoader.Mode.Rayman2PC && !append))
            {
                for (int i = 0; i < num_banks; i++)
                {
                    if (banks[i].a3d_general.reservedMemory > 0)
                    {
                        banks[i].a3d_general.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].vectors.reservedMemory > 0)
                    {
                        banks[i].vectors.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].quaternions.reservedMemory > 0)
                    {
                        banks[i].quaternions.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].hierarchies.reservedMemory > 0)
                    {
                        banks[i].hierarchies.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].NTTO.reservedMemory > 0)
                    {
                        banks[i].NTTO.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].onlyFrames.reservedMemory > 0)
                    {
                        banks[i].onlyFrames.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].channels.reservedMemory > 0)
                    {
                        banks[i].channels.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].framesNumOfNTTO.reservedMemory > 0)
                    {
                        banks[i].framesNumOfNTTO.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].framesKFIndex.reservedMemory > 0)
                    {
                        banks[i].framesKFIndex.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].keyframes.reservedMemory > 0)
                    {
                        banks[i].keyframes.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].events.reservedMemory > 0)
                    {
                        banks[i].events.off_data = Pointer.Read(reader);
                    }
                    if (banks[i].morphData.reservedMemory > 0)
                    {
                        banks[i].morphData.off_data = Pointer.Read(reader);
                    }
                    if (l.mode != MapLoader.Mode.Rayman2PC && banks[i].deformations.reservedMemory > 0)
                    {
                        banks[i].deformations.off_data = Pointer.Read(reader);
                    }
                }
            }
            Pointer off_current = Pointer.Current(reader);
            Pointer off_a3d     = null;
            uint    num_a3d     = (uint)banks.Sum(b => b.a3d_general.count);

            FileFormat.FileWithPointers kfFile = null;
            if (index == 0 && l.files_array[MapLoader.Mem.FixKeyFrames] != null)
            {
                kfFile = MapLoader.Loader.files_array[MapLoader.Mem.FixKeyFrames];
            }
            if (index > 0 && l.files_array[MapLoader.Mem.LvlKeyFrames] != null)
            {
                kfFile = MapLoader.Loader.files_array[MapLoader.Mem.LvlKeyFrames];
            }
            if (kfFile != null && l.mode == MapLoader.Mode.Rayman3GC)
            {
                kfFile.GotoHeader();
                reader = kfFile.reader;
                uint[] a3d_sizes = new uint[num_a3d];
                for (uint i = 0; i < num_a3d; i++)
                {
                    a3d_sizes[i] = reader.ReadUInt32();
                }
                off_a3d = Pointer.Current(reader);
                uint current_anim = 0;
                for (uint i = 0; i < banks.Length; i++)
                {
                    uint num_a3d_in_bank = banks[i].a3d_general.count;
                    for (uint j = 0; j < num_a3d_in_bank; j++)
                    {
                        Pointer.Goto(ref reader, off_a3d);
                        // Read animation data here
                        banks[i].animations[j] = AnimA3DGeneral.Read(reader, off_a3d);
                        AnimA3DGeneral a = banks[i].animations[j];
                        a.vectors       = new AnimVector[a.num_vectors];
                        a.quaternions   = new AnimQuaternion[a.num_quaternions];
                        a.hierarchies   = new AnimHierarchy[a.num_hierarchies];
                        a.ntto          = new AnimNTTO[a.num_NTTO];
                        a.onlyFrames    = new AnimOnlyFrame[a.num_onlyFrames];
                        a.channels      = new AnimChannel[a.num_channels];
                        a.numOfNTTO     = new AnimNumOfNTTO[a.num_numNTTO * a.num_channels];
                        a.framesKFIndex = new AnimFramesKFIndex[a.num_onlyFrames * a.num_channels];
                        a.keyframes     = new AnimKeyframe[a.num_keyframes];
                        a.events        = new AnimEvent[a.num_events];
                        a.morphData     = new AnimMorphData[a.num_morphData];
                        a.deformations  = new AnimDeformation[a.num_deformations];
                        for (uint k = 0; k < a.vectors.Length; k++)
                        {
                            a.vectors[k] = AnimVector.Read(reader);
                        }
                        for (uint k = 0; k < a.quaternions.Length; k++)
                        {
                            a.quaternions[k] = AnimQuaternion.Read(reader);
                        }
                        for (uint k = 0; k < a.hierarchies.Length; k++)
                        {
                            a.hierarchies[k] = AnimHierarchy.Read(reader);
                        }
                        for (uint k = 0; k < a.ntto.Length; k++)
                        {
                            a.ntto[k] = AnimNTTO.Read(reader);
                        }
                        for (uint k = 0; k < a.onlyFrames.Length; k++)
                        {
                            a.onlyFrames[k] = AnimOnlyFrame.Read(reader);
                        }
                        reader.Align(4);
                        for (uint k = 0; k < a.channels.Length; k++)
                        {
                            a.channels[k] = AnimChannel.Read(reader);
                        }
                        for (uint k = 0; k < a.numOfNTTO.Length; k++)
                        {
                            a.numOfNTTO[k] = AnimNumOfNTTO.Read(reader);
                        }
                        reader.Align(4);
                        for (uint k = 0; k < a.framesKFIndex.Length; k++)
                        {
                            a.framesKFIndex[k] = AnimFramesKFIndex.Read(reader);
                        }
                        for (uint k = 0; k < a.keyframes.Length; k++)
                        {
                            a.keyframes[k] = AnimKeyframe.Read(reader);
                        }
                        reader.Align(4);
                        for (uint k = 0; k < a.events.Length; k++)
                        {
                            a.events[k] = AnimEvent.Read(reader);
                        }
                        for (uint k = 0; k < a.morphData.Length; k++)
                        {
                            a.morphData[k] = AnimMorphData.Read(reader);
                        }
                        reader.Align(4);
                        for (uint k = 0; k < a.deformations.Length; k++)
                        {
                            a.deformations[k] = AnimDeformation.Read(reader);
                        }
                        off_a3d += a3d_sizes[current_anim];

                        // Check if read correctly
                        Pointer off_postAnim = Pointer.Current(reader);
                        if (off_postAnim != off_a3d)
                        {
                            l.print("Animation block size does not match data size: " +
                                    "Current offset: " + off_postAnim + " - Expected offset: " + off_a3d +
                                    " - Block start: " + (off_a3d + -(int)(a3d_sizes[current_anim])));
                        }

                        current_anim++;
                    }
                }
            }
            else if (kfFile == null && (l.mode == MapLoader.Mode.Rayman3PC || l.mode == MapLoader.Mode.Rayman2PC))
            {
                bool readArraysDirectly = l.mode == MapLoader.Mode.Rayman2PC && index == 0;
                for (uint i = 0; i < banks.Length; i++)
                {
                    banks[i].animations           = new AnimA3DGeneral[banks[i].a3d_general.Count(append)];
                    banks[i].global_vectors       = new AnimVector[banks[i].vectors.Count(append)];
                    banks[i].global_quaternions   = new AnimQuaternion[banks[i].quaternions.Count(append)];
                    banks[i].global_hierarchies   = new AnimHierarchy[banks[i].hierarchies.Count(append)];
                    banks[i].global_NTTO          = new AnimNTTO[banks[i].NTTO.Count(append)];
                    banks[i].global_onlyFrames    = new AnimOnlyFrame[banks[i].onlyFrames.Count(append)];
                    banks[i].global_channels      = new AnimChannel[banks[i].channels.Count(append)];
                    banks[i].global_numOfNTTO     = new AnimNumOfNTTO[banks[i].framesNumOfNTTO.Count(append)];
                    banks[i].global_framesKFIndex = new AnimFramesKFIndex[banks[i].framesKFIndex.Count(append)];
                    banks[i].global_keyframes     = new AnimKeyframe[banks[i].keyframes.Count(append)];
                    banks[i].global_events        = new AnimEvent[banks[i].events.Count(append)];
                    banks[i].global_morphData     = new AnimMorphData[banks[i].morphData.Count(append)];
                    if (l.mode != MapLoader.Mode.Rayman2PC)
                    {
                        banks[i].global_deformations = new AnimDeformation[banks[i].deformations.Count(append)];
                    }
                    if (banks[i].animations.Length > 0)
                    {
                        if (banks[i].a3d_general.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].a3d_general.off_data);
                        }
                        for (uint j = 0; j < banks[i].animations.Length; j++)
                        {
                            banks[i].animations[j] = AnimA3DGeneral.Read(reader, Pointer.Current(reader));
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(56 * banks[i].animations.Length, 4);
                        }
                    }
                    if (banks[i].global_vectors.Length > 0)
                    {
                        if (banks[i].vectors.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].vectors.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_vectors.Length; j++)
                        {
                            banks[i].global_vectors[j] = AnimVector.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(12 * banks[i].global_vectors.Length, 4);
                        }
                    }
                    if (banks[i].global_quaternions.Length > 0)
                    {
                        if (banks[i].quaternions.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].quaternions.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_quaternions.Length; j++)
                        {
                            banks[i].global_quaternions[j] = AnimQuaternion.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(8 * banks[i].global_quaternions.Length, 4);
                        }
                    }
                    if (banks[i].global_hierarchies.Length > 0)
                    {
                        if (banks[i].hierarchies.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].hierarchies.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_hierarchies.Length; j++)
                        {
                            banks[i].global_hierarchies[j] = AnimHierarchy.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(4 * banks[i].global_hierarchies.Length, 4);
                        }
                    }
                    if (banks[i].global_NTTO.Length > 0)
                    {
                        if (banks[i].NTTO.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].NTTO.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_NTTO.Length; j++)
                        {
                            banks[i].global_NTTO[j] = AnimNTTO.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(6 * banks[i].global_NTTO.Length, 4);
                        }
                    }
                    if (banks[i].global_onlyFrames.Length > 0)
                    {
                        if (banks[i].onlyFrames.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].onlyFrames.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_onlyFrames.Length; j++)
                        {
                            banks[i].global_onlyFrames[j] = AnimOnlyFrame.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(10 * banks[i].global_onlyFrames.Length, 4);
                        }
                    }
                    if (banks[i].global_channels.Length > 0)
                    {
                        if (banks[i].channels.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].channels.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_channels.Length; j++)
                        {
                            banks[i].global_channels[j] = AnimChannel.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(16 * banks[i].global_channels.Length, 4);
                        }
                    }
                    if (banks[i].global_numOfNTTO.Length > 0)
                    {
                        if (banks[i].framesNumOfNTTO.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].framesNumOfNTTO.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_numOfNTTO.Length; j++)
                        {
                            banks[i].global_numOfNTTO[j] = AnimNumOfNTTO.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(2 * banks[i].global_numOfNTTO.Length, 4);
                        }
                    }
                    if (banks[i].global_framesKFIndex.Length > 0)
                    {
                        if (banks[i].framesKFIndex.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].framesKFIndex.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_framesKFIndex.Length; j++)
                        {
                            banks[i].global_framesKFIndex[j] = AnimFramesKFIndex.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(4 * banks[i].global_framesKFIndex.Length, 4);
                        }
                    }
                    if (banks[i].global_keyframes.Length > 0)
                    {
                        if (banks[i].keyframes.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].keyframes.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_keyframes.Length; j++)
                        {
                            banks[i].global_keyframes[j] = AnimKeyframe.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(36 * banks[i].global_keyframes.Length, 4);
                        }
                    }
                    if (banks[i].global_events.Length > 0)
                    {
                        if (banks[i].events.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].events.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_events.Length; j++)
                        {
                            banks[i].global_events[j] = AnimEvent.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(12 * banks[i].global_events.Length, 4);
                        }
                    }
                    if (banks[i].global_morphData.Length > 0)
                    {
                        if (banks[i].morphData.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].morphData.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_morphData.Length; j++)
                        {
                            banks[i].global_morphData[j] = AnimMorphData.Read(reader);
                        }
                        if (l.mode == MapLoader.Mode.Rayman2PC)
                        {
                            reader.PreAlign(8 * banks[i].global_morphData.Length, 4);
                        }
                    }
                    if (banks[i].global_deformations != null && banks[i].global_deformations.Length > 0)
                    {
                        if (banks[i].deformations.off_data != null)
                        {
                            Pointer.Goto(ref reader, banks[i].deformations.off_data);
                        }
                        for (uint j = 0; j < banks[i].global_deformations.Length; j++)
                        {
                            banks[i].global_deformations[j] = AnimDeformation.Read(reader);
                        }
                    }
                    if (append)
                    {
                        AnimationBank b = l.animationBanks[index + i];
                        b.a3d_general     = banks[i].a3d_general;
                        b.vectors         = banks[i].vectors;
                        b.quaternions     = banks[i].quaternions;
                        b.hierarchies     = banks[i].hierarchies;
                        b.NTTO            = banks[i].NTTO;
                        b.onlyFrames      = banks[i].onlyFrames;
                        b.channels        = banks[i].channels;
                        b.framesNumOfNTTO = banks[i].framesNumOfNTTO;
                        b.framesKFIndex   = banks[i].framesKFIndex;
                        b.keyframes       = banks[i].keyframes;
                        b.events          = banks[i].events;
                        b.morphData       = banks[i].morphData;
                        b.deformations    = banks[i].deformations;
                        //Util.AppendArray(ref b.animations, ref banks[i].animations);
                        Util.AppendArrayAndMergeReferences(ref b.global_vectors, ref banks[i].global_vectors, (int)banks[i].vectors.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_quaternions, ref banks[i].global_quaternions, (int)banks[i].quaternions.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_hierarchies, ref banks[i].global_hierarchies, (int)banks[i].hierarchies.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_NTTO, ref banks[i].global_NTTO, (int)banks[i].NTTO.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_onlyFrames, ref banks[i].global_onlyFrames, (int)banks[i].onlyFrames.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_channels, ref banks[i].global_channels, (int)banks[i].channels.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_numOfNTTO, ref banks[i].global_numOfNTTO, (int)banks[i].framesNumOfNTTO.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_framesKFIndex, ref banks[i].global_framesKFIndex, (int)banks[i].framesKFIndex.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_keyframes, ref banks[i].global_keyframes, (int)banks[i].keyframes.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_events, ref banks[i].global_events, (int)banks[i].events.countInFix);
                        Util.AppendArrayAndMergeReferences(ref b.global_morphData, ref banks[i].global_morphData, (int)banks[i].morphData.countInFix);
                        if (banks[i].deformations != null)
                        {
                            Util.AppendArrayAndMergeReferences(ref b.global_deformations, ref banks[i].global_deformations, (int)banks[i].deformations.countInFix);
                        }

                        /*Array.Resize(ref b.animations, b.animations.Length + banks[i].animations.Length);
                         * Array.Resize(ref b.global_vectors, b.global_vectors.Length + banks[i].global_vectors.Length);
                         * Array.Resize(ref b.global_quaternions, b.global_quaternions.Length + banks[i].global_quaternions.Length);
                         * Array.Resize(ref b.global_hierarchies, b.global_hierarchies.Length + banks[i].global_hierarchies.Length);
                         * Array.Resize(ref b.global_NTTO, b.global_NTTO.Length + banks[i].global_NTTO.Length);
                         * Array.Resize(ref b.global_onlyFrames, b.global_onlyFrames.Length + banks[i].global_onlyFrames.Length);
                         * Array.Resize(ref b.global_channels, b.global_channels.Length + banks[i].global_channels.Length);
                         * Array.Resize(ref b.global_numOfNTTO, b.global_numOfNTTO.Length + banks[i].global_numOfNTTO.Length);
                         * Array.Resize(ref b.global_framesKFIndex, b.global_framesKFIndex.Length + banks[i].global_framesKFIndex.Length);
                         * Array.Resize(ref b.global_keyframes, b.global_keyframes.Length + banks[i].global_keyframes.Length);
                         * Array.Resize(ref b.global_events, b.global_events.Length + banks[i].global_events.Length);
                         * Array.Resize(ref b.global_morphData, b.global_morphData.Length + banks[i].global_morphData.Length);
                         * if (banks[i].deformations != null) Array.Resize(ref b.global_deformations, b.global_deformations.Length + banks[i].global_deformations.Length);
                         * Array.Copy(banks[i].global_vectors, 0, b.global_vectors, banks[i].vectors.countInFix, banks[i].global_vectors.Length);
                         * Array.Copy(banks[i].global_quaternions, 0, b.global_quaternions, banks[i].quaternions.countInFix, banks[i].global_quaternions.Length);
                         * Array.Copy(banks[i].global_hierarchies, 0, b.global_hierarchies, banks[i].hierarchies.countInFix, banks[i].global_hierarchies.Length);
                         * Array.Copy(banks[i].global_NTTO, 0, b.global_NTTO, banks[i].NTTO.countInFix, banks[i].global_NTTO.Length);
                         * Array.Copy(banks[i].global_onlyFrames, 0, b.global_onlyFrames, banks[i].onlyFrames.countInFix, banks[i].global_onlyFrames.Length);
                         * Array.Copy(banks[i].global_channels, 0, b.global_channels, banks[i].channels.countInFix, banks[i].global_channels.Length);
                         * Array.Copy(banks[i].global_numOfNTTO, 0, b.global_numOfNTTO, banks[i].framesNumOfNTTO.countInFix, banks[i].global_numOfNTTO.Length);
                         * Array.Copy(banks[i].global_framesKFIndex, 0, b.global_framesKFIndex, banks[i].framesKFIndex.countInFix, banks[i].global_framesKFIndex.Length);
                         * Array.Copy(banks[i].global_keyframes, 0, b.global_keyframes, banks[i].keyframes.countInFix, banks[i].global_keyframes.Length);
                         * Array.Copy(banks[i].global_events, 0, b.global_events, banks[i].events.countInFix, banks[i].global_events.Length);
                         * Array.Copy(banks[i].global_morphData, 0, b.global_morphData, banks[i].morphData.countInFix, banks[i].global_morphData.Length);
                         * if (banks[i].deformations != null) Array.Copy(banks[i].global_deformations, 0, b.global_deformations, banks[i].deformations.countInFix, banks[i].global_deformations.Length);*/
                    }

                    if (banks[i].animations.Length > 0)
                    {
                        AnimationBank srcBank = append ? l.animationBanks[index + i] : banks[i];
                        for (uint j = 0; j < banks[i].animations.Length; j++)
                        {
                            banks[i].animations[j].vectors       = srcBank.global_vectors;
                            banks[i].animations[j].quaternions   = srcBank.global_quaternions;
                            banks[i].animations[j].hierarchies   = srcBank.global_hierarchies;
                            banks[i].animations[j].ntto          = srcBank.global_NTTO;
                            banks[i].animations[j].onlyFrames    = srcBank.global_onlyFrames;
                            banks[i].animations[j].channels      = srcBank.global_channels;
                            banks[i].animations[j].numOfNTTO     = srcBank.global_numOfNTTO;
                            banks[i].animations[j].framesKFIndex = srcBank.global_framesKFIndex;
                            banks[i].animations[j].keyframes     = srcBank.global_keyframes;
                            banks[i].animations[j].events        = srcBank.global_events;
                            banks[i].animations[j].morphData     = srcBank.global_morphData;
                            banks[i].animations[j].deformations  = srcBank.global_deformations;
                        }
                    }
                    if (append)
                    {
                        Util.AppendArrayAndMergeReferences(ref l.animationBanks[index + i].animations, ref banks[i].animations, (int)banks[i].a3d_general.countInFix);
                    }
                }
            }
            Pointer.Goto(ref reader, off_current);
            return(banks);
        }