LEB

Revision as of 06:30, 3 November 2021 by Glan (talk | contribs) (→‎Grid Section: added info)

LEB is a custom format used to store room data in Link's Awakening.

This format is still in the process of being reverse engineered and so this page is currently incomplete.

Format

LEB files are in a FixedHash format, with the data for actors stored in the data section and the names section. There is consistency in how the FixedHash is built for LEB files, with the exception of Lv07EagleTower_05E (the lower part of the Eagle boss room), which for some reason is different than all other rooms. Aside from this room, LEBs always have 0x17 hash table buckets and 0x4 child FixedHash nodes. The buckets are always the same, so the start of LEB files always look like:

3d01 1700 0400 0000 ffff ffff 0000 0000

2000 0000 ffff ffff ffff ffff ffff ffff

ffff ffff ffff ffff 4000 0000 ffff ffff

ffff ffff 5000 0000 ffff ffff 3000 0000

ffff ffff ffff ffff ffff ffff ffff ffff

ffff ffff ffff ffff ffff ffff ffff ffff

ffff ffff

Entries Section

There are 6 entries in most LEB files.

Node Index Name Offset Name Hash Next entry offset Data Offset
0xFFF0 Offset of versionin the names section Hash of version 0xFFFFFFFF Offset to version section
0xFFF0 Offset of infomationin the names section [sic] Hash of infomation 0xFFFFFFFF Offset to infomation
0x0 Offset of pointin the names section Hash of point 0xFFFFFFFF Offset to point section
0x1 Offset of railin the names section Hash of rail 0xFFFFFFFF Offset to rail section
0x2 Offset of actorin the names section Hash of actor 0x10 Offset to actor section
0x3 Offset of gridin the names section Hash of grid 0xFFFFFFFF Offset to grid secion


Data Section

The data section contains one subsection for each entry (usually six).

Version Section

This section holds a u64 with the value 0x3 (specifying 3 bytes of data), followed by the 3 bytes of data, which seem to always be 0x1001D4. Whether it has a purpose is unclear. Given the name, it could just be a version marker. Following this is five empty bytes.

Infomation Section

This section holds a u64 with the value 0x4 (specifying 4 bytes of data), followed by the 4 bytes of data. Its purpose is unknown. Following this is four empty bytes.

Point Section

This is a FixedHash child. It's usually empty and has 1 bucket and no child nodes. The names section is empty. Purpose unknown.

An example of a room which has a non-empty FixedHash here is Lv01TailCave_04G (Moldorm boss room).

Rail Section

This is another FixedHash child. Usually it's empty and has 1 bucket and no child nodes. The names section is empty. Purpose unknown.

An example of a room which has a non-empty FixedHash here is Lv01TailCave_04G (Moldorm boss room).

Actor Section

This section is a FixedHash which holds actor data. Each entry corresponds to one actor. Every entry points to non-node data, a block with a minimum size of 0x90 bytes, but can be longer. The names section is empty. The data block for each actor is formatted as follows. Some properties are related to measurements along the three axes; since Link's Awakening is a top-down game we will call the vertical axis Z (i.e. the axis perpendicular to the plane of the floor), and X and Y will be as normal for a 2D game.

Offset Type Description
0x0 u64 Actor key. This value must match the hex value of the corresponding actor label in the (top-level) names section.
0x8 u32 Names section offset. This stores the offset in the (top-level) names section for the start of the label that corresponds to this actor.
0xC u16 Actor ID
0xE u16 Padding?
0x10 u32 Room ID. The actor loads when entering the specified room and unloads when leaving it. Generally this should be consistent across all actors in the file, since each room has its own file.
0x14 float[3] Co-ordinates as [X, Z, Y]. One in-game "tile" is 1.5 units.

The co-ordinate system spans entire maps and is not specific to each room. [0, 0, 0] is the very top left corner of the map, at the elevation of the main floor plane of the map.

Each room is 10x8 tiles, so they span 15 units along the X axis and 12 along the Y axis.

0x20 float[3] Rotation about the [X, Z, Y] axes respectively, in degrees.
0x2C float[3] Scaling along the [X, Z, Y] axes respectively. Note that scaling doesn't seem to affect collision for every actor and only scales the model in some cases.
0x38 u32[16] Parameters. This section contains 16 u32's, which are grouped into 8 pairs of [parameter, parameter type].

For any pair, the first 4 bytes make up the value of the parameter. This can be basically anything (will include some known parameters for certain actor types below).

The second 4 bytes indicate what the purpose of the parameter is. There are only 3 observed values so far:

  • 0, which indicates the parameter is not used?
  • 2, unknown purpose. Observable on the small key in Lv04AnglersTunnel_06A among other rooms, but the parameters appear to not do anything.
  • 3, which indicates that the parameter is an integer parameter, taken as just the value of the first u32.
  • 4, which indicates that the parameter is a string parameter specified in the names section. The value in the previous u32 is the offset in the names section for this parameter.

Unused parameters are entered as offsets to a null byte in the names section, as a type 4 parameter.

0x78 Actor Switches. Defines 4 actor switches for the event. These are used for the behavior of many things like small keys, chests, NPCs, loading zones, doors, blocks, etc.


First there is 4 bytes which define the usage of actor switches 0-3 respectively:

  • 0: Appears to define an index in set a of local flags for the room. For example, whether a torch is lit or not, a bush is cut or not, etc.
  • 1: The actor switch is the index of a global flag.
  • 2: Defines a hardcoded value for the switch, usually 1. For example, while some treasure chests appear based on a global flag being set, some don't; these ones would just use this hardcoded 1 instead of a flag index.
  • 3: Used only on actors in panel dungeon rooms. Appears to be an index for a flag system specific to panel dungeons.
  • 4: The switch is unused.


Following this are the four actor switch definitions, each 2 bytes (u16).

0x84 Actor Relationships. Defines the relationship this actor has with other actors in the room, primarily for use with events. This section uses a lot of actor indexes, which are the based on the order the actors are defined in the room. That is, the first defined actor is 0, the second is 1, etc.


The sections starts with 8 bytes which define the structure and purpose of the data in the section, followed by 4 null bytes, and then followed by 3 sections of data.


xx bb kk ee 00 00 yy zz 00 00 00 00

x indicates the number of entries in section 1.

y indicates the number of entries in section 2.

z indicates the number of entries in section 3.

b appears to be 01 if the enemy appears from the +enemies tile in a chamber dungeon and 00 otherwise.

k is 01 only for TagHolocaustChecker actors. Probably indicates looking at enemy spawns/kills.

e is 01 for all enemies and 00 for anything else.


Section 1 defines which other actors have behaviors controlled by this actor. This includes actors which get used by this actor's event, enemies that a TagHolocaustChecker watches for, that an AreaEventBox/AreaLevelOpen/etc will trigger this actor, and possibly other uses. It consists of a sequence of 20-byte structures, which are each 2 parameters (8 bytes each, same format as parameter section) and a 4-byte actor index.


Section 2's purpose is not yet known. It consists of a sequence of 24-byte structures, which are each 2 parameters (8 bytes each), and 2 u32's.


Section 3 defines which actors can call upon use of this actor. It is simply a sequence of 4-byte actor indexes. This should line up with section 1 of other actors. As an example, if actor[2] defines control of actor[5] in its section 1, then actor[5]'s section 3 should contain 0x02.

Grid Section

This section is a child FixedHash which appears to define collision properties of the room. It has two or three entries: data, sometimes chain, and info.


The data in the data section contains blocks 0x10 bytes each which define some properties for every tile on the screen, for a total of 0x500 bytes for top-down rooms and 0x140 bytes for sidescroller rooms. The format of these is not fully understood yet.

Offset Type Description
0x0 u32? Unknown. The most significant byte appears to always be 0x80.
0x4 u32? Unknown, seems to always be identical to the value at 0x0.
0x8 u32 Chain index. Defines which chain to use as an index into the sequence of chains. If the tile doesn't refer to a chain tile, or there is no chain table defined, this will be 0xFFFFFFFF.
0xC float Elevation. Specifies the height of the surface that Link walks on over this tile. It is still unclear what causes tiles' elevations to be gradient (a ramp) or a sudden increase or decrease (a wall).


The chain section is used for when there needs to be a higher walkable surface directly above a lower one. This is common in sidescroller rooms, but is also used in some overworld areas; mainly in Tal Tal Mountains where there are some walkable surfaces inside cliff faces which can be reached with out of bounds methods. Chain entries can still index to other chains.


The info block is always 0x10 bytes and holds some essentially metadata about the room, probably to be used alongside the other data here to determine collision.

Offset Type Description
0x0 u16 How many tiles tall the room is. Will always be 0x8 for top-down rooms and 0x2 for sidescroller rooms.
0x2 u16 How many tiles wide the room is. Seems to always be 0xA (10)
0x4 float The size of 1 tile in units. Seems to always be 1.5.
0x8 float X co-ordinate of the left edge of the room.
0xC float Y co-ordinate of the top edge of the room. For sidescroller rooms this seems to always be -1.5.

Names Section

The names section contains a list of actors by name, followed by a hyphen (-), followed by a 16-digit hexadecimal number. This also includes some plaintext parameters for some objects, such as the contents of a chest (ObjTreasureBox) or the destination of a loading zone (AreaLevelOpen). Note that these do not define what actors exist, in fact it seems like the actual labels here are meaningless aside from the aforementioned parameters.

All labels in the names section are separated by null bytes. Of note, there seems to always be one separator that 2 null bytes instead of 1. Depending on the file, this is either between point and rail at the start of the names section, or between the 1st and 2nd listed actors (it is more commonly the latter).