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; } }
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"); } }