8569f3461b
Force close streams if formats are not loaded. Fix compression menu with null returns. (Used if settings is canceled) Some msbt saving progress. Need to fixup TXT2 section. Add VIBS saving
262 lines
10 KiB
C#
262 lines
10 KiB
C#
using Syroot.BinaryData;
|
|
using System.IO;
|
|
using System;
|
|
using System.IO.Compression;
|
|
using OpenTK;
|
|
using System.Windows.Forms;
|
|
|
|
namespace Toolbox.Library.IO
|
|
{
|
|
public class STFileLoader
|
|
{
|
|
/// <summary>
|
|
/// Gets the <see cref="TreeNodeFile"/> from a file or byte array.
|
|
/// </summary>
|
|
/// <param name="FileName">The name of the file</param>
|
|
/// <param name="data">The byte array of the data</param>
|
|
/// <param name="InArchive">If the file is in an archive so it can be saved back</param>
|
|
/// <param name="archiveNode">The node being replaced from an archive</param>
|
|
/// <param name="ArchiveHash">The unique hash from an archive for saving</param>
|
|
/// <param name="Compressed">If the file is being compressed or not</param>
|
|
/// <param name="CompType">The type of <see cref="CompressionType"/> being used</param>
|
|
/// <returns></returns>
|
|
public static TreeNode GetNodeFileFormat(string FileName, bool InArchive = false,
|
|
bool LeaveStreamOpen = false, bool Compressed = false, ICompressionFormat CompressionFormat = null)
|
|
{
|
|
IFileFormat format = OpenFileFormat(FileName, LeaveStreamOpen, InArchive);
|
|
|
|
if (format is TreeNode)
|
|
return (TreeNode)format;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
public static Type CheckFileFormatType(string FileName, Type[] FileTypes, byte[] data = null)
|
|
{
|
|
//Todo. Create a compression list like IFileFormat to decompress via an Identiy method
|
|
data = CheckCompression(FileName, data);
|
|
|
|
Stream stream;
|
|
if (data != null)
|
|
stream = new MemoryStream(data);
|
|
else
|
|
stream = File.OpenRead(FileName);
|
|
|
|
foreach (IFileFormat fileFormat in FileManager.GetFileFormats())
|
|
{
|
|
fileFormat.FileName = Path.GetFileName(FileName);
|
|
|
|
foreach (Type type in FileTypes)
|
|
{
|
|
if (fileFormat.Identify(stream) && fileFormat.GetType() == type)
|
|
return type;
|
|
}
|
|
}
|
|
|
|
return typeof(IFileFormat);
|
|
}
|
|
|
|
public static IFileFormat OpenFileFormat(string FileName, Type[] FileTypes, byte[] data = null)
|
|
{
|
|
//Todo. Create a compression list like IFileFormat to decompress via an Identiy method
|
|
data = CheckCompression(FileName, data);
|
|
|
|
Stream stream;
|
|
if (data != null)
|
|
stream = new MemoryStream(data);
|
|
else
|
|
stream = File.OpenRead(FileName);
|
|
|
|
foreach (IFileFormat fileFormat in FileManager.GetFileFormats())
|
|
{
|
|
fileFormat.FileName = Path.GetFileName(FileName);
|
|
|
|
foreach (Type type in FileTypes)
|
|
{
|
|
if (fileFormat.Identify(stream) && fileFormat.GetType() == type)
|
|
{
|
|
fileFormat.IFileInfo = new IFileInfo();
|
|
return OpenFileFormat(new MemoryStream(data), FileName);
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static IFileFormat OpenFileFormat(string FileName, Type FileType, byte[] data = null)
|
|
{
|
|
CheckCompression(FileName, data);
|
|
|
|
Stream stream;
|
|
if (data != null)
|
|
stream = new MemoryStream(data);
|
|
else
|
|
stream = File.OpenRead(FileName);
|
|
|
|
foreach (IFileFormat fileFormat in FileManager.GetFileFormats())
|
|
{
|
|
if (fileFormat.GetType() == FileType)
|
|
return OpenFileFormat(stream, FileName);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static byte[] CheckCompression(string FileName, byte[] data)
|
|
{
|
|
if (data != null)
|
|
{
|
|
using (var reader = new FileReader(data))
|
|
{
|
|
return DecompressData(reader, FileName, data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (var reader = new FileReader(FileName))
|
|
{
|
|
return DecompressData(reader, FileName, data);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static byte[] DecompressData(FileReader reader, string FileName, byte[] data)
|
|
{
|
|
reader.ByteOrder = ByteOrder.BigEndian;
|
|
reader.Position = 0;
|
|
uint MagicHex = reader.ReadUInt32();
|
|
string Magic = reader.ReadMagic(0, 4);
|
|
reader.Position = 0;
|
|
|
|
if (Magic == "Yaz0")
|
|
{
|
|
if (data != null)
|
|
return EveryFileExplorer.YAZ0.Decompress(data);
|
|
else
|
|
return EveryFileExplorer.YAZ0.Decompress(FileName);
|
|
}
|
|
if (MagicHex == 0x28B52FFD || MagicHex == 0xFD2FB528)
|
|
{
|
|
if (data != null)
|
|
return Zstb.SDecompress(data);
|
|
else
|
|
return Zstb.SDecompress(File.ReadAllBytes(FileName));
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="IFileFormat"/> from a file or byte array.
|
|
/// </summary>
|
|
/// <param name="FileName">The name of the file</param>
|
|
/// <param name="data">The byte array of the data</param>
|
|
/// <param name="InArchive">If the file is in an archive so it can be saved back</param>
|
|
/// <param name="archiveNode">The node being replaced from an archive</param>
|
|
/// <param name="Compressed">If the file is being compressed or not</param>
|
|
/// <param name="CompType">The type of <see cref="CompressionType"/> being used</param>
|
|
/// <returns></returns>
|
|
public static IFileFormat OpenFileFormat(string FileName, bool LeaveStreamOpen = false, bool InArchive = false,
|
|
bool Compressed = false, ICompressionFormat CompressionFormat = null, uint DecompressedSize = 0, uint CompressedSize = 0)
|
|
{
|
|
return OpenFileFormat(File.OpenRead(FileName), FileName, LeaveStreamOpen, InArchive,
|
|
Compressed, CompressionFormat, DecompressedSize, CompressedSize);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="IFileFormat"/> from a file or byte array.
|
|
/// </summary>
|
|
/// <param name="FileName">The name of the file</param>
|
|
/// <param name="data">The byte array of the data</param>
|
|
/// <param name="InArchive">If the file is in an archive so it can be saved back</param>
|
|
/// <param name="Compressed">If the file is being compressed or not</param>
|
|
/// <param name="CompressionFormat">The type of <see cref="ICompressionFormat"/> being used</param>
|
|
/// <returns></returns>
|
|
public static IFileFormat OpenFileFormat(Stream stream, string FileName, bool LeaveStreamOpen = false, bool InArchive = false,
|
|
bool Compressed = false, ICompressionFormat CompressionFormat = null, long DecompressedSize = 0, long CompressedSize = 0)
|
|
{
|
|
if (!Compressed)
|
|
DecompressedSize = stream.Length;
|
|
|
|
long streamStartPos = stream.Position;
|
|
|
|
if (stream.Length < 8) return null;
|
|
|
|
//Try catch incase it fails, continute to load the file anyways if the check may be false
|
|
try
|
|
{
|
|
//Check all supported compression formats and decompress. Then loop back
|
|
if (!Compressed)
|
|
{
|
|
foreach (ICompressionFormat compressionFormat in FileManager.GetCompressionFormats())
|
|
{
|
|
stream.Position = streamStartPos;
|
|
if (compressionFormat.Identify(stream, FileName))
|
|
{
|
|
stream.Position = streamStartPos;
|
|
|
|
stream = compressionFormat.Decompress(stream);
|
|
CompressedSize = stream.Length;
|
|
|
|
return OpenFileFormat(stream, FileName, LeaveStreamOpen, InArchive,
|
|
true, compressionFormat, DecompressedSize, CompressedSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.ToString());
|
|
}
|
|
|
|
|
|
stream.Position = streamStartPos;
|
|
foreach (IFileFormat fileFormat in FileManager.GetFileFormats())
|
|
{
|
|
//Set the file name so we can check it's extension in the identifier.
|
|
//Most is by magic but some can be extension or name.
|
|
|
|
fileFormat.FileName = Path.GetFileName(FileName);
|
|
|
|
if (fileFormat.Identify(stream))
|
|
{
|
|
fileFormat.IFileInfo = new IFileInfo();
|
|
fileFormat.IFileInfo.DecompressedSize = (uint)DecompressedSize;
|
|
fileFormat.IFileInfo.CompressedSize = (uint)CompressedSize;
|
|
return SetFileFormat(fileFormat, FileName, stream, LeaveStreamOpen, InArchive, Compressed, CompressionFormat);
|
|
}
|
|
}
|
|
|
|
stream.Close();
|
|
|
|
return null;
|
|
}
|
|
|
|
private static IFileFormat SetFileFormat(IFileFormat fileFormat, string FileName, Stream stream, bool LeaveStreamOpen = false, bool InArchive = false,
|
|
bool Compressed = false, ICompressionFormat FileCompression = null)
|
|
{
|
|
fileFormat.IFileInfo.FileCompression = FileCompression;
|
|
fileFormat.IFileInfo.FileIsCompressed = Compressed;
|
|
fileFormat.FileName = Path.GetFileName(FileName);
|
|
fileFormat.FilePath = FileName;
|
|
fileFormat.IFileInfo.InArchive = InArchive;
|
|
fileFormat.IFileInfo.FileIsCompressed = Compressed;
|
|
fileFormat.Load(stream);
|
|
//After file has been loaded and read, we'll dispose unless left open
|
|
|
|
if (fileFormat is ILeaveOpenOnLoad) {
|
|
LeaveStreamOpen = true;
|
|
}
|
|
|
|
if (!LeaveStreamOpen)
|
|
{
|
|
stream.Dispose();
|
|
GC.SuppressFinalize(stream);
|
|
}
|
|
|
|
return fileFormat;
|
|
}
|
|
}
|
|
}
|