public static FontInfo Read(Stream stream) => BinaryMapping.ReadObject <FontInfo>(stream);
public static SaveKh3 Read(Stream stream) => BinaryMapping.ReadObject(new BinaryReader(stream), new SaveKh3()) as SaveKh3;
private Motion(Stream stream) { stream.Position += ReservedSize; var header = BinaryMapping.ReadObject <Header>(stream); IsRaw = header.Version == 1; UnkFlag = header.Unk04 != 0; if (IsRaw) { var raw = BinaryMapping.ReadObject <RawMotionInternal>(stream); Raw = new RawMotion { BoneCount = raw.BoneCount, Unk28 = raw.Unk28, Unk2c = raw.Unk2c, BoundingBoxMinX = raw.BoundingBoxMinX, BoundingBoxMinY = raw.BoundingBoxMinY, BoundingBoxMinZ = raw.BoundingBoxMinZ, BoundingBoxMinW = raw.BoundingBoxMinW, BoundingBoxMaxX = raw.BoundingBoxMaxX, BoundingBoxMaxY = raw.BoundingBoxMaxY, BoundingBoxMaxZ = raw.BoundingBoxMaxZ, BoundingBoxMaxW = raw.BoundingBoxMaxW, FrameLoop = raw.FrameLoop, FrameEnd = raw.FrameEnd, FramePerSecond = raw.FramePerSecond, FrameCount = raw.FrameCount }; var reader = new BinaryReader(stream); Raw.Matrices = new List <Matrix4x4[]>(raw.TotalFrameCount); for (var i = 0; i < raw.TotalFrameCount; i++) { var matrices = new Matrix4x4[Raw.BoneCount]; for (var j = 0; j < Raw.BoneCount; j++) { matrices[j] = ReadMatrix(reader); } Raw.Matrices.Add(matrices); } if (raw.Unk2c > 0) { stream.Position = ReservedSize + raw.Unk2c; Raw.Matrices2 = new Matrix4x4[raw.TotalFrameCount]; for (var j = 0; j < Raw.Matrices2.Length; j++) { Raw.Matrices2[j] = ReadMatrix(reader); } } else { Raw.Matrices2 = new Matrix4x4[0]; } } else { var reader = new BinaryReader(stream); var motion = BinaryMapping.ReadObject <InterpolatedMotionInternal>(stream); Interpolated = new InterpolatedMotion { BoneCount = motion.BoneCount, TotalFrameCount = motion.TotalFrameCount, Unk48 = motion.Unk48, BoundingBoxMinX = motion.BoundingBoxMinX, BoundingBoxMinY = motion.BoundingBoxMinY, BoundingBoxMinZ = motion.BoundingBoxMinZ, BoundingBoxMinW = motion.BoundingBoxMinW, BoundingBoxMaxX = motion.BoundingBoxMaxX, BoundingBoxMaxY = motion.BoundingBoxMaxY, BoundingBoxMaxZ = motion.BoundingBoxMaxZ, BoundingBoxMaxW = motion.BoundingBoxMaxW, FrameLoop = motion.FrameLoop, FrameEnd = motion.FrameEnd, FramePerSecond = motion.FramePerSecond, FrameCount = motion.FrameCount, Unk98 = motion.Unk98, Unk9c = motion.Unk9c, }; stream.Position = ReservedSize + motion.StaticPoseOffset; Interpolated.StaticPose = Enumerable .Range(0, motion.StaticPoseCount) .Select(x => BinaryMapping.ReadObject <StaticPoseTable>(stream)) .ToList(); stream.Position = ReservedSize + motion.ModelBoneAnimationOffset; Interpolated.ModelBoneAnimation = Enumerable .Range(0, motion.ModelBoneAnimationCount) .Select(x => BinaryMapping.ReadObject <BoneAnimationTableInternal>(stream)) .Select(Map) .ToList(); stream.Position = ReservedSize + motion.IKHelperAnimationOffset; Interpolated.IKHelperAnimation = Enumerable .Range(0, motion.IKHelperAnimationCount) .Select(x => BinaryMapping.ReadObject <BoneAnimationTableInternal>(stream)) .Select(Map) .ToList(); stream.Position = ReservedSize + motion.TimelineOffset; var estimatedTimelineCount = (motion.KeyFrameOffset - motion.TimelineOffset) / 8; var rawTimeline = Enumerable .Range(0, estimatedTimelineCount) .Select(x => BinaryMapping.ReadObject <TimelineTableInternal>(stream)) .ToList(); stream.Position = ReservedSize + motion.KeyFrameOffset; var keyFrames = Enumerable .Range(0, motion.KeyFrameCount) .Select(x => reader.ReadSingle()) .ToList(); stream.Position = ReservedSize + motion.TransformationValueOffset; var estimatedKeyFrameCount = (motion.TangentOffset - motion.TransformationValueOffset) / 4; var transformationValues = Enumerable .Range(0, estimatedKeyFrameCount) .Select(x => reader.ReadSingle()) .ToList(); stream.Position = ReservedSize + motion.TangentOffset; var estimatedTangentCount = (motion.IKChainOffset - motion.TangentOffset) / 4; var tangentValues = Enumerable .Range(0, estimatedTangentCount) .Select(x => reader.ReadSingle()) .ToList(); stream.Position = ReservedSize + motion.IKChainOffset; Interpolated.IKChains = Enumerable .Range(0, motion.IKChainCount) .Select(x => BinaryMapping.ReadObject <IKChainTable>(stream)) .ToList(); stream.Position = ReservedSize + motion.Table8Offset; var estimatedTable8Count = (motion.Table7Offset - motion.Table8Offset) / 0x30; Interpolated.Table8 = Enumerable .Range(0, estimatedTable8Count) .Select(x => BinaryMapping.ReadObject <UnknownTable8>(stream)) .ToList(); stream.Position = ReservedSize + motion.Table7Offset; Interpolated.Table7 = Enumerable .Range(0, motion.Table7Count) .Select(x => BinaryMapping.ReadObject <UnknownTable7>(stream)) .ToList(); stream.Position = ReservedSize + motion.Table6Offset; Interpolated.Table6 = Enumerable .Range(0, motion.Table6Count) .Select(x => BinaryMapping.ReadObject <UnknownTable6>(stream)) .ToList(); stream.Position = ReservedSize + motion.IKHelperOffset; Interpolated.IKHelpers = Enumerable .Range(0, motion.TotalBoneCount - motion.BoneCount) .Select(x => BinaryMapping.ReadObject <IKHelperTable>(stream)) .ToList(); stream.Position = ReservedSize + motion.JointIndexOffset; Interpolated.Joints = Enumerable .Range(0, motion.TotalBoneCount + 1) .Select(x => BinaryMapping.ReadObject <JointTable>(stream)) .ToList(); Interpolated.Timeline = rawTimeline .Select(x => new TimelineTable { Interpolation = (Interpolation)(x.Time & 3), KeyFrame = keyFrames[Math.Min(keyFrames.Count - 1, x.Time >> 2)], Value = transformationValues[Math.Min(transformationValues.Count - 1, x.ValueIndex)], TangentEaseIn = tangentValues[x.TangentIndexEaseIn], TangentEaseOut = tangentValues[x.TangentIndexEaseOut], }) .ToList(); stream.Position = ReservedSize + motion.FooterOffset; Interpolated.Footer = BinaryMapping.ReadObject <FooterTable>(stream); stream.Position = ReservedSize + motion.UnknownTable1Offset; } }
public void Write(Stream stream) => BinaryMapping.WriteObject(stream.FromBegin(), this);
public TextureFooterData(Stream stream) { var shouldEmitDMYAtFirst = false; var index = -1; while (stream.Position < stream.Length) { ++index; var tag = Encoding.ASCII.GetString(stream.ReadBytes(4)); if (tag == "_KN5") { ShouldEmitDMYAtFirst = (index == 1) && shouldEmitDMYAtFirst; ShouldEmitKN5 = true; UnkFooter = stream.ReadBytes(); break; } var length = stream.ReadInt32(); var nextTag = stream.Position + length; var subStreamPos = Convert.ToInt32(stream.Position); if (tag == "UVSC") { UvscList.Add(BinaryMapping.ReadObject <UvScroll>(stream)); } else if (tag == "TEXA") { var header = BinaryMapping.ReadObject <TextureAnimation>(stream); stream.Position = subStreamPos + header.OffsetSlotTable; header.SlotTable = Enumerable.Range(0, 1 + header.MaximumSlotIndex - header.BaseSlotIndex) .Select(_ => stream.ReadInt16()) .ToArray(); stream.Position = subStreamPos + header.OffsetAnimationTable; var frameGroupOffsetList = Enumerable.Range(0, header.NumAnimations) .Select(idx => stream.ReadUInt32()) .ToArray(); header.FrameGroupList = frameGroupOffsetList .Select( firstPosition => { stream.Position = subStreamPos + firstPosition; var indexedFrameList = new Dictionary <int, TextureFrame>(); var idx = 0; while (true) { if (indexedFrameList.ContainsKey(idx)) { break; } var frame = BinaryMapping.ReadObject <TextureFrame>(stream); indexedFrameList[idx] = frame; if (frame.FrameControl == TextureFrameControl.Jump || frame.FrameControl == TextureFrameControl.Stop) { idx += frame.FrameIndexDelta; stream.Seek(TextureFrame.SizeInBytes * (-1 + frame.FrameIndexDelta), SeekOrigin.Current); } else { idx++; } } return(new TextureFrameGroup { IndexedFrameList = indexedFrameList, }); } ) .ToArray(); header.SpriteImage = stream .SetPosition(subStreamPos + header.OffsetSpriteImage) .ReadBytes(header.SpriteStride * header.SpriteHeight * header.NumSpritesInImageData); TextureAnimationList.Add(header); } else if (tag == "_DMY") { shouldEmitDMYAtFirst |= (index == 0) ? true : false; } stream.Position = nextTag; } }
public static IEnumerable <Entry> Read(Stream stream) => Enumerable .Range(0, (int)(stream.Length / 0x20)) .Select(_ => BinaryMapping.ReadObject <Entry>(stream));
public static void ReadMeshData(Stream stream, Pmo pmo, int MeshNumber = 0) { // Go to mesh position. if (MeshNumber == 0) { stream.Seek(pmo.header.MeshOffset0, SeekOrigin.Begin); } else { stream.Seek(pmo.header.MeshOffset1, SeekOrigin.Begin); } UInt16 VertCnt = 0xFFFF; while (VertCnt > 0) { MeshChunks meshChunk = new MeshChunks(); meshChunk.MeshNumber = MeshNumber; meshChunk.SectionInfo = BinaryMapping.ReadObject <MeshSection>(stream); // Exit if Vertex Count is zero. if (meshChunk.SectionInfo.VertexCount <= 0) { break; } meshChunk.TextureID = meshChunk.SectionInfo.TextureID; VertexFlags flags = GetFlags(meshChunk.SectionInfo); bool isColorFlagRisen = flags.UniformDiffuseFlag; if (pmo.header.SkeletonOffset != 0) { meshChunk.SectionInfo_opt1 = BinaryMapping.ReadObject <MeshSectionOptional1>(stream); } if (isColorFlagRisen) { meshChunk.SectionInfo_opt2 = BinaryMapping.ReadObject <MeshSectionOptional2>(stream); } if (meshChunk.SectionInfo.TriangleStripCount > 0) { meshChunk.TriangleStripValues = new UInt16[meshChunk.SectionInfo.TriangleStripCount]; for (int i = 0; i < meshChunk.SectionInfo.TriangleStripCount; i++) { meshChunk.TriangleStripValues[i] = stream.ReadUInt16(); } } // Get Formats. CoordinateFormat TexCoordFormat = flags.TextureCoordinateFormat; CoordinateFormat VertexPositionFormat = flags.PositionFormat; CoordinateFormat WeightFormat = flags.WeightFormat; ColorFormat ColorFormat = flags.ColorFormat; UInt32 SkinningWeightsCount = flags.SkinningWeightsCount; BinaryReader r = new BinaryReader(stream); long positionAfterHeader = stream.Position; if (meshChunk.SectionInfo.TriangleStripCount > 0) { int vertInd = 0; for (int p = 0; p < meshChunk.SectionInfo.TriangleStripCount; p++) { for (int s = 0; s < (meshChunk.TriangleStripValues[p] - 2); s++) { if (s % 2 == 0) { meshChunk.Indices.Add(vertInd + s + 0); meshChunk.Indices.Add(vertInd + s + 1); meshChunk.Indices.Add(vertInd + s + 2); } else { meshChunk.Indices.Add(vertInd + s + 0); meshChunk.Indices.Add(vertInd + s + 2); meshChunk.Indices.Add(vertInd + s + 1); } } vertInd += meshChunk.TriangleStripValues[p]; } } else { if (flags.Primitive == PrimitiveType.PRIMITIVE_TRIANGLE_STRIP) { for (int s = 0; s < (meshChunk.SectionInfo.VertexCount - 2); s++) { if (s % 2 == 0) { meshChunk.Indices.Add(s + 0); meshChunk.Indices.Add(s + 1); meshChunk.Indices.Add(s + 2); } else { meshChunk.Indices.Add(s + 1); meshChunk.Indices.Add(s + 0); meshChunk.Indices.Add(s + 2); } } } } for (int v = 0; v < meshChunk.SectionInfo.VertexCount; v++) { long vertexStartPos = stream.Position; int vertexIncreaseAmount = 0; if (pmo.header.SkeletonOffset != 0 && WeightFormat != CoordinateFormat.NO_VERTEX) { for (int i = 0; i < (SkinningWeightsCount + 1); i++) { switch (WeightFormat) { case CoordinateFormat.NORMALIZED_8_BITS: meshChunk.jointWeights.Add(stream.ReadByte() / 127.0f); break; case CoordinateFormat.NORMALIZED_16_BITS: meshChunk.jointWeights.Add(stream.ReadUInt16() / 32767.0f); break; case CoordinateFormat.FLOAT_32_BITS: meshChunk.jointWeights.Add(stream.ReadFloat()); break; case CoordinateFormat.NO_VERTEX: break; } } } Vector2 currentTexCoord; switch (TexCoordFormat) { case CoordinateFormat.NORMALIZED_8_BITS: currentTexCoord.X = stream.ReadByte() / 127.0f; currentTexCoord.Y = stream.ReadByte() / 127.0f; meshChunk.textureCoordinates.Add(currentTexCoord); break; case CoordinateFormat.NORMALIZED_16_BITS: vertexIncreaseAmount = ((0x2 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x1)) & 0x1); stream.Seek(vertexIncreaseAmount, SeekOrigin.Current); currentTexCoord.X = stream.ReadUInt16() / 32767.0f; currentTexCoord.Y = stream.ReadUInt16() / 32767.0f; meshChunk.textureCoordinates.Add(currentTexCoord); break; case CoordinateFormat.FLOAT_32_BITS: vertexIncreaseAmount = ((0x4 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x3)) & 0x3); stream.Seek(vertexIncreaseAmount, SeekOrigin.Current); currentTexCoord.X = stream.ReadFloat(); currentTexCoord.Y = stream.ReadFloat(); meshChunk.textureCoordinates.Add(currentTexCoord); break; } switch (ColorFormat) { case Pmo.ColorFormat.NO_COLOR: meshChunk.colors.Add(new Vector4(0xFF, 0xFF, 0xFF, 0xFF)); break; case Pmo.ColorFormat.BGR_5650_16BITS: stream.ReadUInt16(); break; case Pmo.ColorFormat.ABGR_5551_16BITS: stream.ReadUInt16(); break; case Pmo.ColorFormat.ABGR_4444_16BITS: stream.ReadUInt16(); break; case Pmo.ColorFormat.ABGR_8888_32BITS: vertexIncreaseAmount = ((0x4 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x3)) & 0x3); stream.Seek(vertexIncreaseAmount, SeekOrigin.Current); Vector4 col; col.X = stream.ReadByte(); col.Y = stream.ReadByte(); col.Z = stream.ReadByte(); col.W = stream.ReadByte(); meshChunk.colors.Add(col); break; } Vector3 currentVertex; // Handle triangles and triangle strips. switch (VertexPositionFormat) { case CoordinateFormat.NORMALIZED_8_BITS: currentVertex.X = r.ReadSByte() / 127.0f; currentVertex.Y = r.ReadSByte() / 127.0f; currentVertex.Z = r.ReadSByte() / 127.0f; meshChunk.vertices.Add(currentVertex); break; case CoordinateFormat.NORMALIZED_16_BITS: vertexIncreaseAmount = ((0x2 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x1)) & 0x1); stream.Seek(vertexIncreaseAmount, SeekOrigin.Current); currentVertex.X = (float)stream.ReadInt16() / 32767.0f; currentVertex.Y = (float)stream.ReadInt16() / 32767.0f; currentVertex.Z = (float)stream.ReadInt16() / 32767.0f; meshChunk.vertices.Add(currentVertex); break; case CoordinateFormat.FLOAT_32_BITS: vertexIncreaseAmount = ((0x4 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x3)) & 0x3); stream.Seek(vertexIncreaseAmount, SeekOrigin.Current); currentVertex.X = stream.ReadFloat(); currentVertex.Y = stream.ReadFloat(); currentVertex.Z = stream.ReadFloat(); meshChunk.vertices.Add(currentVertex); break; } stream.Seek(vertexStartPos + meshChunk.SectionInfo.VertexSize, SeekOrigin.Begin); if (flags.Primitive == PrimitiveType.PRIMITIVE_TRIANGLE) { meshChunk.Indices.Add(v); } } VertCnt = meshChunk.SectionInfo.VertexCount; pmo.Meshes.Add(meshChunk); // Find position of next data chunk. stream.Seek(positionAfterHeader + (meshChunk.SectionInfo.VertexCount * meshChunk.SectionInfo.VertexSize), SeekOrigin.Begin); stream.Seek(stream.Position % 4, SeekOrigin.Current); } }
public static Signal Read(Stream stream) => BinaryMapping.ReadObject <Signal>(stream);
public static void Write(Stream stream, Signal entity) => BinaryMapping.WriteObject(stream, entity);
public static ReturnParameter Read(Stream stream) => BinaryMapping.ReadObject <ReturnParameter>(stream);
public static void Write(Stream stream, ReturnParameter entity) => BinaryMapping.WriteObject(stream, entity);
private static M4 ReadAsMap(Stream stream) { var header = BinaryMapping.ReadObject <SubModelMapHeader>(stream); if (header.Type != Map) { throw new NotSupportedException("Type must be 2 for maps"); } var dmaChainMaps = For(header.DmaChainMapCount, () => BinaryMapping.ReadObject <DmaChainMap>(stream)); stream.Position = header.Offset1; // The original game engine ignores header.Count1 for some reason var count1 = (short)((stream.ReadInt32() - header.Offset1) / 4); stream.Position -= 4; var alb2 = For(count1, () => stream.ReadInt32()) .Select(offset => ReadAlb2t2(stream.SetPosition(offset)).ToArray()) .ToList(); stream.Position = header.Offset2; var offb1t2t2 = stream.ReadInt32(); var unknownTableCount = (offb1t2t2 - header.Offset2) / 4 - 1; var unknownTable = For(unknownTableCount, () => stream.ReadInt32()) .ToArray(); stream.Position = offb1t2t2; var alb1t2 = ReadAlb2t2(stream).ToList(); var vifPackets = dmaChainMaps .Select(dmaChain => { var currentVifOffset = dmaChain.VifOffset; DmaTag dmaTag; var packet = new List <byte>(); var sizePerDma = new List <ushort>(); do { stream.Position = currentVifOffset; dmaTag = BinaryMapping.ReadObject <DmaTag>(stream); var packets = stream.ReadBytes(8 + 16 * dmaTag.Qwc); packet.AddRange(packets); sizePerDma.Add(dmaTag.Qwc); currentVifOffset += 16 + 16 * dmaTag.Qwc; } while (dmaTag.TagId < 2); return(new VifPacketDescriptor { VifPacket = packet.ToArray(), TextureId = dmaChain.TextureIndex, Unk08 = dmaChain.Unk08, Unk0c = dmaChain.Unk0c, DmaPerVif = sizePerDma.ToArray(), }); }) .ToList(); return(new M4 { unk04 = header.Unk04, unk08 = header.Unk08, nextOffset = header.NextOffset, va4 = header.va4, count1 = header.Count1, alb1t2 = alb1t2.ToList(), alb2 = alb2, unknownTable = unknownTable, VifPackets = vifPackets }); }
private static void WriteAsMap(Stream stream, M4 mapModel) { var mapHeader = new SubModelMapHeader { Type = Map, DmaChainMapCount = mapModel.VifPackets.Count, Unk04 = mapModel.unk04, Unk08 = mapModel.unk08, NextOffset = mapModel.nextOffset, va4 = mapModel.va4, Count1 = mapModel.count1, // in a form, ignored by the game engine }; BinaryMapping.WriteObject(stream, mapHeader); var dmaChainMapDescriptorOffset = (int)stream.Position; stream.Position += mapModel.VifPackets.Count * 0x10; mapHeader.Offset1 = (int)stream.Position; stream.Position += mapModel.alb2.Count * 4; var alb2Offsets = new List <int>(); foreach (var alb2 in mapModel.alb2) { alb2Offsets.Add((int)stream.Position); WriteAlb2(stream, alb2); } var endAlb2Offset = Helpers.Align((int)stream.Position, 4); stream.Position = mapHeader.Offset1; foreach (var alb2Offset in alb2Offsets) { stream.Write(alb2Offset); } stream.Position = endAlb2Offset; mapHeader.Offset2 = endAlb2Offset; stream.Write(endAlb2Offset + 4 + mapModel.unknownTable.Length * 4); stream.Write(mapModel.unknownTable); WriteAlb2(stream, mapModel.alb1t2); stream.AlignPosition(0x10); var dmaChainVifOffsets = new List <int>(); foreach (var dmaChainMap in mapModel.VifPackets) { var vifPacketIndex = 0; dmaChainVifOffsets.Add((int)stream.Position); foreach (var packetCount in dmaChainMap.DmaPerVif) { BinaryMapping.WriteObject(stream, new DmaTag { Qwc = packetCount, Address = 0, TagId = packetCount > 0 ? 1 : 6, Irq = false, }); var packetLength = packetCount * 0x10 + 8; stream.Write(dmaChainMap.VifPacket, vifPacketIndex, packetLength); vifPacketIndex += packetLength; } } stream.AlignPosition(0x80); stream.SetLength(stream.Position); stream.Position = dmaChainMapDescriptorOffset; for (var i = 0; i < mapModel.VifPackets.Count; i++) { var dmaChainMap = mapModel.VifPackets[i]; BinaryMapping.WriteObject(stream, new DmaChainMap { VifOffset = dmaChainVifOffsets[i], TextureIndex = dmaChainMap.TextureId, Unk08 = dmaChainMap.Unk08, Unk0c = dmaChainMap.Unk0c }); } stream.Position = 0; BinaryMapping.WriteObject(stream, mapHeader); }
public void Write(Stream stream) => BinaryMapping.WriteObject(stream, this);
private static Bone ReadBone(Stream stream) => BinaryMapping.ReadObject <Bone>(stream);
public static TSaveKhDDD Read <TSaveKhDDD>(Stream stream) where TSaveKhDDD : class, ISaveKhDDD => BinaryMapping.ReadObject <TSaveKhDDD>(stream.SetPosition(0));
private static void WriteBone(Stream stream, Bone bone) => BinaryMapping.WriteObject(stream, bone);
public static void Write <TSaveKhDDD>(Stream stream, TSaveKhDDD save) where TSaveKhDDD : class, ISaveKhDDD { BinaryMapping.WriteObject(stream.FromBegin(), save); }
public static void ReadHeader(Stream stream, Pmo pmo) { pmo.header = BinaryMapping.ReadObject <Header>(stream.SetPosition(0)); }
public void Write(Stream stream) { stream.MustWriteAndSeek(); var header = new Header { MagicCode = MagicCodeValidator, Unknown04 = Unknown04, SpriteDesc = new Section() { Count = Sprites.Count }, SpritePartDesc = new Section() { Count = SpriteGroups.Sum(x => x.Count) }, SpriteGroupDesc = new Section() { Count = SpriteGroups.Count }, AnimationDesc = new Section() { Count = AnimationGroups.Sum(x => x.Animations.Count) }, AnimationGroupDesc = new Section() { Count = AnimationGroups.Count }, }; var index = 0; var basePosition = stream.Position; stream.Position = basePosition + MinimumLength; header.SpriteDesc.Offset = (int)(stream.Position - basePosition); header.SpritePartDesc.Offset = stream.WriteList(Sprites.Select(x => new RawSprite { U0 = x.Left, V0 = x.Top, U1 = x.Right, V1 = x.Bottom, UScroll = x.UTranslation, VScroll = x.VTranslation, ColorLeft = x.ColorLeft, ColorTop = x.ColorTop, ColorRight = x.ColorRight, ColorBottom = x.ColorBottom, })) + header.SpriteDesc.Offset; header.SpriteGroupDesc.Offset = stream.WriteList(SpriteGroups.SelectMany(x => x)) + header.SpritePartDesc.Offset; index = 0; foreach (var spriteGroup in SpriteGroups) { BinaryMapping.WriteObject(stream, new RawSpriteGroup { Start = (short)index, Count = (short)spriteGroup.Count }); index += spriteGroup.Count; } header.AnimationDesc.Offset = SpriteGroups.Count * 4 + header.SpriteGroupDesc.Offset; header.AnimationGroupDesc.Offset = stream.WriteList(AnimationGroups.SelectMany(x => x.Animations)) + header.AnimationDesc.Offset; index = 0; foreach (var animGroup in AnimationGroups) { BinaryMapping.WriteObject(stream, new RawAnimationGroup { AnimationIndex = (short)index, Count = (short)animGroup.Animations.Count, Loop = animGroup.DoNotLoop, Flags = animGroup.Unknown06, FrameStart = animGroup.LoopStart, FrameEnd = animGroup.LoopEnd, X = animGroup.LightPositionX, Y = animGroup.TextPositionY, Size = animGroup.TextScale, Unknown1C = animGroup.UiPadding, Unknown20 = animGroup.TextPositionX, }); index += animGroup.Animations.Count; } var endPosition = stream.Position; stream.Position = basePosition; BinaryMapping.WriteObject(stream, header); stream.Position = endPosition; }
public static void Write(Stream stream, Pmo pmo) { stream.Position = 0; bool hasSwappedToSecondModel = false; BinaryMapping.WriteObject <Pmo.Header>(stream, pmo.header); for (int i = 0; i < pmo.header.TextureCount; i++) { BinaryMapping.WriteObject <Pmo.TextureInfo>(stream, pmo.textureInfo[i]); } // Write Mesh Data. for (int j = 0; j < pmo.Meshes.Count; j++) { if (!hasSwappedToSecondModel && pmo.Meshes[j].MeshNumber == 1) { hasSwappedToSecondModel = true; for (uint b = 0; b < 0xC; b++) { stream.Write((byte)0x00); } for (uint b = 0; stream.Position % 0x10 != 0; b++) { stream.Write((byte)0x00); } } MeshChunks chunk = pmo.Meshes[j]; BinaryMapping.WriteObject <Pmo.MeshSection>(stream, chunk.SectionInfo); if (chunk.SectionInfo_opt1 != null) { BinaryMapping.WriteObject <Pmo.MeshSectionOptional1>(stream, chunk.SectionInfo_opt1); } if (chunk.SectionInfo_opt2 != null) { BinaryMapping.WriteObject <Pmo.MeshSectionOptional2>(stream, chunk.SectionInfo_opt2); } if (chunk.TriangleStripValues.Length > 0) { for (int z = 0; z < chunk.TriangleStripValues.Length; z++) { stream.Write((ushort)chunk.TriangleStripValues[z]); } } for (int k = 0; k < pmo.Meshes[j].SectionInfo.VertexCount; k++) { long vertexStartPos = stream.Position; int vertexIncreaseAmount = 0; VertexFlags flags = Pmo.GetFlags(chunk.SectionInfo); // Write Joints. if (flags.WeightFormat != CoordinateFormat.NO_VERTEX) { for (int w = 0; w < flags.SkinningWeightsCount + 1; w++) { int currentIndex = w + (k * (flags.SkinningWeightsCount + 1)); switch (flags.WeightFormat) { case CoordinateFormat.NORMALIZED_8_BITS: stream.Write((byte)(chunk.jointWeights[currentIndex] * 127.0f)); break; case CoordinateFormat.NORMALIZED_16_BITS: stream.Write((byte)(chunk.jointWeights[currentIndex] * 32767.0f)); break; case CoordinateFormat.FLOAT_32_BITS: StreamExtensions.Write(stream, chunk.jointWeights[currentIndex]); break; } } } // Write Texture Coords. switch (flags.TextureCoordinateFormat) { case CoordinateFormat.NORMALIZED_8_BITS: stream.Write((byte)(chunk.textureCoordinates[k].X * 127.0f)); stream.Write((byte)(chunk.textureCoordinates[k].Y * 127.0f)); break; case CoordinateFormat.NORMALIZED_16_BITS: vertexIncreaseAmount = ((0x2 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x1)) & 0x1); for (int a = 0; a < vertexIncreaseAmount; a++) { stream.Write((byte)0xAB); } stream.Write((ushort)(chunk.textureCoordinates[k].X * 32767.0f)); stream.Write((ushort)(chunk.textureCoordinates[k].Y * 32767.0f)); break; case CoordinateFormat.FLOAT_32_BITS: vertexIncreaseAmount = ((0x4 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x3)) & 0x3); for (int a = 0; a < vertexIncreaseAmount; a++) { stream.Write((byte)0xAB); } StreamExtensions.Write(stream, chunk.textureCoordinates[k].X); StreamExtensions.Write(stream, chunk.textureCoordinates[k].Y); break; } // Write colors. switch (flags.ColorFormat) { case Pmo.ColorFormat.NO_COLOR: break; case Pmo.ColorFormat.BGR_5650_16BITS: break; case Pmo.ColorFormat.ABGR_5551_16BITS: break; case Pmo.ColorFormat.ABGR_4444_16BITS: break; case Pmo.ColorFormat.ABGR_8888_32BITS: vertexIncreaseAmount = ((0x4 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x3)) & 0x3); for (int a = 0; a < vertexIncreaseAmount; a++) { stream.Write((byte)0xAB); } stream.Write((byte)(chunk.colors[k].X)); stream.Write((byte)(chunk.colors[k].Y)); stream.Write((byte)(chunk.colors[k].Z)); stream.Write((byte)(chunk.colors[k].W)); break; } // Write vertices. switch (flags.PositionFormat) { case CoordinateFormat.NORMALIZED_8_BITS: StreamExtensions.Write(stream, (sbyte)(chunk.vertices[k].X * 127.0f)); StreamExtensions.Write(stream, (sbyte)(chunk.vertices[k].Y * 127.0f)); StreamExtensions.Write(stream, (sbyte)(chunk.vertices[k].Z * 127.0f)); break; case CoordinateFormat.NORMALIZED_16_BITS: vertexIncreaseAmount = ((0x2 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x1)) & 0x1); for (int a = 0; a < vertexIncreaseAmount; a++) { stream.Write((byte)0xAB); } StreamExtensions.Write(stream, (short)(chunk.vertices[k].X * 32767.0f)); StreamExtensions.Write(stream, (short)(chunk.vertices[k].Y * 32767.0f)); StreamExtensions.Write(stream, (short)(chunk.vertices[k].Z * 32767.0f)); break; case CoordinateFormat.FLOAT_32_BITS: vertexIncreaseAmount = ((0x4 - (Convert.ToInt32(stream.Position - vertexStartPos) & 0x3)) & 0x3); for (int a = 0; a < vertexIncreaseAmount; a++) { stream.Write((byte)0xAB); } StreamExtensions.Write(stream, chunk.vertices[k].X); StreamExtensions.Write(stream, chunk.vertices[k].Y); StreamExtensions.Write(stream, chunk.vertices[k].Z); break; } int padding = ((int)vertexStartPos + chunk.SectionInfo.VertexSize) - (int)stream.Position; for (int p = 0; p < padding; p++) { stream.Write((byte)0xAB); } } // Remainder. uint remainder = (uint)stream.Position % 4; for (int p = 0; p < remainder; p++) { stream.Write((byte)0x00); } if (j == (pmo.Meshes.Count - 1)) { for (uint b = 0; b < 0xC; b++) { stream.Write((byte)0x00); } for (uint b = 0; stream.Position % 0x10 != 0; b++) { stream.Write((byte)0x00); } } } // Write textures. for (int t = 0; t < pmo.texturesData.Count; t++) { stream.Write(pmo.texturesData[t]); } if (pmo.header.SkeletonOffset != 0) { BinaryMapping.WriteObject <SkeletonHeader>(stream, pmo.skeletonHeader); for (int joint = 0; joint < pmo.jointList.Length; joint++) { BinaryMapping.WriteObject <JointData>(stream, pmo.jointList[joint]); } } }
private Coct(Stream stream) : this() { if (!IsValid(stream)) { throw new InvalidDataException("Invalid header"); } var header = BinaryMapping.ReadObject <Header>(stream.SetPosition(0)); Depth = header.Depth; Type = header.Type; var rawNodeList = ReactCoctEntry <RawNode>(stream, header.Entries[1], NodeSize); var rawCollisionMeshList = ReactCoctEntry <RawCollisionMesh>(stream, header.Entries[2], MeshSize); var rawCollisionList = ReactCoctEntry <RawCollision>(stream, header.Entries[3], PolygonSize); VertexList = ReadValueEntry <Vector4>(stream, header.Entries[4], Col4Size, ReadVector4); var planeList = ReadValueEntry <Plane>(stream, header.Entries[5], Col5Size, ReadPlane); var boundingBoxes = ReadValueEntry(stream, header.Entries[6], BoundingBoxSize, ReadBoundingBoxInt16); var attributesList = ReactCoctEntry <Attributes>(stream, header.Entries[7], AttributesSize); var collisionList = rawCollisionList .Select(x => new Collision { Ground = x.Ground, FloorLevel = x.FloorLevel, Vertex1 = x.Vertex1, Vertex2 = x.Vertex2, Vertex3 = x.Vertex3, Vertex4 = x.Vertex4, Plane = planeList[x.PlaneIndex], BoundingBox = x.BoundingBoxIndex >= 0 ? boundingBoxes[x.BoundingBoxIndex] : BoundingBoxInt16.Invalid, Attributes = attributesList[x.AttributeIndex], }) .ToList(); var collisionMeshList = rawCollisionMeshList .Select(x => new CollisionMesh { BoundingBox = x.BoundingBox, Collisions = Enumerable.Range(x.CollisionStart, x.CollisionEnd - x.CollisionStart) .Select(i => collisionList[i]) .ToList(), Visibility = x.Visibility, Group = x.Group }) .ToList(); Nodes = rawNodeList .Select(x => new CollisionNode { Child1 = x.Child1, Child2 = x.Child2, Child3 = x.Child3, Child4 = x.Child4, Child5 = x.Child5, Child6 = x.Child6, Child7 = x.Child7, Child8 = x.Child8, BoundingBox = x.BoundingBox, Meshes = Enumerable.Range(x.CollisionMeshStart, x.CollisionMeshEnd - x.CollisionMeshStart) .Select(i => collisionMeshList[i]) .ToList(), }) .ToList(); }
public void Write(Stream stream) { if (ShouldEmitDMYAtFirst) { // Some map files has style "_DMY" "_KN5". This is for that consistency. stream.Write(_DMY); stream.Write(0); } foreach (var item in TextureAnimationList) { var texaStream = new MemoryStream(); { item.NumAnimations = Convert.ToUInt16(item.FrameGroupList.Length); var animationTable = new int[item.NumAnimations]; for (var pass = 1; pass <= 2; pass++) { texaStream.Position = 0; BinaryMapping.WriteObject(texaStream, item); item.OffsetSlotTable = Convert.ToInt32(texaStream.Position); item.SlotTable.ToList().ForEach(texaStream.Write); texaStream.AlignPosition(4); item.OffsetAnimationTable = Convert.ToInt32(texaStream.Position); texaStream.Write(animationTable); foreach (var(group, groupIndex) in item.FrameGroupList.Select((group, groupIndex) => (group, groupIndex))) { animationTable[groupIndex] = Convert.ToInt32(texaStream.Position); if (group.IndexedFrameList.Any()) { int minIdx = group.IndexedFrameList.Keys.Min(); int maxIdx = group.IndexedFrameList.Keys.Max(); for (; minIdx <= maxIdx; minIdx++) { group.IndexedFrameList.TryGetValue(minIdx, out TextureFrame frame); frame = frame ?? new TextureFrame(); BinaryMapping.WriteObject(texaStream, frame); } } } texaStream.AlignPosition(16); item.OffsetSpriteImage = Convert.ToInt32(texaStream.Position); texaStream.Write(item.SpriteImage); texaStream.AlignPosition(16); } } stream.Write(_DMY); stream.Write(0); stream.Write(TEXA); stream.Write(Convert.ToUInt32(texaStream.Length)); texaStream.Position = 0; texaStream.CopyTo(stream); } if (UvscList.Any()) { // Before first "UVSC", "_DMY" has to be placed. This is for that consistency. stream.Write(_DMY); stream.Write(0); foreach (var item in UvscList) { stream.Write(UVSC); stream.Write(12); BinaryMapping.WriteObject(stream, item); } } else if (TextureAnimationList.Any()) { // Between "TEXA" and "_KN5", "_DMY" has to be placed. This is for that consistency. stream.Write(_DMY); stream.Write(0); } if (ShouldEmitKN5) { stream.Write(_KN5); } if (UnkFooter != null) { stream.Write(UnkFooter); } }
public void Write(Stream stream) { var collisionList = new List <Collision>(); var collisionMeshList = new List <RawCollisionMesh>(); var collisionMeshGroupList = new List <RawNode>(); foreach (var node in Nodes) { var start = node.Meshes.Count > 0 ? collisionMeshList.Count : 0; collisionMeshGroupList.Add(new RawNode { Child1 = node.Child1, Child2 = node.Child2, Child3 = node.Child3, Child4 = node.Child4, Child5 = node.Child5, Child6 = node.Child6, Child7 = node.Child7, Child8 = node.Child8, BoundingBox = node.BoundingBox, CollisionMeshStart = (ushort)start, CollisionMeshEnd = (ushort)(start + node.Meshes.Count) }); foreach (var mesh in node.Meshes) { collisionMeshList.Add(new RawCollisionMesh { BoundingBox = mesh.BoundingBox, CollisionStart = (ushort)collisionList.Count, CollisionEnd = (ushort)(collisionList.Count + mesh.Collisions.Count), Visibility = mesh.Visibility, Group = mesh.Group }); collisionList.AddRange(mesh.Collisions); } } var bbCache = new WriteCache <BoundingBoxInt16, string>(x => x.ToString()); bbCache.AddConstant(BoundingBoxInt16.Invalid, -1); foreach (var item in collisionList) { bbCache.Add(item.BoundingBox); } var surfaceCache = new WriteCache <Attributes, int>(x => x.Flags); foreach (var item in collisionList) { surfaceCache.Add(item.Attributes); } var planeCache = new WriteCache <Plane, string>(x => x.ToString()); foreach (var item in collisionList) { planeCache.Add(item.Plane); } var entries = new List <Entry>(8); AddEntry(entries, HeaderSize, 1); AddEntry(entries, Nodes.Count * NodeSize, 0x10); AddEntry(entries, collisionMeshList.Count * MeshSize, 0x10); AddEntry(entries, collisionList.Count * PolygonSize, 4); AddEntry(entries, VertexList.Count * Col4Size, 0x10); AddEntry(entries, planeCache.Count * Col5Size, 0x10); AddEntry(entries, bbCache.Count * BoundingBoxSize, 0x10); AddEntry(entries, surfaceCache.Count * AttributesSize, 4); stream.Position = 0; BinaryMapping.WriteObject(stream, new Header { MagicCode = MagicCode, Version = 1, Depth = Depth, Type = Type, Entries = entries.ToArray() }); WriteCoctEntry(stream, collisionMeshGroupList); WriteCoctEntry(stream, collisionMeshList); WriteCoctEntry(stream, collisionList .Select(x => new RawCollision { Ground = x.Ground, FloorLevel = x.FloorLevel, Vertex1 = x.Vertex1, Vertex2 = x.Vertex2, Vertex3 = x.Vertex3, Vertex4 = x.Vertex4, PlaneIndex = planeCache[x.Plane], BoundingBoxIndex = bbCache[x.BoundingBox], AttributeIndex = surfaceCache[x.Attributes], })); stream.AlignPosition(0x10); WriteValueEntry(stream, VertexList, WriteVector4); WriteValueEntry(stream, planeCache, WritePlane); WriteValueEntry(stream, bbCache, WriteBoundingBoxInt16); WriteCoctEntry(stream, surfaceCache); }
public void Write(Stream stream) => BinaryMapping.WriteObject(new BinaryWriter(stream), this);
private static TSaveData Read <TSaveData>(Stream stream) where TSaveData : class, ISaveData => BinaryMapping.ReadObject <TSaveData>(stream.FromBegin());
private static TSaveKh2 Read <TSaveKh2>(Stream stream) where TSaveKh2 : class, ISaveKh2 => BinaryMapping.ReadObject <TSaveKh2>(stream.FromBegin());
private static DmaChainHeader WriteDmaChain(Stream stream, DmaChain dmaChain) { var dmaChainHeader = new DmaChainHeader { Unk00 = dmaChain.Unk00, TextureIndex = dmaChain.TextureIndex, Unk08 = dmaChain.Unk08, DmaLength = dmaChain.DmaLength, }; var dmaVifs = dmaChain.DmaVifs; var vifPacketOffsets = new List <int>(); foreach (var dmaVif in dmaVifs) { vifPacketOffsets.Add((int)stream.Position); stream.Write(dmaVif.VifPacket); } dmaChainHeader.DmaOffset = (int)stream.Position; for (var i = 0; i < dmaVifs.Count; i++) { if (dmaVifs[i].BaseAddress > 0) { BinaryMapping.WriteObject(stream, new DmaPacket { DmaTag = new DmaTag { Qwc = (ushort)(dmaVifs[i].VifPacket.Length / 0x10), TagId = 3, Irq = false, Address = vifPacketOffsets[i] }, VifCode = new VifCode { }, Parameter = 0 }); for (var j = 0; j < dmaVifs[i].Alaxi.Length; j++) { BinaryMapping.WriteObject(stream, new DmaPacket { DmaTag = new DmaTag { Qwc = 4, TagId = 3, Irq = false, Address = dmaVifs[i].Alaxi[j] }, VifCode = DefaultVifCode, Parameter = dmaVifs[i].BaseAddress + j * 4 }); } } BinaryMapping.WriteObject(stream, CloseDmaPacket); } var alv1 = new List <int>(); foreach (var vif in dmaVifs) { alv1.AddRange(vif.Alaxi); alv1.Add(-1); } alv1.RemoveAt(alv1.Count - 1); dmaChainHeader.Count1aOffset = (int)stream.Position; stream.Write(alv1.Count); foreach (var alvItem in alv1) { stream.Write(alvItem); } stream.AlignPosition(0x10); return(dmaChainHeader); }
private static void Write(Stream stream, InterpolatedMotion motion, bool unkFlag) { var valuePool = new PoolValues <float>(); var keyFramePool = new PoolValues <float>(motion.Timeline.Select(x => x.KeyFrame).Distinct().OrderBy(x => x)); var tangentPool = new PoolValues <float>(); var rawTimeline = new List <TimelineTableInternal>(motion.Timeline.Count); foreach (var item in motion.Timeline) { rawTimeline.Add(new TimelineTableInternal { Time = (short)(((int)item.Interpolation & 3) | (keyFramePool.GetIndex(item.KeyFrame) << 2)), ValueIndex = (short)valuePool.GetIndex(item.Value), TangentIndexEaseIn = (short)tangentPool.GetIndex(item.TangentEaseIn), TangentIndexEaseOut = (short)tangentPool.GetIndex(item.TangentEaseOut), }); } var writer = new BinaryWriter(stream); var header = new InterpolatedMotionInternal { BoneCount = motion.BoneCount, TotalFrameCount = motion.TotalFrameCount, Unk48 = motion.Unk48, BoundingBoxMinX = motion.BoundingBoxMinX, BoundingBoxMinY = motion.BoundingBoxMinY, BoundingBoxMinZ = motion.BoundingBoxMinZ, BoundingBoxMinW = motion.BoundingBoxMinW, BoundingBoxMaxX = motion.BoundingBoxMaxX, BoundingBoxMaxY = motion.BoundingBoxMaxY, BoundingBoxMaxZ = motion.BoundingBoxMaxZ, BoundingBoxMaxW = motion.BoundingBoxMaxW, FrameLoop = motion.FrameLoop, FrameEnd = motion.FrameEnd, FramePerSecond = motion.FramePerSecond, FrameCount = motion.FrameCount, Unk98 = motion.Unk98, Unk9c = motion.Unk9c, }; stream.Write(new byte[ReservedSize], 0, ReservedSize); BinaryMapping.WriteObject(stream, new Header { }); BinaryMapping.WriteObject(stream, new InterpolatedMotionInternal { }); header.StaticPoseCount = motion.StaticPose.Count; header.StaticPoseOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.StaticPose) { BinaryMapping.WriteObject(stream, item); } header.ModelBoneAnimationCount = motion.ModelBoneAnimation.Count; header.ModelBoneAnimationOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.ModelBoneAnimation.Select(Map)) { BinaryMapping.WriteObject(stream, item); } header.IKHelperAnimationCount = motion.IKHelperAnimation.Count; header.IKHelperAnimationOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.IKHelperAnimation.Select(Map)) { BinaryMapping.WriteObject(stream, item); } header.TimelineOffset = (int)(stream.Position - ReservedSize); foreach (var item in rawTimeline) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(4); header.KeyFrameCount = keyFramePool.Values.Count; header.KeyFrameOffset = (int)(stream.Position - ReservedSize); foreach (var item in keyFramePool.Values) { writer.Write(item); } header.TransformationValueOffset = (int)(stream.Position - ReservedSize); foreach (var item in valuePool.Values) { writer.Write(item); } header.TangentOffset = (int)(stream.Position - ReservedSize); foreach (var item in tangentPool.Values) { writer.Write(item); } header.IKChainCount = motion.IKChains.Count; header.IKChainOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.IKChains) { BinaryMapping.WriteObject(stream, item); } header.Unk48 = (int)(stream.Position - ReservedSize); stream.AlignPosition(0x10); header.Table8Offset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Table8) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(0x10); header.Table7Count = motion.Table7.Count; header.Table7Offset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Table7) { BinaryMapping.WriteObject(stream, item); } header.Table6Count = motion.Table6.Count; header.Table6Offset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Table6) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(0x10); header.TotalBoneCount = (short)(motion.BoneCount + motion.IKHelpers.Count); header.IKHelperOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.IKHelpers) { BinaryMapping.WriteObject(stream, item); } header.JointIndexOffset = (int)(stream.Position - ReservedSize); foreach (var item in motion.Joints) { BinaryMapping.WriteObject(stream, item); } stream.AlignPosition(0x10); header.FooterOffset = (int)(stream.Position - ReservedSize); BinaryMapping.WriteObject(stream, motion.Footer); header.UnknownTable1Offset = (int)(stream.Position - ReservedSize); header.UnknownTable1Count = 0; stream.AlignPosition(0x10); stream.SetLength(stream.Position); stream.SetPosition(ReservedSize); BinaryMapping.WriteObject(stream, new Header { Version = 0, Unk04 = unkFlag ? 1 : 0, ByteCount = (int)(stream.Length - ReservedSize), Unk0c = 0, }); BinaryMapping.WriteObject(stream, header); }
public static VpuHeader Header(Stream stream) => BinaryMapping.ReadObject <VpuHeader>(stream);