Difference between revisions of "MLVL (File Format)"
m (→Audio Groups) |
(→Area Dependencies) |
||
(30 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
The '''MLVL format''' defines worlds in the Metroid Prime trilogy and Donkey Kong Country Returns. While the [[MREA (File Format)|MREA format]] defines individual areas, the MLVL is what links together all the areas to create a single cohesive world. | The '''MLVL format''' defines worlds in the Metroid Prime trilogy and Donkey Kong Country Returns. While the [[MREA (File Format)|MREA format]] defines individual areas, the MLVL is what links together all the areas to create a single cohesive world. | ||
− | {{research| | + | {{research|minor|There's a couple unknown values in this format, but they all seem to have constant values.}} |
__TOC__ | __TOC__ | ||
Line 8: | Line 8: | ||
The format largely defines properties related to each area in general and how they link together, as well as things that apply to the world on a global scale across all areas, such as the skybox. | The format largely defines properties related to each area in general and how they link together, as well as things that apply to the world on a global scale across all areas, such as the skybox. | ||
− | |||
− | |||
− | |||
− | |||
{| class="wikitable" | {| class="wikitable" | ||
! Type | ! Type | ||
− | ! | + | ! Count |
− | ! | + | ! Name |
+ | ! Notes | ||
! MP1 | ! MP1 | ||
! MP2 | ! MP2 | ||
Line 23: | Line 20: | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | 1 |
− | | '''Magic''' | + | | '''Magic''' |
+ | | Always <code>0xDEAFBABE</code> | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 31: | Line 29: | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | 1 |
− | | '''Version''' | + | | '''Version''' |
+ | | [[#Version|See below]] | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 38: | Line 37: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | [[STRG (File Format)|STRG]] | + | | Asset ID ([[STRG (File Format)|STRG]]) |
− | | | + | | 1 |
− | | '''World | + | | '''World Name ID''' |
+ | | [[STRG (File Format)|STRG]] file for the world name. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 46: | Line 46: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | [[STRG (File Format)|STRG]] | + | | Asset ID ([[STRG (File Format)|STRG]]) |
− | | | + | | 1 |
− | | '''Dark World Name''' | + | | '''Dark World Name ID''' |
+ | | [[STRG (File Format)|STRG]] file for the Dark World name. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{check}} | | {{check}} | ||
Line 55: | Line 56: | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | 1 |
− | + | | '''Temple Key World Index''' | |
+ | | Controls which temple key icons appear on the map screen. Appears in Prime 3 but always 0. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{check}} | | {{check}} | ||
Line 64: | Line 66: | ||
| bool | | bool | ||
| 1 | | 1 | ||
− | | | + | | '''Has Time Attack''' |
+ | | Indicates whether this world has a Time Attack mode. '''If false, the next five values are not present.''' | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
Line 72: | Line 75: | ||
| string | | string | ||
| 1 | | 1 | ||
− | | '''Level | + | | '''Level Number''' |
+ | | String of the world/level number; for example, "1-1". Purpose unknown. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
Line 79: | Line 83: | ||
|- | |- | ||
| float | | float | ||
− | | | + | | 1 |
− | + | | '''Time Attack Bronze Time''' | |
+ | | Target time for a bronze medal in Time Attack. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
Line 87: | Line 92: | ||
|- | |- | ||
| float | | float | ||
− | | | + | | 1 |
− | + | | '''Time Attack Silver Time''' | |
+ | | Target time for a silver medal in Time Attack. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
Line 95: | Line 101: | ||
|- | |- | ||
| float | | float | ||
− | | | + | | 1 |
− | + | | '''Time Attack Gold Time''' | |
+ | | Target time for a gold medal in Time Attack. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
Line 103: | Line 110: | ||
|- | |- | ||
| float | | float | ||
− | | | + | | 1 |
− | + | | '''Time Attack Shiny Gold Time''' | |
+ | | Target time for a shiny gold medal in Time Attack. | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
Line 110: | Line 118: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | [[SAVW (File Format)|SAVW]] | + | | Asset ID ([[SAVW (File Format)|SAVW]]) |
− | | | + | | 1 |
− | | '''World | + | | '''World Save Info ID''' |
+ | | Asset ID for this world's [[SAVW (File Format)|SAVW]] file. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 118: | Line 127: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | [[CMDL (File Format)|CMDL]] | + | | Asset ID ([[CMDL (File Format)|CMDL]]) |
− | | | + | | 1 |
− | | ''' | + | | '''Default Skybox ID''' |
+ | | [[CMDL (File Format)|CMDL]] file for this world's default skybox model. This can be overridden per-area by AreaAttributes objects. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Memory Relay Count''' | ||
+ | | Count of all outgoing connections from Memory Relay instances in this world. | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | [[#Memory Relay|Memory Relay]] | ||
+ | | ''Memory Relay Count'' | ||
+ | | '''Memory Relay Array''' | ||
+ | | Array describing all outgoing Memory Relay connections in this world. Memory Relays connected to multiple objects are listed multiple times. | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Area Count''' | ||
+ | | Count of areas in this world. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | {{unknown|Unknown}} | ||
+ | | Always 1? | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | [[#Area|Area]] | ||
+ | | ''Area Count'' | ||
+ | | '''Area Array''' | ||
+ | | Array defining all areas that appear in this world. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | Asset ID ([[MAPW (File Format)|MAPW]]) | ||
+ | | 1 | ||
+ | | '''World Map ID''' | ||
+ | | ID of this world's [[MAPW (File Format)|MAPW]] file. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | u8 | ||
+ | | 1 | ||
+ | | {{unknown|Unknown}} | ||
+ | | This is presumably the same unknown value as at the beginning of the [[Scriptable Layers (Metroid Prime)|SCLY]] format. Always 0. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Script Instance Count''' | ||
+ | | The MLVL format embeds a script layer. This script layer is used in the MP1 demo for storing Dock instances, but it's unused in all retail builds, so this is always 0. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Audio Group Count''' | ||
+ | | Count of all audio groups used in this world. | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | [[#Audio Group|Audio Group]] | ||
+ | | ''Audio Group Count'' | ||
+ | | '''Audio Group Array''' | ||
+ | | Array describing all audio groups used in this world. | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | string | ||
+ | | 1 | ||
+ | | {{unknown|Unknown}} | ||
+ | | Always empty, so the only value that ever appears here is the terminating 0. | ||
+ | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Area Count''' | ||
+ | | Will be equal to the earlier area count. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | [[#Area Layer Flags|Area Layer Flags]] | ||
+ | | ''Area Count'' | ||
+ | | '''Area Layer Flags''' | ||
+ | | This array initializes the default active state for all script layers in each area. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Layer Name Count''' | ||
+ | | Count of layer names in the next array. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | string | ||
+ | | ''Layer Name Count'' | ||
+ | | '''Layer Name Array''' | ||
+ | | Array of all layer names in the world. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Layer GUID Count''' | ||
+ | | Count of layer GUIDs in the next array. | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | [[GUID]] | ||
+ | | ''Layer GUID Count'' | ||
+ | | '''Layer GUID Array''' | ||
+ | | Array of GUIDs for each layer. These GUIDs are responsible for storing the layer's ''Active'' state in the save file and are referenced by ScriptLayerController objects. | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | 1 | ||
+ | | '''Area Count''' | ||
+ | | Identical to the previous two area counts. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | u32 | ||
+ | | ''Area Count'' | ||
+ | | '''Area Layer Name Offset Array''' | ||
+ | | Each value is an offset into the layer name array and points to where the layer names for each area begins. | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | colspan=8 {{unknown|End of file}} | ||
|} | |} | ||
− | + | === Version === | |
These are the known version numbers: | These are the known version numbers: | ||
Line 154: | Line 337: | ||
|} | |} | ||
− | === Memory | + | === Memory Relay === |
− | This | + | This structure only appears in Prime 1. It describes an outgoing connection from a Memory Relay to another script instance. Any Memory Relays connected to multiple objects will appear in the array multiple times. |
− | + | ||
− | + | ||
{| class="wikitable" | {| class="wikitable" | ||
! Offset | ! Offset | ||
! Type | ! Type | ||
− | ! | + | ! Name |
− | ! | + | ! Notes |
|- | |- | ||
| 0x0 | | 0x0 | ||
| u32 | | u32 | ||
− | + | | '''Memory Relay Instance ID''' | |
− | | '''Memory Relay | + | | Instance ID of the sender Memory Relay. |
|- | |- | ||
| 0x4 | | 0x4 | ||
| u32 | | u32 | ||
− | + | | '''Target Instance ID''' | |
− | | '''Target | + | | Instance ID of the receiver object. |
|- | |- | ||
| 0x8 | | 0x8 | ||
− | | | + | | u16 |
− | + | ||
| '''Message''' | | '''Message''' | ||
+ | | Script message sent to the receiver object. | ||
|- | |- | ||
− | | | + | | 0xA |
− | | | + | | bool |
− | + | | '''Active''' | |
− | + | | Whether this Memory Relay object is active by default; almost always 0. | |
+ | |- | ||
+ | | 0xB | ||
+ | | colspan=3 {{unknown|End of Memory Relay connection}} | ||
|} | |} | ||
− | === | + | === Area === |
− | This | + | This structure defines a single area and describes its position in the world and how it connects to other areas. |
{| class="wikitable" | {| class="wikitable" | ||
! Type | ! Type | ||
− | ! | + | ! Count |
− | ! | + | ! Name |
+ | ! Notes | ||
! MP1 | ! MP1 | ||
! MP2 | ! MP2 | ||
Line 200: | Line 385: | ||
! DKCR | ! DKCR | ||
|- | |- | ||
− | | | + | | Asset ID ([[STRG (File Format)|STRG]]) |
− | | | + | | 1 |
− | | '''Area | + | | '''Area Name ID''' |
+ | | [[STRG (File Format)|STRG]] ID for the area name. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 208: | Line 394: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | | + | | float |
− | | | + | | 12 |
− | + | | '''Area Transform''' | |
− | | | + | | Area's transform matrix. Most area data is pre-transformed, but there are a few things that need to be transformed by this matrix. |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 236: | Line 403: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | float | + | | float |
− | | | + | | 6 |
− | | ''' | + | | '''Area Bounding Box''' |
+ | | This is the bounding box of the area's collision mesh and is equivalent to the bounding box found in the [[MREA (File Format)|MREA]] collision section. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 244: | Line 412: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | | + | | Asset ID ([[MREA (File Format)|MREA]]) |
− | | | + | | 1 |
− | | ''' | + | | '''Area MREA ID''' |
+ | | ID of this area's [[MREA (File Format)|MREA]] file. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 252: | Line 421: | ||
| {{check}} | | {{check}} | ||
|- | |- | ||
− | | | + | | Asset ID |
− | | | + | | 1 |
− | | '''Area | + | | '''Internal Area ID''' |
+ | | Doesn't actually refer to an asset, but has the same length as an asset ID. This ID is used internally by some things to refer to this area, such as Script Layer Controllers. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 261: | Line 431: | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | 1 |
− | | '''Area | + | | '''Attached Area Count''' |
+ | | Count of areas attached to this one. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
+ | | {{nocheck}} | ||
+ | |- | ||
+ | | u16 | ||
+ | | ''Attached Area Count'' | ||
+ | | '''Attached Area Index Array''' | ||
+ | | Array of area indices attached to this one. | ||
| {{check}} | | {{check}} | ||
− | |} | + | | {{check}} |
− | + | | {{check}} | |
− | + | | {{nocheck}} | |
− | + | |- | |
− | + | | [[#Area Dependencies|Area Dependencies]] | |
− | + | | 1 | |
− | + | | '''Dependencies''' | |
− | { | + | | Asset dependencies in this area. See below for details. Starting in Prime 3, this section has been moved inside the [[MREA (File Format)|MREA]] file. |
− | + | | {{check}} | |
− | + | | {{check}} | |
− | + | | {{nocheck}} | |
− | + | | {{nocheck}} | |
− | + | ||
− | + | ||
− | + | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | 1 |
− | | ''' | + | | '''Dock Count''' |
+ | | Count of Dock instances in this area. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 291: | Line 466: | ||
| {{nocheck}} | | {{nocheck}} | ||
|- | |- | ||
− | | | + | | [[#Dock|Dock]] |
− | | | + | | ''Dock Count'' |
− | | ''' | + | | '''Dock Array''' |
+ | | Array describing all docks in this area. | ||
| {{check}} | | {{check}} | ||
| {{check}} | | {{check}} | ||
Line 299: | Line 475: | ||
| {{nocheck}} | | {{nocheck}} | ||
|- | |- | ||
− | | | + | | [[#Area Module Dependencies|Area Module Dependencies]] |
− | | | + | | 1 |
− | + | | '''Module Dependencies''' | |
− | | {{ | + | | REL module dependencies in this area. See below for details. The equivalent section in Prime 3 and DKCR describing RSO modules has been moved inside the [[MREA (File Format)|MREA]] format. |
+ | | {{nocheck}} | ||
| {{check}} | | {{check}} | ||
| {{nocheck}} | | {{nocheck}} | ||
| {{nocheck}} | | {{nocheck}} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
− | |||
| u32 | | u32 | ||
− | | | + | | 1 |
− | | | + | | {{unknown|Unknown}} |
+ | | Always 0? | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
|- | |- | ||
− | | | + | | string |
− | | | + | | 1 |
− | + | | '''Internal Area Name''' | |
− | | ''' | + | | Internal name of this area. This name will be used ingame on the map screen if no ''Area Name ID'' is specified, prefixed with "!!". |
+ | | {{nocheck}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | | {{check}} | ||
+ | |- | ||
+ | | colspan=8 {{unknown|End of area}} | ||
|} | |} | ||
− | ==== | + | ==== Area Dependencies ==== |
− | This | + | This is a data chunk appearing in the area definition in Metroid Prime 1 and 2 that lists all assets needed to load the area. It's extremely important that this list be optimized and complete, as all assets listed here will be perpetually kept in memory as long as the area itself is in memory; the list also specifies the order that assets are loaded in, so '''it must be grouped by load order to roughly match the [[PAK (File Format)|PAK]] file for optimized load times'''. Assets that are missing will still be dynamically loaded after the area itself is loaded, but this will cause the game to freeze up until the load is finished. There are a few exceptions that are excluded from this list in the original game files (and should be excluded in custom MLVLs as well to avoid out-of-memory crashes): |
− | + | * [[SCAN (File Format)|SCAN]] files and their dependencies are not included in the list in MP1. These are loaded dynamically after the area itself is finished loading, presumably so that scan dependencies are not kept in memory when the scan isn't actually in use. In MP2, SCANs are actually included in the list but their dependencies aren't. | |
− | + | * [[ANCS (File Format)|ANCS]] per-character dependencies for PlayerActor script instances are not included; this allows the game to avoid keeping assets in memory for suits that the player doesn't have. The exception is the Empty Suit character (character index 5 in MP1, and index 3 in MP2), which is a low-memory-overhead character that allows for the list to include all common assets that are stored in the file per-character (such as particle effects). | |
− | + | * The skybox model and its dependencies are not included. | |
− | + | ||
− | + | The dependency list is split by layer; after the dependencies itself, an array of offsets into the dependency list is provided that allows the game to only load assets for layers that are currently active. The last offset points to all common resources used by the area that aren't layer-specific. With that in mind, every layer needs to have a full list of its required assets even if they're also used by other layers. There's no harm in including an asset multiple times, as if an asset is already in memory then it'll simply be skipped over. | |
− | + | ||
− | + | ||
− | | '' | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | This data chunk still exists in Prime 3 and DKCR, but it's been moved inside the [[MREA (File Format)|MREA]] format. | |
{| class="wikitable" | {| class="wikitable" | ||
! Type | ! Type | ||
! Count | ! Count | ||
− | ! | + | ! Name |
+ | ! Notes | ||
|- | |- | ||
| u32 | | u32 | ||
| 1 | | 1 | ||
− | | | + | | {{unknown|Unknown}} |
− | + | | Always 0? | |
− | + | ||
− | | | + | |
− | | | + | |
|- | |- | ||
| u32 | | u32 | ||
| 1 | | 1 | ||
− | + | | '''Dependency Count''' | |
+ | | Count of dependencies. | ||
|- | |- | ||
− | | | + | | [[#Dependency|Dependency]] |
− | | | + | | ''Dependency Count'' |
− | | ''' | + | | '''Dependency Array''' |
− | | | + | | Array of all asset dependencies in this area. |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
|- | |- | ||
| u32 | | u32 | ||
| 1 | | 1 | ||
− | | ''' | + | | '''Dependency Offset Count''' |
+ | | Count of dependency offsets. This will be equal to the area script layer count + 1. | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | ''Dependency Offset Count'' |
− | | ''' | + | | '''Dependency Offset Array''' |
+ | | Array of offsets into the dependency array. There is one offset per script layer, with the offset referring to the index of that layer's first dependency. There is a final extra offset that points to area dependencies that are not layer-specific. | ||
|} | |} | ||
− | ==== | + | ===== Dependency ===== |
− | + | ||
− | + | ||
{| class="wikitable" | {| class="wikitable" | ||
+ | ! Offset | ||
! Type | ! Type | ||
! Count | ! Count | ||
− | ! | + | ! Name |
|- | |- | ||
− | | | + | | 0x0 |
+ | | Asset ID | ||
| 1 | | 1 | ||
− | | ''' | + | | '''Dependency Asset ID''' |
|- | |- | ||
− | | | + | | 0x4 |
− | | | + | | char |
− | | | + | | 4 |
− | + | | '''Dependency Asset Type''' | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | | ''' | + | |
|} | |} | ||
− | ==== | + | ==== Dock ==== |
{| class="wikitable" | {| class="wikitable" | ||
! Type | ! Type | ||
− | ! | + | ! Count |
− | ! | + | ! Name |
− | ! | + | ! Notes |
− | + | ||
− | + | ||
− | + | ||
|- | |- | ||
| u32 | | u32 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
| 1 | | 1 | ||
− | | ''' | + | | '''Connecting Dock Count''' |
− | | | + | | Count of docks connecting to this one. Typically 1 (but there are docks in Prime 3 that connect to multiple areas). |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
|- | |- | ||
− | | [[ | + | | [[#Connecting Dock|Connecting Dock]] |
− | | | + | | ''Connecting Dock Count'' |
− | | ''' | + | | '''Connecting Dock Array''' |
+ | | Array describing all docks connected to this one. | ||
|- | |- | ||
| u32 | | u32 | ||
| 1 | | 1 | ||
− | + | | '''Dock Coordinate Count''' | |
+ | | Array of dock coordinates in the next array. | ||
|- | |- | ||
− | | | + | | Vector3 |
− | | | + | | ''Dock Coordinate Count'' |
− | + | | '''Dock Coordinates''' | |
+ | | Exact purpose/function of this is not known yet. | ||
|} | |} | ||
− | === | + | ===== Connecting Dock ===== |
− | + | ||
− | + | ||
{| class="wikitable" | {| class="wikitable" | ||
+ | ! Offset | ||
! Type | ! Type | ||
− | ! | + | ! Name |
− | ! | + | ! Notes |
|- | |- | ||
+ | | 0x0 | ||
| u32 | | u32 | ||
− | + | | '''Area Index''' | |
− | + | | Index of the area this dock is in. | |
− | | | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
|- | |- | ||
+ | | 0x4 | ||
| u32 | | u32 | ||
− | + | | '''Dock Index''' | |
− | + | | Index of this dock within its area. | |
− | | | + | |
− | + | ||
− | + | ||
− | + | ||
|} | |} | ||
− | === | + | ==== Area Module Dependencies ==== |
− | + | ||
− | + | ||
− | + | ||
− | == | + | |
− | + | ||
− | + | ||
− | + | This is a data chunk appearing in the area definitions that describes all REL modules that must be linked in for this area to run. These are tied to script objects. The list is split per-layer so that only modules being used by the active layer are linked in; modules will appear once in the list for each layer that uses it. After the REL list, there is an array of offsets that points to the starting index in the list for each script layer, similar to the regular area dependencies list. For an unknown reason, the offsets list contains two offsets per layer. The first one refers to the layer's start index while the second one is usually empty, which effectively makes it an end index. | |
{| class="wikitable" | {| class="wikitable" | ||
! Type | ! Type | ||
− | ! | + | ! Count |
− | ! | + | ! Name |
+ | ! Notes | ||
|- | |- | ||
| u32 | | u32 | ||
− | | | + | | 1 |
− | | ''' | + | | '''REL Module Count''' |
+ | | Count of REL modules in the next array. | ||
|- | |- | ||
− | | | + | | string |
− | | | + | | ''REL Module Count'' |
− | | ''' | + | | '''REL Module Array''' |
− | | | + | | REL modules used by this area. Each array entry is the filename of a .REL module. |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
|- | |- | ||
| u32 | | u32 | ||
| 1 | | 1 | ||
− | | ''' | + | | '''REL Offset Count''' |
+ | | Count of REL offsets in the next array. Should be equal to the area script layer count * 2. | ||
|- | |- | ||
− | | | + | | u32 |
− | | | + | | ''REL Offset Count'' |
− | | ''' | + | | '''REL Offset Array''' |
+ | | Array of offsets into the ''REL Module Array''. There are two offsets per script layer, with the first one being that layer's start index and the second one effectively being that layer's end index. | ||
|} | |} | ||
− | === | + | === Audio Group === |
− | This | + | This structure is only present in Prime 1 and describes an [[AGSC (File Format)|AGSC]] file being used in this world. |
{| class="wikitable" | {| class="wikitable" | ||
+ | ! Offset | ||
! Type | ! Type | ||
− | ! | + | ! Name |
− | ! | + | ! Notes |
|- | |- | ||
+ | | 0x0 | ||
| u32 | | u32 | ||
− | | | + | | '''Group ID''' |
− | | | + | | Group ID for this audio group. This is the same value that can be found in the Project chunk in the referenced [[AGSC (File Format)|AGSC]] file. |
+ | |- | ||
+ | | 0x4 | ||
+ | | Asset ID ([[AGSC (File Format)|AGSC]]) | ||
+ | | '''AGSC ID''' | ||
+ | | The [[AGSC (File Format)|AGSC]] file for this audio group. | ||
|- | |- | ||
− | | | + | | 0x8 |
− | + | | colspan=3 {{unknown|End of audio group definition}} | |
− | | {{unknown| | + | |
|} | |} | ||
− | === | + | === Area Layer Flags === |
+ | |||
+ | This is a small structure that determines which areas are active by default. It contains a layer count and then a 64-bit flag, with each bit corresponding to a particular layer; if the bit is set, then the layer will be active on a new save file. The low-order bits correspond to the lower layer indices. Bits for layers that don't exist are defaulted to on. | ||
− | + | Note that due to the size of these flags as well as a few other pieces of data in other formats, the maximum number of layers that can be contained in a single area is 64. | |
{| class="wikitable" | {| class="wikitable" | ||
+ | ! Offset | ||
! Type | ! Type | ||
− | ! | + | ! Name |
− | ! | + | ! Notes |
|- | |- | ||
+ | | 0x0 | ||
| u32 | | u32 | ||
− | + | | '''Layer Count''' | |
− | | ''' | + | | Count of layers in this area. |
|- | |- | ||
− | | | + | | 0x4 |
− | | | + | | u64 |
− | | ''' | + | | '''Layer Flags''' |
+ | | See above for a description of how these work. | ||
+ | |- | ||
+ | | 0x8 | ||
+ | | colspan=3 {{unknown|End of area layer flags}} | ||
|} | |} | ||
Latest revision as of 10:13, 10 August 2019
The MLVL format defines worlds in the Metroid Prime trilogy and Donkey Kong Country Returns. While the MREA format defines individual areas, the MLVL is what links together all the areas to create a single cohesive world.
This file format is almost completely documented There's a couple unknown values in this format, but they all seem to have constant values. |
Contents
Format
The format largely defines properties related to each area in general and how they link together, as well as things that apply to the world on a global scale across all areas, such as the skybox.
Type | Count | Name | Notes | MP1 | MP2 | MP3 | DKCR |
---|---|---|---|---|---|---|---|
u32 | 1 | Magic | Always 0xDEAFBABE
|
✔ | ✔ | ✔ | ✔ |
u32 | 1 | Version | See below | ✔ | ✔ | ✔ | ✔ |
Asset ID (STRG) | 1 | World Name ID | STRG file for the world name. | ✔ | ✔ | ✔ | ✔ |
Asset ID (STRG) | 1 | Dark World Name ID | STRG file for the Dark World name. | ✖ | ✔ | ✖ | ✖ |
u32 | 1 | Temple Key World Index | Controls which temple key icons appear on the map screen. Appears in Prime 3 but always 0. | ✖ | ✔ | ✔ | ✖ |
bool | 1 | Has Time Attack | Indicates whether this world has a Time Attack mode. If false, the next five values are not present. | ✖ | ✖ | ✖ | ✔ |
string | 1 | Level Number | String of the world/level number; for example, "1-1". Purpose unknown. | ✖ | ✖ | ✖ | ✔ |
float | 1 | Time Attack Bronze Time | Target time for a bronze medal in Time Attack. | ✖ | ✖ | ✖ | ✔ |
float | 1 | Time Attack Silver Time | Target time for a silver medal in Time Attack. | ✖ | ✖ | ✖ | ✔ |
float | 1 | Time Attack Gold Time | Target time for a gold medal in Time Attack. | ✖ | ✖ | ✖ | ✔ |
float | 1 | Time Attack Shiny Gold Time | Target time for a shiny gold medal in Time Attack. | ✖ | ✖ | ✖ | ✔ |
Asset ID (SAVW) | 1 | World Save Info ID | Asset ID for this world's SAVW file. | ✔ | ✔ | ✔ | ✔ |
Asset ID (CMDL) | 1 | Default Skybox ID | CMDL file for this world's default skybox model. This can be overridden per-area by AreaAttributes objects. | ✔ | ✔ | ✔ | ✔ |
u32 | 1 | Memory Relay Count | Count of all outgoing connections from Memory Relay instances in this world. | ✔ | ✖ | ✖ | ✖ |
Memory Relay | Memory Relay Count | Memory Relay Array | Array describing all outgoing Memory Relay connections in this world. Memory Relays connected to multiple objects are listed multiple times. | ✔ | ✖ | ✖ | ✖ |
u32 | 1 | Area Count | Count of areas in this world. | ✔ | ✔ | ✔ | ✔ |
u32 | 1 | Unknown | Always 1? | ✔ | ✖ | ✖ | ✖ |
Area | Area Count | Area Array | Array defining all areas that appear in this world. | ✔ | ✔ | ✔ | ✔ |
Asset ID (MAPW) | 1 | World Map ID | ID of this world's MAPW file. | ✔ | ✔ | ✔ | ✖ |
u8 | 1 | Unknown | This is presumably the same unknown value as at the beginning of the SCLY format. Always 0. | ✔ | ✔ | ✔ | ✖ |
u32 | 1 | Script Instance Count | The MLVL format embeds a script layer. This script layer is used in the MP1 demo for storing Dock instances, but it's unused in all retail builds, so this is always 0. | ✔ | ✔ | ✔ | ✖ |
u32 | 1 | Audio Group Count | Count of all audio groups used in this world. | ✔ | ✖ | ✖ | ✖ |
Audio Group | Audio Group Count | Audio Group Array | Array describing all audio groups used in this world. | ✔ | ✖ | ✖ | ✖ |
string | 1 | Unknown | Always empty, so the only value that ever appears here is the terminating 0. | ✔ | ✖ | ✖ | ✖ |
u32 | 1 | Area Count | Will be equal to the earlier area count. | ✔ | ✔ | ✔ | ✔ |
Area Layer Flags | Area Count | Area Layer Flags | This array initializes the default active state for all script layers in each area. | ✔ | ✔ | ✔ | ✔ |
u32 | 1 | Layer Name Count | Count of layer names in the next array. | ✔ | ✔ | ✔ | ✔ |
string | Layer Name Count | Layer Name Array | Array of all layer names in the world. | ✔ | ✔ | ✔ | ✔ |
u32 | 1 | Layer GUID Count | Count of layer GUIDs in the next array. | ✖ | ✖ | ✔ | ✔ |
GUID | Layer GUID Count | Layer GUID Array | Array of GUIDs for each layer. These GUIDs are responsible for storing the layer's Active state in the save file and are referenced by ScriptLayerController objects. | ✖ | ✖ | ✔ | ✔ |
u32 | 1 | Area Count | Identical to the previous two area counts. | ✔ | ✔ | ✔ | ✔ |
u32 | Area Count | Area Layer Name Offset Array | Each value is an offset into the layer name array and points to where the layer names for each area begins. | ✔ | ✔ | ✔ | ✔ |
End of file |
Version
These are the known version numbers:
ID | Game |
---|---|
0xD | Metroid Prime Demo |
0x11 | Metroid Prime |
0x14 | Metroid Prime 2 Demo |
0x17 | Metroid Prime 2 |
0x19 | Metroid Prime 3 |
0x1B | Donkey Kong Country Returns |
Memory Relay
This structure only appears in Prime 1. It describes an outgoing connection from a Memory Relay to another script instance. Any Memory Relays connected to multiple objects will appear in the array multiple times.
Offset | Type | Name | Notes |
---|---|---|---|
0x0 | u32 | Memory Relay Instance ID | Instance ID of the sender Memory Relay. |
0x4 | u32 | Target Instance ID | Instance ID of the receiver object. |
0x8 | u16 | Message | Script message sent to the receiver object. |
0xA | bool | Active | Whether this Memory Relay object is active by default; almost always 0. |
0xB | End of Memory Relay connection |
Area
This structure defines a single area and describes its position in the world and how it connects to other areas.
Type | Count | Name | Notes | MP1 | MP2 | MP3 | DKCR |
---|---|---|---|---|---|---|---|
Asset ID (STRG) | 1 | Area Name ID | STRG ID for the area name. | ✔ | ✔ | ✔ | ✔ |
float | 12 | Area Transform | Area's transform matrix. Most area data is pre-transformed, but there are a few things that need to be transformed by this matrix. | ✔ | ✔ | ✔ | ✔ |
float | 6 | Area Bounding Box | This is the bounding box of the area's collision mesh and is equivalent to the bounding box found in the MREA collision section. | ✔ | ✔ | ✔ | ✔ |
Asset ID (MREA) | 1 | Area MREA ID | ID of this area's MREA file. | ✔ | ✔ | ✔ | ✔ |
Asset ID | 1 | Internal Area ID | Doesn't actually refer to an asset, but has the same length as an asset ID. This ID is used internally by some things to refer to this area, such as Script Layer Controllers. | ✔ | ✔ | ✔ | ✔ |
u32 | 1 | Attached Area Count | Count of areas attached to this one. | ✔ | ✔ | ✔ | ✖ |
u16 | Attached Area Count | Attached Area Index Array | Array of area indices attached to this one. | ✔ | ✔ | ✔ | ✖ |
Area Dependencies | 1 | Dependencies | Asset dependencies in this area. See below for details. Starting in Prime 3, this section has been moved inside the MREA file. | ✔ | ✔ | ✖ | ✖ |
u32 | 1 | Dock Count | Count of Dock instances in this area. | ✔ | ✔ | ✔ | ✖ |
Dock | Dock Count | Dock Array | Array describing all docks in this area. | ✔ | ✔ | ✔ | ✖ |
Area Module Dependencies | 1 | Module Dependencies | REL module dependencies in this area. See below for details. The equivalent section in Prime 3 and DKCR describing RSO modules has been moved inside the MREA format. | ✖ | ✔ | ✖ | ✖ |
u32 | 1 | Unknown | Always 0? | ✖ | ✖ | ✖ | ✔ |
string | 1 | Internal Area Name | Internal name of this area. This name will be used ingame on the map screen if no Area Name ID is specified, prefixed with "!!". | ✖ | ✔ | ✔ | ✔ |
End of area |
Area Dependencies
This is a data chunk appearing in the area definition in Metroid Prime 1 and 2 that lists all assets needed to load the area. It's extremely important that this list be optimized and complete, as all assets listed here will be perpetually kept in memory as long as the area itself is in memory; the list also specifies the order that assets are loaded in, so it must be grouped by load order to roughly match the PAK file for optimized load times. Assets that are missing will still be dynamically loaded after the area itself is loaded, but this will cause the game to freeze up until the load is finished. There are a few exceptions that are excluded from this list in the original game files (and should be excluded in custom MLVLs as well to avoid out-of-memory crashes):
- SCAN files and their dependencies are not included in the list in MP1. These are loaded dynamically after the area itself is finished loading, presumably so that scan dependencies are not kept in memory when the scan isn't actually in use. In MP2, SCANs are actually included in the list but their dependencies aren't.
- ANCS per-character dependencies for PlayerActor script instances are not included; this allows the game to avoid keeping assets in memory for suits that the player doesn't have. The exception is the Empty Suit character (character index 5 in MP1, and index 3 in MP2), which is a low-memory-overhead character that allows for the list to include all common assets that are stored in the file per-character (such as particle effects).
- The skybox model and its dependencies are not included.
The dependency list is split by layer; after the dependencies itself, an array of offsets into the dependency list is provided that allows the game to only load assets for layers that are currently active. The last offset points to all common resources used by the area that aren't layer-specific. With that in mind, every layer needs to have a full list of its required assets even if they're also used by other layers. There's no harm in including an asset multiple times, as if an asset is already in memory then it'll simply be skipped over.
This data chunk still exists in Prime 3 and DKCR, but it's been moved inside the MREA format.
Type | Count | Name | Notes |
---|---|---|---|
u32 | 1 | Unknown | Always 0? |
u32 | 1 | Dependency Count | Count of dependencies. |
Dependency | Dependency Count | Dependency Array | Array of all asset dependencies in this area. |
u32 | 1 | Dependency Offset Count | Count of dependency offsets. This will be equal to the area script layer count + 1. |
u32 | Dependency Offset Count | Dependency Offset Array | Array of offsets into the dependency array. There is one offset per script layer, with the offset referring to the index of that layer's first dependency. There is a final extra offset that points to area dependencies that are not layer-specific. |
Dependency
Offset | Type | Count | Name |
---|---|---|---|
0x0 | Asset ID | 1 | Dependency Asset ID |
0x4 | char | 4 | Dependency Asset Type |
Dock
Type | Count | Name | Notes |
---|---|---|---|
u32 | 1 | Connecting Dock Count | Count of docks connecting to this one. Typically 1 (but there are docks in Prime 3 that connect to multiple areas). |
Connecting Dock | Connecting Dock Count | Connecting Dock Array | Array describing all docks connected to this one. |
u32 | 1 | Dock Coordinate Count | Array of dock coordinates in the next array. |
Vector3 | Dock Coordinate Count | Dock Coordinates | Exact purpose/function of this is not known yet. |
Connecting Dock
Offset | Type | Name | Notes |
---|---|---|---|
0x0 | u32 | Area Index | Index of the area this dock is in. |
0x4 | u32 | Dock Index | Index of this dock within its area. |
Area Module Dependencies
This is a data chunk appearing in the area definitions that describes all REL modules that must be linked in for this area to run. These are tied to script objects. The list is split per-layer so that only modules being used by the active layer are linked in; modules will appear once in the list for each layer that uses it. After the REL list, there is an array of offsets that points to the starting index in the list for each script layer, similar to the regular area dependencies list. For an unknown reason, the offsets list contains two offsets per layer. The first one refers to the layer's start index while the second one is usually empty, which effectively makes it an end index.
Type | Count | Name | Notes |
---|---|---|---|
u32 | 1 | REL Module Count | Count of REL modules in the next array. |
string | REL Module Count | REL Module Array | REL modules used by this area. Each array entry is the filename of a .REL module. |
u32 | 1 | REL Offset Count | Count of REL offsets in the next array. Should be equal to the area script layer count * 2. |
u32 | REL Offset Count | REL Offset Array | Array of offsets into the REL Module Array. There are two offsets per script layer, with the first one being that layer's start index and the second one effectively being that layer's end index. |
Audio Group
This structure is only present in Prime 1 and describes an AGSC file being used in this world.
Offset | Type | Name | Notes |
---|---|---|---|
0x0 | u32 | Group ID | Group ID for this audio group. This is the same value that can be found in the Project chunk in the referenced AGSC file. |
0x4 | Asset ID (AGSC) | AGSC ID | The AGSC file for this audio group. |
0x8 | End of audio group definition |
Area Layer Flags
This is a small structure that determines which areas are active by default. It contains a layer count and then a 64-bit flag, with each bit corresponding to a particular layer; if the bit is set, then the layer will be active on a new save file. The low-order bits correspond to the lower layer indices. Bits for layers that don't exist are defaulted to on.
Note that due to the size of these flags as well as a few other pieces of data in other formats, the maximum number of layers that can be contained in a single area is 64.
Offset | Type | Name | Notes |
---|---|---|---|
0x0 | u32 | Layer Count | Count of layers in this area. |
0x4 | u64 | Layer Flags | See above for a description of how these work. |
0x8 | End of area layer flags |