public UByteCodeDecompiler( UStruct container )
 {
     _Container = container;
     AlignMemorySizes();
 }
Example #2
0
        protected override void Deserialize()
        {
            base.Deserialize();

            StructObject = (UStruct)GetIndexObject( _Buffer.ReadObjectIndex() );
        }
        protected override void Deserialize()
        {
            base.Deserialize();

            StructObject = (UStruct)GetIndexObject(_Buffer.ReadObjectIndex());
        }
        private UProperty FindProperty(out UStruct outer)
        {
            //If the object is from the import table. Try to find the export object in the package it originates from.
            UStruct GetRealObject(UObject _object)
            {
                if (_object.ExportTable == null)
                {
                    var realClass = UnrealLoader.FindClassInCache(_object.Name);
                    //var realClass = UnrealLoader.FindClassInPackage(_object.Outer.Name, _object.Name);
                    return(realClass);
                }
                return(_object as UStruct);
            }

            UProperty property = null;

            outer = _Outer ?? _Container.Class as UStruct;
            //outer = GetRealObject(outer);
            for (var structField = outer; structField != null; structField = structField.Super as UStruct)
            {
                var temp = structField;
                structField = GetRealObject(structField);
                if (structField == null)
                {
                    structField = temp;
                }
                if (structField.Variables == null || !structField.Variables.Any())
                {
                    continue;
                }

                property = structField.Variables.Find(i => i.Name == Name);
                if (property == null)
                {
                    continue;
                }

                switch (property.Type)
                {
                case PropertyType.StructProperty:
                    outer = ((UStructProperty)property).StructObject;
                    break;

                case PropertyType.ArrayProperty:
                    var arrayField = property as UArrayProperty;
                    Debug.Assert(arrayField != null, "arrayField != null");
                    var arrayInnerField = arrayField.InnerProperty;
                    if (arrayInnerField.Type == PropertyType.StructProperty)
                    {
                        _Outer = ((UStructProperty)arrayInnerField).StructObject;
                    }
                    break;

                default:
                    outer = structField;
                    break;
                }
                break;
            }
            return(property);
        }
        /// <summary>
        /// Deserialize a default property value of a specified type.
        /// </summary>
        /// <param name="type">Kind of type to try deserialize.</param>
        /// <returns>The deserialized value if any.</returns>
        private string DeserializeDefaultPropertyValue(PropertyType type, ref DeserializeFlags deserializeFlags)
        {
            if (_Buffer.Position - _ValueOffset > Size)
            {
                throw new DeserializationException("End of defaultproperties stream reached...");
            }

            var    orgOuter      = _Outer;
            string propertyValue = String.Empty;

            try
            {
                // Deserialize Value
                switch (type)
                {
                case PropertyType.BoolProperty:
                {
                    var value = _BoolValue;
                    if (Size == 1 && _Buffer.Version < V3)
                    {
                        value = _Buffer.ReadByte() > 0;
                    }
                    propertyValue = value ? "true" : "false";
                    break;
                }

                case PropertyType.StrProperty:
                    propertyValue = "\"" + _Buffer.ReadText().Escape() + "\"";
                    break;

                case PropertyType.NameProperty:
                    propertyValue = _Buffer.ReadName();
                    break;

                case PropertyType.IntProperty:
                    propertyValue = _Buffer.ReadInt32().ToString(CultureInfo.InvariantCulture);
                    break;

                case PropertyType.QWordProperty:
                    propertyValue = _Buffer.ReadInt64().ToString(CultureInfo.InvariantCulture);
                    break;

                case PropertyType.FloatProperty:
                    propertyValue = _Buffer.ReadFloat().ToUFloat();
                    break;

                case PropertyType.ByteProperty:
                    if (_Buffer.Version >= V3 && Size == 8)
                    {
                        var enumValue = _Buffer.ReadName();
                        propertyValue = enumValue;
                        if (_Buffer.Version >= VEnumName)
                        {
                            propertyValue = EnumName + "." + propertyValue;
                        }
                    }
                    else
                    {
                        propertyValue = _Buffer.ReadByte().ToString(CultureInfo.InvariantCulture);
                    }
                    break;

                case PropertyType.InterfaceProperty:
                case PropertyType.ComponentProperty:
                case PropertyType.ObjectProperty:
                {
                    var uObject = _Buffer.ReadObject();
                    uObjects.Add(uObject);
                    _Container.Record("object", uObject);
                    if (uObject != null)
                    {
                        bool inline = false;
                        // If true, object is an archetype or subobject.
                        if (uObject.Outer == _Container && (deserializeFlags & DeserializeFlags.WithinStruct) == 0)
                        {
                            // Unknown objects are only deserialized on demand.
                            uObject.BeginDeserializing();
                            if (uObject.Properties != null && uObject.Properties.Count > 0)
                            {
                                inline        = true;
                                propertyValue = uObject.Decompile() + "\r\n" + UDecompilingState.Tabs;

                                _TempFlags |= DoNotAppendName;
                                if ((deserializeFlags & DeserializeFlags.WithinArray) != 0)
                                {
                                    _TempFlags    |= ReplaceNameMarker;
                                    propertyValue += "%ARRAYNAME%=" + uObject.Name;
                                }
                                else
                                {
                                    propertyValue += Name + "=" + uObject.Name;
                                }
                            }
                        }

                        if (!inline)
                        {
                            // =CLASS'Package.Group(s)+.Name'
                            propertyValue = String.Format("{0}\'{1}\'", uObject.GetClassName(), uObject.GetOuterGroup());
                        }
                    }
                    else
                    {
                        // =none
                        propertyValue = "none";
                    }
                    break;
                }

                case PropertyType.ClassProperty:
                {
                    var uObject = _Buffer.ReadObject();
                    uObjects.Add(uObject);
                    _Container.Record("object", uObject);
                    propertyValue = (uObject != null ? "class\'" + uObject.Name + "\'" : "none");
                    break;
                }

                case PropertyType.DelegateProperty:
                {
                    _TempFlags |= DoNotAppendName;
                    int    outerIndex    = _Buffer.ReadObjectIndex();   // Where the assigned delegate property exists.
                    var    delegateValue = _Buffer.ReadName();
                    string delegateName  = ((string)(Name)).Substring(2, Name.Length - 12);
                    propertyValue = delegateName + "=" + delegateValue;
                    break;
                }

                    #region HardCoded Struct Types
                case PropertyType.Color:
                {
                    string b = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);
                    string g = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);
                    string r = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);
                    string a = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);

                    propertyValue += "R=" + r +
                                     ",G=" + g +
                                     ",B=" + b +
                                     ",A=" + a;
                    break;
                }

                case PropertyType.LinearColor:
                {
                    string b = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string g = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string r = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string a = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += "R=" + r +
                                     ",G=" + g +
                                     ",B=" + b +
                                     ",A=" + a;
                    break;
                }

                case PropertyType.Vector:
                {
                    string x = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string y = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string z = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += "X=" + x +
                                     ",Y=" + y +
                                     ",Z=" + z;
                    break;
                }

                case PropertyType.TwoVectors:
                {
                    string v1 = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string v2 = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);

                    propertyValue += "v1=(" + v1 + "),v2=(" + v2 + ")";
                    break;
                }

                case PropertyType.Vector4:
                {
                    string plane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);

                    propertyValue += plane;
                    break;
                }

                case PropertyType.Vector2D:
                {
                    string x = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string y = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += "X=" + x +
                                     ",Y=" + y;
                    break;
                }

                case PropertyType.Rotator:
                {
                    string pitch = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string yaw   = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string roll  = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);

                    propertyValue += "Pitch=" + pitch +
                                     ",Yaw=" + yaw +
                                     ",Roll=" + roll;
                    break;
                }

                case PropertyType.Guid:
                {
                    string a = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string b = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string c = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string d = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);

                    propertyValue += "A=" + a +
                                     ",B=" + b +
                                     ",C=" + c +
                                     ",D=" + d;
                    break;
                }

                case PropertyType.Sphere:
                case PropertyType.Plane:
                {
                    string v = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string w = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);

                    propertyValue += v + ",W=" + w;
                    break;
                }

                case PropertyType.Scale:
                {
                    string scale     = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string sheerRate = DeserializeDefaultPropertyValue(PropertyType.FloatProperty, ref deserializeFlags);
                    string sheerAxis = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);

                    propertyValue += "Scale=(" + scale + ")" +
                                     ",SheerRate=" + sheerRate +
                                     ",SheerAxis=" + sheerAxis;
                    break;
                }

                case PropertyType.Box:
                {
                    string min     = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string max     = DeserializeDefaultPropertyValue(PropertyType.Vector, ref deserializeFlags);
                    string isValid = DeserializeDefaultPropertyValue(PropertyType.ByteProperty, ref deserializeFlags);

                    propertyValue += "Min=(" + min + ")" +
                                     ",Max=(" + max + ")" +
                                     ",IsValid=" + isValid;
                    break;
                }

                /*case PropertyType.InterpCurve:
                 * {
                 *  // HACK:
                 *  UPropertyTag tag = new UPropertyTag( _Owner );
                 *  tag.Serialize();
                 *  buffer.Seek( tag.ValueOffset, System.IO.SeekOrigin.Begin );
                 *
                 *  int curvescount = buffer.ReadIndex();
                 *  if( curvescount <= 0 )
                 *  {
                 *      break;
                 *  }
                 *  propertyvalue += tag.Name + "=(";
                 *  for( int i = 0; i < curvescount; ++ i )
                 *  {
                 *      propertyvalue += "(" + SerializeDefaultPropertyValue( PropertyType.InterpCurvePoint, buffer, ref serializeFlags ) + ")";
                 *      if( i != curvescount - 1 )
                 *      {
                 *          propertyvalue += ",";
                 *      }
                 *  }
                 *  propertyvalue += ")";
                 *  break;
                 * }*/

                /*case PropertyType.InterpCurvePoint:
                 * {
                 *  string InVal = SerializeDefaultPropertyValue( PropertyType.Float, buffer, ref serializeFlags );
                 *  string OutVal = SerializeDefaultPropertyValue( PropertyType.Float, buffer, ref serializeFlags );
                 *
                 *  propertyvalue += "InVal=" + InVal +
                 *      ",OutVal=" + OutVal;
                 *  break;
                 * }*/

                case PropertyType.Quat:
                {
                    propertyValue += DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    break;
                }

                case PropertyType.Matrix:
                {
                    string xPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    string yPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    string zPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    string wPlane = DeserializeDefaultPropertyValue(PropertyType.Plane, ref deserializeFlags);
                    propertyValue += "XPlane=(" + xPlane + ")" +
                                     ",YPlane=(" + yPlane + ")" +
                                     ",ZPlane=(" + zPlane + ")" +
                                     ",WPlane=(" + wPlane + ")";
                    break;
                }

                case PropertyType.IntPoint:
                {
                    string x = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);
                    string y = DeserializeDefaultPropertyValue(PropertyType.IntProperty, ref deserializeFlags);

                    propertyValue += "X=" + x + ",Y=" + y;
                    break;
                }
                    #endregion

                case PropertyType.PointerProperty:
                case PropertyType.StructProperty:
                {
                    deserializeFlags |= DeserializeFlags.WithinStruct;
                    bool isHardCoded      = false;
                    var  hardcodedStructs = (PropertyType[])Enum.GetValues(typeof(PropertyType));
                    for (var i = (byte)PropertyType.StructOffset; i < hardcodedStructs.Length; ++i)
                    {
                        var structType = Enum.GetName(typeof(PropertyType), (byte)hardcodedStructs[i]);
                        if (String.Compare(ItemName, structType, StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            continue;
                        }

                        isHardCoded    = true;
                        propertyValue += DeserializeDefaultPropertyValue(hardcodedStructs[i], ref deserializeFlags);
                        break;
                    }

                    if (!isHardCoded)
                    {
                        // We have to modify the outer so that dynamic arrays within this struct
                        // will be able to find its variables to determine the array type.
                        FindProperty(out _Outer);
                        while (true)
                        {
                            var tag = new UDefaultProperty(_Container, _Outer);
                            if (tag.Deserialize())
                            {
                                propertyValue += tag.Name +
                                                 (tag.ArrayIndex > 0 && tag.Type != PropertyType.BoolProperty
                                            ? "[" + tag.ArrayIndex + "]" : String.Empty) +
                                                 "=" + tag.DeserializeValue(deserializeFlags) + ",";
                            }
                            else
                            {
                                if (propertyValue.EndsWith(","))
                                {
                                    propertyValue = propertyValue.Remove(propertyValue.Length - 1, 1);
                                }
                                break;
                            }
                        }
                    }
                    propertyValue = propertyValue.Length != 0 ? "(" + propertyValue + ")" : "none";
                    break;
                }

                case PropertyType.ArrayProperty:
                {
                    int arraySize = _Buffer.ReadIndex();
                    _Container.Record("arraySize", arraySize);
                    if (arraySize == 0)
                    {
                        propertyValue = "none";
                        break;
                    }

                    // Find the property within the outer/owner or its inheritances.
                    // If found it has to modify the outer so structs within this array can find their array variables.
                    // Additionally we need to know the property to determine the array's type.
                    var arrayType = PropertyType.None;
                    var property  = FindProperty(out _Outer) as UArrayProperty;
                    if (property != null && property.InnerProperty != null)
                    {
                        arrayType = property.InnerProperty.Type;
                    }
                    // If we did not find a reference to the associated property(because of imports)
                    // then try to determine the array's type by scanning the definined array types.
                    else if (UnrealConfig.VariableTypes != null && UnrealConfig.VariableTypes.ContainsKey(Name))
                    {
                        var varTuple = UnrealConfig.VariableTypes[Name];
                        if (varTuple != null)
                        {
                            arrayType = varTuple.Item2;
                        }
                    }

                    if (arrayType == PropertyType.None)
                    {
                        propertyValue = "/* Array type was not detected. */";
                        break;
                    }

                    deserializeFlags |= DeserializeFlags.WithinArray;
                    if ((deserializeFlags & DeserializeFlags.WithinStruct) != 0)
                    {
                        // Hardcoded fix for InterpCurve and InterpCurvePoint.
                        if (String.Compare(Name, "Points", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            arrayType = PropertyType.StructProperty;
                        }
                        var sb = new StringBuilder();
                        sb.Append("(");
                        for (int i = 0; i < arraySize; ++i)
                        {
                            sb.Append(DeserializeDefaultPropertyValue(arrayType, ref deserializeFlags)
                                      + (i != arraySize - 1 ? "," : String.Empty));
                            //propertyValue += DeserializeDefaultPropertyValue( arrayType, ref deserializeFlags )
                            //    + (i != arraySize - 1 ? "," : String.Empty);
                        }
                        sb.Append(")");
                        propertyValue = sb.ToString();
                        //propertyValue = "(" + propertyValue + ")";
                    }
                    else
                    {
                        var sb = new StringBuilder();
                        for (int i = 0; i < arraySize; ++i)
                        {
                            string elementValue = DeserializeDefaultPropertyValue(arrayType, ref deserializeFlags);
                            if ((_TempFlags & ReplaceNameMarker) != 0)
                            {
                                sb.Append(elementValue.Replace("%ARRAYNAME%", Name + "(" + i + ")"));

                                //propertyValue += elementValue.Replace( "%ARRAYNAME%", Name + "(" + i + ")" );
                                _TempFlags = 0x00;
                            }
                            else
                            {
                                sb.Append($"{Name}({i})={elementValue}");
                                //propertyValue += Name + "(" + i + ")=" + elementValue;
                            }

                            if (i != arraySize - 1)
                            {
                                sb.Append($"\r\n{UDecompilingState.Tabs}");
                                //propertyValue += "\r\n" + UDecompilingState.Tabs;
                            }
                        }
                        propertyValue += sb.ToString();
                    }

                    _TempFlags |= DoNotAppendName;
                    break;
                }

                default:
                    propertyValue = "/* Unknown default property type! */";
                    break;
                }
            }
            catch (Exception e)
            {
                return(propertyValue + "\r\n/* Exception thrown while deserializing " + Name + "\r\n" + e + " */");
            }
            finally
            {
                _Outer = orgOuter;
            }
            return(propertyValue);
        }
 public UDefaultProperty(UObject owner, UStruct outer = null)
 {
     _Container = owner;
     _Outer     = (outer ?? _Container as UStruct) ?? _Container.Outer as UStruct;
 }