Example #1
0
        public IEnumerable <BaseNode> GetEquivalentNodes(int size)
        {
            while (size != 0)
            {
                BaseNode paddingNode;
#if RECLASSNET64
                if (size >= 8)
                {
                    paddingNode = new Hex64Node();
                }
                else
#endif
                if (size >= 4)
                {
                    paddingNode = new Hex32Node();
                }
                else if (size >= 2)
                {
                    paddingNode = new Hex16Node();
                }
                else
                {
                    paddingNode = new Hex8Node();
                }

                paddingNode.Comment = Comment;

                size -= paddingNode.MemorySize;

                yield return(paddingNode);
            }
        }
Example #2
0
        private IEnumerable <BaseNode> ReadNodeElements(IEnumerable <XElement> elements, ClassNode parent, IReadOnlyDictionary <string, ClassNode> classes, Type[] typeMap, ILogger logger)
        {
            Contract.Requires(elements != null);
            Contract.Requires(parent != null);
            Contract.Requires(classes != null);
            Contract.Requires(typeMap != null);
            Contract.Requires(logger != null);

            foreach (var element in elements)
            {
                Type nodeType = null;

                if (int.TryParse(element.Attribute("Type")?.Value, out var typeVal))
                {
                    if (typeVal >= 0 && typeVal < typeMap.Length)
                    {
                        nodeType = typeMap[typeVal];
                    }
                }

                if (nodeType == null)
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute("Type")?.Value}");
                    logger.Log(LogLevel.Warning, element.ToString());

                    continue;
                }

                var node = Activator.CreateInstance(nodeType) as BaseNode;
                if (node == null)
                {
                    logger.Log(LogLevel.Error, $"Could not create node of type: {nodeType}");

                    continue;
                }

                node.Name    = element.Attribute("Name")?.Value ?? string.Empty;
                node.Comment = element.Attribute("Comment")?.Value ?? string.Empty;

                // Convert the Custom node into normal hex nodes.
                if (node is CustomNode)
                {
                    int.TryParse(element.Attribute("Size")?.Value, out var size);

                    while (size != 0)
                    {
                        BaseNode paddingNode;
#if RECLASSNET64
                        if (size >= 8)
                        {
                            paddingNode = new Hex64Node();
                        }
                        else
#endif
                        if (size >= 4)
                        {
                            paddingNode = new Hex32Node();
                        }
                        else if (size >= 2)
                        {
                            paddingNode = new Hex16Node();
                        }
                        else
                        {
                            paddingNode = new Hex8Node();
                        }

                        paddingNode.Comment = node.Comment;

                        size -= paddingNode.MemorySize;

                        yield return(paddingNode);
                    }

                    continue;
                }

                if (node is BaseReferenceNode referenceNode)
                {
                    string reference;
                    if (referenceNode is ClassInstanceArrayNode)
                    {
                        reference = element.Element("Array")?.Attribute("Name")?.Value;
                    }
                    else
                    {
                        reference = element.Attribute("Pointer")?.Value ?? element.Attribute("Instance")?.Value;
                    }

                    if (reference == null || !classes.ContainsKey(reference))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {reference}");
                        logger.Log(LogLevel.Warning, element.ToString());

                        continue;
                    }

                    var innerClassNode = classes[reference];
                    if (referenceNode.PerformCycleCheck && !ClassUtil.IsCycleFree(parent, innerClassNode, project.Classes))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with cycle reference: {parent.Name}->{node.Name}");

                        continue;
                    }

                    referenceNode.ChangeInnerNode(innerClassNode);
                }

                switch (node)
                {
                case VTableNode vtableNode:
                    element
                    .Elements("Function")
                    .Select(e => new VMethodNode
                    {
                        Name    = e.Attribute("Name")?.Value ?? string.Empty,
                        Comment = e.Attribute("Comment")?.Value ?? string.Empty
                    })
                    .ForEach(vtableNode.AddNode);
                    break;

                case ClassInstanceArrayNode classInstanceArrayNode:
                {
                    TryGetAttributeValue(element, "Total", out var count, logger);
                    classInstanceArrayNode.Count = count;
                    break;
                }

                case ClassPtrArrayNode classPtrArrayNode:
                {
                    TryGetAttributeValue(element, "Size", out var count, logger);
                    classPtrArrayNode.Count = count / IntPtr.Size;
                    break;
                }

                case BaseTextNode textNode:
                {
                    TryGetAttributeValue(element, "Size", out var length, logger);
                    textNode.Length = textNode is Utf16TextNode ? length / 2 : length;
                    break;
                }

                case BitFieldNode bitFieldNode:
                {
                    TryGetAttributeValue(element, "Size", out var bits, logger);
                    bitFieldNode.Bits = bits * 8;
                    break;
                }
                }

                yield return(node);
            }
        }