1
0
mirror of synced 2025-02-22 05:19:50 +01:00
KillzXGaming 32fb5444e7 Add all the newest changes.
Add support for bayonetta/astral chain dat.
Add support for darc archives.
Support previewing window panes for bflyt (1 frame atm with around kind)
Add bflan reading. Saving needs more testing and will be enabled soon.
Bflyt editor will keep the editor open within an archive when saved.
A custom dialog will be added soon to customize saving parameters.
Bflims will be loaded if in the same folder as the bflyt when opened.
2019-09-10 18:42:48 -04:00

427 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Syroot.BinaryData;
using System.IO;
using System.IO.Compression;
using OpenTK;
using System.Runtime.InteropServices;
namespace Toolbox.Library.IO
{
public class FileReader : BinaryDataReader
{
public FileReader(Stream stream, bool leaveOpen = false)
: base(stream, Encoding.ASCII, leaveOpen)
{
this.Position = 0;
}
public FileReader(string fileName)
: this(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
this.Position = 0;
}
public FileReader(byte[] data)
: this(new MemoryStream(data))
{
this.Position = 0;
}
//Checks signature (no stream advancement)
public bool CheckSignature(int length, string Identifier, long position = 0)
{
if (Position + length + position >= BaseStream.Length || position < 0)
return false;
Position = position;
string signature = ReadString(length, Encoding.ASCII);
//Reset position
Position = 0;
return signature == Identifier;
}
//From kuriimu https://github.com/IcySon55/Kuriimu/blob/master/src/Kontract/IO/BinaryReaderX.cs#L40
public T ReadStruct<T>() => ReadBytes(Marshal.SizeOf<T>()).BytesToStruct<T>(ByteOrder == ByteOrder.BigEndian);
public List<T> ReadMultipleStructs<T>(int count) => Enumerable.Range(0, count).Select(_ => ReadStruct<T>()).ToList();
public List<T> ReadMultipleStructs<T>(uint count) => Enumerable.Range(0, (int)count).Select(_ => ReadStruct<T>()).ToList();
public bool CheckSignature(uint Identifier, long position = 0)
{
if (Position + 4 >= BaseStream.Length || position < 0 || position + 4 >= BaseStream.Length)
return false;
Position = position;
uint signature = ReadUInt32();
//Reset position
Position = 0;
return signature == Identifier;
}
public int ReadInt32(int position)
{
long origin = this.Position;
SeekBegin(position);
int value = ReadInt32();
SeekBegin(origin + sizeof(int));
return value;
}
public uint ReadUInt32(int position)
{
long origin = this.Position;
SeekBegin(position);
uint value = ReadUInt32();
SeekBegin(origin + sizeof(uint));
return value;
}
public string ReadNameOffset(bool IsRelative, Type OffsetType, bool ReadNameLength = false, bool IsNameLengthShort = false)
{
long pos = Position;
long offset = 0;
if (OffsetType == typeof(long))
offset = ReadInt64();
if (OffsetType == typeof(ulong))
offset = (long)ReadUInt64();
if (OffsetType == typeof(uint))
offset = ReadUInt32();
if (OffsetType == typeof(int))
offset = ReadInt32();
if (IsRelative && offset != 0)
offset += pos;
if (offset != 0)
{
using (TemporarySeek(offset, SeekOrigin.Begin))
{
uint NameLength = 0;
if (ReadNameLength)
{
if (IsNameLengthShort)
NameLength = ReadUInt16();
else
NameLength = ReadUInt32();
}
return ReadString(BinaryStringFormat.ZeroTerminated);
}
}
else
return "";
}
public List<string> ReadNameOffsets(uint Count, bool IsRelative, Type OffsetType, bool ReadNameLength = false)
{
List<string> Names = new List<string>();
for (int i = 0; i < Count; i++)
Names.Add(ReadNameOffset(IsRelative, OffsetType, ReadNameLength));
return Names;
}
public string ReadString(int length, bool removeSpaces)
{
return ReadString(length).Replace("\0", string.Empty);
}
public string ReadZeroTerminatedString(Encoding encoding = null)
{
return ReadString(BinaryStringFormat.ZeroTerminated, encoding ?? Encoding);
}
public string[] ReadZeroTerminatedStrings(uint count, Encoding encoding = null)
{
string[] str = new string[count];
for (int i = 0; i < count; i++)
str[i] = ReadString(BinaryStringFormat.ZeroTerminated, encoding ?? Encoding);
return str;
}
public string ReadUTF16String()
{
List<byte> chars = new List<byte>();
while (true)
{
ushort val = ReadUInt16();
if (val == 0)
{
return Encoding.ASCII.GetString(chars.ToArray());
}
else
chars.Add((byte)val); // casting to byte will remove the period, which is a part of UTF-16
}
}
/// <summary>
/// Checks the byte order mark to determine the endianness of the reader.
/// </summary>
/// <param name="ByteOrderMark">The byte order value being read. 0xFFFE = Little, 0xFEFF = Big. </param>
/// <returns></returns>
public void CheckByteOrderMark(uint ByteOrderMark)
{
SetByteOrder(ByteOrderMark == 0xFEFF);
}
public void SetByteOrder(bool IsBigEndian)
{
if (IsBigEndian)
ByteOrder = ByteOrder.BigEndian;
else
ByteOrder = ByteOrder.LittleEndian;
}
public string ReadSignature(int length, string ExpectedSignature, bool TrimEnd = false)
{
string RealSignature = ReadString(length, Encoding.ASCII);
if (TrimEnd) RealSignature = RealSignature.TrimEnd(' ');
if (RealSignature != ExpectedSignature)
throw new Exception($"Invalid signature {RealSignature}! Expected {ExpectedSignature}.");
return RealSignature;
}
public float ReadByteAsFloat()
{
return ReadByte() / 255.0f;
}
public float ReadHalfSingle()
{
return new Syroot.IOExtension.Half(ReadUInt16());
}
public Matrix4 ReadMatrix4(bool SwapRows = false)
{
Matrix4 mat4 = new Matrix4();
if (SwapRows)
{
mat4.M11 = ReadSingle();
mat4.M21 = ReadSingle();
mat4.M31 = ReadSingle();
mat4.M41 = ReadSingle();
mat4.M12 = ReadSingle();
mat4.M22 = ReadSingle();
mat4.M32 = ReadSingle();
mat4.M42 = ReadSingle();
mat4.M13 = ReadSingle();
mat4.M23 = ReadSingle();
mat4.M33 = ReadSingle();
mat4.M43 = ReadSingle();
mat4.M14 = ReadSingle();
mat4.M24 = ReadSingle();
mat4.M34 = ReadSingle();
mat4.M44 = ReadSingle();
}
else
{
mat4.M11 = ReadSingle();
mat4.M12 = ReadSingle();
mat4.M13 = ReadSingle();
mat4.M14 = ReadSingle();
mat4.M21 = ReadSingle();
mat4.M22 = ReadSingle();
mat4.M23 = ReadSingle();
mat4.M24 = ReadSingle();
mat4.M31 = ReadSingle();
mat4.M32 = ReadSingle();
mat4.M33 = ReadSingle();
mat4.M34 = ReadSingle();
mat4.M41 = ReadSingle();
mat4.M42 = ReadSingle();
mat4.M43 = ReadSingle();
mat4.M44 = ReadSingle();
}
return mat4;
}
public void SeekBegin(uint Offset) { Seek(Offset, SeekOrigin.Begin); }
public void SeekBegin(int Offset) { Seek(Offset, SeekOrigin.Begin); }
public void SeekBegin(long Offset) { Seek(Offset, SeekOrigin.Begin); }
public void SeekBegin(ulong Offset) { Seek((long)Offset, SeekOrigin.Begin); }
public long ReadOffset(bool IsRelative, Type OffsetType)
{
long pos = Position;
long offset = 0;
if (OffsetType == typeof(long))
offset = ReadInt64();
if (OffsetType == typeof(ulong))
offset = (long)ReadUInt64();
if (OffsetType == typeof(uint))
offset = ReadUInt32();
if (OffsetType == typeof(int))
offset = ReadInt32();
if (IsRelative && offset != 0)
return pos + offset;
else
return offset;
}
public string LoadString(bool IsRelative, Type OffsetType, Encoding encoding = null, uint ReadStringLength = 0)
{
long pos = Position;
long offset = 0;
int size = 0;
if (OffsetType == typeof(long))
offset = ReadInt64();
if (OffsetType == typeof(ulong))
offset = (long)ReadUInt64();
if (OffsetType == typeof(uint))
offset = ReadUInt32();
if (OffsetType == typeof(int))
offset = ReadInt32();
if (offset == 0) return string.Empty;
if (IsRelative)
offset = offset + pos;
encoding = encoding ?? Encoding;
using (TemporarySeek(offset, SeekOrigin.Begin))
{
//Read the size of the string if set
uint stringLength = 0;
if (ReadStringLength == 2)
stringLength = ReadUInt16();
if (ReadStringLength == 4)
stringLength = ReadUInt32();
return ReadString(BinaryStringFormat.ZeroTerminated, encoding);
}
}
public STColor8[] ReadColor8sRGBA(int count)
{
STColor8[] colors = new STColor8[count];
for (int i = 0; i < count; i++)
colors[i] = STColor8.FromBytes(ReadBytes(4));
return colors;
}
public STColor8 ReadColor8RGBA()
{
return STColor8.FromBytes(ReadBytes(4));
}
public STColor16[] ReadColor16sRGBA(int count)
{
STColor16[] colors = new STColor16[count];
for (int i = 0; i < count; i++)
colors[i] = STColor16.FromShorts(ReadUInt16s(4));
return colors;
}
public STColor16 ReadColor16RGBA()
{
return STColor16.FromShorts(ReadUInt16s(4));
}
public STColor[] ReadColorsRGBA(int count)
{
STColor[] colors = new STColor[count];
for (int i = 0; i < count; i++)
colors[i] = STColor.FromFloats(ReadSingles(4));
return colors;
}
public STColor ReadColorRGBA()
{
return STColor.FromFloats(ReadSingles(4));
}
public static byte[] DeflateZLIB(byte[] i)
{
MemoryStream output = new MemoryStream();
output.WriteByte(0x78);
output.WriteByte(0x9C);
using (DeflateStream dstream = new DeflateStream(output, CompressionLevel.Optimal))
{
dstream.Write(i, 0, i.Length);
}
return output.ToArray();
}
public byte[] getSection(uint offset, uint size)
{
Position = offset;
return ReadBytes((int)size);
}
public byte[] getSection(int offset, int size)
{
Position = offset;
return ReadBytes(size);
}
public Vector4 ReadVec4()
{
return new Vector4(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());
}
public Vector3 ReadVec3()
{
return new Vector3(ReadSingle(), ReadSingle(), ReadSingle());
}
public Syroot.Maths.Vector3F ReadVec3SY()
{
return new Syroot.Maths.Vector3F(ReadSingle(), ReadSingle(), ReadSingle());
}
public Vector2 ReadVec2()
{
return new Vector2(ReadSingle(), ReadSingle());
}
public Syroot.Maths.Vector2F ReadVec2SY()
{
return new Syroot.Maths.Vector2F(ReadSingle(), ReadSingle());
}
public static byte[] InflateZLIB(byte[] i)
{
var stream = new MemoryStream();
var ms = new MemoryStream(i);
ms.ReadByte();
ms.ReadByte();
var zlibStream = new DeflateStream(ms, CompressionMode.Decompress);
byte[] buffer = new byte[4095];
while (true)
{
int size = zlibStream.Read(buffer, 0, buffer.Length);
if (size > 0)
stream.Write(buffer, 0, buffer.Length);
else
break;
}
zlibStream.Close();
return stream.ToArray();
}
public string ReadMagic(int Offset, int Length)
{
Seek(Offset, SeekOrigin.Begin);
return ReadString(Length);
}
}
}