diff --git a/CathodeLib/Scripts/Utilities.cs b/CathodeLib/Scripts/Utilities.cs index 24cc851..388ddc2 100644 --- a/CathodeLib/Scripts/Utilities.cs +++ b/CathodeLib/Scripts/Utilities.cs @@ -1,57 +1,57 @@ using CATHODE; using CATHODE.Scripting; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Numerics; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; -using System.Text; - -namespace CathodeLib -{ - public class Utilities - { - //Read a single templated object - public static T Consume(BinaryReader reader) - { - byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); - return Consume(bytes); - } - public static T Consume(byte[] bytes) - { - GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); - handle.Free(); - return theStructure; - } - - //Read a templated array - public static T[] ConsumeArray(BinaryReader reader, int count) - { - T[] toReturn = new T[count]; - for (int i = 0; i < count; i++) toReturn[i] = Consume(reader); - return toReturn; - } - public static T[] ConsumeArray(byte[] bytes, int count) - { - T[] toReturn = new T[count]; - for (int i = 0; i < count; i++) toReturn[i] = Consume(bytes); - return toReturn; - } - - //Align the stream - public static void Align(BinaryReader reader, int val = 4) - { - while (reader.BaseStream.Position % val != 0) reader.ReadByte(); - } - public static void Align(BinaryWriter writer, int val = 4, byte fillWith = 0x00) - { - while (writer.BaseStream.Position % val != 0) writer.Write(fillWith); - } - - //Reads a string with alternating nulls up to a trailing 0x00 byte +using System.Text; + +namespace CathodeLib +{ + public class Utilities + { + //Read a single templated object + public static T Consume(BinaryReader reader) + { + byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); + return Consume(bytes); + } + public static T Consume(byte[] bytes) + { + GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); + T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); + handle.Free(); + return theStructure; + } + + //Read a templated array + public static T[] ConsumeArray(BinaryReader reader, int count) + { + T[] toReturn = new T[count]; + for (int i = 0; i < count; i++) toReturn[i] = Consume(reader); + return toReturn; + } + public static T[] ConsumeArray(byte[] bytes, int count) + { + T[] toReturn = new T[count]; + for (int i = 0; i < count; i++) toReturn[i] = Consume(bytes); + return toReturn; + } + + //Align the stream + public static void Align(BinaryReader reader, int val = 4) + { + while (reader.BaseStream.Position % val != 0) reader.ReadByte(); + } + public static void Align(BinaryWriter writer, int val = 4, byte fillWith = 0x00) + { + while (writer.BaseStream.Position % val != 0) writer.Write(fillWith); + } + + //Reads a string with alternating nulls up to a trailing 0x00 byte public static string ReadStringAlternating(byte[] bytes) { byte[] trimmed = new byte[bytes.Length / 2]; @@ -64,156 +64,149 @@ public static string ReadStringAlternating(byte[] bytes) x++; } return ReadString(trimmed); - } - - //Reads a string up to a trailing 0x00 byte - public static string ReadString(byte[] bytes, int position) - { - string to_return = ""; - for (int i = 0; i < int.MaxValue; i++) - { - byte this_byte = bytes[position + i]; - if (this_byte == 0x00) break; - to_return += (char)this_byte; - } - return to_return; - } - public static string ReadString(BinaryReader reader, int position, bool resetPosition = true) - { - long startPos = reader.BaseStream.Position; - reader.BaseStream.Position = position; - - string to_return = ""; - for (int i = 0; i < int.MaxValue; i++) - { - byte this_byte = reader.ReadByte(); - if (this_byte == 0x00) break; - to_return += (char)this_byte; - } - - if (resetPosition) reader.BaseStream.Position = startPos; - return to_return; - } - public static string ReadString(BinaryReader reader) - { - string to_return = ""; - for (int i = 0; i < int.MaxValue; i++) - { - byte this_byte = reader.ReadByte(); - if (this_byte == 0x00) break; - to_return += (char)this_byte; - } - return to_return; - } - public static string ReadString(byte[] bytes) - { - string to_return = ""; - for (int i = 0; i < bytes.Length; i++) - { - byte this_byte = bytes[i]; - if (this_byte == 0x00) break; - to_return += (char)this_byte; - } - return to_return; - } - - //Writes a string without a leading length value - public static void WriteString(string string_to_write, BinaryWriter writer, bool trailingByte = false) - { - foreach (char character in string_to_write) - writer.Write(character); - - if (trailingByte) writer.Write((char)0x00); + } + + //Reads a string up to a trailing 0x00 byte + public static string ReadString(byte[] bytes, int position) + { + string to_return = ""; + for (int i = 0; i < int.MaxValue; i++) + { + byte this_byte = bytes[position + i]; + if (this_byte == 0x00) break; + to_return += (char)this_byte; + } + return to_return; + } + public static string ReadString(BinaryReader reader, int position, bool resetPosition = true) + { + long startPos = reader.BaseStream.Position; + reader.BaseStream.Position = position; + + string to_return = ""; + for (int i = 0; i < int.MaxValue; i++) + { + byte this_byte = reader.ReadByte(); + if (this_byte == 0x00) break; + to_return += (char)this_byte; + } + + if (resetPosition) reader.BaseStream.Position = startPos; + return to_return; + } + public static string ReadString(BinaryReader reader) + { + string to_return = ""; + for (int i = 0; i < int.MaxValue; i++) + { + byte this_byte = reader.ReadByte(); + if (this_byte == 0x00) break; + to_return += (char)this_byte; + } + return to_return; + } + public static string ReadString(byte[] bytes) + { + string to_return = ""; + for (int i = 0; i < bytes.Length; i++) + { + byte this_byte = bytes[i]; + if (this_byte == 0x00) break; + to_return += (char)this_byte; + } + return to_return; + } + + //Writes a string without a leading length value + public static void WriteString(string string_to_write, BinaryWriter writer, bool trailingByte = false) + { + foreach (char character in string_to_write) + writer.Write(character); + + if (trailingByte) writer.Write((char)0x00); } //Gets a string from a byte array (at position) by reading chars until a null is hit - public static string GetStringFromByteArray(byte[] byte_array, int position) - { - string to_return = ""; - for (int i = 0; i < 999999999; i++) - { - byte this_byte = byte_array[position + i]; - if (this_byte == 0x00) - { - break; - } - to_return += (char)this_byte; - } - return to_return; - } - - //Removes the leading nulls from a byte array, useful for cleaning byte-aligned file extracts - public static byte[] RemoveLeadingNulls(byte[] extracted_file) - { - //Remove from leading - int start_offset = 0; - for (int i = 0; i < 4; i++) - { - if (extracted_file[i] == 0x00) - { - start_offset = i + 1; - continue; - } - break; - } - byte[] to_return = new byte[extracted_file.Length - start_offset]; - Array.Copy(extracted_file, start_offset, to_return, 0, to_return.Length); - return to_return; - } - - //Write a templated type - public static void Write(BinaryWriter stream, T aux) - { - int length = Marshal.SizeOf(aux); - IntPtr ptr = Marshal.AllocHGlobal(length); - byte[] myBuffer = new byte[length]; - - Marshal.StructureToPtr(aux, ptr, true); - Marshal.Copy(ptr, myBuffer, 0, length); - Marshal.FreeHGlobal(ptr); - - stream.Write(myBuffer); - } - public static void Write(BinaryWriter stream, T[] aux) - { - for (int i = 0; i < aux.Length; i++) Write(stream, aux[i]); - } - public static void Write(BinaryWriter stream, List aux) - { - Write(stream, aux.ToArray()); - } - - //Clones an object (slow!) - public static T CloneObject(T obj) - { - //A somewhat hacky an inefficient way of deep cloning an object (TODO: optimise this as we use it a lot!) - MemoryStream ms = new MemoryStream(); - new BinaryFormatter().Serialize(ms, obj); - ms.Position = 0; - T obj2 = (T)new BinaryFormatter().Deserialize(ms); - ms.Close(); - return obj2; - //obj.MemberwiseClone(); - } - - //Generate a hashed string for use in the animation system (FNV hash) - public static uint AnimationHashedString(string str) - { - uint hash = 0x811c9dc5; - uint prime = 0x1000193; - - for (int i = 0; i < str.Length; ++i) - { - char value = str[i]; - hash = hash ^ value; - hash *= prime; - } - - return hash; - } - - //Generate a hashed string for use in sound system (wwise FNV-1) + public static string GetStringFromByteArray(byte[] byte_array, int position) + { + string to_return = ""; + for (int i = 0; i < 999999999; i++) + { + byte this_byte = byte_array[position + i]; + if (this_byte == 0x00) + { + break; + } + to_return += (char)this_byte; + } + return to_return; + } + + //Removes the leading nulls from a byte array, useful for cleaning byte-aligned file extracts + public static byte[] RemoveLeadingNulls(byte[] extracted_file) + { + //Remove from leading + int start_offset = 0; + for (int i = 0; i < 4; i++) + { + if (extracted_file[i] == 0x00) + { + start_offset = i + 1; + continue; + } + break; + } + byte[] to_return = new byte[extracted_file.Length - start_offset]; + Array.Copy(extracted_file, start_offset, to_return, 0, to_return.Length); + return to_return; + } + + //Write a templated type + public static void Write(BinaryWriter stream, T aux) + { + int length = Marshal.SizeOf(aux); + IntPtr ptr = Marshal.AllocHGlobal(length); + byte[] myBuffer = new byte[length]; + + Marshal.StructureToPtr(aux, ptr, true); + Marshal.Copy(ptr, myBuffer, 0, length); + Marshal.FreeHGlobal(ptr); + + stream.Write(myBuffer); + } + public static void Write(BinaryWriter stream, T[] aux) + { + for (int i = 0; i < aux.Length; i++) Write(stream, aux[i]); + } + public static void Write(BinaryWriter stream, List aux) + { + Write(stream, aux.ToArray()); + } + + //Clones an object (slow!) + public static T CloneObject(T obj) + { + return ( T ) obj.GetType().GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(obj, Array.Empty()); + } + + //Generate a hashed string for use in the animation system (FNV hash) + public static uint AnimationHashedString(string str) + { + uint hash = 0x811c9dc5; + uint prime = 0x1000193; + + for (int i = 0; i < str.Length; ++i) + { + char value = str[i]; + hash = hash ^ value; + hash *= prime; + } + + return hash; + } + + //Generate a hashed string for use in sound system (wwise FNV-1) public static uint SoundHashedString(string str) { byte[] namebytes = Encoding.UTF8.GetBytes(str.ToLower()); @@ -226,9 +219,9 @@ public static uint SoundHashedString(string str) hash = hash & 0xFFFFFFFF; } return hash; - } - - //Read a PAK + } + + //Read a PAK public static List ReadPAK(string path, FileIdentifiers type) { List content = new List(); @@ -268,9 +261,9 @@ public static List ReadPAK(string path, FileIdentifiers type) } return content; - } - - //Write a PAK + } + + //Write a PAK public static void WritePAK(string path, FileIdentifiers type, List content) { bool e = type == FileIdentifiers.MODEL_DATA; @@ -323,15 +316,15 @@ public static void WritePAK(string path, FileIdentifiers type, List int unk = type == FileIdentifiers.MODEL_DATA ? 1 : 0; writer.Write(e ? BigEndianUtils.FlipEndian((Int32)unk) : BitConverter.GetBytes((Int32)unk)); } - } - + } + public class PAKContent { public int BinIndex = 0; public byte[] Data; - } - } - + } + } + public static class MathsUtils { public static (decimal, decimal, decimal) ToYawPitchRoll(this Quaternion q) @@ -369,78 +362,78 @@ private static float NormalizeAngle(float angle) } return angle; } - } - - public static class BigEndianUtils - { - public static Int64 ReadInt64(BinaryReader Reader, bool bigEndian = true) - { - var data = Reader.ReadBytes(8); - if (bigEndian) Array.Reverse(data); - return BitConverter.ToInt64(data, 0); - } - public static UInt64 ReadUInt64(BinaryReader Reader, bool bigEndian = true) - { - var data = Reader.ReadBytes(8); - if (bigEndian) Array.Reverse(data); - return BitConverter.ToUInt64(data, 0); - } - - public static Int32 ReadInt32(BinaryReader Reader, bool bigEndian = true) - { - byte[] data = Reader.ReadBytes(4); - if (bigEndian) Array.Reverse(data); - return BitConverter.ToInt32(data, 0); - } - public static UInt32 ReadUInt32(BinaryReader Reader, bool bigEndian = true) - { - var data = Reader.ReadBytes(4); - if (bigEndian) Array.Reverse(data); - return BitConverter.ToUInt32(data, 0); - } - - public static Int16 ReadInt16(BinaryReader Reader, bool bigEndian = true) - { - var data = Reader.ReadBytes(2); - if (bigEndian) Array.Reverse(data); - return BitConverter.ToInt16(data, 0); - } - public static UInt16 ReadUInt16(BinaryReader Reader, bool bigEndian = true) - { - var data = Reader.ReadBytes(2); - if (bigEndian) Array.Reverse(data); - return BitConverter.ToUInt16(data, 0); - } - - public static byte[] FlipEndian(byte[] ThisEndian) - { - Array.Reverse(ThisEndian); - return ThisEndian; - } - public static byte[] FlipEndian(Int64 ThisEndian) - { - return FlipEndian(BitConverter.GetBytes(ThisEndian)); - } - public static byte[] FlipEndian(UInt64 ThisEndian) - { - return FlipEndian(BitConverter.GetBytes(ThisEndian)); - } - public static byte[] FlipEndian(Int32 ThisEndian) - { - return FlipEndian(BitConverter.GetBytes(ThisEndian)); - } - public static byte[] FlipEndian(UInt32 ThisEndian) - { - return FlipEndian(BitConverter.GetBytes(ThisEndian)); - } - public static byte[] FlipEndian(Int16 ThisEndian) - { - return FlipEndian(BitConverter.GetBytes(ThisEndian)); - } - public static byte[] FlipEndian(UInt16 ThisEndian) - { - return FlipEndian(BitConverter.GetBytes(ThisEndian)); - } + } + + public static class BigEndianUtils + { + public static Int64 ReadInt64(BinaryReader Reader, bool bigEndian = true) + { + var data = Reader.ReadBytes(8); + if (bigEndian) Array.Reverse(data); + return BitConverter.ToInt64(data, 0); + } + public static UInt64 ReadUInt64(BinaryReader Reader, bool bigEndian = true) + { + var data = Reader.ReadBytes(8); + if (bigEndian) Array.Reverse(data); + return BitConverter.ToUInt64(data, 0); + } + + public static Int32 ReadInt32(BinaryReader Reader, bool bigEndian = true) + { + byte[] data = Reader.ReadBytes(4); + if (bigEndian) Array.Reverse(data); + return BitConverter.ToInt32(data, 0); + } + public static UInt32 ReadUInt32(BinaryReader Reader, bool bigEndian = true) + { + var data = Reader.ReadBytes(4); + if (bigEndian) Array.Reverse(data); + return BitConverter.ToUInt32(data, 0); + } + + public static Int16 ReadInt16(BinaryReader Reader, bool bigEndian = true) + { + var data = Reader.ReadBytes(2); + if (bigEndian) Array.Reverse(data); + return BitConverter.ToInt16(data, 0); + } + public static UInt16 ReadUInt16(BinaryReader Reader, bool bigEndian = true) + { + var data = Reader.ReadBytes(2); + if (bigEndian) Array.Reverse(data); + return BitConverter.ToUInt16(data, 0); + } + + public static byte[] FlipEndian(byte[] ThisEndian) + { + Array.Reverse(ThisEndian); + return ThisEndian; + } + public static byte[] FlipEndian(Int64 ThisEndian) + { + return FlipEndian(BitConverter.GetBytes(ThisEndian)); + } + public static byte[] FlipEndian(UInt64 ThisEndian) + { + return FlipEndian(BitConverter.GetBytes(ThisEndian)); + } + public static byte[] FlipEndian(Int32 ThisEndian) + { + return FlipEndian(BitConverter.GetBytes(ThisEndian)); + } + public static byte[] FlipEndian(UInt32 ThisEndian) + { + return FlipEndian(BitConverter.GetBytes(ThisEndian)); + } + public static byte[] FlipEndian(Int16 ThisEndian) + { + return FlipEndian(BitConverter.GetBytes(ThisEndian)); + } + public static byte[] FlipEndian(UInt16 ThisEndian) + { + return FlipEndian(BitConverter.GetBytes(ThisEndian)); + } } public enum FileIdentifiers @@ -603,15 +596,15 @@ public float z } */ - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct fourcc - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - public char[] V; - + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct fourcc + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public char[] V; + public override string ToString() { return new string(V); - } - } -} \ No newline at end of file + } + } +}