MKX Format - thethiny/NRS-Asset-Manager GitHub Wiki
MKX (Mortal Kombat X) File Format
Binary format specification for MKX .xxx files. File version 677 (0x2A5), licensee version 157 (0x9D), FourCC "MK10".
Header (FPackageFileSummary) — Variable Size
Unlike IJ2's fixed 100-byte header, MKX serializes FString and TArray fields inline, making the header variable-size.
| # | Field | Type | Notes |
|---|---|---|---|
| 1 | Magic | u32 | 0x9E2A83C1 |
| 2 | FileVersion | u32 | Low u16 = 0x2A5 (677), high u16 = 0x9D (157) |
| 3 | TotalHeaderSize | u32 | Offset where export data begins |
| 4 | MidwayTeamFourCC | 4B | "MK10" |
| 5 | MidwayTeamVersion | u32 | 80 |
| 6 | ShaderVersion | u32 | 102 |
| 7 | MetadataVersion | 16B | MD5 hash (not in IJ2 or MK11) |
| 8 | FolderName | FString | Typically "None\0" (not in IJ2 or MK11) |
| 9 | PackageFlags | u32 | |
| 10 | NameCount | u32 | |
| 11 | NameOffset | u64 | |
| 12 | ExportCount | u32 | |
| 13 | ExportOffset | u64 | |
| 14 | ImportCount | u32 | |
| 15 | ImportOffset | u64 | |
| 16 | GameThreadExportCount | u32 | |
| 17 | DependsOffset | u64 | Not in IJ2 |
| 18 | BulkDataOffset | u64 | Not in IJ2 |
| 19 | ImportExportGuidsOffset | u64 | |
| 20 | ImportGuidsCount | u32 | |
| 21 | ExportGuidsCount | u32 | |
| 22 | ThumbnailTableOffset | u64 | |
| 23 | GUID | 16B | |
| 24 | EngineVersion | u32 | |
| 25 | CookedContentVersion | u32 | |
| 26 | CompressionFlags | u32 | 0x02 = ZLIB |
| 27 | CompressedChunks | TArray | u32 count + FCompressedChunk[] (inline) |
| 28 | AdditionalPackagesToCook | TArray | u32 count + FString[] |
After the TArrays: DiskSizeOfMD5Set (u32+skip), DiskSizeOfClassVersionTable (u32+skip), LinkerRootFullyQualifiedPath (FString, licensee >= 0x75).
FCompressedChunk — 24 bytes
| Field | Size | Type |
|---|---|---|
| UncompressedOffset | 8 | u64 |
| UncompressedSize | 4 | u32 |
| CompressedOffset | 8 | u64 |
| CompressedSize | 4 | u32 |
Export Table Entry (FObjectExport) — 88+ bytes
Variable size due to ComponentMap TMap. Minimum 88 bytes (when ComponentMap count = 0).
| Field | Size | Type | Notes |
|---|---|---|---|
| ClassIndex | 4 | i32 | resolve_object |
| SuperIndex | 4 | i32 | resolve_object |
| OuterIndex | 4 | i32 | resolve_object |
| ObjectName | 8 | FName | index + number |
| ObjectGuid | 16 | GUID | Before ArchetypeIndex (IJ2 puts it after ObjectFlags) |
| ArchetypeIndex | 4 | i32 | resolve_object |
| ReferencedObjects | 4 | i32 | |
| ObjectFlags | 8 | u64 | |
| SerialSize | 4 | u32 | Export data size |
| SerialOffset | 8 | u64 | Export data offset |
| ComponentMap | var | TMap | u32 count + entries (12B each: FName + i32) |
| ExportFlags | 4 | u32 | |
| PackageGuid | 16 | GUID | Not in IJ2 |
Import Table Entry (FObjectImport) — 44 bytes
| Field | Size | Type | Notes |
|---|---|---|---|
| ClassPackage | 8 | FName | |
| ClassName | 8 | FName | |
| OuterIndex | 4 | i32 | |
| ObjectName | 8 | FName | |
| ObjectGuid | 16 | GUID | Not in IJ2 (IJ2 imports are 28 bytes) |
Compression
Algorithm: ZLIB (flag 0x02). NOT Oodle.
Block framing is the same as IJ2:
- BlockHeader (32B): Magic (u32) + Padding (u32) + ChunkSize (u64) + CompressedSize (u64) + DecompressedSize (u64)
- ChunkHeader (16B): CompressedSize (u64) + DecompressedSize (u64)
Also supports LZO (flag 0x01).
Bulk Data
Uses TFC companion files (same mechanism as IJ2), not PSF tables (like MK11).
SkeletalMesh Geometry
Vertex data stored in separated buffers (unlike IJ2's interleaved FSoftSkinVertex chunks):
Sections → IndexBuffer → ShadowIndices → ActiveBoneIndices →
Chunks → NumVertices → Edges → RequiredBones →
PositionVertexBuffer → TangentVertexBuffer → WeightVertexBuffer →
UVVertexBuffer → [ColorVertexBuffer] → DQBlendWeightVertexBuffer →
VertexBufferGPUMorphSkin → AdjacencyIndexBuffer
Position buffer applies X-negation for LH→RH coordinate conversion.
MKO (MKScript) Format
Header: 72 bytes (18 × u32), same as IJ2. Key difference: field 13 is tweakvars_size (byte count) in MKX vs tweakvars (item count) in IJ2.
Function headers: 80 bytes. Uses u64 offsets vs u32 + padding in IJ2.
Section order differs from IJ2: MKX puts bytecode at the END (after all tables), IJ2 puts it at the START. Checked pointers are 4 bytes in MKX (vs 8 in IJ2). Parse success: 462/463 files (99.8%).
FMOD Audio
SND packages contain FmodDesignerProject, FmodEventFile, FmodSourceData, and FmodEvent exports.
FSB encryption: type 1 cipher — decrypted[i] = reverse_bits(encrypted[i]) ^ key[i % key_len]. Key: 996164B5FC0F402983F61F220BB51DC6 (32-byte ASCII). The bIsEncrypted flag at project offset +200 bit 2 controls application.
Cross-Game Comparison
| Feature | MKX (0x2A5) | IJ2 (0x2DC) | MK11 (0x301) |
|---|---|---|---|
| FourCC | MK10 | DCF2 | MK11 |
| Header | Variable (FString+TArray inline) | Fixed 100B | Fixed 104B |
| MetadataVersion | 16-byte MD5 | Not present | Not present |
| FolderName | FString in header | Not present | Not present |
| Compressed chunks | Inline TArray | After header (flat) | Named packages |
| FObjectExport | 88B+ (has PackageGuid) | 72B | 76B |
| FObjectImport | 44B (has ObjectGuid) | 28B | 20B |
| Compression | ZLIB / LZO | Oodle v4 | Oodle v5 |
| Bulk data | TFC files | TFC files | PSF tables |