Beco: Difference between revisions

2,254 bytes added ,  2 years ago
→‎Getting data for a given coordinate: replace pseudocode with actual C++ source code (from the decomp project)
imported>Leoetlino
No edit summary
(→‎Getting data for a given coordinate: replace pseudocode with actual C++ source code (from the decomp project))
 
(12 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{lowercase}}
'''beco''' is a file format that is used for storing per-coordinate data.
'''beco''' is a file format that is used for storing per-coordinate data.


Line 11: Line 12:
| 0x0 || u32 || Magic (0x00112233)
| 0x0 || u32 || Magic (0x00112233)
|-
|-
| 0x4 || u32 || Number of tables
| 0x4 || u32 || Number of rows
|-
|-
| 0x8 || u32 || Divisor
| 0x8 || u32 || Divisor
Line 18: Line 19:
|}
|}


=== Table offsets ===
=== Offsets ===
{{empty section}}
{| class="wikitable"
|-
! Offset !! Type !! Description
|-
| 0x0 || u32[num_rows] || Offsets to row data, divided by 2 and relative to the start of the row section
|}
 
=== Rows ===
==== Segment ====
{| class="wikitable"
|-
! Offset !! Type !! Description
|-
| 0x0 || u16 || Custom data
|-
| 0x2 || u16 || Length (X axis)
|}
 
This structure is repeated until the entire row has been covered by segments. The sum of all segment lengths is equal to the length of the map on the X axis.
 
== Operations ==
 
=== Getting data for a given coordinate ===
The algorithm that returns the custom data that is associated with a coordinate is very simple. It consists of determining the correct row index in the table, then iterating over segments in that row and returning the segment data when the X coordinate is within its bounds.
 
<syntaxhighlight lang="c++">
s32 Ecosystem::getMapArea(const EcoMapInfo& info, f32 posX, f32 posZ) const {
    posX = sead::Mathf::clamp(posX, -5000.0f, 4999.0f);
    posZ = sead::Mathf::clamp(posZ, -4000.0f, 4000.0f);
 
    const auto epsilon = [](float n) { return n >= 0.0f ? 0.5f : -0.5f; };
 
    s32 x = s32(posX + 5000.0f + epsilon(posX + 5000.0f));
    s32 z = s32(posZ + 4000.0f + epsilon(posZ + 4000.0f)) / info.mHeader->divisor;
    s32 row = sead::Mathi::clamp(z, 0, info.mHeader->num_rows - 2);
 
    if (info.mHeader->divisor == 10)
        x /= 10;
 
    if (info.mRowOffsets[row] >= info.mRowOffsets[row + 1])
        return -1;
 
    auto* segmentEnd = reinterpret_cast<const Segment*>(info.mRows + 2 * info.mRowOffsets[row + 1]);
    auto* segment = reinterpret_cast<const Segment*>(info.mRows + 2 * info.mRowOffsets[row]);
    s32 totalLength = 0;
    while (true) {
        totalLength += segment->length;
        if (x < totalLength)
            break;
        ++segment;
        if (segment >= segmentEnd)
            return -1;
    }
    return segment->value;
}
</syntaxhighlight>


=== Table ===
Source: https://github.com/zeldaret/botw/blob/022f029db1ef03d900fb54bad0807939c9695720/src/KingSystem/Ecosystem/ecoSystem.cpp#L100
{{empty section}}


== Usage in ''Breath of the Wild'' ==
beco files are used in ''Breath of the Wild'' to map coordinates to arbitrary u16 data. Three beco files are used for different purposes: [[FieldMapArea.beco]], [[MapTower.beco]] and [[LoadBalancer.beco]].


[[Category:File formats]]
[[Category:File formats]]
[[Category:File extensions]]
[[Category:File extensions]]