Example #1
0
 public void UpdateSize(Subrecord sr)
 {
     sr.size = 0;
     foreach (var sre in sr.Elements)
     {
         sr.size += sre.size;
     }
 }
Example #2
0
        internal void MergeRecord(Subrecord baseRecord, Subrecord updateRecord)
        {
            if (baseRecord == null)
            {
                return;
            }

            if (updateRecord.desc == updateRecord.name && !string.IsNullOrEmpty(baseRecord.desc))
            {
                updateRecord.desc = baseRecord.desc;
            }

            var  baseItr   = baseRecord.Elements.GetEnumerator();
            var  updateItr = updateRecord.Elements.GetEnumerator();
            bool baseOk    = baseItr.MoveNext();
            bool updateOk  = updateItr.MoveNext();

            while (baseOk && updateOk)
            {
                var bse = baseItr.Current;
                var use = updateItr.Current;
                if (bse == null && use == null)
                {
                    break;
                }
                if (use.name.StartsWith("Unknown", StringComparison.InvariantCultureIgnoreCase))
                {
                    use.name = bse.name;

                    if (bse.type == use.type)
                    {
                        use.notininfo = bse.notininfo;
                        use.options   = bse.options;
                        use.flags     = bse.flags;
                        use.hexview   = bse.hexview;
                        use.multiline = bse.multiline;
                    }
                    if (bse.type == "string" && use.type == "int")
                    {
                        // likely an lstring
                        use.type      = "lstring";
                        use.notininfo = bse.notininfo;
                        use.options   = bse.options;
                        use.flags     = bse.flags;
                        use.hexview   = bse.hexview;
                        use.multiline = bse.multiline;
                    }
                }
                baseOk   = baseItr.MoveNext();
                updateOk = updateItr.MoveNext();
            }
        }
Example #3
0
 protected SubrecordBase(Subrecord node)
 {
     if (node.name.StartsWith("&#x"))
     {
         string[] val = node.name.Split(new[] {';'}, 2, StringSplitOptions.None);
         var c = (char) int.Parse(val[0].Substring(3), NumberStyles.HexNumber, null);
         name = c + val[1];
     }
     else
         name = node.name;
     repeat = node.repeat;
     optional = node.optional;
     desc = node.desc;
 }
Example #4
0
        public SubrecordStructure(Subrecord node) : base(node)
        {
            notininfo = node.notininfo;
            size = node.size;
            Condition = (!string.IsNullOrEmpty(node.condition))
                            ? (CondType) Enum.Parse(typeof (CondType), node.condition, true)
                            : CondType.None;
            CondID = node.condid;
            CondOperand = node.condvalue;
            UseHexEditor = node.usehexeditor;
            //if (optional && repeat)
            //{
            //    throw new RecordXmlException("repeat and optional must both have the same value if they are non zero");
            //}

            var elements = new List<ElementStructure>();
            foreach (var elem in node.Elements)
                elements.Add(new ElementStructure(elem));
            this.elements = elements.ToArray();

            ContainsConditionals = this.elements.Count(x => x.CondID != 0) > 0;
        }
Example #5
0
        private bool CreateSubrecords(RecordsRecord rr, Record r)
        {
            //int srIdx = 0;
            var groups = from psr in r.SubRecords
                         group psr by psr.Name
                         into g
                         select new { Name = g.Key, Records = g.ToArray() };

            int lastIndex = 0;
            var dict      = new Dictionary <string, Subrecord>();

            foreach (var kvp in groups)
            {
                if (IsCanceled)
                {
                    return(false);
                }
                //if (kvp.Name.Count(a => !Char.IsLetterOrDigit(a)) > 0) continue;
                int n = kvp.Records.Length;

                Subrecord sr = rr.Subrecords.FirstOrDefault(x => x.name == kvp.Name);
                if (sr == null)
                {
                    sr          = new Subrecord();
                    sr.name     = sr.desc = kvp.Name;
                    sr.optional = 1;
                    if (lastIndex + 1 <= rr.Items.Count)
                    {
                        rr.Items.Insert(++lastIndex, sr);
                    }
                    else
                    {
                        rr.Items.Add(sr);
                    }
                }
                else
                {
                    lastIndex = rr.Items.IndexOf(sr, (lastIndex < 0) ? lastIndex : 0);
                    if (lastIndex < 0) // out of order
                    {
                        lastIndex = rr.Items.IndexOf(sr);
                    }
                }

                // Group Detection
                if (n > 0)
                {
                    int idx1 = r.SubRecords.IndexOf(kvp.Records[0]);
                    int idx2 = idx1;
                    for (int i = 1; i < n; ++i, idx1 = idx2)
                    {
                        idx2 = r.SubRecords.IndexOf(kvp.Records[i]);
                        int diff = r.SubRecords.Skip(idx1).Take(idx2 - idx1).Select((a) => a.Name).Distinct().Count();
                        if (diff > sr.repeat)
                        {
                            sr.optional = sr.repeat = diff;
                        }
                    }
                    if (sr.repeat == 0 && n > 1)
                    {
                        sr.optional = sr.repeat = 1;
                    }
                }
            }
            return(true);
        }
Example #6
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());
                }
            }
        }