Skip to main content

.streamdb File Extension

.streamdb stands for stream database. The ".tga"streamdb files usedcontain the majority of game data in Doom Eternal are not targa images. They are actually "BIM" (or .bimage) files.

These files are stored in two parts. The header is embedded in Doom Eternal's .resources files. The body of the file is embedded in Doom Eternal's .streamdb files.Eternal. 

File Signature

Doom Eternal ".tga"streamdb" files can be identified by the first 38 bytes of the file header, which is alwaysalways: 0x42 0x49 0x4D0x50A5C2292EF3C761. or "BIM", short for "bimage" or "binary image".

HeaderBasic Structure

The .tgastreamdb headerfile consists of 3 parts. An INDEX section, which is extracteda fromlist Doomof Eternal'sall the files contained within, followed (optionally) by a PREFETCH section, and finally the DATA section, which contains data referenced by the index.

The INDEX contains a list of hashed IDs rather than plaintext names. All files contained within the .streamdb are stored in a headerless format, and are usually compressed via Oodle Kraken or Oodle Leviathan compression technology. This means the files are impossible to identify by looking at the .streamdb alone. (They can, however, be identified by using the .resources files. files as a starting point).

struct STREAM_DB_FILE
{
	INDEX index;
    PREFETCH prefetch;
    DATA data;
};

Index Structure

The .streamdb INDEX structure is of varying length. It consists of of a 63-32-byteHEADER struct,header, followed by a variable number of 36-16-byte MIPMAPentries. structs. EverythingThe overall structure is little-endian.

described

Theas technical details of .resources file extraction are beyond the scope of this article. You can extract the .tga headers yourself using the EternalResourceExtractor toolfollows:

struct ETERNAL_TGA_HEADERINDEX
{
	HEADERstreamDatabaseHeader_t header;					MIPMAP// mipmap[File signature + metadata
	streamDatabaseEntry2_t streamdbEntries[];		// FlexibleOne array16-byte member,entry lengthfor varies witheach header.MipCount;numEntries
};

The HEADERstreamDatabaseHeader_t struct is a 63-32-byte sequence:

struct HEADERstreamDatabaseHeader_t
{		
	charuint64 Signature[3];magic;							// "BIM"50 byteA5 Version;C2 29 2E F3 C7 61
	uint32 headerLength;	
	uint32 pad0;							// 0x15null intpadding
	TextureType;uint32 pad1;							// enumnull textureType_tpadding
	intuint32 TextureMaterialKind;pad2;							// enumnull textureMaterialKind_tpadding
	intuint32 PixelWidth;numEntries;						// imageDoes widthnot ininclude pixelsprefetch intentries
	PixelHeight;uint32 flags;							// imageAlways height in pixels
	int Depth;
    int MipCount; 					// determines # of MIPMAP structs to follow
	int64_t MipLevel;				
	float unkFloat1; 				// usually 1.0, purpose unknown
	byte boolIsEnvironmentMap;		// 1 if image is an environment map
	int TextureFormat;				// enum textureFormat_t
	int Always7;					// literally always 7, purpose unknown
	int nullPadding;
	short AtlasPadding;
	byte boolIsStreamed;			// 1 if file is located in streamDB
	byte unkBool;
	byte boolNoMips;				// 1 if image has no mips
	byte boolFFTBloom;				// 1 if using FFT Bloom
	int StreamDBMipCount; 			// usually same number of mips stored in streamdb3
};

    The

  • TextureType is a member of the enum textureType_t - it marks the image as 2-dimensional, 3-dimensional, or cubic.
  • TextureMaterialKind is a member of the enum textureMaterialKind_t - it tells the engine what type of material this texture is (albedo, normal, specular, etc).
  • TextureFormat is a member of the enum textureFormat_t - it tells the engine how the image is encoded (image format, block compression type, etc).

Mipmap Struct

The MIPMAPstreamDatabaseEntry2_t struct is a 36-16-byte sequencesequence. that comes immediately after the HEADER. This structIt will be repeated repeated n times, where n = streamDatabaseHeader_t.numEntries is. equal to HEADER.MipCount above.

struct MIPMAP
{
	int64_t MipLevel;				// Starts at 0, increment by 1 each time it repeats
	int MipPixelWidth;				// Original PixelWidth reduced by 50% for each MipLevel
	int MipPixelHeight;				// Original PixelHeight reduced by 50% for each MipLevel
	int UnknownFlagA;
	int DecompressedSize;			// Decompressed size in bytes
	int FlagIsCompressed;			// 1 ifTherefore, the texture is compressed
	int CompressedSize;				// Compressed size in bytes
	int CumulativeSizeStreamDB;		
};
  • CumulativeSizeStreamDB is always zero for the first mipmap. For additional mipmaps, it is the sum of previous mipmaps compressed sizes.

The total size (in bytes)length of the TGA_FILE_HEADERINDEX section can be calculated as:as length 63= 32 + (3616 * HEADER.MipCount)streamDatabaseHeader_t.numEntries). 

Non-Streaming
struct Images

streamDatabaseEntry2_t

In{ mostuint64 cases,identity; // Shuffled version of .resources ID uint32 offset16; // Multiply by 16 for data offset within .streamdb uint32 length; // Size of the full-size versions of these ".tga" images are storedfile in .streamdb files,(usually wherecompressed) they}; are

After accessedthe last entry, the INDEX section ends and the PREFETCH section begins.

Prefetch Structure

The .streamdb PREFETCH structure is of varying length. It consists of a 16-byte header, followed (optionally) by theeither gameone engineor two 16-byte prefetchBlocks, and a number of 8-byte prefetchIDs.

The overall PREFETCH structure is described as needed.follows:

However,
struct somePREFETCH 
images{
    arestreamDatabasePrefetchHeader_t prefetchHeader;	// Prefetch section header
    streamDatabasePrefetchBlock_t prefetchBlock[];	// (Optional) Between 0-2 prefetch "non-streaming,"blocks"
	whichuint64 meansprefetchEntries[];						they// aren't(Optional) 0 or more prefetch file IDs.
};

The streamDatabasePrefetchHeader_t struct is a 16-byte sequence. It is always present in the .streamdb filesfile, ateven all.if Non-streamingthis images.streamdb willdoes alwaysnot havecontain aany prefetch entries.

HEADER.boolIsStreamedstruct streamDatabasePrefetchHeader_t
{
	uint32 numPrefetchBlocks;
	uint32 totalLength;						// Total length of 0prefetch header, blocks, entries
}; (false).

InTHIS thatSECTION case,INCOMPLETE, the body of the image is stored in the .resources file, and begins immediately after the TGA_FILE_HEADER structure described above. The offset (in bytes) at which the TGA_FILE_HEADER ends and the non-streamed image begins can be calculated as 63 + (36 * HEADER.MipCount).

Often, there will be several images packed together here (starting with the largest "mip"). The size of each of each image (in bytes) is given by MIPMAP.DecompressedSize.  WIP

010 Editor Template

A 010 Editor template for use with Doom Eternal's TGA.streamdb file headersfiles can be found here: https://github.com/brongo/eternal-010-templates/blob/main/templates/DoomEternalTGA.DoomEternalStreamDB.bt