From ab9e52b6e8f5235490a522e9170c72fbe3045be3 Mon Sep 17 00:00:00 2001 From: Asgard Date: Tue, 2 Aug 2022 09:24:15 -0600 Subject: [PATCH] Improve skeletons * Animation skeleton is now changeable * Skeleton id in SKLB is now changeable * Parent/fallback skeletons can now be edited in SKLB --- XAT/XAT/Game/Formats/Sklb/SklbFormat.cs | 121 ++++++++++++++++------ XAT/XAT/UI/Animation/AnimationEditor.xaml | 3 + XAT/XAT/UI/Skeleton/SkeletonTab.xaml | 30 ++++++ 3 files changed, 124 insertions(+), 30 deletions(-) diff --git a/XAT/XAT/Game/Formats/Sklb/SklbFormat.cs b/XAT/XAT/Game/Formats/Sklb/SklbFormat.cs index 63cabeb..3401b5d 100644 --- a/XAT/XAT/Game/Formats/Sklb/SklbFormat.cs +++ b/XAT/XAT/Game/Formats/Sklb/SklbFormat.cs @@ -12,7 +12,37 @@ public class SklbFormat { private const string MAGIC = "blks"; - public byte[] PreHavokData { get; set; } + public short Header1 { get; set; } + public short Header2 { get; set; } + + [DependsOn(nameof(Header1), nameof(Header2))] + public bool OldHeader + { + get + { + switch (Header2) + { + case 0x3132: + return true; + + case 0x3133: + return false; + + default: + Log.Warning($"Unknown sklb headers: Part 1: 0x{Header1.ToString("X")}, Part 2: 0x{Header2.ToString("X")} - Assume it's new for now"); + return false; + } + } + } + + public int Unk1 { get; set; } + + public int Skeleton { get; set; } + public int[] ParentSkeletons { get; set; } + + public byte[] Unk2 { get; set; } + public byte[] Unk3 { get; set; } + public byte[] HavokData { get; set; } public SklbFormat(BinaryReader reader) @@ -23,51 +53,82 @@ public SklbFormat(BinaryReader reader) throw new Exception("Invalid sklb file - magic incorrect"); // Read header - int header1 = reader.ReadInt16(); - int header2 = reader.ReadInt16(); - bool oldHeader; + Header1 = reader.ReadInt16(); + Header2 = reader.ReadInt16(); + Log.Debug($"Sklb headers were: Part 1: 0x{Header1.ToString("X")}, Part 2: 0x{Header2.ToString("X")}"); - Log.Debug($"Sklb headers were: Part 1: 0x{header1.ToString("X")}, Part 2: 0x{header2.ToString("X")}"); - - switch (header2) - { - case 0x3132: - oldHeader = true; - break; - - case 0x3133: - oldHeader = false; - break; - - default: - Log.Warning($"Unknown sklb headers: Part 1: 0x{header1.ToString("X")}, Part 2: 0x{header2.ToString("X")} - Assume it's new for now"); - oldHeader = false; - break; - } - - // Havok offset + // Offsets int havokOffset; - if (oldHeader) + int unknownOffset; + if (OldHeader) { - reader.BaseStream.Seek(10, SeekOrigin.Begin); + unknownOffset = reader.ReadInt16(); havokOffset = reader.ReadInt16(); } else { - reader.BaseStream.Seek(12, SeekOrigin.Begin); + unknownOffset = reader.ReadInt32(); havokOffset = reader.ReadInt32(); + Unk1 = reader.ReadInt32(); } - // Havok data - reader.BaseStream.Seek(0, SeekOrigin.Begin); - this.PreHavokData = reader.ReadBytes(havokOffset); + Skeleton = reader.ReadInt32(); + + ParentSkeletons = new int[4]; + for (int i = 0; i < ParentSkeletons.Length; ++i) + { + ParentSkeletons[i] = reader.ReadInt32(); + } + + this.Unk2 = reader.ReadBytes((int)(unknownOffset - reader.BaseStream.Position)); + + this.Unk3 = reader.ReadBytes((int)(havokOffset - reader.BaseStream.Position)); + this.HavokData = reader.ReadBytes((int)reader.BaseStream.Length - havokOffset); } public void Serialize(BinaryWriter writer) { - writer.Write(this.PreHavokData); + writer.WriteEncodedString(MAGIC); + writer.Write(Header1); + writer.Write(Header2); + + if(OldHeader) + { + writer.Write((short)0); + writer.Write((short)0); + } + else + { + writer.Write((int)0); + writer.Write((int)0); + writer.Write(Unk1); + } + + writer.Write(Skeleton); + for (int i = 0; i < ParentSkeletons.Length; ++i) + { + writer.Write(ParentSkeletons[i]); + } + + writer.Write(Unk2); + int firstOffset = (int) writer.BaseStream.Position; + writer.Write(Unk3); + + int havokOffset = (int)writer.BaseStream.Position; writer.Write(this.HavokData); + + writer.BaseStream.Seek(8, SeekOrigin.Begin); + if (OldHeader) + { + writer.Write((short)firstOffset); + writer.Write((short)havokOffset); + } + else + { + writer.Write((int)firstOffset); + writer.Write((int)havokOffset); + } } public byte[] ToBytes() diff --git a/XAT/XAT/UI/Animation/AnimationEditor.xaml b/XAT/XAT/UI/Animation/AnimationEditor.xaml index 6951f80..65968a8 100644 --- a/XAT/XAT/UI/Animation/AnimationEditor.xaml +++ b/XAT/XAT/UI/Animation/AnimationEditor.xaml @@ -43,6 +43,9 @@ + + + diff --git a/XAT/XAT/UI/Skeleton/SkeletonTab.xaml b/XAT/XAT/UI/Skeleton/SkeletonTab.xaml index 9d6ea34..d30e5b1 100644 --- a/XAT/XAT/UI/Skeleton/SkeletonTab.xaml +++ b/XAT/XAT/UI/Skeleton/SkeletonTab.xaml @@ -35,6 +35,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +