Files
YarikStudio/AssetStudio/EndianBinaryReader.cs
2023-09-22 20:31:55 +04:00

312 lines
8.2 KiB
C#

using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace AssetStudio
{
public class EndianBinaryReader : BinaryReader
{
private readonly byte[] buffer;
public EndianType Endian;
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian, bool leaveOpen = false) : base(stream, Encoding.UTF8, leaveOpen)
{
Endian = endian;
buffer = new byte[8];
}
public long Position
{
get => BaseStream.Position;
set => BaseStream.Position = value;
}
public long Length => BaseStream.Length;
public long Remaining => Length - Position;
public override short ReadInt16()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 2);
return BinaryPrimitives.ReadInt16BigEndian(buffer);
}
return base.ReadInt16();
}
public override int ReadInt32()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
return BinaryPrimitives.ReadInt32BigEndian(buffer);
}
return base.ReadInt32();
}
public override long ReadInt64()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
return BinaryPrimitives.ReadInt64BigEndian(buffer);
}
return base.ReadInt64();
}
public override ushort ReadUInt16()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 2);
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
}
return base.ReadUInt16();
}
public override uint ReadUInt32()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
}
return base.ReadUInt32();
}
public override ulong ReadUInt64()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
}
return base.ReadUInt64();
}
public override float ReadSingle()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
Array.Reverse(buffer, 0, 4);
return BitConverter.ToSingle(buffer, 0);
}
return base.ReadSingle();
}
public override double ReadDouble()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
Array.Reverse(buffer);
return BitConverter.ToDouble(buffer, 0);
}
return base.ReadDouble();
}
public void AlignStream()
{
AlignStream(4);
}
public void AlignStream(int alignment)
{
var pos = Position;
var mod = pos % alignment;
if (mod != 0)
{
Position += alignment - mod;
}
}
public string ReadAlignedString()
{
var length = ReadInt32();
if (length > 0 && length <= Remaining)
{
var stringData = ReadBytes(length);
var result = Encoding.UTF8.GetString(stringData);
AlignStream(4);
return result;
}
return "";
}
public string ReadStringToNull(int maxLength = 32767)
{
var bytes = new List<byte>();
int count = 0;
while (Remaining > 0 && count < maxLength)
{
var b = ReadByte();
if (b == 0)
{
break;
}
bytes.Add(b);
count++;
}
return Encoding.UTF8.GetString(bytes.ToArray());
}
public Quaternion ReadQuaternion()
{
return new Quaternion(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());
}
public Vector2 ReadVector2()
{
return new Vector2(ReadSingle(), ReadSingle());
}
public Vector3 ReadVector3()
{
return new Vector3(ReadSingle(), ReadSingle(), ReadSingle());
}
public Vector4 ReadVector4()
{
return new Vector4(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());
}
public Color ReadColor4()
{
return new Color(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());
}
public Matrix4x4 ReadMatrix()
{
return new Matrix4x4(ReadSingleArray(16));
}
public XForm ReadXForm(int[] version, bool isVector4 = false)
{
var t = (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) && !isVector4 ? ReadVector3() : (Vector3)ReadVector4();//5.4 and up
var q = ReadQuaternion();
var s = (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) && !isVector4 ? ReadVector3() : (Vector3)ReadVector4();//5.4 and up
return new XForm(t, q, s);
}
public Float ReadFloat()
{
return new Float(ReadSingle());
}
public int ReadMhy0Int()
{
var buffer = ReadBytes(6);
return buffer[2] | (buffer[4] << 8) | (buffer[0] << 0x10) | (buffer[5] << 0x18);
}
public uint ReadMhy0UInt()
{
var buffer = ReadBytes(7);
return (uint)(buffer[1] | (buffer[6] << 8) | (buffer[3] << 0x10) | (buffer[2] << 0x18));
}
public string ReadMhy0String()
{
var pos = BaseStream.Position;
var str = ReadStringToNull();
BaseStream.Position += 0x105 - (BaseStream.Position - pos);
return str;
}
private T[] ReadArray<T>(Func<T> del, int length)
{
var array = new T[length];
for (int i = 0; i < length; i++)
{
array[i] = del();
}
return array;
}
public bool[] ReadBooleanArray()
{
return ReadArray(ReadBoolean, ReadInt32());
}
public byte[] ReadUInt8Array()
{
return ReadBytes(ReadInt32());
}
public short[] ReadInt16Array()
{
return ReadArray(ReadInt16, ReadInt32());
}
public short[] ReadInt16Array(int length)
{
return ReadArray(ReadInt16, length);
}
public ushort[] ReadUInt16Array()
{
return ReadArray(ReadUInt16, ReadInt32());
}
public int[] ReadInt32Array()
{
return ReadArray(ReadInt32, ReadInt32());
}
public int[] ReadInt32Array(int length)
{
return ReadArray(ReadInt32, length);
}
public uint[] ReadUInt32Array()
{
return ReadArray(ReadUInt32, ReadInt32());
}
public uint[][] ReadUInt32ArrayArray()
{
return ReadArray(ReadUInt32Array, ReadInt32());
}
public uint[] ReadUInt32Array(int length)
{
return ReadArray(ReadUInt32, length);
}
public float[] ReadSingleArray()
{
return ReadArray(ReadSingle, ReadInt32());
}
public float[] ReadSingleArray(int length)
{
return ReadArray(ReadSingle, length);
}
public string[] ReadStringArray()
{
return ReadArray(ReadAlignedString, ReadInt32());
}
public Vector2[] ReadVector2Array()
{
return ReadArray(ReadVector2, ReadInt32());
}
public Vector4[] ReadVector4Array()
{
return ReadArray(ReadVector4, ReadInt32());
}
public Matrix4x4[] ReadMatrixArray()
{
return ReadArray(ReadMatrix, ReadInt32());
}
}
}