Overview
The ChunkAssetEntry class represents chunk assets in the Frostbite engine. Chunks are binary data blocks used for large resources like texture mipmaps, mesh LODs, and streaming data.
Class Definition
public class ChunkAssetEntry : AssetEntry
{
public override string Name => Id.ToString();
public override string Type => "Chunk";
public override string AssetType => "chunk";
public Guid Id;
public uint BundledSize;
public uint LogicalOffset;
public uint LogicalSize;
public uint RangeStart;
public uint RangeEnd;
public int H32;
public int FirstMip;
public bool IsTocChunk;
public bool TocChunkSpecialHack;
}
Location: FrostySdk/Managers/AssetManager.cs:394
Properties
Unique identifier for the chunk. Used as the chunk’s name.
Size of the chunk data when stored in a bundle (may differ from actual size).
Logical offset within the parent resource (for texture mips or mesh sections).
Logical size of the chunk data after decompression.
Start offset in the range of data covered by this chunk.
End offset in the range of data covered by this chunk.
32-bit hash of the parent resource name (FNV-1 hash). Links chunk to its owner.
For texture chunks, indicates the first mipmap level. -1 if not applicable.
True if this chunk is stored in a Table of Contents chunk bundle.
Internal flag for special TOC chunk handling.
Returns the chunk GUID as a string (since chunks are identified by GUID).
Returns "chunk" to identify this as a chunk asset entry.
Inherited Properties
See EbxAssetEntry for complete list of base properties including:
- Sha1, Size, OriginalSize
- IsModified, IsDirty, IsAdded
- Bundles, LinkedAssets
- Location, IsInline
Methods
AddToBundle (Override)
public override bool AddToBundle(int bid)
Adds the chunk to a bundle. Overridden to prevent adding orphaned chunks.
Bundle index to add the chunk to
True if successfully added. Returns false if chunk has no bundles and is not a new chunk.
Chunks cannot be added to bundles unless they already belong to at least one bundle or were explicitly created via AddChunk().
Inherited Methods
Chunk entries inherit methods from AssetEntry:
AddToBundles(IEnumerable<int>) - Add to multiple bundles
IsInBundle(int bid) - Check bundle membership
EnumerateBundles(bool addedOnly) - Iterate bundles
LinkAsset(AssetEntry) - Link to parent assets
See EbxAssetEntry for detailed method documentation.
Usage Examples
Reading a Chunk
Guid chunkId = /* ... chunk GUID ... */;
ChunkAssetEntry entry = assetManager.GetChunkEntry(chunkId);
if (entry != null)
{
Console.WriteLine($"Chunk ID: {entry.Id}");
Console.WriteLine($"Logical Size: {entry.LogicalSize} bytes");
Console.WriteLine($"First Mip: {entry.FirstMip}");
Console.WriteLine($"Is TOC Chunk: {entry.IsTocChunk}");
}
Loading Chunk Data
ChunkAssetEntry chunk = assetManager.GetChunkEntry(chunkId);
using (Stream stream = assetManager.GetChunk(chunk))
{
byte[] chunkData = new byte[chunk.LogicalSize];
stream.Read(chunkData, 0, (int)chunk.LogicalSize);
// Process chunk data
}
Modifying a Chunk
Guid chunkId = /* ... */;
byte[] newData = /* ... modified chunk data ... */;
// For regular chunks
assetManager.ModifyChunk(chunkId, newData);
// For texture chunks (preserves mip information)
Texture texture = /* ... */;
assetManager.ModifyChunk(chunkId, newData, texture);
Creating a New Chunk
byte[] chunkData = /* ... your chunk data ... */;
int[] bundles = { bundleId };
// Create with auto-generated GUID
Guid newChunkId = assetManager.AddChunk(chunkData, bundles: bundles);
// Create with specific GUID
Guid customGuid = Guid.NewGuid();
Guid chunkId = assetManager.AddChunk(
chunkData,
overrideGuid: customGuid,
bundles: bundles
);
Console.WriteLine($"Created chunk: {chunkId}");
Creating a Texture Chunk
Texture texture = /* ... texture resource ... */;
byte[] mipData = /* ... mipmap level data ... */;
int[] bundles = { bundleId };
// Create chunk with texture information
Guid chunkId = assetManager.AddChunk(
mipData,
texture: texture,
bundles: bundles
);
ChunkAssetEntry chunk = assetManager.GetChunkEntry(chunkId);
Console.WriteLine($"Mip level: {chunk.FirstMip}");
Console.WriteLine($"Range: {chunk.RangeStart} - {chunk.RangeEnd}");
Linking Chunks to Resources
ResAssetEntry res = assetManager.GetResEntry("textures/character/diffuse");
ChunkAssetEntry chunk = assetManager.GetChunkEntry(chunkId);
// Link chunk to resource
res.LinkAsset(chunk);
// The chunk now has H32 set to the resource's name hash
Console.WriteLine($"Parent hash: 0x{chunk.H32:X8}");
Finding Parent Resource
ChunkAssetEntry chunk = assetManager.GetChunkEntry(chunkId);
// H32 contains FNV-1 hash of parent resource name
int parentHash = chunk.H32;
// Search for parent resource by hash
foreach (ResAssetEntry res in assetManager.EnumerateRes())
{
int resHash = Fnv1.HashString(res.Name.ToLower());
if (resHash == parentHash)
{
Console.WriteLine($"Parent resource: {res.Name}");
break;
}
}
Enumerating Texture Mipmaps
ResAssetEntry texRes = assetManager.GetResEntry("textures/ui/icon");
// Enumerate linked chunks (mipmaps)
foreach (AssetEntry linked in texRes.LinkedAssets)
{
if (linked is ChunkAssetEntry chunk)
{
Console.WriteLine($"Mip {chunk.FirstMip}: " +
$"{chunk.LogicalSize} bytes, " +
$"range {chunk.RangeStart}-{chunk.RangeEnd}");
}
}
Working with Modified Chunks
ChunkAssetEntry chunk = assetManager.GetChunkEntry(chunkId);
if (chunk.HasModifiedData)
{
ModifiedAssetEntry mod = chunk.ModifiedEntry;
Console.WriteLine($"Modified Size: {mod.Data.Length}");
Console.WriteLine($"Logical Size: {mod.LogicalSize}");
Console.WriteLine($"First Mip: {mod.FirstMip}");
Console.WriteLine($"Range: {mod.RangeStart} - {mod.RangeEnd}");
// Modified chunks may have H32 set
if (mod.H32 != 0)
{
Console.WriteLine($"Parent: 0x{mod.H32:X8}");
}
}
Checking Chunk Bundle Membership
ChunkAssetEntry chunk = assetManager.GetChunkEntry(chunkId);
Console.WriteLine($"In {chunk.Bundles.Count} bundles:");
foreach (int bundleId in chunk.EnumerateBundles())
{
BundleEntry bundle = assetManager.GetBundleEntry(bundleId);
Console.WriteLine($" - {bundle.Name}");
}
// Check if chunk is in specific bundle
if (chunk.IsInBundle(targetBundleId))
{
Console.WriteLine("Chunk is in target bundle");
}
Chunk Compression
Chunks are compressed based on the game profile:
// Compression is handled automatically by AssetManager
// FIFA 18/20 use Oodle compression
if (ProfilesLibrary.DataVersion == (int)ProfileVersion.Fifa18 ||
ProfilesLibrary.DataVersion == (int)ProfileVersion.Fifa20)
{
// Uses Oodle compression
}
else
{
// Uses default compression (ZLib or ZStd)
}
Modified Chunk Entry
When a chunk is modified, additional data is stored:
public class ModifiedAssetEntry
{
public byte[] Data; // Compressed chunk data
public Sha1 Sha1; // SHA-1 hash
public long OriginalSize; // Original size
// Chunk-specific fields
public uint LogicalOffset;
public uint LogicalSize;
public uint RangeStart;
public uint RangeEnd;
public int FirstMip;
public int H32; // Parent resource hash
public bool AddToChunkBundle; // Add to chunk bundle?
public bool IsInline; // Inline in bundle?
}
Special Chunk Types
TOC Chunks
Table of Contents chunks store chunk bundles:
if (chunk.IsTocChunk)
{
Console.WriteLine("This is a TOC chunk");
// TOC chunks have special handling for bundle storage
}
Texture Chunks
Texture mipmaps are stored as chunks:
if (chunk.FirstMip >= 0)
{
Console.WriteLine($"Texture mip level {chunk.FirstMip}");
Console.WriteLine($"Mip range: {chunk.RangeStart} to {chunk.RangeEnd}");
}
Mesh Chunks
Mesh sections may be stored as chunks for streaming:
ChunkAssetEntry meshChunk = /* ... */;
Console.WriteLine($"Mesh section size: {meshChunk.LogicalSize}");