예제 #1
0
        public List <object> GetExportProperties(FObjectExport export)
        {
            List <object> properties = new List <object>();
            long          lastPos    = this._openExportStream.Position;

            if (this._openExportStream.Position != export.ExportFileOffset)
            {
                this._openExportStream.Seek(export.ExportFileOffset, SeekOrigin.Begin);
            }

            while (this._openExportStream.Position < export.ExportFileOffset + export.SerialSize)
            {
                long propPos = this._openExportStream.Position;
                (bool, object?)property = GetProperty();

                if (property.Item1)
                {
                    properties.Add(property.Item2);
                }
                else if (property.Item2 is not null)
                {
                    properties.Add(property.Item2);
                    this._openExportStream.Seek(propPos, SeekOrigin.Begin);
                    this._openExportStream.Seek((int)((dynamic)property.Item2).Size + 25, SeekOrigin.Current);
                }
                else
                {
                    break;
                }
            }
            this._openExportStream.Seek(lastPos, SeekOrigin.Begin);

            return(properties);
        }
예제 #2
0
        PackageReader(BinaryReader uasset, BinaryReader uexp, Stream ubulk)
        {
            Loader             = uasset;
            PackageFileSummary = new FPackageFileSummary(Loader);

            NameMap         = SerializeNameMap();
            ImportMap       = SerializeImportMap();
            ExportMap       = SerializeExportMap();
            DataExports     = new IUExport[ExportMap.Length];
            DataExportTypes = new FName[ExportMap.Length];
            Loader          = uexp;
            for (int i = 0; i < ExportMap.Length; i++)
            {
                FObjectExport Export = ExportMap[i];
                {
                    FName ExportType;
                    if (Export.ClassIndex.IsNull)
                    {
                        ExportType = DataExportTypes[i] = ReadFName(); // check if this is true, I don't know if Fortnite ever uses this
                    }
                    else if (Export.ClassIndex.IsExport)
                    {
                        ExportType = DataExportTypes[i] = ExportMap[Export.ClassIndex.AsExport].SuperIndex.Resource.ObjectName;
                    }
                    else if (Export.ClassIndex.IsImport)
                    {
                        ExportType = DataExportTypes[i] = ImportMap[Export.ClassIndex.AsImport].ObjectName;
                    }
                    else
                    {
                        throw new FileLoadException("Can't get class name"); // Shouldn't reach this unless the laws of math have bent to MagmaReef's will
                    }
                    if (ExportType.String.Equals("BlueprintGeneratedClass"))
                    {
                        continue;
                    }

                    var pos = Position = Export.SerialOffset - PackageFileSummary.TotalHeaderSize;
                    DataExports[i] = ExportType.String switch
                    {
                        "Texture2D" => new UTexture2D(this, ubulk, ExportMap.Sum(e => e.SerialSize) + PackageFileSummary.TotalHeaderSize),
                        "CurveTable" => new UCurveTable(this),
                        "DataTable" => new UDataTable(this),
                        "FontFace" => new UFontFace(this, ubulk),
                        "SoundWave" => new USoundWave(this, ubulk, ExportMap.Sum(e => e.SerialSize) + PackageFileSummary.TotalHeaderSize),
                        "StringTable" => new UStringTable(this),
                        _ => new UObject(this),
                    };

#if DEBUG
                    if (pos + Export.SerialSize != Position)
                    {
                        System.Diagnostics.Debug.WriteLine($"[ExportType={ExportType.String}] Didn't read {Export.ObjectName} correctly (at {Position}, should be {pos + Export.SerialSize}, {pos + Export.SerialSize - Position} behind)");
                    }
#endif
                }
            }
            return;
        }
예제 #3
0
 public static IExportObject VisitSubtype(BinaryReader reader, FObjectExport export, FPackageFileSummary summary)
 {
     if (ExportVisitors.TryGetValue(export.ClassIndex.Name, out var visitor))
     {
         return(visitor(reader, export, summary));
     }
     return(null);
 }
예제 #4
0
 public ExportLoader(Package package, FObjectExport export, FAssetArchive archive)
 {
     _package = package;
     _export  = export;
     _archive = archive;
     Lazy     = new(() =>
     {
         Fire(LoadPhase.Serialize);
         return(_object);
     });
     export.ExportObject = Lazy;
 }
예제 #5
0
        public static IExportObject Deserialize(BinaryReader reader, FObjectExport export, FPackageFileSummary summary)
        {
            var instance = new StringTable();

            instance.Name = LSerializer.FString(reader);
            var count = reader.ReadInt32();

            for (int i = 0; i < count; ++i)
            {
                instance.Add(LSerializer.FString(reader), LSerializer.FString(reader));
            }
            return(instance);
        }
예제 #6
0
        public static IExportObject Deserialize(BinaryReader reader, FObjectExport export, FPackageFileSummary summary)
        {
            StringTable stringTable = new StringTable();

            stringTable.Name = LSerializer.FString(reader);
            int num = reader.ReadInt32();

            for (int i = 0; i < num; i++)
            {
                stringTable.Add(LSerializer.FString(reader), LSerializer.FString(reader));
            }
            return(stringTable);
        }
예제 #7
0
        FObjectExport[] SerializeExportMap()
        {
            if (PackageFileSummary.ExportCount > 0)
            {
                Loader.BaseStream.Position = PackageFileSummary.ExportOffset;

                var OutExportMap = new FObjectExport[PackageFileSummary.ExportCount];
                for (int ExportMapIdx = 0; ExportMapIdx < PackageFileSummary.ExportCount; ++ExportMapIdx)
                {
                    OutExportMap[ExportMapIdx] = new FObjectExport(this);
                }
                return(OutExportMap);
            }
            return(Array.Empty <FObjectExport>());
        }
예제 #8
0
        public static IExportObject Deserialize(BinaryReader reader, FObjectExport export, FPackageFileSummary summary)
        {
            var instance = new UDataTable();
            var count    = reader.ReadInt32();

            for (int i = 0; i < count; ++i)
            {
                var index = LSerializer.Deserialize <FName>(reader);
                index.Ref(summary);
                var uobj = new UObject(reader, summary, false);
                uobj.Name = index;
                instance.Add(index, uobj);
            }
            return(instance);
        }
예제 #9
0
        public static IExportObject Deserialize(BinaryReader reader, FObjectExport export, FPackageFileSummary summary)
        {
            UDataTable uDataTable = new UDataTable();
            int        num        = reader.ReadInt32();

            for (int i = 0; i < num; i++)
            {
                FName fName = LSerializer.Deserialize <FName>(reader);
                fName.Ref(summary);
                UObject uObject = new UObject(reader, summary, pad: false);
                uObject.Name = fName;
                uDataTable.Add(fName, uObject);
            }
            return(uDataTable);
        }
예제 #10
0
        private MemoryStream GetUEventStream(FObjectExport export, Stream uasset, Stream uexp)
        {
            Span <byte> buffer = new Span <byte>(new byte[export.SerialSize]);

            if (uexp != null)
            {
                uexp.Position = export.SerialOffset - Summary.TotalHeaderSize;
                uexp.Read(buffer);
            }
            else
            {
                uasset.Position = export.SerialOffset;
                uasset.Read(buffer);
            }
            return(new MemoryStream(buffer.ToArray()));
        }
예제 #11
0
        public static IExportObject Deserialize(BinaryReader reader, FObjectExport export, FPackageFileSummary summary)
        {
            var instance = new EndTextResource();
            var count    = reader.ReadInt32();

            for (int i = 0; i < count; ++i)
            {
                var key = LSerializer.FString(reader);
                if (string.IsNullOrEmpty(key) || key[0] != '$')
                {
                    throw new InvalidDataException("The key does not start with magic symbol");
                }
                var obj = LSerializer.Deserialize <FF7TxtRes>(reader);
                obj.GetEntries(reader, summary);
                instance.Add(key, obj);
            }
            return(instance);
        }
예제 #12
0
파일: UAsset.cs 프로젝트: kthulhu/UE4View
        public UAsset(byte[] data, int version) : base(data)
        {
            Version = version;
            ReadSummary();

            Seek(Summary.NameOffset);
            foreach (var i in Enumerable.Range(0, Summary.NameCount))
            {
                var entry = new FNameEntrySerialized();
                entry.Serialize(this);
                NameMap.Add(entry.Name);
            }
            Seek(Summary.GatherableTextDataOffset);
            foreach (var i in Enumerable.Range(0, Summary.GatherableTextDataCount))
            {
                Debugger.Break();
                // check whether it reads stuff properly
                var gatherable = new FGatherableTextData();
                gatherable.Serialize(this);
                GatherableTextDataMap.Add(gatherable);
            }
            Seek(Summary.ImportOffset);
            foreach (var i in Enumerable.Range(0, Summary.ImportCount))
            {
                var imp = new FObjectImport();
                imp.Serialize(this);
                ImportMap.Add(imp);
            }
            Seek(Summary.ExportOffset);
            foreach (var i in Enumerable.Range(0, Summary.ExportCount))
            {
                var exp = new FObjectExport();
                exp.Serialize(this);
                ExportMap.Add(exp);
            }
            Seek(Summary.StringAssetReferencesOffset);
            foreach (var i in Enumerable.Range(0, Summary.StringAssetReferencesCount))
            {
                StringAssetReferences.Add(ToFString());
            }

            // TODO: Fixup import, fixup exports, match exports with exporter object
        }
예제 #13
0
        public UObject(BinaryReader data, FPackageFileSummary summary, bool pad = true, FObjectExport export = null)
        {
            while (true)
            {
                var start = data.BaseStream.Position;
#if DEBUG
                CachedPos.Add(start);
#endif

                var name = LSerializer.Deserialize <FName>(data);
                name.Ref(summary);
                if (name == "None")
                {
                    break;
                }
                data.BaseStream.Position = start;

                var tag = LSerializer.Deserialize <FPropertyTag>(data);
                data.BaseStream.Position = start;
                tag.Ref(summary);

                tag = VisitorFactory.Visit(data, tag, summary);
                tag.Ref(summary);
                Add(tag);
            }

            if (pad)
            {
                data.BaseStream.Position += 4;
            }
            if (export != null)
            {
                ObjectData = VisitorFactory.VisitSubtype(data, export, summary);
            }
        }
예제 #14
0
 public UObject(FObjectExport exportObject) : base(exportObject)
 {
     Properties = new List <FPropertyTag>();
 }
예제 #15
0
        public Package(FArchive uasset, FArchive?uexp, Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null, IFileProvider?provider = null, TypeMappings?mappings = null, bool useLazySerialization = true)
            : base(uasset.Name.SubstringBeforeLast(".uasset"), provider, mappings)
        {
            // We clone the version container because it can be modified with package specific versions when reading the summary
            uasset.Versions = (VersionContainer)uasset.Versions.Clone();
            var uassetAr = new FAssetArchive(uasset, this);

            Summary = new FPackageFileSummary(uassetAr);

            uassetAr.SeekAbsolute(Summary.NameOffset, SeekOrigin.Begin);
            NameMap = new FNameEntrySerialized[Summary.NameCount];
            uassetAr.ReadArray(NameMap, () => new FNameEntrySerialized(uassetAr));

            uassetAr.SeekAbsolute(Summary.ImportOffset, SeekOrigin.Begin);
            ImportMap = new FObjectImport[Summary.ImportCount];
            uassetAr.ReadArray(ImportMap, () => new FObjectImport(uassetAr));

            uassetAr.SeekAbsolute(Summary.ExportOffset, SeekOrigin.Begin);
            ExportMap = new FObjectExport[Summary.ExportCount]; // we need this to get its final size in some case
            uassetAr.ReadArray(ExportMap, () => new FObjectExport(uassetAr));

            FAssetArchive uexpAr = uexp != null ? new FAssetArchive(uexp, this, (int)uassetAr.Length) : uassetAr;  // allows embedded uexp data

            if (ubulk != null)
            {
                //var offset = (int) (Summary.TotalHeaderSize + ExportMap.Sum(export => export.SerialSize));
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UBULK, offset, ubulk);
            }

            if (uptnl != null)
            {
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UPTNL, offset, uptnl);
            }

            if (useLazySerialization)
            {
                foreach (var export in ExportMap)
                {
                    export.ExportObject = new Lazy <UObject>(() =>
                    {
                        // Create
                        var obj      = ConstructObject(ResolvePackageIndex(export.ClassIndex)?.Object?.Value as UStruct);
                        obj.Name     = export.ObjectName.Text;
                        obj.Outer    = (ResolvePackageIndex(export.OuterIndex) as ResolvedExportObject)?.Object.Value ?? this;
                        obj.Super    = ResolvePackageIndex(export.SuperIndex) as ResolvedExportObject;
                        obj.Template = ResolvePackageIndex(export.TemplateIndex) as ResolvedExportObject;
                        obj.Flags   |= (EObjectFlags)export.ObjectFlags; // We give loaded objects the RF_WasLoaded flag in ConstructObject, so don't remove it again in here

                        // Serialize
                        uexpAr.SeekAbsolute(export.SerialOffset, SeekOrigin.Begin);
                        DeserializeObject(obj, uexpAr, export.SerialSize);
                        // TODO right place ???
                        obj.Flags |= EObjectFlags.RF_LoadCompleted;
                        obj.PostLoad();
                        return(obj);
                    });
                }
            }
            else
            {
                var newObjNames = new List <string>();
                foreach (var export in ExportMap)
                {
                    if (export.ExportObject == null)
                    {
                        var obj = ConstructObject(ResolvePackageIndex(export.ClassIndex)?.Object?.Value as UStruct);
                        obj.Name     = export.ObjectName.Text;
                        obj.Super    = ResolvePackageIndex(export.SuperIndex) as ResolvedExportObject;
                        obj.Template = ResolvePackageIndex(export.TemplateIndex) as ResolvedExportObject;
                        obj.Flags   |= (EObjectFlags)export.ObjectFlags; // We give loaded objects the RF_WasLoaded flag in ConstructObject, so don't remove it again in here

                        export.ExportObject = new Lazy <UObject>(obj);
                        newObjNames.Add(export.ObjectName.Text);
                    }
                }

                foreach (var export in ExportMap)
                {
                    if (newObjNames.Contains(export.ObjectName.Text))
                    {
                        var obj = export.ExportObject.Value;

                        uexpAr.SeekAbsolute(export.SerialOffset, SeekOrigin.Begin);
                        DeserializeObject(obj, uexpAr, export.SerialSize);
                    }
                }

                foreach (var export in ExportMap)
                {
                    if (newObjNames.Contains(export.ObjectName.Text))
                    {
                        var obj = export.ExportObject.Value;
                        obj.Outer = (ResolvePackageIndex(export.OuterIndex) as ResolvedExportObject)?.Object.Value ?? this;
                    }
                }

                foreach (var export in ExportMap)
                {
                    if (newObjNames.Contains(export.ObjectName.Text))
                    {
                        var obj = export.ExportObject.Value;

                        obj.Flags |= EObjectFlags.RF_LoadCompleted;
                        obj.PostLoad();
                    }
                }
            }
        }
예제 #16
0
 public ResolvedExportObject(int index, Package package) : base(package, index)
 {
     _export = package.ExportMap[index];
 }
예제 #17
0
 protected UExport(FObjectExport exportObject) : this(exportObject.ClassName)
 {
     Export = exportObject;
     Name   = exportObject.ObjectName.Text;
 }
예제 #18
0
        public Package(FArchive uasset, FArchive uexp, Lazy <FArchive?>?ubulk = null, Lazy <FArchive?>?uptnl = null, IFileProvider?provider = null, TypeMappings?mappings = null)
            : base(uasset.Name.SubstringBeforeLast(".uasset"), provider, mappings)
        {
            var uassetAr = new FAssetArchive(uasset, this);

            Summary = new FPackageFileSummary(uassetAr);
            if (Summary.Tag != PackageMagic)
            {
                throw new ParserException(uassetAr, $"Invalid uasset magic: {Summary.Tag} != {PackageMagic}");
            }

            uassetAr.Seek(Summary.NameOffset, SeekOrigin.Begin);
            NameMap = new FNameEntrySerialized[Summary.NameCount];
            uassetAr.ReadArray(NameMap, () => new FNameEntrySerialized(uassetAr));

            uassetAr.Seek(Summary.ImportOffset, SeekOrigin.Begin);
            ImportMap = new FObjectImport[Summary.ImportCount];
            uassetAr.ReadArray(ImportMap, () => new FObjectImport(uassetAr));

            uassetAr.Seek(Summary.ExportOffset, SeekOrigin.Begin);
            ExportMap = new FObjectExport[Summary.ExportCount]; // we need this to get its final size in some case
            uassetAr.ReadArray(ExportMap, () => new FObjectExport(uassetAr));

            var uexpAr = new FAssetArchive(uexp, this, Summary.TotalHeaderSize);

            if (ubulk != null)
            {
                //var offset = (int) (Summary.TotalHeaderSize + ExportMap.Sum(export => export.SerialSize));
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UBULK, offset, ubulk);
            }

            if (uptnl != null)
            {
                var offset = Summary.BulkDataStartOffset;
                uexpAr.AddPayload(PayloadType.UPTNL, offset, uptnl);
            }

            foreach (var it in ExportMap)
            {
                if (ResolvePackageIndex(it.ClassIndex)?.Object?.Value is not UStruct uStruct)
                {
                    continue;
                }
                var export = ConstructObject(uStruct);
                export.Name     = it.ObjectName.Text;
                export.Outer    = (ResolvePackageIndex(it.OuterIndex) as ResolvedExportObject)?.Object?.Value ?? this;
                export.Template = ResolvePackageIndex(it.TemplateIndex) as ResolvedExportObject;
                export.Flags    = (int)it.ObjectFlags;
                it.ExportType   = export.GetType();
                it.ExportObject = new Lazy <UObject>(() =>
                {
                    uexpAr.SeekAbsolute(it.RealSerialOffset, SeekOrigin.Begin);
                    var validPos = uexpAr.Position + it.SerialSize;
                    try
                    {
                        export.Deserialize(uexpAr, validPos);
#if DEBUG
                        if (validPos != uexpAr.Position)
                        {
                            Log.Warning("Did not read {0} correctly, {1} bytes remaining", export.ExportType, validPos - uexpAr.Position);
                        }
                        else
                        {
                            Log.Debug("Successfully read {0} at {1} with size {2}", export.ExportType, it.RealSerialOffset, it.SerialSize);
                        }
#endif

                        // TODO right place ???
                        export.PostLoad();
                    }
                    catch (Exception e)
                    {
                        Log.Error(e, "Could not read {0} correctly", export.ExportType);
                    }

                    return(export);
                });
            }
        }
예제 #19
0
 public UObject(BinaryReader data, FPackageFileSummary summary, bool pad = true, FObjectExport export = null)
 {
     while (true)
     {
         long  position = data.BaseStream.Position;
         FName fName    = LSerializer.Deserialize <FName>(data);
         fName.Ref(summary);
         if ((string)fName == "None")
         {
             break;
         }
         data.BaseStream.Position = position;
         FPropertyTag fPropertyTag = LSerializer.Deserialize <FPropertyTag>(data);
         data.BaseStream.Position = position;
         fPropertyTag.Ref(summary);
         fPropertyTag = VisitorFactory.Visit(data, fPropertyTag, summary);
         fPropertyTag.Ref(summary);
         Add(fPropertyTag);
     }
     if (pad)
     {
         data.BaseStream.Position += 4L;
     }
     if (export != null)
     {
         ObjectData = VisitorFactory.VisitSubtype(data, export, summary);
     }
 }