GameScene

Revision as of 08:42, 31 October 2018 by imported>Leoetlino (→‎Definitions)

GameScene is a critical subsystem that is responsible for core functionality such as initialising other components, creating stages (world, title screen, etc.) and handling the game's main loop.

GameScene
Subsystem
Official name Yes
Description Handles the main loop and stages
Init function Switch 1.5.0: 0x71007D1DD8
Wii U 1.5.0: ???
Debug only No

Unlike most other subsystems, GameScene is not a singleton: it is a member of the uking::frm::System structure[1].

Definitions

Stages

Also called scenes in XLink code.

Type Description Map types
0 Invalid ("None") -
1 Open world stage (except GameTestField) ("オープンワールド") MainField, AocField
2 Indoor stage ("Cダンジョン") CDungeon, MainFieldSpot, GameTestDungeon
3 Open world stage (GameTestField) ("GameTset") GameTestField
4 MainFieldDungeon ("四大遺物") MainFieldDungeon
5 Indoor stage or viewer stage ("ビューワー") ActorViewer

Maps that have the same stage type typically use the same subsystems and share most characteristics. For example, all open world stages use the Tera height map terrain system and load map units in the same way.

StageBinders

Stage binder types[2]
Type Description
0 OpenWorldStage
1 IndoorStage (CDungeon, ...)
2 MainFieldDungeonStage
3 TitleStage
4 StartupSaveCheckStage
5 Viewer

Fade types

Type Description
0
1
2 Show logo[3]

GameScene state strings

List of state strings in 1.5.0 (incomplete)[4]
Name Description
1st Demo mode [check]
2nd Demo mode
初回シーケンス Initial sequence - New save
TitleMenu Title menu
Presentation Demo mode
E3_2016/Presentation Demo mode
StartupSaveCheckStage
Viewer
CDungeon
MainFieldDungeonStage
MainField
GameTestField
GameTestField2
AocField
GameTestDungeon
MonolithTestDungeon
SrdTestDungeon
MarioClubTestDungeon
TestField
研修用
MonolithTest100enemy
MinimumField
ActorViewer

Init

Initial state

The initial state the game launches into is determined by GameScene[5].

const bool isFirstLaunch = SaveSystem::sInstance->isFirstLaunch();
State* state = isFirstLaunch ? &state_NewSave : &state_LunchTitle;

if ( aocManager::sInstance && aocManager::sInstance->flags & 2 )
  nn::err::ShowUnacceptableAddOnContentVersionError();

const bool isDemo = E3Mgr::sInstance && E3Mgr::sInstance->isDemoMode();
if (isDemo)
  state = &state_LunchTitle;

if (!isDemo && isFirstLaunch)
  sIsFirstNonDemoLaunch = 1;

StateMachine::changeState(&this->stateMachine, state);

States

Note: when the Indoor stage binder is initialised and if the map name changes, a "dungeon" telemetry report is emitted with "leave" or "enter" as the event name and the old/new map name as additional data[6].

StageMgr

StageSelect

StageTransition

Entered before stage generation starts and after Fade (loading screen) has been initialised and made visible. This state machine state is a noop.

LunchTitle

LunchTitle (sic) is entered when the game is launched. The internal state string is "TitleMenu" or (in demo mode) "2nd".

The run function is extremely simple: it simply creates the TitleStage binder (with doNotShowLogo=true[7]) when the "common run" status (see below) is 0xa, then calls the "common run" function (with isNewSave=false[8]).

NewSave

Entered on the first boot or when the new game option is selected. The associated state string is "初回シーケンス" ("initial sequence").

PatchError

Main loop

Three GameScene functions are called in a row from RootTask (see Executable) after initialisation has completed, i.e. in the game's main loop. (Note: these 3 names are unofficial.)

precalc

  • FadeProgress: Update the progress gauge on the Fade screen (animated).
  • Update current map name based on player position (when Link is not in a dungeon).
  • Run StageMgr and StageSelect code.
  • ??? (runs only if this->field_8CB is non zero)
  • If stage status is "NeedsGeneration":
    • Call some MCMgr function at 0x71007A9198.
    • Run save upload subsystem if needed.
    • Call GameScene::genStage with second argument being !EventMgr::sInstance->hasActiveEvent() || EventMgr::sInstance->getActiveEvent()->name != "Demo169_0".
  • If stage status is "NeedsUnload":
    • Call some MCMgr function at 0x71007A9198.
    • Run save upload subsystem if needed.
    • Call GameScene::unloadStage.
  • ??? (something involving the previous stage binder[check])
  • ??? (something involving GameScene Subsystem #12)
  • Call some MCMgr function at 0x71007A9198, again.
  • ??? (runs if the GameScene state is StageMgr)

calc

postcalc

Common state run function

Called from StageSelectRun, LunchTitleRun and NewSaveRun.

  • Status 0:
    • Start loading
      • Finish startup logo (Switch)[9]
      • If the state string is set to 初回シーケンス, clear the Resource system cache ("ClearAllCaches")[10].
      • Debug stuff[11].
      • E3 Demo stuff[12].
      • Show the Fade screen (loading screen) if the state string does not[13] end with "Viewer" or is not any of the following strings: 1st, 2nd, Presentation, TitleMenu, 初回シーケンス, StartupSaveCheckStage
        • And then show the FadeStatus[14] and the LoadSaveIcon screens[15].
        • Otherwise, only open the Fade screen but do not show loading progress[16].
      • StageSelect stuff[17].
      • Stop "resource compaction" and wait for it to be stopped[18].
      • If the stage string starts with CDungeon[19] or MainFieldDungeonStage[20], start loading the associated DungeonPack[21].
      • BaseProcMgr: start ActorCreate initializer thread[22][check].
      • FadeProgress: reset internal state[23], set progress to 0%[24] and mark loading as active[25].
  • Status 2:
    • If the GameScene state machine's current state is StageSelect or NewSave, do something involving LayerMgrTask and the Renderer.[check]
  • Status 0xa:
    • TipsMgr: update tips if the loading screen is visible (not just opened). TipsMgr will load tips depending on the stage that is being loaded.
  • Status 0xb:
    • Set GameScene's isNewSave property.
    • Reset status to 0.
    • Change GameScene state to StageTransition[26].
    • Set stage status to "NeedsGeneration" (2)[27].

Stage generation

  • Terrain::sInstance->flags |= 0x180u
  • Step 0
    • Reload Title.pack if the stage that needs to be generated is TitleStage (3)[28].
    • StageSelect checks[29]
  • Step 1
    • If a pack was loaded by DungeonPackMgr, wait for DungeonPack loading to finish[30] and switch active pack to the dungeon pack.
  • Step 2
    • If the stage to load is TitleStage, wait for TitlePack loading to finish[31] and switch active pack to the title pack.
  • Step 3: start stage generation[32]
    • PlacementMgr
    • ActorSystem::sInstance->field_13A = 0
    • Update current map flags (e.g. sIsDungeon)
    • Clear BaseProcMgr ActorCreate queue[check]
    • Create uking::Stage::ForBaseProcDual heap (if not already done), which will be used for actors, ActorCreator and BaseProcMgr
    • ActorSystem::sInstance->field_139 = 0
    • If the state string starts with 初回シーケンス, MainField, GameTestField, GameTestField2, AocField, CDungeon, MainFieldDungeonStage, GameTestDungeon, MonolithTestDungeon, SrdTestDungeon, MarioClubTestDungeon, TestField, 研修用, MonolithTest100enemy, MinimumField, or ActorViewer, call GameScene::startBgProcessing (0x71007B2054)
    • If "new save" was selected, initialize PauseMenuDataMgr data
    • If the stage to load is TitleStage, load Layout/Title.blarc for ui::LayoutResourceMgr.
    • If "new save" was selected and the awakening demo hasn't been played since the game was launched[33], ask EventMgr to call Demo169_0.
    • Some PhysicsMemSys stuff (0x71007ADBE0).
  • Step 4
    • Wait for completion of Title BG processing (20% of the loading bar)
    • uiManager (0x71007ACD04)
    • Initialize StatisticsMgr paths depending on current map type.
    • Update aoc2's mapType and mapName fields.
  • Step 5
    • PhysicsMemSys stuff (0x71007ACDB8, 0x71007ACDC0, 0x71007ACDD0)
    • BaseProcMgr: request "PreDelete" actors[34]
    • BaseProcMgr: stop ActorCreate initializer thread and clean up internal state[check]
    • agl::lyr::Renderer and Graphics stuff
  • Step 6
    • Load env.genvb binary (gsys::ModelSceneEnv::clearImpl + loadBinaryImpl)
    • If the stage binder type is 0, 1 or 2 (OpenWorldStage, IndoorStage or MainFieldDungeonStage):
      • Set loading progress to 40%.
      • Graphics stuff, again
      • OnUiActorMgr
      • GameScene::loadTera (on a separate thread)
  • Step 7
    • If the stage binder type is 0, 1 or 2 (OpenWorldStage, IndoorStage or MainFieldDungeonStage):
      • Wait for Tera to load[35]
  • Step 8
    • ...
    • Wait for Tera to generate collision
    • ...
  • Step 9
  • Step 10
  • Step 11
  • Step 12
  • Step 13

References

  1. uking::frm::System::gameScene @ 0x10 (Switch)
  2. As returned by the first virtual function in the StageBinderBase interface
  3. See 0x71007B8CD0 and AIDef:Action/ExitGame
  4. The state string is a sead::FixedSafeString<0x100> stored in GameScene @ 0x720.
  5. GameScene::initialize, 0x71007A86CC
  6. StageBinder::initAndReportDungeonLeaveEnter[unofficial name] at 0x71007B79A8
  7. 0x71007B47D8
  8. 0x71007B47F4
  9. 0x71007AF6F8
  10. 0x71007AFBDC
  11. 0x71007AFDE4
  12. 0x71007AFEF4
  13. 0x71007AFF08
  14. 0x71007AFFC4
  15. 0x71007AFFCC
  16. See function at 0x71007B0C60
  17. 0x71007B0000
  18. 0x71007B00B4 (stop compaction) to 0x71007B010C (end of the busy loop)
  19. 0x71007B0124
  20. 0x71007B0160
  21. 0x71007B0190
  22. 0x71011BF1C4
  23. 0x71007B01D4
  24. 0x71007B01E0
  25. 0x71007B01E8
  26. 0x71007B1058
  27. 0x71007B105C
  28. 0x71007AC8A0
  29. 0x71007AD3AC
  30. DungeonPack読み込み待ち
  31. TitlePack読み込み待ち
  32. ステージ生成開始
  33. 0x71007ADB3C
  34. 0x71007ACDE4
  35. tera読み込み待ち