MREA (Metroid Prime 2)
See MREA (File Format) for the other revisions of this format.
The MREA format defines areas (rooms) in Metroid Prime 2. It serves the same purpose as the MREA files from Prime 1, but in Echoes it was updated with new features, including some new data sections and the ability to compress most of the data in the file.
To do: Rest of the article needs to be written. There's a lot known about this format that should be documented. |
Format
Like CMDL, MREA files are split up into a number of 32-byte aligned sections. Every section both starts and ends on a 32-byte boundary. These are used to separate different parts of the file; different types of sections typically indicate different sets of data. The header declares the section count and the size of each one; using these is the only way to navigate the file.
Header
Offset | Type | Count | Name | Description |
---|---|---|---|---|
0x0 | u32 | 1 | Magic | Always 0xDEADBEEF .
|
0x4 | u32 | 1 | Version | See hub article for a list of possible version numbers. |
0x8 | float | 12 | Area Transform | Matrix that represents the area's transform from the origin. Most area data is pre-transformed, so this matrix is only used occasionally. |
0x38 | u32 | 1 | World Model Count | Number of world models in this area. |
0x3C | u32 | 1 | Script Layer Count | Number of script layers in this area. |
0x40 | u32 | 1 | Data Section Count | Number of data sections in the file. |
0x44 | u32 | 1 | Geometry Section | Section index for world geometry data. Always 0; starts on materials. |
0x48 | u32 | 1 | Script Layers Section | Section index for script layer data. |
0x4C | u32 | 1 | Generated Script Objects Section | Section index for generated script object data. |
0x50 | u32 | 1 | Collision Section | Section index for collision data. |
0x54 | u32 | 1 | Unknown Section 1 | Section index for first unknown section. |
0x58 | u32 | 1 | Lights Section | Section index for light data. |
0x5C | u32 | 1 | Visibility Tree Section | Section index for visibility tree data. |
0x60 | u32 | 1 | Path Section | Section index for path data. |
0x64 | u32 | 1 | Unknown Section 2 | Section index for second unknown section. |
0x68 | u32 | 1 | Portal Area Section | Section index for portal area data. |
0x6C | u32 | 1 | Object-To-Static-Geometry Mapping Section | Section index for object-to-static-geometry mapping data. |
0x70 | u32 | 1 | Compressed Block Count | Number of compressed data blocks in the file. |
0x74 | u32 | 3 | Padding | Padding bytes that align the file with the next multiple-of-32 offset. |
0x80 | u32 | Data Section Count | Data Section Sizes | Array containing the size of each data section in the file. Every size is always a multiple of 32. |
Pad to 32 bytes before compressed block definitions begins |
Compressed Blocks
The MREA format contains compressed blocks that can each contain a number of regular file sections within them. The data defining these blocks is at the end of the MREA header; the beginning and end of the compressed block list is padded to 32 bytes. The decompressed size of a block is capped at 0x20000 bytes; each section contains as many MREA sections as it can fit under that size limit. There are two exceptions:
- If a single section's uncompressed size is larger than 0x20000, then its corresponding compressed block can exceed the size limit.
- Each SCLY and SCGN layer is always in its own block, regardless of how close to the limit it is.
This is the structure of each block definition:
Offset | Type | Count | Name | Notes | |
---|---|---|---|---|---|
0x0 | u32 | 1 | Buffer Size | This is always 0x120 bytes larger than the uncompressed size on compressed bytes, and the same value as the uncompressed size on uncompressed blocks | |
0x4 | u32 | 1 | Uncompressed Size | ||
0x8 | u32 | 1 | Compressed Size | This is 0 on uncompressed blocks. | |
0xC | u32 | 1 | Data Section Count | The number of regular data sections contained in this block. | |
0x10 | Block definition end |
The actual data contained in these blocks is padded to 32 bytes, but their padding is located at the beginning of the block rather than the end, so it's required to account for the padding before you start decompressing. Thee data is compressed using segmented LZO1X-999; the "segmented" part means there's multiple segments of data that are compressed/decompressed separately. Each segment starts with a 16-bit size value. The size value is signed; a negative value indicates the segment is not compressed (this is done when compressing a segment doesn't reduce its size). Each segment is 0x4000 bytes large when decompressed (except the last one).