Unreal Engine 4 UASSET UEXP
Back to index | Edit this page
UASSET, UEXP
- Format Type : Archive
- Endian Order : Little Endian
- Signature : C1 83 2A 9E
Format Specifications
Unreal Engine 4 uasset file
DETAILS OF THE IMPORT DIRECTORY...
The ParentDirectoryNameID is the name
The first few entries in the Import directory is ClassID = "Class" and NameID = the main data type (eg "Texture2D", "Material")
The last entry is ClassID = "Package" and NameID = the main package name (eg "/Script/Engine")
FILE HEADER
uint32 {4} - Unreal Signature (193,131,42,158) // C1 83 2A 9E
uint32 {4} - Version (6) (XOR with 255)
byte {16} - null
uint32 {4} - File Directory Offset?
uint32 {4} - Unknown (5)
uint32 {4} - Package Name (None)
uint32 {4} - null
byte {1} - Unknown (128)
uint32 {4} - Number of Names
uint32 {4} - Name Directory Offset
uint64 {8} - null
uint32 {4} - Number Of Exports
uint32 {4} - Exports Directory Offset
uint32 {4} - Number Of Imports
uint32 {4} - Import Directory Offset
byte {20} - null
byte {16} - GUID Hash
uint32 {4} - Unknown (1)
uint32 {4} - Unknown (1/2)
uint32 {4} - Unknown (Number of Names - again?)
byte {36} - null
uint32 {4} - Unknown
uint32 {4} - null
uint32 {4} - Padding Offset
uint32 {4} - File Length [+4] (not always - sometimes an unknown length/offset)
byte {12} - null
uint32 {4} - Unknown (-1)
uint32 {4} - Files Data Offset
NAMES DIRECTORY
for each name
uint32 {4} - Name Length (including null)
byte {X} - Name
byte {1} - null Name Terminator
uint32 {4} - Flags
IMPORT DIRECTORY
for each import (28 bytes per entry)
uint64 {8} - Parent Directory Name ID
uint64 {8} - Class ID (ID to "Package", "Class", etc)
uint32 {4} - Parent Import Object ID (-1 for no parent) (XOR with 255)
uint32 {4} - Name ID
uint32 {4} - Unknown ID
EXPORTS DIRECTORY
for each export (100 bytes per entry)
byte {100} - Unknown
PADDING
uint32 {4} - null
FILE DATA
for each file ???
for each property (continue until NameID == "None")
uint64 {8} - Name ID
if (NameID != None){
uint64 {8} - Class ID
uint64 {8} - Length Property
if (classID == StructProperty){
uint64 {8} - Class ID
uint64 {8} - null
uint64 {8} - null
if (classID == IntPoint){
byte {1} - null
uint32 {4} - Point X
uint32 {4} - Point Y
}
else if (classID == Guid){
byte {1} - null
byte {16} - GUID
}
else if (classID == ColorMaterialInput){
byte {1} - null
byte {X} - Color Material Input Data (the length of X = LengthProperty from above)
}
else if (classID == ScalarMaterialInput){
byte {1} - null
byte {X} - Scalar Material Input Data (the length of X = LengthProperty from above)
}
else if (classID == TextureStreamingData){
byte {1} - null
uint64 {8} - null
uint64 {8} - null
}
else if (classID == MaterialTextureInfo){
byte {1} - null
Now keep reading properties until a "None" is reached - all these properties form the MaterialTextureInfo class
}
else if (classID == FontCharacter){
byte {1} - null
uint32 {4} - Unknown
uint32 {4} - Unknown
uint32 {4} - Unknown
uint64 {8} - Unknown
}
else if (classID == FontImportOptionsData){
byte {1} - null
Now keep reading properties until a "None" is reached - all these properties form the FontImportOptionsData class
These fields come after the property reading above
uint64 {8} - Class ID (points to None)
uint32 {4} - null
uint32 {4} - Extra Data Length [*4]
byte {X} - Extra Data
}
else {
use the structure of one of the other properties (eg BoolProperty, ByteProperty, etc)
}
}
else if (classID == BoolProperty){
uint16 {2} - Boolean Value (0/1)
}
else if (classID == FloatProperty){
byte {1} - null
uint32 {4} - Float Value
}
else if (classID == NameProperty){
byte {1} - null
uint32 {4} - Name ID
uint32 {4} - Unknown
}
else if (classID == IntProperty){
byte {1} - null
uint32 {4} - Integer Value
}
else if (classID == StrProperty){
byte {1} - null
uint32 {4} - String Length (including null terminator)
byte {X} - String
byte {1} - null String Terminator
}
else if (classID == ObjectProperty){
uint32 {4} - Property
}
else if (classID == ByteProperty){
byte {X} - Bytes (the length of X = LengthProperty from above)
byte {1} - null
byte {X} - Bytes (the length of X = LengthProperty from above)
}
else if (classID == ArrayProperty){
uint64 {8} - Class ID
byte {1} - null
NOTE: LengthProperty from above gives the length of the next 4-byte field and the full contents of the array "for" loop
uint32 {4} - Number of Values in the Array
if (classID == StructProperty){
first comes the normal 4-field handler
uint64 {8} - Name ID
uint64 {8} - Class ID
uint64 {8} - Length Property
then comes the normal StructProperty handler
uint64 {8} - Class ID <-- this is the Class for each item in the array
uint64 {8} - null
uint64 {8} - null
}
for each value in the array {
use the structure of one of the other properties (eg BoolProperty, ByteProperty, etc)
Either use the ClassID from the ArrayProperty definition, or if that is a StructProperty, use the ClassID in the StructProperty handler (details above)
}
if (classID == StructProperty && numberOfValuesInArray > 1){
byte {1} - null
}
}
}
uint32 {4} - null
uint16 {2} - Flags (1/3)
uint16 {2} - Flags (1/0)
uint32 {4} - Unknown (1)
uint64 {8} - Type ID (points to "PF_DXT5", "PF_B8G8R8A8", etc for a Texture2D Image)
if (typeID == PF_DXT5 || PF_DXT3 || PF_DXT1){
uint32 {4} - Offset to Largest Mipmap [+8]
uint32 {4} - Original Image Width
uint32 {4} - Original Image Height
uint32 {4} - Unknown (1)
uint32 {4} - Type Name Length (including null) (8)
byte {7} - Type Name (PF_DXT5/3/1)
byte {1} - null Type Name Terminator
uint32 {4} - null
uint32 {4} - Mipmap Count
for each large mipmap (where width/height >= 128), starting with largest mipmap and decreasing each time by /2
uint32 {4} - Entry Indicator (1)
uint32 {4} - Flags (1025)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Relative Offset to this mipmap (relative to the start of the largest mipmap data)
uint32 {4} - This Mipmap Width
uint32 {4} - This Mipmap Height
for each Small Mipmap...
uint32 {4} - Entry Indicator (1)
uint32 {4} - Flags (72)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Offset to start of Mipmap Data
byte {X} - DXT5/3/1 Pixel Data
uint32 {4} - This Mipmap Width
uint32 {4} - This Mipmap Height
uint32 {4} - Mipmap Count
uint32 {4} - null
for each large mipmap (where width/height >= 128), starting with largest mipmap and decreasing each time by /2
byte {X} - DXT5/3/1 Pixel Data
}
else if (typeID == PF_B8G8R8A8){
uint32 {4} - Offset to Largest Mipmap [+8]
uint32 {4} - Original Image Width
uint32 {4} - Original Image Height
uint32 {4} - Unknown (1)
uint32 {4} - Type Name Length (including null) (12)
byte {11} - Type Name (PF_B8G8R8A8)
byte {1} - null Type Name Terminator
uint32 {4} - null
uint32 {4} - Mipmap Count
for each large mipmap (where width/height >= 128), starting with largest mipmap and decreasing each time by /2
uint32 {4} - Entry Indicator (1)
uint32 {4} - Flags (1025)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Relative Offset to this mipmap (relative to the start of the largest mipmap data)
uint32 {4} - This Mipmap Width
uint32 {4} - This Mipmap Height
for each Small Mipmap...
uint32 {4} - Entry Indicator (1)
uint32 {4} - Flags (72)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Offset to start of Mipmap Data
byte {X} - BGRA Pixel Data
uint32 {4} - This Mipmap Width
uint32 {4} - This Mipmap Height
uint32 {4} - Mipmap Count
uint32 {4} - null
for each large mipmap (where width/height >= 128), starting with largest mipmap and decreasing each time by /2
byte {X} - BGRA Pixel Data
}
else if (typeID == PF_BC5){
uint32 {4} - Offset to Largest Mipmap [+8]
uint32 {4} - Original Image Width
uint32 {4} - Original Image Height
uint32 {4} - Unknown (1)
uint32 {4} - Type Name Length (including null) (7)
byte {6} - Type Name (PF_BC5)
byte {1} - null Type Name Terminator
uint32 {4} - Unknown (1)
uint32 {4} - Mipmap Count
for each large mipmap (where width/height >= 128), starting with largest mipmap and decreasing each time by /2
uint32 {4} - Entry Indicator (1)
uint32 {4} - Flags (1025)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Relative Offset to this mipmap (relative to the start of the largest mipmap data)
uint32 {4} - This Mipmap Width
uint32 {4} - This Mipmap Height
for each small mipmap (where width/height < 128), decreasing each time by /2..
uint32 {4} - Entry Indicator (1)
uint32 {4} - Flags (72)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Offset to start of Mipmap Data
byte {X} - BC5 Pixel Data
uint32 {4} - This Mipmap Width
uint32 {4} - This Mipmap Height
uint32 {4} - Mipmap Count
uint32 {4} - null
for each large mipmap (where width/height >= 128), starting with largest mipmap and decreasing each time by /2
byte {X} - BC5 Pixel Data
}
else if (typeID == PF_G8){
uint32 {4} - Length of Image Data?
uint32 {4} - Image Width
uint32 {4} - Image Height
uint32 {4} - Unknown (1)
uint32 {4} - Type Name Length (including null) (6)
byte {5} - Type Name (PF_G8)
byte {1} - null Type Name Terminator
uint32 {4} - null
uint32 {4} - Mipmap Count (1)
uint32 {4} - Unknown (1)
uint32 {4} - Flags? (72)
uint32 {4} - Length of Mipmap Data
uint32 {4} - Length of Mipmap Data
uint64 {8} - Offset to start of Mipmap Data (absolute offset)
byte {X} - Greyscale Pixel Data
uint32 {4} - Image Width
uint32 {4} - ImageHeight
uint64 {8} - Unknown (28)
}
else {
NOT A TEXTURE IMAGE (or an unknown Texture format)
byte {X} - File Data
}
FILE FOOTER
uint32 {4} - Unreal Signature (193,131,42,158) // C1 83 2A 9E
MultiEx BMS Script
Not written yet.
Notes and Comments
- Archives may be splitted to .uasset and .uexp files - the first one contains file header, second one - all the data.
- There is a method to make working translations for games when UEXP files contain only text data:
- Parse uexp file and extract text.
- Translate text to your language
- Rebuild uexp file. Add 4-byte footer at the end of the file.
- Update uexp size in the uasset's footer.
Games
List of games using this file format:
- Bravely Default II (*.uasset / *.uexp)
- Daymare: 1994 Sandcastle (*.uasset / *.uexp)
- Dreadout 2 (*.uasset / *.uexp)
- GUILTY GEAR -STRIVE- (*.uasset / *.uexp)
- Man of Medan (*.uasset / *.uexp)
- Martha Is Dead (*.uasset / *.uexp)
- Marvel vs. Capcom: Infinite (*.uasset)
- Monkey King: Hero is Back (*.uasset / *.uexp)
- My Hero One's Justice 2 (*.uasset / *.uexp)
- No More Heroes 3 (*.uasset / *.uexp)
- Pumpkin Jack (PC) (*.uasset)
- Remothered Tormented Fathers (PC) (*.uasset)
- Shinobi Striker (*.uasset)
- Soul Calibur VI (*.uasset)
- Tekken 7 (PC) (*.uasset)
- The Sinking City (*.uasset / *.uexp)
- many more...
Compatible Programs
- CUE4Parse
- DAUM
- Game Extractor
- Gildor's Tools
- FModel
- pyUE4Parse
- uasset-dt-to-json
- uexptool + source code (only for Soul Calibur VI?)
- Unreal Engine Uasset Viewer/Editor
- Unreal Engine (Since Unreal 4.22 you can load cooked asset(.uasset .uexp) in the engine itself. But that requiere that you use the same engine version as the file was cook with.)
See Also
Gallery
-
FModel
-
Asset Editor