This commit is contained in:
erik 2025-06-09 02:03:11 +02:00
parent 01151e679b
commit 57b2f0400e
265 changed files with 22828 additions and 6 deletions

View file

@ -0,0 +1,509 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Decal.Adapter.NetParser;
using Decal.Interop.Net;
namespace Decal.Adapter;
/// <summary>
/// Protocol Message Data
/// </summary>
public class Message : MessageStruct
{
private static Dictionary<int, MemberParser> mRecv;
private static Dictionary<int, MemberParser> mSend;
private static Dictionary<string, MemberParser> mTypes;
private int mType;
internal MessageStruct mStruct;
/// <summary>
/// Message Type
/// </summary>
public int Type => mType;
/// <summary>
/// Returns the number of fields (or vector length)
/// </summary>
public override int Count => mStruct.Count;
/// <summary>
/// Returns the specified field data
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Field value</returns>
public override object this[int index] => mStruct[index];
/// <summary>
/// Returns the specified field data
/// </summary>
/// <param name="name">Field name</param>
/// <returns>Field value</returns>
public override object this[string name] => mStruct[name];
/// <summary>
/// Returns the raw bytes for this field
/// </summary>
public override byte[] RawData => mStruct.RawData;
/// <summary>
/// Returns the next object in the (parent) vector
/// </summary>
public override object Next => mStruct.Next;
/// <summary>
/// Returns the parent field
/// </summary>
public override MessageStruct Parent => mStruct.Parent;
internal Message()
{
}
internal Message(IMessage2 msg, MessageDirection dir)
{
mType = BitConverter.ToInt32(msg.RawData, 0);
mStruct = new MessageStruct(msg.RawData, 4, GetParser(mType, dir));
}
internal Message(byte[] Data, MemberParser Parser)
{
mType = BitConverter.ToInt32(Data, 0);
mStruct = new MessageStruct(Data, 4, Parser);
}
internal Message(Message Source)
{
mType = Source.mType;
mStruct = Source.mStruct;
}
internal static MemberParser GetParser(int type, MessageDirection dir)
{
MemberParser result = null;
switch (dir)
{
case MessageDirection.Inbound:
if (mRecv.ContainsKey(type))
{
result = mRecv[type];
}
break;
case MessageDirection.Outbound:
if (mSend.ContainsKey(type))
{
result = mSend[type];
}
break;
}
return result;
}
/// <summary>
/// Return the field name for the specified index
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Name of the field</returns>
public override string Name(int index)
{
return mStruct.Name(index);
}
/// <summary>
/// Returns the passed in value?
/// </summary>
/// <param name="memberName"></param>
/// <returns></returns>
public override string Name(string memberName)
{
return mStruct.Name(memberName);
}
/// <summary>
/// Returns the specified child structure
/// </summary>
/// <param name="index">Field index</param>
/// <returns>MessageStruct for the specified field</returns>
public override MessageStruct Struct(int index)
{
return mStruct.Struct(index);
}
/// <summary>
/// Returns the specified child structure
/// </summary>
/// <param name="name">Field name</param>
/// <returns>MessageStruct for the specified field</returns>
public override MessageStruct Struct(string name)
{
return mStruct.Struct(name);
}
/// <summary>
/// Returns the specified field value
/// </summary>
/// <typeparam name="FieldType">Type of the field</typeparam>
/// <param name="index">Field index</param>
/// <returns>Field value cast to the specified FieldType</returns>
public override FieldType Value<FieldType>(int index)
{
return mStruct.Value<FieldType>(index);
}
/// <summary>
/// Returns the specified field value
/// </summary>
/// <typeparam name="FieldType">Type of the field</typeparam>
/// <param name="name">Field name</param>
/// <returns>Field value cast to the specified FieldType</returns>
public override FieldType Value<FieldType>(string name)
{
return mStruct.Value<FieldType>(name);
}
/// <summary>
/// Returns the raw bytes of the specified field
/// </summary>
/// <param name="index">Field index</param>
/// <returns>Raw field value</returns>
public override byte[] RawValue(int index)
{
return mStruct.RawValue(index);
}
/// <summary>
/// Returns the raw bytes of the specified field
/// </summary>
/// <param name="name">Field name</param>
/// <returns>Raw field value</returns>
public override byte[] RawValue(string name)
{
return mStruct.RawValue(name);
}
internal static void Initialize(string xmlFile)
{
mRecv = new Dictionary<int, MemberParser>();
mSend = new Dictionary<int, MemberParser>();
mTypes = new Dictionary<string, MemberParser>();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(xmlFile);
foreach (XmlNode item in xmlDocument.SelectNodes("/schema/datatypes/type"))
{
ParseType(item, xmlDocument);
}
foreach (XmlNode item2 in xmlDocument.SelectNodes("/schema/messages/message"))
{
ParseMessage(item2, xmlDocument);
}
}
private static void ParseType(XmlNode node, XmlDocument doc)
{
XmlAttribute xmlAttribute = node.Attributes["name"];
if (xmlAttribute == null)
{
return;
}
string value = xmlAttribute.Value;
if (mTypes.ContainsKey(value))
{
return;
}
MemberParser memberParser = new MemberParser();
mTypes.Add(value, memberParser);
xmlAttribute = node.Attributes["primitive"];
if (xmlAttribute != null && string.Compare(xmlAttribute.Value, "true", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
if (string.Compare(value, "BYTE", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.BYTE;
}
else if (string.Compare(value, "WORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.WORD;
}
else if (string.Compare(value, "PackedWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.PackedWORD;
}
else if (string.Compare(value, "DWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.DWORD;
}
else if (string.Compare(value, "PackedDWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.PackedDWORD;
}
else if (string.Compare(value, "QWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.QWORD;
}
else if (string.Compare(value, "float", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.@float;
}
else if (string.Compare(value, "double", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.@double;
}
else if (string.Compare(value, "String", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.String;
}
else if (string.Compare(value, "WString", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser.MemberType = MemberParserType.WString;
}
}
else
{
memberParser.MemberType = MemberParserType.Struct;
memberParser.Child = ParseStruct(node.ChildNodes, doc);
}
}
private static void ParseMessage(XmlNode node, XmlDocument doc)
{
XmlAttribute xmlAttribute = node.Attributes["type"];
if (xmlAttribute == null)
{
return;
}
string text = xmlAttribute.Value;
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
{
text = text.Substring(2);
}
int key = int.Parse(text, NumberStyles.HexNumber);
bool flag = true;
bool flag2 = false;
xmlAttribute = node.Attributes["direction"];
if (xmlAttribute != null)
{
if (string.Compare(xmlAttribute.Value, "outbound", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
flag = false;
flag2 = true;
}
else if (string.Compare(xmlAttribute.Value, "both", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
flag2 = true;
}
}
if ((flag && !mRecv.ContainsKey(key)) || (flag2 && !mSend.ContainsKey(key)))
{
MemberParser value = ParseStruct(node.ChildNodes, doc);
if (flag && !mRecv.ContainsKey(key))
{
mRecv.Add(key, value);
}
if (flag2 && !mSend.ContainsKey(key))
{
mSend.Add(key, value);
}
}
}
private static MemberParser ParseStruct(XmlNodeList nodes, XmlDocument doc)
{
MemberParser memberParser = new MemberParser();
MemberParser memberParser2 = memberParser;
int count = nodes.Count;
for (int i = 0; i < count; i++)
{
XmlNode xmlNode = nodes[i];
if (xmlNode.NodeType != XmlNodeType.Element)
{
continue;
}
string name = xmlNode.Name;
if (string.Compare(name, "field", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
XmlAttribute xmlAttribute = xmlNode.Attributes["type"];
if (xmlAttribute != null)
{
string value = xmlAttribute.Value;
if (!mTypes.ContainsKey(value))
{
ParseType(doc.SelectSingleNode("/schema/datatypes/type[@name='" + value + "']"), doc);
}
memberParser2.Next = new MemberParser(mTypes[value]);
memberParser2 = memberParser2.Next;
memberParser2.MemberName = xmlNode.Attributes["name"].Value;
}
}
else if (string.Compare(name, "maskmap", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
XmlAttribute xmlAttribute = xmlNode.Attributes["xor"];
long conditionXor = 0L;
string value;
if (xmlAttribute != null)
{
value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
conditionXor = long.Parse(value, NumberStyles.HexNumber);
}
value = xmlNode.Attributes["name"].Value;
memberParser2.Next = ParseMaskMap(xmlNode.ChildNodes, doc);
while (memberParser2.Next != null)
{
memberParser2 = memberParser2.Next;
memberParser2.Condition = MemberParserCondition.NE;
memberParser2.ConditionResult = 0L;
memberParser2.ConditionField = value;
memberParser2.ConditionXor = conditionXor;
}
}
else if (string.Compare(name, "switch", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
string value = xmlNode.Attributes["name"].Value;
XmlAttribute xmlAttribute = xmlNode.Attributes["mask"];
long conditionXor = -1L;
if (xmlAttribute != null)
{
value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
conditionXor = long.Parse(value, NumberStyles.HexNumber);
}
memberParser2.Next = ParseSwitch(xmlNode.ChildNodes, doc);
while (memberParser2.Next != null)
{
memberParser2 = memberParser2.Next;
memberParser2.Condition = MemberParserCondition.EQ;
memberParser2.ConditionField = value;
memberParser2.ConditionAnd = conditionXor;
}
}
else if (string.Compare(name, "vector", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.Next = new MemberParser();
memberParser2 = memberParser2.Next;
memberParser2.MemberType = MemberParserType.Vector;
memberParser2.MemberName = xmlNode.Attributes["name"].Value;
memberParser2.LengthField = xmlNode.Attributes["length"].Value;
XmlAttribute xmlAttribute = xmlNode.Attributes["mask"];
long conditionXor = -1L;
if (xmlAttribute != null)
{
string value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
conditionXor = long.Parse(value, NumberStyles.HexNumber);
}
memberParser2.LengthMask = conditionXor;
xmlAttribute = xmlNode.Attributes["skip"];
int num = 0;
if (xmlAttribute != null)
{
string value = xmlAttribute.Value;
if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'))
{
value = value.Substring(2);
}
num = int.Parse(value, NumberStyles.HexNumber);
}
memberParser2.LengthDelta = -num;
memberParser2.Child = ParseStruct(xmlNode.ChildNodes, doc);
}
else if (string.Compare(name, "align", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
string value = xmlNode.Attributes["type"].Value;
if (string.Compare(value, "WORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.PostAlignment = 2;
}
else if (string.Compare(value, "DWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.PostAlignment = 4;
}
else if (string.Compare(value, "QWORD", ignoreCase: true, CultureInfo.InvariantCulture) == 0)
{
memberParser2.PostAlignment = 8;
}
}
}
if (memberParser.PostAlignment != 0 && memberParser.Next != null)
{
memberParser.Next.PreAlignment = memberParser.PostAlignment;
}
return memberParser.Next;
}
private static MemberParser ParseMaskMap(XmlNodeList nodes, XmlDocument doc)
{
MemberParser memberParser = new MemberParser();
MemberParser memberParser2 = memberParser;
int count = nodes.Count;
for (int i = 0; i < count; i++)
{
XmlNode xmlNode = nodes[i];
if (xmlNode.NodeType != XmlNodeType.Element || string.Compare(xmlNode.Name, "mask", ignoreCase: true, CultureInfo.InvariantCulture) != 0)
{
continue;
}
long conditionAnd = 0L;
XmlAttribute xmlAttribute = xmlNode.Attributes["value"];
if (xmlAttribute != null)
{
string text = xmlAttribute.Value;
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
{
text = text.Substring(2);
}
conditionAnd = long.Parse(text, NumberStyles.HexNumber);
}
memberParser2.Next = new MemberParser();
memberParser2 = memberParser2.Next;
memberParser2.MemberType = MemberParserType.Case;
memberParser2.ConditionAnd = conditionAnd;
memberParser2.Child = ParseStruct(xmlNode.ChildNodes, doc);
}
return memberParser.Next;
}
private static MemberParser ParseSwitch(XmlNodeList nodes, XmlDocument doc)
{
MemberParser memberParser = new MemberParser();
MemberParser memberParser2 = memberParser;
int count = nodes.Count;
for (int i = 0; i < count; i++)
{
XmlNode xmlNode = nodes[i];
if (xmlNode.NodeType != XmlNodeType.Element || string.Compare(xmlNode.Name, "case", ignoreCase: true, CultureInfo.InvariantCulture) != 0)
{
continue;
}
long conditionResult = 0L;
XmlAttribute xmlAttribute = xmlNode.Attributes["value"];
if (xmlAttribute != null)
{
string text = xmlAttribute.Value;
if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X'))
{
text = text.Substring(2);
}
conditionResult = long.Parse(text, NumberStyles.HexNumber);
}
memberParser2.Next = new MemberParser();
memberParser2 = memberParser2.Next;
memberParser2.MemberType = MemberParserType.Case;
memberParser2.ConditionResult = conditionResult;
memberParser2.Child = ParseStruct(xmlNode.ChildNodes, doc);
}
return memberParser.Next;
}
}