Switch-Toolbox/Switch_FileFormatsMain/FileFormats/XLINK/XLINK.cs
2019-04-22 17:52:21 -04:00

201 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library;
using System.Windows.Forms;
namespace FirstPlugin
{
public class XLINK : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Effect Link" };
public string[] Extension { get; set; } = new string[] { "*.bslnk", "*.belnk" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "XLNK");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
CanSave = false;
Text = FileName;
Header Header = new Header();
Header.Read(new FileReader(stream));
var userData = new TreeNode("User Data");
Nodes.Add(userData);
var hashes = new TreeNode("Hashes");
userData.Nodes.Add(hashes);
foreach (var hash in Header.UserDataTable.CRC32Hashes)
hashes.Nodes.Add(new TreeNode(hash.ToString("x")));
var paramDefines = new TreeNode("Param Defines");
Nodes.Add(paramDefines);
foreach (var param in Header.ParamDefineTable.UserParams)
paramDefines.Nodes.Add(param.Name);
foreach (var param in Header.ParamDefineTable.TriggerParams)
paramDefines.Nodes.Add(param.Name);
foreach (var param in Header.ParamDefineTable.UserParams)
paramDefines.Nodes.Add(param.Name);
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
//Documentation from https://github.com/Kinnay/Nintendo-File-Formats/wiki/XLINK-File-Format#header
public class Header
{
public ushort ByteOrderMark;
public UserDataTable UserDataTable;
public ParamDefineTable ParamDefineTable;
public void Read(FileReader reader)
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
reader.ReadSignature(4, "XLNK");
uint FileSize = reader.ReadUInt32();
uint Version = reader.ReadUInt32();
uint numResParam = reader.ReadUInt32();
uint numResAssetParam = reader.ReadUInt32();
uint numResTriggerOverwriteParam = reader.ReadUInt32();
uint triggerOverwriteParamTablePos = reader.ReadUInt32();
uint localPropertyNameRefTablePos = reader.ReadUInt32();
uint numLocalPropertyNameRefTable = reader.ReadUInt32();
uint numLocalPropertyEnumNameRefTable = reader.ReadUInt32();
uint numDirectValueTable = reader.ReadUInt32();
uint numRandomTable = reader.ReadUInt32();
uint numCurveTable = reader.ReadUInt32();
uint numCurvePointTable = reader.ReadUInt32();
uint exRegionPos = reader.ReadUInt32();
uint numUser = reader.ReadUInt32();
uint conditionTablePos = reader.ReadUInt32();
uint nameTablePos = reader.ReadUInt32();
UserDataTable = new UserDataTable();
UserDataTable.Read(reader, (int)numUser);
ParamDefineTable = new ParamDefineTable();
ParamDefineTable.Read(reader);
}
}
public class UserDataTable
{
public uint[] CRC32Hashes;
public uint[] ExRegionOffsets;
public void Read(FileReader reader, int EntryCount)
{
CRC32Hashes = reader.ReadUInt32s(EntryCount);
ExRegionOffsets = reader.ReadUInt32s(EntryCount);
}
}
public class ParamDefineTable
{
public List<ParamDefineEntry> UserParams = new List<ParamDefineEntry>();
public List<ParamDefineEntry> AssetParams = new List<ParamDefineEntry>();
public List<ParamDefineEntry> TriggerParams = new List<ParamDefineEntry>();
public void Read(FileReader reader)
{
uint SectionSize = reader.ReadUInt32();
uint numUserParams = reader.ReadUInt32();
uint numAssetParams = reader.ReadUInt32();
uint unknown = reader.ReadUInt32();
uint numTriggerParams = reader.ReadUInt32();
for (int i = 0; i < numUserParams; i++)
{
var entry = new ParamDefineEntry();
entry.Read(reader);
UserParams.Add(entry);
}
for (int i = 0; i < numAssetParams; i++)
{
var entry = new ParamDefineEntry();
entry.Read(reader);
AssetParams.Add(entry);
}
for (int i = 0; i < numTriggerParams; i++)
{
var entry = new ParamDefineEntry();
entry.Read(reader);
TriggerParams.Add(entry);
}
List<byte> StringTable = new List<byte>();
long StringTablePosition = reader.Position;
foreach (var param in UserParams)
param.ReadString(reader, StringTablePosition);
foreach (var param in AssetParams)
param.ReadString(reader, StringTablePosition);
foreach (var param in TriggerParams)
param.ReadString(reader, StringTablePosition);
}
}
public class ParamDefineEntry
{
internal uint NamePos;
public string Name { get; set; }
public uint Type { get; set; }
public byte[] DefaultValue { get; set; }
public void Read(FileReader reader)
{
NamePos = reader.ReadUInt32(); //Offset from string table
Type = reader.ReadUInt32();
DefaultValue = reader.ReadBytes(4);
}
public void ReadString(FileReader reader, long TablePosition)
{
Console.WriteLine("NamePos " + NamePos);
reader.Position = TablePosition + NamePos;
Name = reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated);
Console.WriteLine("Name " + Name);
}
}
}
}