BFEVFL: Difference between revisions

651 bytes added ,  2 years ago
fix incorrect documentation
imported>Leoetlino
(move LAS section to LAS wiki)
(fix incorrect documentation)
Line 1: Line 1:
<onlyinclude>'''bfevfl''' is a binary file format for [[Event flow|'''ev'''ent '''fl'''ows]].</onlyinclude> In ''Breath of the Wild'' and other Nintendo games such as ''Splatoon 2'' and ''Link's Awakening'', binary event flows are parsed by Nintendo's EventFlow/evfl library.
<onlyinclude>'''BFEVFL''' is a binary file format for [[Event flow|'''ev'''ent '''fl'''ows]].</onlyinclude> In ''Breath of the Wild'' and other Nintendo games such as ''Splatoon 2'' and ''Link's Awakening'', binary event flows are parsed by Nintendo's EventFlow/evfl library.


== Structures ==
== Structures ==
bfevfl is a little endian format, so values are stored in little endian even on Wii U.
BFEVFL is a format that supports both big endian and little endian; however, event flows typically use little endian even on Wii U, as is the case in ''Breath of the Wild''.


bfevfl uses pointers very heavily to refer to strings, to other sections, etc. All pointers are always 64 bit long -- since the same format is used on the Switch which is a 64 bit platform. They must be present in the [[#Relocation table]] if the file is to be loaded correctly by the official bfevfl code.
BFEVFL uses pointers very heavily to refer to strings, to other sections, etc. All pointers are always 64-bit long -- this is because the same format is used on 64-bit platforms like the Switch. Pointers must be present in the [[#Relocation table]] if the file is to be loaded correctly by the official EventFlow code.


As a direct consequence, most sections don't have any fixed order. Therefore, this article will only document the data structures and mention the order Nintendo places sections in. For more details, it is recommended to look at the [https://github.com/leoetlino/evfl <code>evfl</code> library] directly.
As a direct consequence, most sections don't have any fixed order. Therefore, this article will only document the data structures and mention the order Nintendo places sections in. For more details, it is recommended to look at the [https://github.com/leoetlino/evfl <code>evfl</code> library] directly.
Line 16: Line 16:
| 0x0 || char[8] || Magic ("BFEVFL\x00\x00")
| 0x0 || char[8] || Magic ("BFEVFL\x00\x00")
|-
|-
| 0x8 || u16 || Version (0x0300)
| 0x8 || u8 || Version (major)
|-
|-
| 0xa || u8 || Unknown (must be zero)
| 0x9 || u8 || Version (minor)
|-
|-
| 0xb || u8 || Unknown
| 0xa || u8 || Version (patch)
|-
|-
| 0xc || u16 || Byte order mark
| 0xb || u8 || Version (sub-patch)
|-
| 0xc || s16 || Byte order mark
|-
|-
| 0xe || u8 || Alignment (to get the actual value: 1 << raw_value)
| 0xe || u8 || Alignment (to get the actual value: 1 << raw_value)
|-
|-
| 0xf || u8 || Unknown
| 0xf || u8 || Padding
|-
|-
| 0x10 || u32 || File name offset
| 0x10 || int || File name offset
|-
|-
| 0x14 || u16 || Is relocated flag (set in memory)
| 0x14 || u16 || Is relocated flag (set in memory)
Line 34: Line 36:
| 0x16 || u16 || First block offset
| 0x16 || u16 || First block offset
|-
|-
| 0x18 || u32 || Relocation table offset
| 0x18 || int || Relocation table offset
|-
|-
| 0x1c || u32 || File size
| 0x1c || int || File size
|-
|-
| 0x20 || u16 || Number of [[#Flowchart|flowchart]]s
| 0x20 || u16 || Number of [[#Flowchart|flowchart]]s
Line 63: Line 65:
| 0x0 || char[4] || Magic ("RELT")
| 0x0 || char[4] || Magic ("RELT")
|-
|-
| 0x4 || u32 || Offset to relocation table start
| 0x4 || int || Offset to relocation table start (<code>table_start_offset</code>)
|-
|-
| 0x8 || u32 || Number of sections
| 0x8 || int || Number of sections
|-
|-
| 0xc || u32 || Padding
| 0xc || u32 || Padding
|-
|-
| 0x10 || Section[num_sections] || Sections
| 0x10 || Section[num_sections] || Sections
|-
| - || Entry[...] || Section entries (emitted in the same order as each section)
|}
|}


Note: the number of sections is almost always 1 because a single section can already fit 2^32 - 1 entries. If you need more than 4 billion entries, you are probably doing something ''very wrong''.
Note: the number of sections is almost always 1 because a single section can already fit 2^32 - 1 entries. If you need more than 4 billion entries, you are probably doing something ''very wrong''.
The table base pointer is calculated as follows: `reinterpret_cast<char*>(&table) - table_start_offset`


==== Relocation table section ====
==== Relocation table section ====
Line 78: Line 84:
! Offset !! Type !! Description
! Offset !! Type !! Description
|-
|-
| 0x0 || void* || Alternative base offset (unused by Nintendo)
| 0x0 || void* || Optional base pointer (<code>ptr</code>)
|-
|-
| 0x8 || u32 || Used to calculate the base pointer if an alternative base offset is used
| 0x8 || int || Optional base pointer offset (<code>offset</code>)
|-
|-
| 0xc || u32 || Data end offset (before alignment)
| 0xc || int || Size
|-
|-
| 0x10 || u32 || Number of entries to skip
| 0x10 || int || Index of the first entry in this section
|-
|-
| 0x14 || u32 || Number of entries (includes skipped entries)
| 0x14 || int || Number of entries
|-
| 0x18 || Entry[num_entries] || Entries
|}
|}
The base pointer (<code>base</code>) is calculated as follows:
* If the optional base pointer field is nullptr, the base pointer is equal to the table base pointer.
* Otherwise, it is equal to <code>ptr - offset</code>.


==== Relocation table entry ====
==== Relocation table entry ====
Line 95: Line 103:
! Offset !! Type !! Description
! Offset !! Type !! Description
|-
|-
| 0x0 || u32 || Offset to pointers to relocate
| 0x0 || u32 || Offset to pointers to relocate, relative to the table base pointer
|-
|-
| 0x4 || u32 || Bit field that determines which pointers need to be relocated (up to 32 contiguous pointers starting from the listed offset)
| 0x4 || u32 || Bit field that determines which pointers need to be relocated (up to 32 contiguous pointers starting from the listed offset)
|}
|}
Offsets are treated as signed 32-bit integers.
Pointers are relocated by overwriting each 64-bit pointer field with <code>base + offset</code>.


=== String pool ===
=== String pool ===