Game Engine Architecture

Entity System, Player Logic, World Map & Save System

With 100% of functions now named (522 total), the complete architecture of Klonoa: Empire of Dreams is mapped. The game is structured around a callback-based state machine with per-frame entity updates, a scene transition system, and a modular level loading pipeline.

Main Game Loop

AgbMain()                          @ 0x08000470 — entry point
  ├─ Clears IWRAM/VRAM/OAM/palette
  ├─ Initializes sound, input, display
  └─ Main loop:
      ├─ ReadKeyInput()               @ debounce + reset combo
      ├─ GameUpdate()                 @ if not paused:
      │   ├─ UpdateWorldMapNodeState()
      │   ├─ UpdatePlayerInput()
      │   ├─ InitPlayerCollision()
      │   └─ UpdateWorldMapCursor()
      ├─ UpdatePaletteAnimations()   @ 0x2C palette slots
      └─ VBlank wait + DMA transfers

Entity System

The game uses a fixed-size entity array at 0x03002920, with each entry being 28 bytes. Entity slot 0 is always the player.

Entity Update Pipeline

EntityBehaviorMasterUpdate()       @ 0x08015220 — 13,237 lines (LARGEST function)
  └─ For each active entity:
      └─ EntityUpdateDispatch()       @ 0x080101E8 — switch on entity type
          ├─ EntityGravityAndFloorCheck()
          ├─ EntityScrollBoundsCheck()
          └─ Type-specific handler...

Entity Types

FunctionLinesDescription
EntityPlatformRide983Moving platform — position relative to BG scroll
EntityThrowUpdate259Thrown entity trajectory with parabolic arc
EntityProjectileUpdate315Projectile movement + collision + particles
EntitySpringBoard213Bounce pad — applies upward velocity on contact
EntityFloatPath216Floating/patrol movement along path
EntityBounceOffWall247Wall bounce with direction reversal
EntityItemDrop190Item drop with state machine (fall → land)
EntityPickupCollect84Collectible pickup + HUD counter update
EntityDeathAnimation188Death/despawn with debris sprites
EntityCutsceneActor360Scripted entity for cutscene sequences

Boss Phases

FunctionLinesDescription
EntityBossPhaseA1,656Multi-state boss AI with sprite DMA + attack patterns
EntityBossPhaseB951Boss variant with distance-based attacks
EntityBossPhaseC1,871Largest boss — multi-attack patterns + health thresholds
EntityBossPhaseD1,640Boss with tile collision + complex movement
EntityMiniBoss276Simpler boss pattern with sound triggers
EntityMiniBossAlt653Multi-state mini-boss variant

Player System

The player has multiple update modes depending on the current game state:

FunctionLinesContext
PlayerMainUpdate4,351Normal gameplay — movement, collision, animation
PlayerMovementPhysics1,421Input-driven movement with tile collision
UpdatePlayerNormal1,728Standard level gameplay (code_3)
UpdatePlayerBoss1,706Boss fight variant
UpdatePlayerMinigame2,181Puzzle/minigame levels
UpdatePlayerAlternate1,839Alternate movement mode
UpdatePlayerSpecial1,475Special interaction mode
UpdatePlayerFinalBoss1,564Final boss encounter

Player Actions

Scene Transition System

The game uses a callback-stack system for scene transitions. Each transition is a function that gets installed into the callback chain and removes itself when complete.

FunctionDescription
TransitionFadeOutDisableIRQFade out then disable HBlank/VCount interrupts
TransitionFadeInBldAlphaFade in using BLDCNT alpha blending
TransitionInitLevelMusicSelect track by world/level, begin playback
TransitionToWorldMapFade to black, set up world map scene (matched)
TransitionGameplayInitFree buffers, install gameplay callbacks
TransitionFadeOutWithMusicFade screen + music volume simultaneously
TransitionGameOverReturn to world map or restart level
TransitionToTitleScreenInstall title screen callbacks
TransitionSoftResetFull-black for 16 frames then SWI reset
TransitionToSaveScreenStop music, install save-screen flow

World Map System

The overworld map manages node-based navigation across 9 worlds, each with 6 visions. Key functions:

FunctionDescription
UpdateWorldMapInputD-pad/button input for map navigation
UpdateWorldMapCursorCursor movement + node selection animation
CheckWorldCompletionChecks gem/star counts per vision
CountCollectedGemsCounts collected gems and stars across visions
UpdateWorldMapNodeTileUpdates node tiles from animation table
FindNextUnlockedVisionBitmask lookup for next available vision
UpdateVisionStarIconsHUD star/gem icon updates per vision

Save System (EEPROM)

The game uses EEPROM for saving via a 5-function pipeline with retry logic:

SaveGameToSRAM()                   @ disable IRQ, stop DMA, write with retry
  └─ SaveGameRetryLoop()           @ up to 10 retries in 64-iteration loop
      └─ EepromWriteSector()       @ build command + 64-bit data, DMA transfer
          └─ EepromDmaTransfer()   @ configure WAITCNT, DMA3 transfer

SaveGameWithVerify()                @ write + read-back verification
  └─ EepromVerifySector()          @ read + compare 4 halfwords
      └─ EepromReadSector()       @ build address command, read 64 bits

LoadGameFromSRAM()                  @ backup DMA regs, read, restore

Level Loading Pipeline

Each of the 9 worlds has 2 vision variants (18 level loaders total) plus a boss arena loader. Each loader DMA-copies ROM tile/map/palette data into VRAM for that specific level.

Address RangeFunctionsDescription
0x080301A8–0x080392A418LoadLevel_World1_Vision1 through World9_Vision2
0x080399201LoadLevel_BossArena (unique tileset)
0x0802688E–0x0802FA2827VBlankDMA_Level1 through Level27 (per-frame VRAM uploads)

Code Statistics

ModuleFunctionsLargest FunctionLines
code_1101EntityBehaviorMasterUpdate13,237
code_388UpdatePlayerMinigame2,181
gfx113SetupLevelTilemap1,836
m4a93MPlayMain565
code_023HandlePauseMenuInput512
engine27CameraModeSwitchHandler638
system10AgbMain258
math7VBlankHandler108
util9EepromWriteSector114
syscalls5LZ77UnCompWram—
Total522