AssetStudio/AssetStudio/TypeTreeHelper.cs

309 lines
13 KiB
C#
Raw Normal View History

2020-08-13 16:02:59 +00:00
using System.Collections.Generic;
using System.IO;
2018-05-09 14:48:50 +00:00
using System.Text;
namespace AssetStudio
{
2018-09-26 21:23:10 +00:00
public static class TypeTreeHelper
2018-05-09 14:48:50 +00:00
{
2020-08-13 16:02:59 +00:00
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, ObjectReader reader)
2018-05-09 14:48:50 +00:00
{
2020-08-13 16:02:59 +00:00
reader.Reset();
2018-05-09 14:48:50 +00:00
for (int i = 0; i < members.Count; i++)
{
ReadStringValue(sb, members, reader, ref i);
}
2020-08-13 16:02:59 +00:00
var readed = reader.Position - reader.byteStart;
if (readed != reader.byteSize)
{
Logger.Error($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
}
2018-05-09 14:48:50 +00:00
}
2018-11-21 07:37:56 +00:00
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
2018-05-09 14:48:50 +00:00
{
var member = members[i];
var level = member.m_Level;
2018-09-26 21:23:10 +00:00
var varTypeStr = member.m_Type;
var varNameStr = member.m_Name;
2018-05-09 14:48:50 +00:00
object value = null;
var append = true;
2018-09-26 21:23:10 +00:00
var align = (member.m_MetaFlag & 0x4000) != 0;
2018-05-09 14:48:50 +00:00
switch (varTypeStr)
{
case "SInt8":
value = reader.ReadSByte();
break;
case "UInt8":
2020-04-10 10:11:56 +00:00
case "char":
2018-05-09 14:48:50 +00:00
value = reader.ReadByte();
break;
case "short":
case "SInt16":
value = reader.ReadInt16();
break;
case "UInt16":
case "unsigned short":
value = reader.ReadUInt16();
break;
case "int":
case "SInt32":
value = reader.ReadInt32();
break;
case "UInt32":
case "unsigned int":
case "Type*":
value = reader.ReadUInt32();
break;
case "long long":
case "SInt64":
value = reader.ReadInt64();
break;
case "UInt64":
case "unsigned long long":
2020-04-10 10:11:56 +00:00
case "FileSize":
2018-05-09 14:48:50 +00:00
value = reader.ReadUInt64();
break;
case "float":
value = reader.ReadSingle();
break;
case "double":
value = reader.ReadDouble();
break;
case "bool":
value = reader.ReadBoolean();
break;
case "string":
append = false;
var str = reader.ReadAlignedString();
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
i += 3;
2018-05-09 14:48:50 +00:00
break;
case "map":
{
2018-09-26 21:23:10 +00:00
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
2018-05-09 14:48:50 +00:00
align = true;
append = false;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
var size = reader.ReadInt32();
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
2020-04-10 10:11:56 +00:00
var map = GetMembers(members, i);
2018-05-09 14:48:50 +00:00
i += map.Count - 1;
2020-04-10 10:11:56 +00:00
var first = GetMembers(map, 4);
var next = 4 + first.Count;
var second = GetMembers(map, next);
2018-05-09 14:48:50 +00:00
for (int j = 0; j < size; j++)
{
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 2)), "pair", "data");
int tmp1 = 0;
int tmp2 = 0;
ReadStringValue(sb, first, reader, ref tmp1);
ReadStringValue(sb, second, reader, ref tmp2);
}
break;
}
case "TypelessData":
{
append = false;
var size = reader.ReadInt32();
reader.ReadBytes(size);
i += 2;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size);
break;
}
default:
{
2020-04-10 10:11:56 +00:00
if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array
2018-06-20 14:48:44 +00:00
{
2020-04-10 10:11:56 +00:00
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
append = false;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
var size = reader.ReadInt32();
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
var vector = GetMembers(members, i);
i += vector.Count - 1;
for (int j = 0; j < size; j++)
{
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
int tmp = 3;
ReadStringValue(sb, vector, reader, ref tmp);
}
break;
2018-06-20 14:48:44 +00:00
}
2020-04-10 10:11:56 +00:00
else //Class
2018-05-09 14:48:50 +00:00
{
2020-04-10 10:11:56 +00:00
append = false;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
var @class = GetMembers(members, i);
i += @class.Count - 1;
for (int j = 1; j < @class.Count; j++)
{
ReadStringValue(sb, @class, reader, ref j);
}
break;
2018-05-09 14:48:50 +00:00
}
}
}
if (append)
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), varTypeStr, varNameStr, value);
if (align)
2018-12-02 18:42:07 +00:00
reader.AlignStream();
2018-05-09 14:48:50 +00:00
}
2019-04-18 02:46:06 +00:00
public static UType ReadUType(List<TypeTreeNode> members, BinaryReader reader)
{
2019-04-18 02:46:06 +00:00
var obj = new UType();
for (int i = 1; i < members.Count; i++)
{
var member = members[i];
2018-09-26 21:23:10 +00:00
var varNameStr = member.m_Name;
2018-11-18 22:48:06 +00:00
obj[varNameStr] = ReadValue(members, reader, ref i);
}
return obj;
}
2018-11-21 07:37:56 +00:00
private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
{
var member = members[i];
2018-09-26 21:23:10 +00:00
var varTypeStr = member.m_Type;
object value;
2018-09-26 21:23:10 +00:00
var align = (member.m_MetaFlag & 0x4000) != 0;
switch (varTypeStr)
{
case "SInt8":
value = reader.ReadSByte();
break;
case "UInt8":
2020-04-10 10:11:56 +00:00
case "char":
value = reader.ReadByte();
break;
case "short":
case "SInt16":
value = reader.ReadInt16();
break;
case "UInt16":
case "unsigned short":
value = reader.ReadUInt16();
break;
case "int":
case "SInt32":
value = reader.ReadInt32();
break;
case "UInt32":
case "unsigned int":
case "Type*":
value = reader.ReadUInt32();
break;
case "long long":
case "SInt64":
value = reader.ReadInt64();
break;
case "UInt64":
case "unsigned long long":
2020-04-10 10:11:56 +00:00
case "FileSize":
value = reader.ReadUInt64();
break;
case "float":
value = reader.ReadSingle();
break;
case "double":
value = reader.ReadDouble();
break;
case "bool":
value = reader.ReadBoolean();
break;
case "string":
value = reader.ReadAlignedString();
i += 3;
break;
case "map":
{
2018-09-26 21:23:10 +00:00
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
2020-04-10 10:11:56 +00:00
var map = GetMembers(members, i);
i += map.Count - 1;
var first = GetMembers(map, 4);
var next = 4 + first.Count;
var second = GetMembers(map, next);
var size = reader.ReadInt32();
var dic = new List<KeyValuePair<object, object>>(size);
for (int j = 0; j < size; j++)
{
int tmp1 = 0;
int tmp2 = 0;
dic.Add(new KeyValuePair<object, object>(ReadValue(first, reader, ref tmp1), ReadValue(second, reader, ref tmp2)));
}
value = dic;
break;
}
case "TypelessData":
{
var size = reader.ReadInt32();
value = reader.ReadBytes(size);
i += 2;
break;
}
default:
{
2020-04-10 10:11:56 +00:00
if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array
2018-06-20 14:48:44 +00:00
{
2019-04-18 02:46:06 +00:00
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
2020-04-10 10:11:56 +00:00
var vector = GetMembers(members, i);
i += vector.Count - 1;
2019-04-18 02:46:06 +00:00
var size = reader.ReadInt32();
var list = new List<object>(size);
for (int j = 0; j < size; j++)
{
2020-04-10 10:11:56 +00:00
int tmp = 3;
2019-04-18 02:46:06 +00:00
list.Add(ReadValue(vector, reader, ref tmp));
}
value = list;
break;
2018-06-20 14:48:44 +00:00
}
2019-04-18 02:46:06 +00:00
else //Class
{
2020-04-10 10:11:56 +00:00
var @class = GetMembers(members, i);
i += @class.Count - 1;
2019-04-18 02:46:06 +00:00
var obj = new UType();
2020-04-10 10:11:56 +00:00
for (int j = 1; j < @class.Count; j++)
2019-04-18 02:46:06 +00:00
{
var classmember = @class[j];
var name = classmember.m_Name;
obj[name] = ReadValue(@class, reader, ref j);
}
value = obj;
break;
}
}
}
if (align)
2018-12-02 18:42:07 +00:00
reader.AlignStream();
return value;
}
2020-04-10 10:11:56 +00:00
private static List<TypeTreeNode> GetMembers(List<TypeTreeNode> members, int index)
2018-05-09 14:48:50 +00:00
{
var member2 = new List<TypeTreeNode>();
2020-04-10 10:11:56 +00:00
member2.Add(members[index]);
var level = members[index].m_Level;
2018-05-09 14:48:50 +00:00
for (int i = index + 1; i < members.Count; i++)
{
var member = members[i];
var level2 = member.m_Level;
2018-05-09 14:48:50 +00:00
if (level2 <= level)
{
return member2;
}
member2.Add(member);
}
return member2;
}
}
}