public FByteBulkDataHeader(FAssetArchive Ar)
        {
            BulkDataFlags = Ar.Read <EBulkDataFlags>();
            ElementCount  = BulkDataFlags.HasFlag(BULKDATA_Size64Bit) ? (int)Ar.Read <long>() : Ar.Read <int>();
            SizeOnDisk    = BulkDataFlags.HasFlag(BULKDATA_Size64Bit) ? (uint)Ar.Read <long>() : Ar.Read <uint>();
            OffsetInFile  = Ar.Ver >= EUnrealEngineObjectUE4Version.BULKDATA_AT_LARGE_OFFSETS ? Ar.Read <long>() : Ar.Read <int>();
            if (!BulkDataFlags.HasFlag(BULKDATA_NoOffsetFixUp)) // UE4.26 flag
            {
                OffsetInFile += Ar.Owner.Summary.BulkDataStartOffset;
            }

            if (BulkDataFlags.HasFlag(BULKDATA_BadDataVersion))
            {
                Ar.Position   += sizeof(ushort);
                BulkDataFlags &= ~BULKDATA_BadDataVersion;
            }
        }
Example #2
0
        public FByteBulkData(FAssetArchive Ar)
        {
            Header        = new FByteBulkDataHeader(Ar);
            BulkDataFlags = Header.BulkDataFlags;

            if (Header.ElementCount == 0)
            {
                // Nothing to do here
            }
            else if (BulkDataFlags.HasFlag(BULKDATA_Unused))
            {
                Log.Warning("Bulk with no data");
            }
            else if (BulkDataFlags.HasFlag(BULKDATA_ForceInlinePayload))
            {
#if DEBUG
                Log.Debug($"bulk data in .uexp file (Force Inline Payload) (flags={BulkDataFlags}, pos={Header.OffsetInFile}, size={Header.SizeOnDisk}))");
#endif
                Data = new byte[Header.ElementCount];
                Ar.Read(Data, 0, Header.ElementCount);
            }
            else if (BulkDataFlags.HasFlag(BULKDATA_OptionalPayload))
            {
#if DEBUG
                Log.Debug($"bulk data in .uptnl file (Optional Payload) (flags={BulkDataFlags}, pos={Header.OffsetInFile}, size={Header.SizeOnDisk}))");
#endif
                if (!Ar.TryGetPayload(PayloadType.UPTNL, out var uptnlAr) || uptnlAr == null)
                {
                    return;
                }

                Data             = new byte[Header.ElementCount];
                uptnlAr.Position = Header.OffsetInFile;
                uptnlAr.Read(Data, 0, Header.ElementCount);
            }
            else if (BulkDataFlags.HasFlag(BULKDATA_PayloadInSeperateFile))
            {
#if DEBUG
                Log.Debug($"bulk data in .ubulk file (Payload In Separate File) (flags={BulkDataFlags}, pos={Header.OffsetInFile}, size={Header.SizeOnDisk}))");
#endif
                if (!Ar.TryGetPayload(PayloadType.UBULK, out var ubulkAr) || ubulkAr == null)
                {
                    return;
                }

                Data             = new byte[Header.ElementCount];
                ubulkAr.Position = Header.OffsetInFile;
                ubulkAr.Read(Data, 0, Header.ElementCount);
            }
            else if (BulkDataFlags.HasFlag(BULKDATA_PayloadAtEndOfFile))
            {
#if DEBUG
                Log.Debug($"bulk data in .uexp file (Payload At End Of File) (flags={BulkDataFlags}, pos={Header.OffsetInFile}, size={Header.SizeOnDisk}))");
#endif
                //stored in same file, but at different position
                //save archive position
                var savePos = Ar.Position;
                if (Header.OffsetInFile + Header.ElementCount <= Ar.Length)
                {
                    Data        = new byte[Header.ElementCount];
                    Ar.Position = Header.OffsetInFile;
                    Ar.Read(Data, 0, Header.ElementCount);
                }
                else
                {
                    throw new ParserException(Ar, $"Failed to read PayloadAtEndOfFile, {Header.OffsetInFile} is out of range");
                }

                Ar.Position = savePos;
            }
            else if (BulkDataFlags.HasFlag(BULKDATA_CompressedZlib))
            {
                throw new ParserException(Ar, "TODO: CompressedZlib");
            }
        }