コード例 #1
0
ファイル: RecordBuilder.cs プロジェクト: benamehdi7/tesv-snip
        public SubrecordElement CreateType(string name, string type)
        {
            var elem = new SubrecordElement();

            elem.name = string.IsNullOrEmpty(name) ? "Unknown" : name;
            elem.type = type;
            return(elem);
        }
コード例 #2
0
        public ElementStructure(SubrecordElement node)
            : base(node)
        {
            //this.name = node.name;
            //this.desc = node.desc;
            this.@group         = node.group;
            this.hexview        = node.hexview;
            this.hexviewwithdec = node.hexviewwithdec;
            this.notininfo      = node.notininfo;
            //this.optional = node.optional != 0;
            this.options = node.options == null
                               ? new string[0]
                               : node.options.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            this.flags = node.flags == null ? new string[0] : node.flags.Split(new[] { ';' });
            //this.repeat = node.repeat;
            this.funcr  = node.funcr;
            this.funcw  = node.funcw;
            this.CondID = node.condid;
            if (this.optional > 0 || this.repeat > 0)
            {
                if (this.@group != 0)
                {
                    throw new RecordXmlException("Elements with a group attribute cant be marked optional or repeat");
                }
            }

            this.FormIDType = null;
            this.multiline  = node.multiline;
            this.type       = (ElementValueType)Enum.Parse(typeof(ElementValueType), node.type, true);
            switch (this.type)
            {
            case ElementValueType.FormID:
                this.FormIDType = node.reftype;
                break;

            case ElementValueType.Blob:
                if (this.repeat > 0 || this.optional > 0)
                {
                    throw new RecordXmlException("blob type elements can't be marked with repeat or optional");
                }

                break;
            }
        }
コード例 #3
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;
            }
        }
コード例 #4
0
ファイル: RecordBuilder.cs プロジェクト: benamehdi7/tesv-snip
        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 = this.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 = this.CreateType(index++, "short");
                            elem.size = 2;
                            sr.Elements.Add(elem);
                            elemSize = 2;
                            continue;
                        }
                        else
                        {
                            var elem = this.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 = this.FormLookup(ui4);
                            if (r != null)
                            {
                                if (string.IsNullOrEmpty(reftype))
                                {
                                    reftype = r.Name;
                                    isFormID++;
                                }
                                else if (reftype == r.Name)
                                {
                                    isFormID++;
                                }
                            }

                            if (!string.IsNullOrEmpty(this.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 = this.CreateType(index++, "float");
                            elem.size = 4;
                            sr.Elements.Add(elem);
                        }
                        else if (num2Short > 0 && shortPct > 0.5f)
                        {
                            var elem = this.CreateType(index++, "short");
                            elem.size = 2;
                            sr.Elements.Add(elem);
                            sr.Elements.Add(elem);
                            this.UpdateSize(sr);
                        }
                        else if (isFormID > 0 && formPct > 0.5f)
                        {
                            var elem = this.CreateType(index++, "formid");
                            elem.reftype = reftype;
                            elem.size    = 4;
                            sr.Elements.Add(elem);
                        }
                        else if (isLString > 0 && lstrPct > 0.5f)
                        {
                            var elem = this.CreateType(index++, "lstring");
                            elem.size = 4;
                            sr.Elements.Add(elem);
                        }
                        else
                        {
                            var elem = this.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 = this.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 = this.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(this.CreateBlob());
                }
            }
        }