2019-04-22 21:52:21 +00:00
|
|
|
|
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
|
|
|
|
|
{
|
2019-05-08 20:45:27 +00:00
|
|
|
|
public FileType FileType { get; set; } = FileType.Effect;
|
|
|
|
|
|
2019-04-22 21:52:21 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|