Ejemplo n.º 1
0
        public SubrecordElement CreateType(string name, string type)
        {
            var elem = new SubrecordElement();

            elem.name = string.IsNullOrEmpty(name) ? "Unknown" : name;
            elem.type = type;
            return(elem);
        }
Ejemplo n.º 2
0
 public ElementStructure(SubrecordElement node)
 {
     name = node.name;
     desc = node.desc;
     @group = node.group;
     hexview = node.hexview;
     notininfo = node.notininfo;
     optional = node.optional != 0;
     options = node.options == null
                   ? new string[0]
                   : node.options.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
     flags = node.flags == null ? new string[0] : node.flags.Split(new[] {';'});
     repeat = node.repeat;
     CondID = node.condid;
     if (optional || repeat > 0)
     {
         if (group != 0)
             throw new RecordXmlException("Elements with a group attribute cant be marked optional or repeat");
     }
     FormIDType = null;
     multiline = node.multiline;
     type = (ElementValueType) Enum.Parse(typeof (ElementValueType), node.type, true);
     switch (type)
     {
         case ElementValueType.FormID:
             FormIDType = node.reftype;
             break;
         case ElementValueType.Blob:
             if (repeat > 0 || optional)
                 throw new RecordXmlException(
                     "blob type elements can't be marked with repeat or optional");
             break;
     }
 }
Ejemplo n.º 3
0
        private void ProcessSubRecord(Subrecord sr, SubRecord[] srs)
        {
            long minSize = srs.Min(a => a.Size);
            long maxSize = srs.Max(a => a.Size);

            if (maxSize == 0) // likely a group start
            {
                sr.size = -1;
                return;
            }

            int szCount = 0;

            foreach (var ss in srs)
            {
                if (ss.Size == 0)
                {
                    continue;
                }

                byte[] data = ss.GetReadonlyData();
                if (IsLikelyString(new ArraySegment <byte>(data, 0, (int)ss.Size)))
                {
                    if (++szCount > 10)
                    {
                        SubrecordElement elem = CreateType(null, "string");
                        sr.Elements.Add(elem);
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
            if (sr.Elements.Count > 0)
            {
                return; // found string
            }


            if (minSize == maxSize && maxSize < 256)
            {
                sr.size = (int)maxSize;
                int index = 0;
                // Walk through each element guessing the data type
                for (int offset = 0, elemSize = 4; offset < maxSize; offset += elemSize)
                {
                    int    numZero   = 0;
                    int    numFloat  = 0;
                    int    num2Short = 0;
                    int    isFormID  = 0;
                    int    numTotal  = 0;
                    int    isLString = 0;
                    string reftype   = null;

                    if (maxSize - offset < 4)
                    {
                        if (maxSize >= 2)
                        {
                            var elem = CreateType(index++, "short");
                            elem.size = 2;
                            sr.Elements.Add(elem);
                            elemSize = 2;
                            continue;
                        }
                        else
                        {
                            var elem = CreateType(index++, "byte");
                            elem.size = 1;
                            sr.Elements.Add(elem);
                            elemSize = 1;
                            continue;
                        }
                    }

                    foreach (var ss in srs) //.Random(srs.Length < 10 ? 0 : srs.Length / 10)
                    {
                        ++numTotal;
                        byte[] data = ss.GetReadonlyData();
                        uint   ui4  = TypeConverter.h2i(data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
                        if (ui4 == 0)
                        {
                            ++numZero;
                            continue;
                        }

                        ushort lhs = TypeConverter.h2s(data[offset], data[offset + 1]);
                        ushort uhs = TypeConverter.h2s(data[offset + 2], data[offset + 3]);
                        float  flt = TypeConverter.h2f(data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
                        if (IsLikelyFloat(flt))
                        {
                            ++numFloat;
                        }
                        if (lhs > 0 && lhs < 255 && uhs > 0 && uhs < 255)
                        {
                            ++num2Short;
                        }
                        if (ui4 > 100)
                        {
                            Record r = FormLookup(ui4);
                            if (r != null)
                            {
                                if (string.IsNullOrEmpty(reftype))
                                {
                                    reftype = r.Name;
                                    isFormID++;
                                }
                                else if (reftype == r.Name)
                                {
                                    isFormID++;
                                }
                            }
                            if (!string.IsNullOrEmpty(StringLookup(ui4)))
                            {
                                ++isLString;
                            }
                        }
                    }
                    if (numTotal > 0)
                    {
                        float floatPct = (numFloat + numZero) / (float)numTotal;
                        float shortPct = (num2Short + numZero) / (float)numTotal;
                        float formPct  = (isFormID + numZero) / (float)numTotal;
                        float lstrPct  = (isLString + numZero) / (float)numTotal;

                        if (numFloat > 0 && floatPct > 0.5f)
                        {
                            var elem = CreateType(index++, "float");
                            elem.size = 4;
                            sr.Elements.Add(elem);
                        }
                        else if (num2Short > 0 && shortPct > 0.5f)
                        {
                            var elem = CreateType(index++, "short");
                            elem.size = 2;
                            sr.Elements.Add(elem);
                            sr.Elements.Add(elem);
                            UpdateSize(sr);
                        }
                        else if (isFormID > 0 && formPct > 0.5f)
                        {
                            var elem = CreateType(index++, "formid");
                            elem.reftype = reftype;
                            elem.size    = 4;
                            sr.Elements.Add(elem);
                        }
                        else if (isLString > 0 && lstrPct > 0.5f)
                        {
                            var elem = CreateType(index++, "lstring");
                            elem.size = 4;
                            sr.Elements.Add(elem);
                        }
                        else
                        {
                            var elem = CreateType(index++, "int");
                            elem.size = 4;
                            sr.Elements.Add(elem);
                        }
                    }
                }
            }
            else // guess dynamically sized object... default to blob
            {
                if (sr.Elements.Count == 0)
                {
                    long modSum = srs.Sum(a => a.Size % 4); // useful if we suspect this is an array of integers
                    if (modSum == 0)
                    {
                        int    count   = 0;
                        string reftype = null;
                        foreach (var ss in srs)
                        {
                            byte[] data   = ss.GetReadonlyData();
                            int    offset = 0;
                            uint   ui4    = GetUInt32(data, offset);
                            if (ui4 < 100)
                            {
                                continue;
                            }

                            Record r = FormLookup(ui4);
                            if (r != null)
                            {
                                if (string.IsNullOrEmpty(reftype))
                                {
                                    reftype = r.Name;
                                }
                                else if (reftype == r.Name)
                                {
                                    if (++count > 10)
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        if (count > 0)
                        {
                            var elem = CreateType("ID", "formid");
                            elem.reftype  = reftype;
                            elem.size     = 4;
                            elem.repeat   = 1;
                            elem.optional = 1;
                            sr.Elements.Add(elem);
                        }
                    }
                }

                // check if it is a string else make it a blob
                sr.size = 0;

                if (sr.Elements.Count == 0)
                {
                    sr.Elements.Add(CreateBlob());
                }
            }
        }