public void Read(BinaryReaderExt reader) { reader.ReadChars(4); dwSize = reader.ReadUInt32(); dwFlags = (DDSD)reader.ReadUInt32(); dwHeight = reader.ReadInt32(); dwWidth = reader.ReadInt32(); dwPitchOrLinearSize = reader.ReadInt32(); dwDepth = reader.ReadInt32(); dwMipMapCount = reader.ReadInt32(); dwReserved1 = new uint[11]; for (int i = 0; i < 11; i++) { dwReserved1[i] = reader.ReadUInt32(); } ddspf.Read(reader); dwCaps = (DDSCAPS)reader.ReadInt32(); dwCaps2 = (DDSCAPS2)reader.ReadInt32(); dwCaps3 = reader.ReadUInt32(); dwCaps4 = reader.ReadUInt32(); dwReserved2 = reader.ReadUInt32(); if (ddspf.dwFlags.HasFlag(DDPF.FOURCC) && ddspf.dwFourCC == 0x30315844) { DXT10Header.Read(reader); } }
/// <summary> /// /// </summary> public void LoadFromStream(Stream s) { using (BinaryReaderExt r = new BinaryReaderExt(s)) { if (s.Length < 0x14) { return; } if (new string(r.ReadChars(4)) != "SPKG") { return; } GroupFlags = r.ReadUInt32(); Flags = r.ReadUInt32(); var ssmSize = r.ReadInt32(); ScriptBank = new SEMBank(); ScriptBank.Scripts = new SEMBankScript[r.ReadInt32()]; for (int i = 0; i < ScriptBank.Scripts.Length; i++) { ScriptBank.Scripts[i] = new SEMBankScript(); ScriptBank.Scripts[i].Decompile(r.GetSection(r.ReadUInt32(), r.ReadInt32())); } var name = r.ReadString(r.ReadByte()); if (ssmSize == 0) { SoundBank = null; } else { SoundBank = new SSM(); using (MemoryStream ssmStream = new MemoryStream(r.ReadBytes(ssmSize))) SoundBank.Open(name, ssmStream); } } }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> public static DSP ToDSP(byte[] data) { DSP dsp = new DSP(); dsp.Channels.Clear(); using (BinaryReaderExt r = new BinaryReaderExt(new MemoryStream(data))) { r.BigEndian = true; if (new string(r.ReadChars(7)) != " HALPST") { throw new NotSupportedException("Invalid HPS file"); } r.ReadByte(); dsp.Frequency = r.ReadInt32(); var channelCount = r.ReadInt32(); if (channelCount != 2) { throw new NotSupportedException("Only HPS with 2 channels are currently supported"); } for (int i = 0; i < channelCount; i++) { var channel = new DSPChannel(); channel.LoopFlag = r.ReadInt16(); channel.Format = r.ReadInt16(); var SA = r.ReadInt32(); var EA = r.ReadInt32(); var CA = r.ReadInt32(); for (int k = 0; k < 0x10; k++) { channel.COEF[k] = r.ReadInt16(); } channel.Gain = r.ReadInt16(); channel.InitialPredictorScale = r.ReadInt16(); channel.InitialSampleHistory1 = r.ReadInt16(); channel.InitialSampleHistory1 = r.ReadInt16(); channel.NibbleCount = EA - CA; channel.LoopStart = SA - CA; dsp.Channels.Add(channel); } // read blocks r.Position = 0x80; Dictionary <int, int> OffsetToLoopPosition = new Dictionary <int, int>(); List <byte> channelData1 = new List <byte>(); List <byte> channelData2 = new List <byte>(); while (true) { var pos = r.Position; var length = r.ReadInt32(); var lengthMinusOne = r.ReadInt32(); var next = r.ReadInt32(); { var initPS = r.ReadInt16(); var initsh1 = r.ReadInt16(); var initsh2 = r.ReadInt16(); var gain = r.ReadInt16(); } { var initPS = r.ReadInt16(); var initsh1 = r.ReadInt16(); var initsh2 = r.ReadInt16(); var gain = r.ReadInt16(); } var extra = r.ReadInt32(); OffsetToLoopPosition.Add((int)pos, channelData1.Count * 2); channelData1.AddRange(r.ReadBytes(length / 2)); channelData2.AddRange(r.ReadBytes(length / 2)); if (next < r.Position || next == -1) { if (next != -1) { foreach (var c in dsp.Channels) { c.LoopStart = OffsetToLoopPosition[next]; } } break; } else { r.Position = (uint)next; } } dsp.Channels[0].Data = channelData1.ToArray(); dsp.Channels[1].Data = channelData2.ToArray(); } return(dsp); }
public void Open(string FileName) { using (BinaryReaderExt stream = new BinaryReaderExt(new FileStream(FileName, FileMode.Open))) { stream.BigEndian = true; Heading = stream.ReadInt32(); VersionMinor = stream.ReadByte(); VersionMajor = stream.ReadByte(); Magic = new string(stream.ReadChars(4)); stream.ReadByte(); var collisionCount = stream.ReadInt32(); for (int i = 0; i < collisionCount; i++) { LVDCollision col = new LVDCollision(); col.Read(stream, VersionMinor); Collisions.Add(col); } stream.ReadByte(); var spawnCount = stream.ReadInt32(); for (int i = 0; i < spawnCount; i++) { LVDSpawn spawn = new LVDSpawn(); spawn.Read(stream); Spawns.Add(spawn); } stream.ReadByte(); var respawnCount = stream.ReadInt32(); for (int i = 0; i < respawnCount; i++) { LVDSpawn respawn = new LVDSpawn(); respawn.Read(stream); Respawns.Add(respawn); } stream.ReadByte(); var boundsCount = stream.ReadInt32(); for (int i = 0; i < boundsCount; i++) { LVDBounds bound = new LVDBounds(); bound.Read(stream); CameraBounds.Add(bound); } stream.ReadByte(); var blastCount = stream.ReadInt32(); for (int i = 0; i < blastCount; i++) { LVDBounds blast = new LVDBounds(); blast.Read(stream); BlastZoneBounds.Add(blast); } stream.ReadByte(); int enemyGenCount = stream.ReadInt32(); for (int i = 0; i < enemyGenCount; i++) { LVDEnemyGenerator enGen = new LVDEnemyGenerator(); enGen.Read(stream); EnemyGenerators.Add(enGen); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); int damageCount = stream.ReadInt32(); for (int i = 0; i < damageCount; i++) { LVDDamageShape shape = new LVDDamageShape(); shape.Read(stream); DamageShapes.Add(shape); } stream.ReadByte(); int itemSpawnCount = stream.ReadInt32(); for (int i = 0; i < itemSpawnCount; i++) { LVDItemSpawner spawn = new LVDItemSpawner(); spawn.Read(stream); ItemSpawners.Add(spawn); } if (VersionMinor > 0xA) { stream.ReadByte(); int genCurveCount = stream.ReadInt32(); for (int i = 0; i < genCurveCount; i++) { LVDRangeCurve point = new LVDRangeCurve(); point.Read(stream); RangeCurves.Add(point); } stream.ReadByte(); int genCurveCount2 = stream.ReadInt32(); for (int i = 0; i < genCurveCount2; i++) { LVDGeneralVector point = new LVDGeneralVector(); point.Read(stream); GeneralVectors.Add(point); } } stream.ReadByte(); int genShapeCount = stream.ReadInt32(); for (int i = 0; i < genShapeCount; i++) { LVDGeneralShape shape = new LVDGeneralShape(); shape.Read(stream); GeneralShapes.Add(shape); } stream.ReadByte(); int genPointCount = stream.ReadInt32(); for (int i = 0; i < genPointCount; i++) { LVDGeneralPoint point = new LVDGeneralPoint(); point.Read(stream); GeneralPoints.Add(point); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } stream.ReadByte(); if (stream.ReadInt32() > 0) { throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X")); } if (VersionMinor > 0xA) { stream.ReadByte(); var shrunkboundsCount = stream.ReadInt32(); for (int i = 0; i < shrunkboundsCount; i++) { LVDBounds bound = new LVDBounds(); bound.Read(stream); ShrunkCameraBounds.Add(bound); } stream.ReadByte(); var shrunkblastCount = stream.ReadInt32(); for (int i = 0; i < shrunkblastCount; i++) { LVDBounds blast = new LVDBounds(); blast.Read(stream); ShrunkBlastZoneBounds.Add(blast); } } if (stream.BaseStream.Length != stream.BaseStream.Position) { stream.PrintPosition(); throw new Exception("Error fully parsing LVD " + stream.BaseStream.Position.ToString("X")); } } }
/// <summary> /// /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static JointAnimManager LoadCHR0(string filePath, JointMap jointMap) { JointAnimManager anim = new JointAnimManager(); for (int i = 0; i < jointMap.Count; i++) { anim.Nodes.Add(new AnimNode()); } using (BinaryReaderExt r = new BinaryReaderExt(new FileStream(filePath, FileMode.Open))) { r.BigEndian = true; if (r.BaseStream.Length < 4 || new string(r.ReadChars(4)) != "CHR0") { throw new InvalidDataException("CHR0 file is not valid"); } r.Skip(4); int versionNum = r.ReadInt32(); if (versionNum != 4) { throw new InvalidDataException($"CHR0 version {versionNum} not supported"); } r.Seek(0x10); var indexGroupOffset = r.ReadUInt32(); var animName = r.ReadString(r.ReadInt32(), -1); r.Skip(4); anim.FrameCount = r.ReadUInt16() - 1; int animDataCount = r.ReadUInt16(); r.Skip(8); r.Seek(indexGroupOffset); var sectionOffset = r.ReadUInt32() + indexGroupOffset; int sectionCount = r.ReadInt32(); for (uint i = 0; i < sectionCount; i++) { r.Seek(indexGroupOffset + 8 + 16 * i); r.Skip(4); // id and unknown r.Skip(2); // let r.Skip(2); // right var boneName = r.ReadString(r.ReadInt32() + (int)indexGroupOffset, -1); var dataOffset = r.ReadUInt32() + indexGroupOffset; if (dataOffset == indexGroupOffset) { sectionCount += 1; continue; } if (jointMap.IndexOf(boneName) == -1) { continue; } r.Seek(dataOffset); var nameOff = r.Position + r.ReadUInt32(); var flags = r.ReadInt32(); //Console.WriteLine(boneName + " " + flags.ToString("X")); //r.PrintPosition(); //01BFE019 int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; AnimNode node = new AnimNode(); FOBJ_Player trackX = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_TRAX }; FOBJ_Player trackY = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_TRAY }; FOBJ_Player trackZ = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_TRAZ }; FOBJ_Player trackRX = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_ROTX }; FOBJ_Player trackRY = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_ROTY }; FOBJ_Player trackRZ = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_ROTZ }; FOBJ_Player trackSX = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_SCAX }; FOBJ_Player trackSY = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_SCAY }; FOBJ_Player trackSZ = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_SCAZ }; if (hasS == 1) { ReadKeys(r, node, (int)anim.FrameCount, trackSX, trackSY, trackSZ, Siso == 1, SXfixed == 1, SYfixed == 1, SZfixed == 1, s_type, dataOffset); } if (hasR == 1) { ReadKeys(r, node, (int)anim.FrameCount, trackRX, trackRY, trackRZ, Riso == 1, RXfixed == 1, RYfixed == 1, RZfixed == 1, r_type, dataOffset); } if (hasT == 1) { ReadKeys(r, node, (int)anim.FrameCount, trackX, trackY, trackZ, Tiso == 1, Xfixed == 1, Yfixed == 1, Zfixed == 1, t_type, dataOffset); } if (trackX.Keys.Count > 0) { node.Tracks.Add(trackX); } if (trackY.Keys.Count > 0) { node.Tracks.Add(trackY); } if (trackZ.Keys.Count > 0) { node.Tracks.Add(trackZ); } if (trackRX.Keys.Count > 0) { node.Tracks.Add(trackRX); } if (trackRY.Keys.Count > 0) { node.Tracks.Add(trackRY); } if (trackRZ.Keys.Count > 0) { node.Tracks.Add(trackRZ); } if (trackSX.Keys.Count > 0) { node.Tracks.Add(trackSX); } if (trackSY.Keys.Count > 0) { node.Tracks.Add(trackSY); } if (trackSZ.Keys.Count > 0) { node.Tracks.Add(trackSZ); } foreach (var k in trackRX.Keys) { k.Value = MathHelper.DegreesToRadians(k.Value); k.Tan = MathHelper.DegreesToRadians(k.Tan); } foreach (var k in trackRY.Keys) { k.Value = MathHelper.DegreesToRadians(k.Value); k.Tan = MathHelper.DegreesToRadians(k.Tan); } foreach (var k in trackRZ.Keys) { k.Value = MathHelper.DegreesToRadians(k.Value); k.Tan = MathHelper.DegreesToRadians(k.Tan); } // make sure all tracks start at frame 0 foreach (var track in node.Tracks) { if (track.Keys.Count > 0 && track.Keys[0].Frame != 0) { track.Keys.Insert(0, new FOBJKey() { Frame = 0, Value = track.Keys[0].Value, InterpolationType = GXInterpolationType.HSD_A_OP_CON, }); } } //Console.WriteLine(boneName + " Tracks:" + node.Tracks.Count + " " + flags.ToString("X")); //Console.WriteLine($"{trackX.Keys.Count} {trackY.Keys.Count} {trackZ.Keys.Count}"); //Console.WriteLine($"{trackRX.Keys.Count} {trackRY.Keys.Count} {trackRZ.Keys.Count}"); //Console.WriteLine($"{trackSX.Keys.Count} {trackSY.Keys.Count} {trackSZ.Keys.Count}"); anim.Nodes[jointMap.IndexOf(boneName)] = node; } } return(anim); }
private static void FromBRSTM(this DSP dsp, string filePath) { using (FileStream s = new FileStream(filePath, FileMode.Open)) using (BinaryReaderExt r = new BinaryReaderExt(s)) { if (new string(r.ReadChars(4)) != "RSTM") { throw new NotSupportedException("File is not a valid BRSTM file"); } r.BigEndian = true; r.BigEndian = r.ReadUInt16() == 0xFEFF; r.Skip(2); // 01 00 version r.Skip(4); // filesize r.Skip(2); // 00 40 - header length r.Skip(2); // 00 02 - header version var headOffset = r.ReadUInt32(); var headSize = r.ReadUInt32(); var adpcOffset = r.ReadUInt32(); var adpcSize = r.ReadUInt32(); var dataOffset = r.ReadUInt32(); var dataSize = r.ReadUInt32(); // can skip adpc section when reading because it just contains sample history // parse head section // -------------------------------------------------------------- r.Position = headOffset; if (new string(r.ReadChars(4)) != "HEAD") { throw new NotSupportedException("BRSTM does not have a valid HEAD"); } r.Skip(4); // section size r.Skip(4); // 01 00 00 00 marker var chunk1Offset = r.ReadUInt32() + 8 + headOffset; r.Skip(4); // 01 00 00 00 marker var chunk2Offset = r.ReadUInt32() + 8 + headOffset; r.Skip(4); // 01 00 00 00 marker var chunk3Offset = r.ReadUInt32() + 8 + headOffset; // -------------------------------------------------------------- r.Seek(chunk1Offset); var codec = (BRSTM_CODEC)r.ReadByte(); var loopFlag = r.ReadByte(); var channelCount = r.ReadByte(); r.Skip(1); // padding if (codec != BRSTM_CODEC.ADPCM_4bit) { throw new NotSupportedException("only 4bit ADPCM files currently supported"); } var sampleRate = r.ReadUInt16(); r.Skip(2); // padding dsp.Frequency = sampleRate; var loopStart = r.ReadUInt32(); var totalSamples = r.ReadUInt32(); var dataPointer = r.ReadUInt32(); // DATA offset int blockCount = r.ReadInt32(); var blockSize = r.ReadUInt32(); var samplesPerBlock = r.ReadInt32(); var sizeOfFinalBlock = r.ReadUInt32(); var samplesInFinalBlock = r.ReadInt32(); var sizeOfFinalBlockWithPadding = r.ReadUInt32(); var samplesPerEntry = r.ReadInt32(); var bytesPerEntry = r.ReadInt32(); // -------------------------------------------------------------- r.Seek(chunk2Offset); var numOfTracks = r.ReadByte(); var trackDescType = r.ReadByte(); r.Skip(2); // padding for (uint i = 0; i < numOfTracks; i++) { r.Seek(chunk1Offset + 4 + 8 * i); r.Skip(1); // 01 padding var descType = r.ReadByte(); r.Skip(2); // padding var descOffset = r.ReadUInt32() + 8 + headOffset; r.Seek(descOffset); switch (descType) { case 0: { int channelsInTrack = r.ReadByte(); int leftChannelID = r.ReadByte(); int rightChannelID = r.ReadByte(); r.Skip(1); // padding } break; case 1: { var volume = r.ReadByte(); var panning = r.ReadByte(); r.Skip(2); // padding r.Skip(4); // padding int channelsInTrack = r.ReadByte(); int leftChannelID = r.ReadByte(); int rightChannelID = r.ReadByte(); r.Skip(1); // 01 padding } break; } } // -------------------------------------------------------------- r.Seek(chunk3Offset); var channelCountAgain = r.ReadByte(); r.Skip(3); for (uint i = 0; i < channelCountAgain; i++) { r.Seek(chunk3Offset + 4 + 8 * i); r.Skip(4); // 01000000 marker var offset = r.ReadUInt32() + headOffset + 8; r.Seek(offset); // channel information var channel = new DSPChannel(); dsp.Channels.Add(channel); channel.LoopFlag = loopFlag; channel.LoopStart = (int)loopStart; r.Skip(4); // 01000000 marker r.Skip(4); // offset to coefficients (they follow directly after) for (int k = 0; k < 0x10; k++) { channel.COEF[k] = r.ReadInt16(); } channel.Gain = r.ReadInt16(); channel.InitialPredictorScale = r.ReadInt16(); channel.InitialSampleHistory1 = r.ReadInt16(); channel.InitialSampleHistory2 = r.ReadInt16(); channel.LoopPredictorScale = r.ReadInt16(); channel.LoopSampleHistory1 = r.ReadInt16(); channel.LoopSampleHistory2 = r.ReadInt16(); r.Skip(2); // padding // get channel data using (MemoryStream channelStream = new MemoryStream()) { for (uint j = 0; j < blockCount; j++) { var bs = blockSize; var actualBlockSize = blockSize; if (j == blockCount - 1) { bs = sizeOfFinalBlockWithPadding; actualBlockSize = sizeOfFinalBlock; } channelStream.Write(r.GetSection(dataPointer + j * (blockSize * channelCountAgain) + bs * i, (int)actualBlockSize), 0, (int)actualBlockSize); } channel.Data = channelStream.ToArray(); channel.NibbleCount = channel.Data.Length * 2; } } dsp.LoopPoint = TimeSpan.FromMilliseconds(loopStart / (double)sampleRate * 1000).ToString(); } }
/// <summary> /// /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static JointAnimManager LoadCHR0(string filePath, Dictionary <int, string> BoneLabelMap) { JointAnimManager anim = new JointAnimManager(); Dictionary <string, int> nameToIndex = new Dictionary <string, int>(); foreach (var v in BoneLabelMap) { nameToIndex.Add(v.Value, v.Key); anim.Nodes.Add(new AnimNode()); } using (BinaryReaderExt r = new BinaryReaderExt(new FileStream(filePath, FileMode.Open))) { r.BigEndian = true; if (r.BaseStream.Length < 4 || new string(r.ReadChars(4)) != "CHR0") { throw new InvalidDataException("CHR0 file is not valid"); } r.Skip(4); int versionNum = r.ReadInt32(); if (versionNum != 4) { throw new InvalidDataException($"CHR0 version {versionNum} not supported"); } System.Console.WriteLine("Reading Track "); r.Seek(0x10); var indexGroupOffset = r.ReadUInt32(); var animName = r.ReadString(r.ReadInt32(), -1); r.Skip(4); anim.FrameCount = r.ReadUInt16(); int animDataCount = r.ReadUInt16(); r.Skip(8); r.Seek(indexGroupOffset); var sectionOffset = r.ReadUInt32() + indexGroupOffset; int sectionCount = r.ReadInt32(); for (uint i = 0; i < sectionCount; i++) { r.Seek(indexGroupOffset + 8 + 16 * i); r.Skip(4); // id and unknown r.Skip(2); // let r.Skip(2); // right var boneName = r.ReadString(r.ReadInt32() + (int)indexGroupOffset, -1); var dataOffset = r.ReadUInt32() + indexGroupOffset; if (dataOffset == indexGroupOffset) { sectionCount += 1; continue; } if (!nameToIndex.ContainsKey(boneName)) { continue; } r.Seek(dataOffset); var nameOff = r.Position + r.ReadUInt32(); var flags = r.ReadInt32(); int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; AnimNode node = new AnimNode(); FOBJ_Player trackX = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_TRAX }; FOBJ_Player trackY = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_TRAY }; FOBJ_Player trackZ = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_TRAZ }; FOBJ_Player trackRX = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_ROTX }; FOBJ_Player trackRY = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_ROTY }; FOBJ_Player trackRZ = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_ROTZ }; FOBJ_Player trackSX = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_SCAX }; FOBJ_Player trackSY = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_SCAY }; FOBJ_Player trackSZ = new FOBJ_Player() { JointTrackType = JointTrackType.HSD_A_J_SCAZ }; if (hasS == 1) { ReadKeys(r, node, (int)anim.FrameCount, trackSX, trackSY, trackSZ, Siso == 1, SXfixed == 1, SYfixed == 1, SZfixed == 1, s_type, dataOffset); } if (hasR == 1) { ReadKeys(r, node, (int)anim.FrameCount, trackRX, trackRY, trackRZ, Riso == 1, RXfixed == 1, RYfixed == 1, RZfixed == 1, r_type, dataOffset); } if (hasT == 1) { ReadKeys(r, node, (int)anim.FrameCount, trackX, trackY, trackZ, Tiso == 1, Xfixed == 1, Yfixed == 1, Zfixed == 1, t_type, dataOffset); } if (trackX.Keys.Count > 1) { node.Tracks.Add(trackX); } if (trackY.Keys.Count > 1) { node.Tracks.Add(trackY); } if (trackZ.Keys.Count > 1) { node.Tracks.Add(trackZ); } if (trackRX.Keys.Count > 1) { node.Tracks.Add(trackRX); } if (trackRY.Keys.Count > 1) { node.Tracks.Add(trackRY); } if (trackRZ.Keys.Count > 1) { node.Tracks.Add(trackRZ); } if (trackSX.Keys.Count > 1) { node.Tracks.Add(trackSX); } if (trackSY.Keys.Count > 1) { node.Tracks.Add(trackSY); } if (trackSZ.Keys.Count > 1) { node.Tracks.Add(trackSZ); } foreach (var k in trackRX.Keys) { k.Value = MathHelper.DegreesToRadians(k.Value); k.Tan = MathHelper.DegreesToRadians(k.Value); } foreach (var k in trackRY.Keys) { k.Value = MathHelper.DegreesToRadians(k.Value); k.Tan = MathHelper.DegreesToRadians(k.Value); } foreach (var k in trackRZ.Keys) { k.Value = MathHelper.DegreesToRadians(k.Value); k.Tan = MathHelper.DegreesToRadians(k.Value); } Console.WriteLine(boneName + " Tracks:" + node.Tracks.Count); Console.WriteLine($"{trackX.Keys.Count} {trackY.Keys.Count} {trackZ.Keys.Count}"); Console.WriteLine($"{trackRX.Keys.Count} {trackRY.Keys.Count} {trackRZ.Keys.Count}"); Console.WriteLine($"{trackSX.Keys.Count} {trackSY.Keys.Count} {trackSZ.Keys.Count}"); anim.Nodes[nameToIndex[boneName]] = node; } } return(anim); }