Example #1
0
        private bool ValidateBlamPointer(BlamPointer blamPointer, ElementArray info, MapStream stream)
        {
            var stringWriter = new StringWriter();

            if (blamPointer.Count == 0 && blamPointer.Address == 0)
            {
                return(true);
            }
            if (blamPointer.Count == 0 ^ blamPointer.Address == 0)
            {
                stringWriter.WriteLine(string.Format("-> null-value count({0}) address({1}) is invalid", blamPointer.Count, blamPointer.Address));
            }
            if (blamPointer.Count < 0)
            {
                stringWriter.WriteLine(string.Format("-> count({0}) is invalid", blamPointer.Count));
            }
            if (blamPointer.Count > info.MaxElementCount && info.MaxElementCount > 0)
            {
                stringWriter.WriteLine(string.Format("-> count({0}) > max-count({1})", blamPointer.Count, info.MaxElementCount));
            }
            if (!stream.ContainsPointer(blamPointer))
            {
                stringWriter.WriteLine(string.Format("-> address({0}) not contained in stream({1})", blamPointer.Address, stream.Name));
            }

            var errors = stringWriter.ToString();

            if (!string.IsNullOrWhiteSpace(errors))
            {
                OnWriteMessage(string.Format("Pointer ({0})\n{1}", info.Name, errors));
                return(false);
            }
            return(true);
        }
Example #2
0
        private void ValidateChildren(ElementArray elementArray, BinaryReader binaryReader, ref int nextAddress)
        {
            var childrenArrayPointers = (from child in elementArray.Children
                                         select new
            {
                ElementArray = child,
                ArrayPointer = new Func <BlamPointer>(() =>
                {
                    using (binaryReader.BaseStream.Pin())
                    {
                        binaryReader.BaseStream.Seek(child.Address, SeekOrigin.Current);
                        var arrayPointer = binaryReader.ReadBlamPointer(child.ElementSize);
                        child.VirtualAddress = arrayPointer.Address;
                        child.Count = arrayPointer.Count;
                        return(arrayPointer);
                    }
                })()
            }).ToList();

            foreach (var child in childrenArrayPointers)
            {
                if (!ValidateBlamPointer(child.ArrayPointer, child.ElementArray, binaryReader.BaseStream as MapStream))
                {
                    continue;
                }
                if (!(child.ArrayPointer.Count == 0 && child.ArrayPointer.Address == 0))
                {
                    ValidateTagBlock(child.ElementArray, child.ArrayPointer, binaryReader, ref nextAddress);
                }
            }
        }
Example #3
0
 public void Append(ElementArray array)
 {
     Name        = string.Format("{0}:{1}", this.Name, array.Name);
     ElementSize = ElementSize + array.ElementSize;
     Alignment   = array.Alignment > this.Alignment ? array.Alignment : this.Alignment;
     Children.AddRange(array.Children);
 }
Example #4
0
 public void Append(ElementArray array)
 {
     name        = string.Format("{0}:{1}", name, array.name);
     elementSize = elementSize + array.elementSize;
     alignment   = array.alignment > alignment ? array.alignment : alignment;
     children.AddRange(array.children);
 }
Example #5
0
        private ElementArray ProcessTagBlockDefinition(ElementArray parent, MoonfishTagDefinition tagBlock,
                                                       ref int offset, bool inline = false)
        {
            var size = tagBlock.CalculateSizeOfFieldSet();

            var blockElementArray = new ElementArray
            {
                name            = tagBlock.Name,
                elementSize     = size,
                address         = offset,
                parent          = parent,
                maxElementCount = tagBlock.MaximumElementCount,
                alignment       = tagBlock.Alignment
            };

            var i           = 0;
            var blockOffset = inline ? offset : 0;

            ProcessFields(tagBlock.Fields, blockElementArray, ref i, ref blockOffset);
            if (inline)
            {
                offset = blockOffset;
            }
            return(blockElementArray);
        }
Example #6
0
        private void ValidateTagBlock(ElementArray info, BlamPointer pointer, BinaryReader reader, ref int address)
        {
            using (reader.BaseStream.Pin())
            {
                // If owned by tag and memory has not been allocated yet*
                var allocated = from item in PointersList
                                where item.Item1.Equals(pointer)
                                select item;
                var partiallyAllocated = from item in PointersList
                                         where item.Item1.Intersects(pointer)
                                         select item;
                if (OwnedByTag(pointer))
                {
                    if (!allocated.Any())
                    {
                        var alignedAddress = (address - startOffset) + Padding.GetCount(address - startOffset, info.Alignment);
                        if (pointer.Address - startOffset != alignedAddress)
                        {
                            MapStream mapStream = reader.BaseStream as MapStream;
                            if (mapStream != null)
                            {
                                OnWriteMessage(string.Format("{2}: Expected address \"{0}\"  - actually was \"{1}\"", address - startOffset, pointer.Address - startOffset, info.Name));
                            }
                        }
                        address = pointer.Address + pointer.PointedSize;
                    }
                    if (allocated.Any())
                    {
                    }
                    else if (partiallyAllocated.Any())
                    {
                        foreach (var overlappingItem in partiallyAllocated)
                        {
                            var overlap = pointer.Address - overlappingItem.Item1.Address - overlappingItem.Item1.PointedSize;
                            OnWriteMessage(string.Format("Overlap of ({0})[{3}] with ({1}) by ({2}) bytes", overlappingItem.Item2.ToHierarchyString(), info.ToHierarchyString(), overlap, overlappingItem.Item1.Count));
                        }
                    }
                }
                else if (!IsValid(pointer))
                {
                    OnWriteMessage(string.Format("INVALID POINTER"));
                    return;
                }
                else
                {
                    OnWriteMessage(string.Format("WILLLLLSOOON SHARE"));
                }

                PointersList.Add(new Tuple <BlamPointer, ElementArray>(pointer, info));

                foreach (var elementAddress in pointer)
                {
                    reader.BaseStream.Position = elementAddress;
                    ValidateChildren(info, reader, ref address);
                }
            }
        }
Example #7
0
        private void ProcessFields(IList <MoonfishTagField> fields, ElementArray elementArray, ref int i, ref int offset)
        {
            for (; i < fields.Count; ++i)
            {
                var field = fields[i];
                // Check the field type.
                switch (field.Type)
                {
                case MoonfishFieldType.FieldBlock:
                {
                    var childElementArray = ProcessTagBlockDefinition(elementArray, field.Definition, ref offset);
                    elementArray.children.Add(childElementArray);
                    break;
                }

                case MoonfishFieldType.FieldStruct:
                {
                    var struct_definition = (MoonfishTagStruct)field.Definition;
                    var structOffset      = offset;
                    var childElementArray = ProcessTagStructDefinition(elementArray, struct_definition.Definition,
                                                                       ref structOffset);
                    elementArray.children.AddRange(childElementArray);

                    break;
                }

                case MoonfishFieldType.FieldData:
                {
                    var data_definition   = (MoonfishTagDataDefinition)field.Definition;
                    var childElementArray = new ElementArray
                    {
                        elementSize = ((MoonfishTagDataDefinition)field.Definition).DataElementSize,
                        name        = data_definition.Name,
                        address     = offset,
                        parent      = elementArray,
                        alignment   = data_definition.Alignment
                    };
                    elementArray.children.Add(childElementArray);
                    break;
                }

                case MoonfishFieldType.FieldArrayStart:
                {
                    ProcessArrayFields(fields, elementArray, field, ref i, ref offset);
                    break;
                }

                case MoonfishFieldType.FieldArrayEnd:
                {
                    return;
                }
                }
                offset += MoonfishTagDefinition.CalculateSizeOfField(field);
            }
        }
Example #8
0
 public ElementArray()
 {
     name            = default(string);
     elementSize     = default(int);
     maxElementCount = default(int);
     count           = default(int);
     address         = -1;
     alignment       = 4;
     children        = new List <ElementArray>();
     parent          = null;
 }
Example #9
0
 public ElementArray()
 {
     Name            = default(string);
     ElementSize     = default(int);
     MaxElementCount = default(int);
     Count           = default(int);
     Address         = -1;
     Alignment       = 4;
     Children        = new List <ElementArray>();
     Parent          = null;
 }
Example #10
0
        private void ProcessArrayFields(IList <tag_field> fields, ElementArray elementArray, ref tag_field field, ref int i, ref int offset)
        {
            var name = field.Name;

            ++i;    //move past field_type._field_array_start
            for (int index = 0; index < field.definition; ++index)
            {
                int startindex = i;
                ProcessFields(fields, elementArray, ref startindex, ref offset);
            }
            ++i;    // move past field_type._field_array_end
        }
Example #11
0
        private void ProcessArrayFields(IList <MoonfishTagField> fields, ElementArray elementArray,
                                        MoonfishTagField field, ref int i, ref int offset)
        {
            var name = field.Strings;

            ++i; //move past field_type._field_array_start
            for (var index = 0; index < field.Count; ++index)
            {
                var startindex = i;
                ProcessFields(fields, elementArray, ref startindex, ref offset);
            }
            ++i; // move past field_type._field_array_end
        }
Example #12
0
        private void ProcessFields(IList <tag_field> fields, ElementArray elementArray, ref int i, ref int offset)
        {
            for (; i < fields.Count; ++i)
            {
                var field = fields[i];
                // Check the field type.
                switch (field.type)
                {
                case field_type._field_block:
                {
                    var childElementArray = ProcessTagBlockDefinition(elementArray, field.Definition, ref offset);
                    elementArray.Children.Add(childElementArray);
                    break;
                }

                case field_type._field_struct:
                {
                    var struct_definition = (tag_struct_definition)field.Definition;
                    var structOffset      = offset;
                    var childElementArray = ProcessTagStructDefinition(elementArray, struct_definition.Definition, ref structOffset);
                    elementArray.Children.AddRange(childElementArray);

                    break;
                }

                case field_type._field_data:
                {
                    var data_definition   = (tag_data_definition)field.Definition;
                    var childElementArray = new ElementArray()
                    {
                        ElementSize = 1, Name = data_definition.Name, Address = offset, Parent = elementArray, Alignment = data_definition.Alignment
                    };
                    elementArray.Children.Add(childElementArray);
                    break;
                }

                case field_type._field_array_start:
                {
                    ProcessArrayFields(fields, elementArray, ref field, ref i, ref offset);
                    break;
                }

                case field_type._field_array_end:
                {
                    return;
                }
                }
                offset += Guerilla.CalculateSizeOfField(field);
            }
        }
Example #13
0
        private IEnumerable <ElementArray> ProcessTagStructDefinition(ElementArray parent, TagBlockDefinition definition, ref int offset)
        {
            var size = Guerilla.CalculateSizeOfFieldSet(definition.LatestFieldSet.Fields);

            var blockElementArray = new ElementArray()
            {
                Name            = definition.Name,
                ElementSize     = size,
                Address         = offset,
                Parent          = parent,
                MaxElementCount = definition.maximum_element_count,
                Alignment       = definition.LatestFieldSet.Alignment,
            };

            var i = 0;

            ProcessFields(definition.LatestFieldSet.Fields, blockElementArray, ref i, ref offset);
            return(blockElementArray.Children);
        }
Example #14
0
        private IEnumerable <ElementArray> ProcessTagStructDefinition(ElementArray parent,
                                                                      MoonfishTagDefinition definition, ref int offset)
        {
            var size = definition.CalculateSizeOfFieldSet();

            var blockElementArray = new ElementArray
            {
                name            = definition.Name,
                elementSize     = size,
                address         = offset,
                parent          = parent,
                maxElementCount = definition.MaximumElementCount,
                alignment       = definition.Alignment
            };

            var i = 0;

            ProcessFields(definition.Fields, blockElementArray, ref i, ref offset);
            return(blockElementArray.children);
        }
Example #15
0
        private ElementArray ProcessTagBlockDefinition(ElementArray parent, TagBlockDefinition tagBlock, ref int offset, bool inline = false, string group_tag = "")
        {
            var size = Guerilla.CalculateSizeOfFieldSet(tagBlock.LatestFieldSet.Fields);

            var blockElementArray = new ElementArray()
            {
                Name            = tagBlock.Name,
                ElementSize     = size,
                Address         = offset,
                Parent          = parent,
                MaxElementCount = tagBlock.maximum_element_count,
                Alignment       = tagBlock.LatestFieldSet.Alignment,
            };

            var i           = 0;
            int blockOffset = inline ? offset : 0;

            ProcessFields(tagBlock.LatestFieldSet.Fields, blockElementArray, ref i, ref blockOffset);
            if (inline)
            {
                offset = blockOffset;
            }
            return(blockElementArray);
        }
 private void ProcessArrayFields(IList<tag_field> fields, ElementArray elementArray, ref tag_field field, ref int i, ref int offset)
 {
     var name = field.Name;
     ++i;    //move past field_type._field_array_start
     for (int index = 0; index < field.definition; ++index)
     {
         int startindex = i;
         ProcessFields(fields, elementArray, ref startindex, ref offset);
     }
     ++i;    // move past field_type._field_array_end
 }
Example #17
0
        private void ValidateTagBlock(ElementArray info, BlamPointer pointer, BinaryReader reader, ref int address)
        {
            using (reader.BaseStream.Pin())
            {
                // If owned by tag and memory has not been allocated yet*
                var allocated = from item in _pointersList
                                where item.Item1.Equals(pointer)
                                select item;
                var partiallyAllocated = from item in _pointersList
                                         where item.Item1.Intersects(pointer)
                                         select item;
                if (IsOwnedByTag(pointer))
                {
                    var enumerable = allocated as IList <Tuple <BlamPointer, ElementArray> > ?? allocated.ToList();
                    if (!enumerable.Any())
                    {
                        var alignedAddress = (address) +
                                             Padding.GetCount(address, info.alignment);
                        if (pointer.StartAddress != alignedAddress)
                        {
                            var mapStream = reader.BaseStream as CacheStream;
                            if (mapStream != null)
                            {
                                error = true;
                                OnWriteMessage(string.Format("{2}: Expected address \"{0}\"  - actually was \"{1}\" delta \"{3}\"",
                                                             (uint)alignedAddress, (uint)pointer.StartAddress, info.name, alignedAddress - pointer.StartAddress));
                            }
                        }
                        address = pointer.StartAddress + pointer.PointedSize;
                    }
                    if (enumerable.Any())
                    {
                    }
                    else
                    {
                        var overlappingItems = partiallyAllocated as IList <Tuple <BlamPointer, ElementArray> > ??
                                               partiallyAllocated.ToList();
                        if (overlappingItems.Any())
                        {
                            foreach (var overlappingItem in overlappingItems)
                            {
                                error = true;
                                var overlap = pointer.StartAddress - overlappingItem.Item1.StartAddress -
                                              overlappingItem.Item1.PointedSize;

                                OnWriteMessage(
                                    string.Format(
                                        "Overlap of ({0})\n{3} elements sized '{5}' at '{4}'\nwith ({1})\n{6} elements sized '{8}' at '{7}'\nby ({2}) bytes",
                                        overlappingItem.Item2.ToHierarchyString(), info.ToHierarchyString(), overlap,
                                        overlappingItem.Item1.ElementCount, overlappingItem.Item1.StartAddress,
                                        overlappingItem.Item1.ElementSize,
                                        pointer.ElementCount, pointer.StartAddress, pointer.ElementSize));
                            }
                        }
                    }
                }
                else if (!IsValid(pointer))
                {
                    //error = true;
                    //OnWriteMessage(string.Format("INVALID POINTER {1} -> {0}", info.name, pointer));
                    return;
                }
                else
                {
                    // OnWriteMessage( string.Format( "EXTERNAL SHARE" ) );
                }

                _pointersList.Add(new Tuple <BlamPointer, ElementArray>(pointer, info));

                foreach (var elementAddress in pointer)
                {
                    reader.BaseStream.Position = elementAddress;
                    ValidateChildren(info, reader, ref address);
                }
            }
        }
 private void ValidateChildren(ElementArray elementArray, BinaryReader binaryReader, ref int nextAddress)
 {
     var childrenArrayPointers = (from child in elementArray.Children
                                  select new
                                  {
                                      ElementArray = child,
                                      ArrayPointer = new Func<BlamPointer>(() =>
                                      {
                                          using (binaryReader.BaseStream.Pin())
                                          {
                                              binaryReader.BaseStream.Seek(child.Address, SeekOrigin.Current);
                                              var arrayPointer = binaryReader.ReadBlamPointer(child.ElementSize);
                                              child.VirtualAddress = arrayPointer.Address;
                                              child.Count = arrayPointer.Count;
                                              return arrayPointer;
                                          }
                                      })()
                                  }).ToList();
     foreach (var child in childrenArrayPointers)
     {
         if (!ValidateBlamPointer(child.ArrayPointer, child.ElementArray, binaryReader.BaseStream as MapStream))
             continue;
         if (!(child.ArrayPointer.Count == 0 && child.ArrayPointer.Address == 0))
         {
             ValidateTagBlock(child.ElementArray, child.ArrayPointer, binaryReader, ref nextAddress);
         }
     }
 }
        private void ValidateTagBlock(ElementArray info, BlamPointer pointer, BinaryReader reader, ref int address)
        {

            using (reader.BaseStream.Pin())
            {
                // If owned by tag and memory has not been allocated yet*
                var allocated = from item in PointersList
                                where item.Item1.Equals(pointer)
                                select item;
                var partiallyAllocated = from item in PointersList
                                         where item.Item1.Intersects(pointer)
                                         select item;
                if (OwnedByTag(pointer))
                {
                    if (!allocated.Any())
                    {
                        var alignedAddress = (address - startOffset) + Padding.GetCount(address - startOffset, info.Alignment);
                        if (pointer.Address - startOffset != alignedAddress)
                        {
                            MapStream mapStream = reader.BaseStream as MapStream;
                            if (mapStream != null)
                            {
                                OnWriteMessage(string.Format("{2}: Expected address \"{0}\"  - actually was \"{1}\"", address - startOffset, pointer.Address - startOffset, info.Name));
                            }
                        }
                        address = pointer.Address + pointer.PointedSize;
                    }
                    if (allocated.Any()) { }
                    else if (partiallyAllocated.Any())
                    {
                        foreach (var overlappingItem in partiallyAllocated)
                        {
                            var overlap = pointer.Address - overlappingItem.Item1.Address - overlappingItem.Item1.PointedSize;
                            OnWriteMessage(string.Format("Overlap of ({0})[{3}] with ({1}) by ({2}) bytes", overlappingItem.Item2.ToHierarchyString(), info.ToHierarchyString(), overlap, overlappingItem.Item1.Count));
                        }
                    }
                }
                else if (!IsValid(pointer))
                {
                    OnWriteMessage(string.Format("INVALID POINTER"));
                    return;
                }
                else
                    OnWriteMessage(string.Format("WILLLLLSOOON SHARE"));

                PointersList.Add(new Tuple<BlamPointer, ElementArray>(pointer, info));

                foreach (var elementAddress in pointer)
                {
                    reader.BaseStream.Position = elementAddress;
                    ValidateChildren(info, reader, ref address);
                }
            }
        }
Example #20
0
        public string Validate(tag_group validateTag, IEnumerable <tag_group> tagPool)
        {
            PointersList = new List <Tuple <BlamPointer, ElementArray> >();
            StreamWriter stringWriter = File.CreateText(string.Format(@"C:\Users\stem\Documents\h2pc to h2xbox\analysis\{0}.txt", validateTag.Class.ToSafeString()));

            WriteMessage = new Log(stringWriter.WriteLine);

            int          offset       = 0;
            ElementArray elementArray = null;

            if (validateTag.ParentClass != TagClass.Null)
            {
                var parentClass = tagPool.Where(x => x.Class == validateTag.ParentClass).Single();
                if (parentClass.ParentClass != TagClass.Null)
                {
                    var baseClass = tagPool.Where(x => x.Class == parentClass.ParentClass).Single();
                    elementArray = ProcessTagBlockDefinition(baseClass.Definition, ref offset, true);
                    elementArray.Append(ProcessTagBlockDefinition(parentClass.Definition, ref offset, true));
                    elementArray.Append(ProcessTagBlockDefinition(validateTag.Definition, ref offset, true));
                }
                else
                {
                    elementArray = ProcessTagBlockDefinition(parentClass.Definition, ref offset, true);
                    elementArray.Append(ProcessTagBlockDefinition(validateTag.Definition, ref offset, true));
                }
            }
            else
            {
                elementArray = ProcessTagBlockDefinition(validateTag.Definition, ref offset, true);
            }

            elementArray.Count = 1;

            var mapFiles = Directory.GetFiles(@"C:\Users\stem\Documents\modding\singleplayer", "*.map", SearchOption.TopDirectoryOnly)
                           .Concat(Directory.GetFiles(@"C:\Users\stem\Documents\modding\multiplayer", "*.map", SearchOption.TopDirectoryOnly))
                           .Concat(Directory.GetFiles(@"C:\Users\stem\Documents\modding\resource", "*.map", SearchOption.TopDirectoryOnly));

            foreach (var file in mapFiles)
            {
                using (var map = new MapStream(file))
                {
                    var binaryReader = new BinaryReader(map);

                    OnWriteMessage(string.Format("Begin ({0})", map.MapName));

                    foreach (var tag in map.Tags)
                    {
                        if (!(tag.Type == validateTag.Class))
                        {
                            continue;
                        }
                        else
                        {
                            VirtualMappedAddress metaTableMemory = new VirtualMappedAddress()
                            {
                                Address = map.Tags[0].VirtualAddress, Length = map.TagCacheLength
                            };
                            isValidDelegate = new Func <BlamPointer, bool>(metaTableMemory.Contains);
                            VirtualMappedAddress virtualTagMemory = new VirtualMappedAddress()
                            {
                                Address = tag.VirtualAddress, Length = tag.Length
                            };
                            IsPointerOwnedByTagDelegate = new Func <BlamPointer, bool>(virtualTagMemory.Contains);
                            OnWriteMessage(string.Format("Tag ({0})", tag.Path));
                            map[tag.Identifier].Seek();
                            offset = (int)map.Position;
                            elementArray.VirtualAddress = map[tag.Identifier].Meta.VirtualAddress;
                            PointersList = new List <Tuple <BlamPointer, ElementArray> >();
                            ValidateTagBlock(elementArray, elementArray.ToFixedArrayPointer(), binaryReader, ref offset);
                            AnalyzePointers(PointersList);
                            stringWriter.Flush();
                        }
                    }
                    Console.WriteLine(string.Format("Parsed ({0})", map.MapName));
                    //OnWriteMessage(string.Format("End ({0})", map.MapName));
                }
            }
            stringWriter.Close();
            return("");
        }
        private bool ValidateBlamPointer(BlamPointer blamPointer, ElementArray info, MapStream stream)
        {
            var stringWriter = new StringWriter();
            if (blamPointer.Count == 0 && blamPointer.Address == 0) return true;
            if (blamPointer.Count == 0 ^ blamPointer.Address == 0)
                stringWriter.WriteLine(string.Format("-> null-value count({0}) address({1}) is invalid", blamPointer.Count, blamPointer.Address));
            if (blamPointer.Count < 0)
                stringWriter.WriteLine(string.Format("-> count({0}) is invalid", blamPointer.Count));
            if (blamPointer.Count > info.MaxElementCount && info.MaxElementCount > 0)
                stringWriter.WriteLine(string.Format("-> count({0}) > max-count({1})", blamPointer.Count, info.MaxElementCount));
            if (!stream.ContainsPointer(blamPointer))
                stringWriter.WriteLine(string.Format("-> address({0}) not contained in stream({1})", blamPointer.Address, stream.Name));

            var errors = stringWriter.ToString();
            if (!string.IsNullOrWhiteSpace(errors))
            {
                OnWriteMessage(string.Format("Pointer ({0})\n{1}", info.Name, errors));
                return false;
            }
            return true;
        }
 public ElementArray()
 {
     Name = default(string);
     ElementSize = default(int);
     MaxElementCount = default(int);
     Count = default(int);
     Address = -1;
     Alignment = 4;
     Children = new List<ElementArray>();
     Parent = null;
 }
 public void Append(ElementArray array)
 {
     Name = string.Format("{0}:{1}", this.Name, array.Name);
     ElementSize = ElementSize + array.ElementSize;
     Alignment = array.Alignment > this.Alignment ? array.Alignment : this.Alignment;
     Children.AddRange(array.Children);
 }
        private ElementArray ProcessTagBlockDefinition(ElementArray parent, tag_block_definition tagBlock, ref int offset, bool inline = false, string group_tag = "")
        {

            var size = Guerilla.CalculateSizeOfFieldSet(tagBlock.LatestFieldSet.Fields);

            var blockElementArray = new ElementArray()
            {
                Name = tagBlock.Name,
                ElementSize = size,
                Address = offset,
                Parent = parent,
                MaxElementCount = tagBlock.maximum_element_count,
                Alignment = tagBlock.LatestFieldSet.Alignment,
            };

            var i = 0;
            int blockOffset = inline ? offset : 0;
            ProcessFields(tagBlock.LatestFieldSet.Fields, blockElementArray, ref i, ref blockOffset);
            if (inline) offset = blockOffset;
            return blockElementArray;
        }
        private void ProcessFields(IList<tag_field> fields, ElementArray elementArray, ref int i, ref int offset)
        {
            for (; i < fields.Count; ++i)
            {
                var field = fields[i];
                // Check the field type.
                switch (field.type)
                {
                    case field_type._field_block:
                        {
                            var childElementArray = ProcessTagBlockDefinition(elementArray, field.Definition, ref offset);
                            elementArray.Children.Add(childElementArray);
                            break;
                        }
                    case field_type._field_struct:
                        {
                            var struct_definition = (tag_struct_definition)field.Definition;
                            var structOffset = offset;
                            var childElementArray = ProcessTagStructDefinition(elementArray, struct_definition.Definition, ref structOffset);
                            elementArray.Children.AddRange(childElementArray);

                            break;
                        }
                    case field_type._field_data:
                        {
                            var data_definition = (tag_data_definition)field.Definition;
                            var childElementArray = new ElementArray() { ElementSize = 1, Name = data_definition.Name, Address = offset, Parent = elementArray, Alignment = data_definition.Alignment };
                            elementArray.Children.Add(childElementArray);
                            break;
                        }
                    case field_type._field_array_start:
                        {
                            ProcessArrayFields(fields, elementArray, ref field, ref i, ref offset);
                            break;
                        }
                    case field_type._field_array_end:
                        {
                            return;
                        }
                }
                offset +=Guerilla.CalculateSizeOfField(field);
            }
        }
        private IEnumerable<ElementArray> ProcessTagStructDefinition(ElementArray parent, tag_block_definition definition, ref int offset)
        {
            var size = Guerilla.CalculateSizeOfFieldSet(definition.LatestFieldSet.Fields);

            var blockElementArray = new ElementArray()
            {
                Name = definition.Name,
                ElementSize = size,
                Address = offset,
                Parent = parent,
                MaxElementCount = definition.maximum_element_count,
                Alignment = definition.LatestFieldSet.Alignment,
            };

            var i = 0;
            ProcessFields(definition.LatestFieldSet.Fields, blockElementArray, ref i, ref offset);
            return blockElementArray.Children;
        }