Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Buffers.Binary;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.InteropServices;
- namespace SA2SetParser
- {
- public enum ByteOrder
- {
- LittleEndian = 0,
- BigEndian = 1
- }
- [AttributeUsage(AttributeTargets.Field)]
- public class Endianness : Attribute
- {
- public ByteOrder ByteOrder;
- public Endianness(ByteOrder byteOrder)
- {
- ByteOrder = byteOrder;
- }
- }
- public static class DataExtensions
- {
- public static unsafe T ToStruct<T>(this IEnumerable<byte> buffer, int offset = 0)
- {
- if (buffer == null) throw new ArgumentNullException($"{nameof(buffer)} cannot be null!");
- if (offset < 0) throw new ArgumentOutOfRangeException($"{nameof(offset)} cannot be less than 0!");
- byte[] bufferAsArray;
- if (buffer is byte[] localBuffer)
- {
- bufferAsArray = localBuffer;
- }
- else
- {
- bufferAsArray = buffer.ToArray();
- }
- T structure;
- fixed (byte* bufferPointer = bufferAsArray)
- {
- structure = Marshal.PtrToStructure<T>((IntPtr)bufferPointer + offset);
- }
- // Sort endianness
- object boxedStruct = structure;
- foreach (var property in typeof(T).GetFields())
- {
- if (property.GetCustomAttribute<Endianness>(true)?.ByteOrder != ByteOrder.BigEndian) continue;
- if (property.FieldType == typeof(float))
- {
- var propVal = (float)property.GetValue(boxedStruct);
- var value = BinaryPrimitives.ReverseEndianness(*(uint*)&propVal);
- property.SetValue(boxedStruct, *(float*)&value);
- }
- else
- {
- var value = BinaryPrimitives.ReverseEndianness(
- (dynamic)property.GetValue(boxedStruct));
- property.SetValue(boxedStruct, value);
- }
- }
- return (T)boxedStruct;
- }
- public static unsafe IEnumerable<byte> ToBytes<T>(this T structure)
- {
- if (structure == null) throw new ArgumentNullException($"{nameof(structure)} cannot be null!");
- var type = structure.GetType();
- if (!type.IsValueType || type.IsEnum) throw new ArgumentException($"{nameof(structure)} must be a struct!");
- var structureClone = structure;
- object boxedStruct = structureClone;
- foreach (var property in typeof(T).GetFields())
- {
- if (property.GetCustomAttribute<Endianness>(true)?.ByteOrder != ByteOrder.BigEndian) continue;
- if (property.FieldType == typeof(float))
- {
- var propVal = (float)property.GetValue(boxedStruct);
- var value = BinaryPrimitives.ReverseEndianness(*(uint*)&propVal);
- property.SetValue(boxedStruct, *(float*)&value);
- }
- else
- {
- var value = BinaryPrimitives.ReverseEndianness(
- (dynamic)property.GetValue(boxedStruct));
- property.SetValue(boxedStruct, value);
- }
- }
- var buffer = new byte[Marshal.SizeOf<T>()];
- fixed (byte* bufferPointer = buffer)
- {
- Marshal.StructureToPtr(structureClone, (IntPtr)bufferPointer, false);
- }
- return buffer;
- }
- }
- public static class SetParser
- {
- //public TextAsset SETFile;
- //public bool SETIsBigEndian = false;
- //public int ChunkSize = 4;
- //public GameObject Placeholder;
- //private byte[] SET;
- //private List<List<byte>> Split;
- [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 32)]
- private struct SetHeader
- {
- [Endianness(ByteOrder.BigEndian)]
- public int ObjectCount;
- }
- [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 32)]
- public struct Object
- {
- [Endianness(ByteOrder.BigEndian)]
- public ushort ObjectInfo;
- [Endianness(ByteOrder.BigEndian)]
- public ushort RotationX;
- [Endianness(ByteOrder.BigEndian)]
- public ushort RotationY;
- [Endianness(ByteOrder.BigEndian)]
- public ushort RotationZ;
- [Endianness(ByteOrder.BigEndian)]
- public float PositionX;
- [Endianness(ByteOrder.BigEndian)]
- public float PositionY;
- [Endianness(ByteOrder.BigEndian)]
- public float PositionZ;
- [Endianness(ByteOrder.BigEndian)]
- public float PropertyA;
- [Endianness(ByteOrder.BigEndian)]
- public float PropertyB;
- [Endianness(ByteOrder.BigEndian)]
- public float PropertyC;
- }
- public unsafe static List<Object> ParseSETFile(string fileLocation)
- {
- if (File.Exists(fileLocation))
- {
- byte[] fileData;
- try
- {
- fileData = File.ReadAllBytes(fileLocation);
- }
- catch
- {
- Console.WriteLine("Unable to read the SET File! It may be in use by another program.");
- return new List<Object>();
- }
- // Get header struct
- var header = fileData.ToStruct<SetHeader>();
- // Iterate through the subentries and convert each to a struct.
- var objectList = new List<Object>();
- try
- {
- for (var i = 0; i < header.ObjectCount; i++)
- {
- objectList.Add(fileData.ToStruct<Object>(sizeof(SetHeader) + i * sizeof(Object)));
- }
- }
- catch
- {
- return objectList; // We hit the end of the file while reading. Return what we have.
- }
- return objectList;
- }
- return new List<Object>();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement