Executable

From ZeldaMods
Jump to: navigation, search

The executable is where all the game code is stored. It is located in the title code directory on Wii U and in the ExeFS on Switch.

File

Switch

BotW's executable is a standard, compressed NSO which is larger than most other games (about 20MB compressed).

The build path is D:\home\Cafe\U-King\trunk\Game\App\Rom\NX64\Product\code\U-King.nss and the build ID for 1.5.0 is 16A91992BBA71201E98756F3BC8F5D2F00000000000000000000000000000000.

Wii U

BotW's executable is a standard, compressed RPX.

Libraries

Full article: Software libraries

Subsystems

Full article: Subsystems

Symbols

Unfortunately, release versions of The Legend of Zelda: Breath of the Wild are stripped and have absolutely no debugging symbols. This has been verified for Switch 1.0.0, Wii U 1.5.0 and Switch 1.5.0.

The Switch 1.5.0 executable only has some RTTI data for UI classes.

However, the game uses lots of software libraries, some of which are included in games that do ship with complete symbols such as Super Mario Odyssey. BotW seems to have been compiled at a higher optimisation level that causes unused functions to be fully removed.

Init and main loop outline

Early init and main loop

  • main
    • nn::oe::Initialize
    • sead::GameFrameworkNx::initialize (implicitly calls nn::oe::Initialize again; this looks like a mistake from the Zelda developers)
      • sead::HeapMgr and root heap
      • sead::ThreadMgr
      • sead::GlobalRandom
      • sead::ResourceMgr
      • sead::FileDeviceMgr
    • GameConfig
    • Unknown 71025D1720
    • uking::GameFramework (derived from sead::GameFrameworkNx)
    • GraphicsSystem
    • sead::GameFrameworkNx::initializeGraphicsSystem
    • [Debug] sead::PrimitiveRenderer
    • [Debug] sead::DebugFontMgrNvn
    • [Debug] sead::DebugFontMgrJis1Nvn
    • RootTask
      • sead::TaskBase::CreateArg
      • sead::Framework::RunArg
      • framework->run
        • Constructs a sead::MethodTreeMgr (note: a custom, derived MethodTreeMgr is used in BotW)
        • Constructs a sead::TaskMgr
          • sead::TaskMgr::doInit_
        • framework->runImpl_
          • framework->waitStartDisplayLoop_
          • framework->mainLoop
            • framework->procFrame
              • framework->procCalc
                • methodTreeMgr->calc (sead::SingleScreenMethodTreeMgr). Runs the following methods (sead::MethodTreeNode):
                  • RootCalc
                  • RootDraw
                    • AppDraw
                    • AppDrawFinal
                    • SysDraw
              • framework->present
              • framework->procReset
              • framework->waitForGpuDone
            • framework->setVBlankWaitInterval

RootTask::prepare

  • framework->createSystemTasks
    • sead::ControllerMgr
    • sead::ProcessMeter
    • [Debug] sead::SeadMenuMgr
    • [Debug] sead::HostIOMgr
    • sead::InfLoopChecker
    • [?] sead::CuckooClock
  • InfLoopChecker setup

RootTask::calc

Internal version

1.0.0's nnMain prints "00000010", whereas 1.5.0 prints "0000002d".

Unused content

Arguments

The game accepts three different options: -fhd (flag for Full HD?), -no_sead_log (flag), -out (string). However the code that handles these arguments does not exist in the release version.

Save-breaking bug

Some development versions (1523941 to 1548881) generated unusable saves. These strings are still present in the release version but they are unused.

.rodata.2:0000007101DE98B0 a15239411548881 DCB "@1523941 ~ @1548881のROMからのセーブデータを利用しているようです。",0xA
.rodata.2:0000007101DE98B0                 DCB "バグ報告をせずに、セーブデータを消去してください。",0xA
.rodata.2:0000007101DE98B0                 DCB "@1523941 ~ @1548881からのセーブデータであるはずがないという場合のみ、バグ報告をしてください。",0xA
.rodata.2:0000007101DE98B0                 DCB "num_valid_normal_mode %d/%d, num_valid_hard_mode %d%d",0

Leftover debug tools

Demo ROM types

The game calls sead::EnvUtil::getRomType() to get the ROM type. The result is printed to a debug log along with SD card, revision and AoC (DLC) information.

The ROM type is loaded from System/RegionLangMask.txt. Possible values are:

  • "Normal": used in retail versions (at least 1.0.0 and 1.5.0)
  • "Show_2017_1st": demo version, used for 12S?
  • "RID_Demo": Retail Interactive Display demo (aka kiosk version). Seen in the Switch kiosk version.
  • Anything else is treated as "Normal".

The release build crashes if the ROM type is set to Show_2017_1st or RID_Demo, presumably because these types activate code paths that require a global debug heap which never gets initialised in release versions.

ErrorViewer and Stage Select

There are references to debugging tools like Error (an in-game integrated bug tracker) and a stage select mode (uking::StageSelect + more strings). UI data and structures for the ErrorViewerTask still exist to a certain extent, but whether these features can be reactivated or not is still unknown.

Disabled functionality

In 1.5.0, the Patrol subsystem has a reference to BUILD_URL. Unfortunately, the function that is supposed to set the BUILD_URL string (sub_7100B0B728) is stubbed in the release build.

Similarly, the Revision subsystem is disabled in release builds. According to strings in the stage select screen function, it would have contained information about a program number (int), resource number (int) and a 'build from' string.

ActorDebug

This is a rather large subsystem that interacts with the actor system and all related components such as demos, events and maps. It can print debug information about the current state and override actor creation behaviour.

Debug options

A large amount of debug config strings have been left in the executable. These show the existence of debug game config files that were used to make testing more convenient during development.

The debug config files do not exist in the release version; the config loading code was removed as well.

.rodata.2:0000007101DC9625 aDebugGameconfi DCB "Debug/GameConfigSettingForGameROM.xml",0
.rodata.2:0000007101DC9625                                         ; DATA XREF: initDebugConfigFilePaths+18↑o
.rodata.2:0000007101DC9625                                         ; initDebugConfigFilePaths+2C↑o
.rodata.2:0000007101DC964B aDebugGameconfi_0 DCB "Debug/GameConfigForGameROM.xml",0
.rodata.2:0000007101DC964B                                         ; DATA XREF: initDebugConfigFilePaths+20↑o
.rodata.2:0000007101DC964B                                         ; initDebugConfigFilePaths+38↑o
.rodata.2:0000007101DC966A aDebugSystemgam DCB "Debug/SystemGameConfigForGameROM.xml",0
.rodata.2:0000007101DC966A                                         ; DATA XREF: initDebugConfigFilePaths+24↑o
.rodata.2:0000007101DC966A                                         ; initDebugConfigFilePaths+3C↑o
.rodata.2:0000007101DC968F aOpenworldOverr DCB "OpenWorld_OverrideStartPos",0
.rodata.2:0000007101DC96AA aOpenworldStart DCB "OpenWorld_StartX",0
.rodata.2:0000007101DC96BB aOpenworldStart_0 DCB "OpenWorld_StartY",0
.rodata.2:0000007101DC96CC aOpenworldStart_1 DCB "OpenWorld_StartZ",0
.rodata.2:0000007101DC96DD aOpenworlddesig DCB "OpenWorldDesign_OverrideStartPos",0
.rodata.2:0000007101DC96FE aOpenworlddesig_0 DCB "OpenWorldDesign_StartX",0
.rodata.2:0000007101DC9715 aOpenworlddesig_1 DCB "OpenWorldDesign_StartY",0
.rodata.2:0000007101DC972C aOpenworlddesig_2 DCB "OpenWorldDesign_StartZ",0
.rodata.2:0000007101DC9743 aIsdisabledpick DCB "IsDisabledPickUpDemo",0
.rodata.2:0000007101DC9758 aIsenabledcdung DCB "IsEnabledCDungeonEntranceDemo",0
.rodata.2:0000007101DC9776 aIsdisabledcdun DCB "IsDisabledCDungeonGoalTerminalDemo",0
.rodata.2:0000007101DC9799 aAlwayswaitscen DCB "AlwaysWaitSceneCreate",0
.rodata.2:0000007101DC97AF aIsequipweaponr DCB "IsEquipWeaponRandom",0
.rodata.2:0000007101DC97C3 aIsequiparmorra DCB "IsEquipArmorRandom",0
.rodata.2:0000007101DC97D6 aIssetweaponran DCB "IsSetWeaponRandom",0
.rodata.2:0000007101DC97E8 aIssetarmorrand DCB "IsSetArmorRandom",0
.rodata.2:0000007101DC97F9 aIssetarmorscri DCB "IsSetArmorScript",0
.rodata.2:0000007101DC980A aIssetitemrando DCB "IsSetItemRandom",0
.rodata.2:0000007101DC981A aIssetcookitemr DCB "IsSetCookItemRandom",0
.rodata.2:0000007101DC982E aDisabletimesto DCB "DisableTimeStop",0
.rodata.2:0000007101DC983E aSetdebugtime   DCB "SetDebugTime",0
.rodata.2:0000007101DC984B aDefaultfinewea DCB "DefaultFineWeather",0
.rodata.2:0000007101DC985E aDefaulttoolenv DCB "DefaultToolEnv",0
.rodata.2:0000007101DC986D aDefaultplayren DCB "DefaultPlayreNoTired",0
.rodata.2:0000007101DC9882 aDefaultplayern DCB "DefaultPlayerNoTemperture",0
.rodata.2:0000007101DC989C aAutoplacement  DCB "AutoPlacement",0
.rodata.2:0000007101DC98AA aTeam           DCB "Team",0
.rodata.2:0000007101DC98AF aShowmergeddung DCB "ShowMergedDungeonActor",0
.rodata.2:0000007101DC98C6 aShowmergedgrud DCB "ShowMergedGrudgeActor",0
.rodata.2:0000007101DC98DC aIsopenmapall   DCB "IsOpenMapAll",0
.rodata.2:0000007101DC98E9 aDebugcameraspe DCB "DebugCameraSpeed",0
.rodata.2:0000007101DC98FA aDebugcamerarep DCB "DebugCameraReplaceStick",0
.rodata.2:0000007101DC9912 aDebugcamerarev DCB "DebugCameraReverseVerticalRotation",0
.rodata.2:0000007101DC9935 aDebugcamerarev_0 DCB "DebugCameraReverseHorizontalRotation",0
.rodata.2:0000007101DC995A aDebugcameracon DCB "DebugCameraControlFovy",0
.rodata.2:0000007101DC9971 aIstexturememor DCB "IsTextureMemoryIncrese",0
.rodata.2:0000007101DC9988 aIstexturememor_0 DCB "IsTextureMemoryBothIncrease",0
.rodata.2:0000007101DC99A4 aIspilottexture DCB "IsPilotTextureMemoryIncrese",0
.rodata.2:0000007101DC99C0 aIspassstagesel DCB "IsPassStageSelect",0
.rodata.2:0000007101DC99D2 aIsstageselectr DCB "IsStageSelectRegularGameOver",0
.rodata.2:0000007101DC99EF aIsenableuidebu DCB "IsEnableUiDebugCommand",0
.rodata.2:0000007101DC9A06 aFirstscene     DCB "FirstScene",0
.rodata.2:0000007101DC9A11 aToolFrontEnd   DCB "Tool Front-End",0
.rodata.2:0000007101DC9A20 aDefaulttoolfro DCB "DefaultToolFrontEndPage",0

Option values are hardcoded in the Switch kiosk version as well.