This article provides an overview on the implementation of The Legend of Zelda: Breath of the Wild.
Framework and engine
Breath of the Wild is a modern Nintendo game which was released in March 2017 for the Wii U and the Switch. Thus, it shares a lot of code with contemporary first-party Nintendo games such as Splatoon 2 and Super Mario Odyssey, notably the sead (Nintendo's in-house framework and utilities for first-party titles) and NintendoWare (GFX, audio, effects, and UI) libraries.
BotW is the first major Nintendo game to use XLink (EffectLink and SoundLink) as a system to make briding code and graphics or sound effects easier, and also marks the first significant use of event flows and the EventFlow/evfl library to implement in-game events such as cutscenes and NPC interactions.
A completely custom engine – which Nintendo seemingly calls KingSystem – is used for Breath of the Wild. It appears to have been written from scratch as nothing significant is shared with previous Zelda games or even older Nintendo games. In particular, Breath of the Wild does not use LunchPack or SMO's engine, even though games using the former appear to use a BotW-inspired ROM structure.
Just like any other Switch game, executable code is stored in the ExeFS – with the game code in the main executable – and content files or assets are stored in the RomFS. The latter is referred to as the game ROM.
BotW is written in C++ with almost no hand-written assembly code and with no usage of the C++ standard library. Standard structures such as strings and associative maps are implemented in the sead library. Standard RTTI is not used; instead the game relies on Nintendo's own implementation of RTTI in sead, which does not leak symbols at all.
The codebase appears to be compiled with high levels of optimisation enabled for both Wii U and Switch releases, with code on the latter platform being better optimised. Since 1.6.0 (Switch only), the game is additionally built with LTO enabled, which results in massive amounts of code bloat. All known public releases are stripped, i.e. don't contain any debugging symbol.
The game is divided into several components and makes heavy use of managers, which are singletons that are usually responsible for one specific task (e.g. PlacementMgr for actor placement, EventMgr for in-game events, etc.). Unlike older Zelda games, most managers are dynamically allocated, not stored in BSS. In general, Breath of the Wild makes use of the heap and virtual functions a lot more.
In total, there are 130+ subsystems.
Resources are organised by type into a directory tree with nested directories.
Each resource type often has its own distinct file extension even when the file format is exactly the same. For example, Bgparamlist (GeneralParamList) and Blifecondition (LifeCondition) are both AAMP files, but they have different file extensions because their types and purposes are different.
Because the game tends to load several resources at the same time, related files are grouped and packed into archives to improve performance. Resources are packed at the actor level, or at the event level, or based on the moment they are loaded by the game, which is the case for dungeon packs and top-level packs for instance.
This archive system does result in content duplication, but it is a fair space-time tradeoff.
Many resources in the ROM are automatically generated during the build process from source files that are not shipped with the game. Examples include Havok source collision data, UI map tiles or terrain statistics files. Some assets are generated by combining information from parameter files; this is done for performance issues as it allows the game to query information without loading any additional file. For example, ActorInfo.product.sbyml exists to avoid having to load entire actors or multiple ActorParam files at the very least.
There is ample evidence implying that resources are packed into archives in a completely automated way.
While Breath of the Wild shares core concepts such as actors, scenes and flags with most (all?) Zelda games since Ocarina of Time, most of them are implemented in radically different ways. New concepts have also been introduced.
Full article: Actor
Actors are in-game objects. Link, enemies, scenery, weapons, NPCs, shrine interiors are all examples of actors.
In Breath of the Wild, actors are implemented through a combination of code and data such as parameter files (ActorParam), models, physics data, etc. Unlike actors in older Zelda games, BotW actors are composed of reusable components and large parts of functionality can be configured via parameter files.
An actor always has an associated bxml.
Demos and cutscenes
Full article: Map
Maps are uniquely identified with a map type and a map name. The identifier is usually written as
MapType/MapName (e.g. MainField/B-3). Confusingly enough, Nintendo sometimes refers to this complete identifier as the map name.
Stages and stage binders
Full article: GameScene
Maps which share characteristics with each other and use the same set of subsystems usually require very similar initialisation and main loop code. In order to avoid code duplication, Breath of the Wild moves such shared code into stages. As an example, all Hyrule and Trial of the Sword maps are handled by OpenWorldStage.
Stage binders are among other things responsible for creating stage instances.
Full article: Scene
Scenes are active instances of a stage. By design, exactly one scene is active at a time. The active scene is managed by GameScene, which is responsible for generating and unloading stages and changing to another scene.
Full article: Map unit
Map units contain placement data for game maps (e.g. MainField/A-1). In other words, they are used to configure fixed object spawns on maps for actors such as scenery and enemies for example, in contrast to the AutoPlacement system, which dynamically spawns actors.
AAMP and BYML are extremely common file formats, as they are most notably used for actor parameter (ActorParam) files, map units and more generally configuration files. They can be found in the ROM with various file extensions.
- "SceneWorkTime" @ 0x7100A89528 (Switch 1.5.0)