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.
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
The game uses a fixed-size entity array at 0x03002920,
with each entry being 28 bytes. Entity slot 0 is always the player.
EntityBehaviorMasterUpdate() @ 0x08015220 — 13,237 lines (LARGEST function)
└─ For each active entity:
└─ EntityUpdateDispatch() @ 0x080101E8 — switch on entity type
├─ EntityGravityAndFloorCheck()
├─ EntityScrollBoundsCheck()
└─ Type-specific handler...
| Function | Lines | Description |
|---|---|---|
| EntityPlatformRide | 983 | Moving platform — position relative to BG scroll |
| EntityThrowUpdate | 259 | Thrown entity trajectory with parabolic arc |
| EntityProjectileUpdate | 315 | Projectile movement + collision + particles |
| EntitySpringBoard | 213 | Bounce pad — applies upward velocity on contact |
| EntityFloatPath | 216 | Floating/patrol movement along path |
| EntityBounceOffWall | 247 | Wall bounce with direction reversal |
| EntityItemDrop | 190 | Item drop with state machine (fall → land) |
| EntityPickupCollect | 84 | Collectible pickup + HUD counter update |
| EntityDeathAnimation | 188 | Death/despawn with debris sprites |
| EntityCutsceneActor | 360 | Scripted entity for cutscene sequences |
| Function | Lines | Description |
|---|---|---|
| EntityBossPhaseA | 1,656 | Multi-state boss AI with sprite DMA + attack patterns |
| EntityBossPhaseB | 951 | Boss variant with distance-based attacks |
| EntityBossPhaseC | 1,871 | Largest boss — multi-attack patterns + health thresholds |
| EntityBossPhaseD | 1,640 | Boss with tile collision + complex movement |
| EntityMiniBoss | 276 | Simpler boss pattern with sound triggers |
| EntityMiniBossAlt | 653 | Multi-state mini-boss variant |
The player has multiple update modes depending on the current game state:
| Function | Lines | Context |
|---|---|---|
| PlayerMainUpdate | 4,351 | Normal gameplay — movement, collision, animation |
| PlayerMovementPhysics | 1,421 | Input-driven movement with tile collision |
| UpdatePlayerNormal | 1,728 | Standard level gameplay (code_3) |
| UpdatePlayerBoss | 1,706 | Boss fight variant |
| UpdatePlayerMinigame | 2,181 | Puzzle/minigame levels |
| UpdatePlayerAlternate | 1,839 | Alternate movement mode |
| UpdatePlayerSpecial | 1,475 | Special interaction mode |
| UpdatePlayerFinalBoss | 1,564 | Final boss encounter |
PlayerGrabInputCheck detects grab input,
EntityStateSwitch_Carried handles carried entity statesCheckTileCollisionVertical and
CheckTileCollisionSloped check against the tile collision mapPlayerRespawnOrDeath saves facing
direction and resets scroll countersThe 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.
| Function | Description |
|---|---|
| TransitionFadeOutDisableIRQ | Fade out then disable HBlank/VCount interrupts |
| TransitionFadeInBldAlpha | Fade in using BLDCNT alpha blending |
| TransitionInitLevelMusic | Select track by world/level, begin playback |
| TransitionToWorldMap | Fade to black, set up world map scene (matched) |
| TransitionGameplayInit | Free buffers, install gameplay callbacks |
| TransitionFadeOutWithMusic | Fade screen + music volume simultaneously |
| TransitionGameOver | Return to world map or restart level |
| TransitionToTitleScreen | Install title screen callbacks |
| TransitionSoftReset | Full-black for 16 frames then SWI reset |
| TransitionToSaveScreen | Stop music, install save-screen flow |
The overworld map manages node-based navigation across 9 worlds, each with 6 visions. Key functions:
| Function | Description |
|---|---|
| UpdateWorldMapInput | D-pad/button input for map navigation |
| UpdateWorldMapCursor | Cursor movement + node selection animation |
| CheckWorldCompletion | Checks gem/star counts per vision |
| CountCollectedGems | Counts collected gems and stars across visions |
| UpdateWorldMapNodeTile | Updates node tiles from animation table |
| FindNextUnlockedVision | Bitmask lookup for next available vision |
| UpdateVisionStarIcons | HUD star/gem icon updates per vision |
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
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 Range | Functions | Description |
|---|---|---|
| 0x080301A8–0x080392A4 | 18 | LoadLevel_World1_Vision1 through World9_Vision2 |
| 0x08039920 | 1 | LoadLevel_BossArena (unique tileset) |
| 0x0802688E–0x0802FA28 | 27 | VBlankDMA_Level1 through Level27 (per-frame VRAM uploads) |
| Module | Functions | Largest Function | Lines |
|---|---|---|---|
| code_1 | 101 | EntityBehaviorMasterUpdate | 13,237 |
| code_3 | 88 | UpdatePlayerMinigame | 2,181 |
| gfx | 113 | SetupLevelTilemap | 1,836 |
| m4a | 93 | MPlayMain | 565 |
| code_0 | 23 | HandlePauseMenuInput | 512 |
| engine | 27 | CameraModeSwitchHandler | 638 |
| system | 10 | AgbMain | 258 |
| math | 7 | VBlankHandler | 108 |
| util | 9 | EepromWriteSector | 114 |
| syscalls | 5 | LZ77UnCompWram | — |
| Total | 522 |