5.7 KiB
RAM Analysis: The Engine's State
This document provides a high-level analysis of how Work RAM (WRAM) and Save RAM (SRAM) are used to manage the game's state. For a raw list of addresses, see Core/ram.asm and Core/sram.asm.
1. The Core Game Loop: WRAM in Motion
The entire game is driven by a master state machine whose state is stored in a single WRAM variable:
MODE($7E0010): This is the game's primary state index. The main loop inbank_00.asmreads this value every frame and jumps to the corresponding module in theModule_MainRoutingtable.SUBMODE($7E0011): Many modules have their own internal state machines. This variable holds the sub-state for the currentMODE.
This MODE/SUBMODE pattern is the fundamental driver of the game's flow. For example:
- When Link opens the menu, the game sets
MODEto0x0E(Interface), which gives control to the menu engine. - When Link talks to a character,
Interface_PrepAndDisplayMessageis called, which saves the current game state toMODECACHE($7E010C) and then setsMODEto0x0Eto display the text box. When the dialogue is finished, the previous state is restored from the cache. - Transitioning between the overworld and underworld involves setting
MODEto0x08(Overworld Load) or0x06(Underworld Load), respectively.
2. Defining the World: Location and Environment
The player's location and the properties of their environment are controlled by a handful of key WRAM variables.
-
INDOORS($7E001B): A simple but powerful flag (0x01for indoors,0x00for outdoors). This variable is checked by numerous systems to alter their behavior. For instance, theZSCustomOverworldsystem reads this flag to determine whether to apply day/night palettes, and the audio engine uses it to select the appropriate music track. -
OWSCR($7E008A) andROOM($7E00A0): These variables store the player's current location.OWSCRholds the Overworld screen ID, whileROOMholds the Underworld room ID.
The interaction between these variables is central to world traversal. When Link enters a cave on OWSCR 0x35, the following happens:
- The game looks up the entrance data for that tile in
Overworld/entrances.asm. - This data specifies the destination
ROOMID (e.g., 0x0104). - The
INDOORSflag is set to0x01. - The main game
MODEis set to0x06(Underworld Load). - The dungeon engine in
bank_01.asmtakes over. It reads theROOMID and uses it to look up the room's header inALTTP/rooms.asm. This header contains pointers to all the data needed to draw the room, including its layout, objects, and sprites.
3. Room-Specific Behavior
Once a room is loaded, its specific behavior is governed by tags and flags.
-
TAG1/TAG2($7E00AE/$AF): These are "Room Effect" tags loaded from the room's header. They trigger special behaviors like kill rooms, shutter doors, or custom events defined inDungeons/custom_tag.asm. For example, a kill room tag will cause theUnderworld_HandleRoomTagsroutine to check if all sprites in the room ($7E0E20+) have been defeated. -
UWDEATH($7FDF80) andOWDEATH($7FEF80): These are large bitfields in SRAM that track the state of every overworld screen and underworld room. When a kill room is cleared or a key is taken from a chest, a bit is set in this array. This ensures that the state persists permanently in the save file, preventing enemies from respawning or chests from reappearing.
4. The Player and Entities
-
Link: The player's state is managed by its own state machine in
bank_07.asm, with the current state held inLINKDO($7E005D). This is covered in detail inDocs/Link.md. -
Sprites and Ancillae: The WRAM regions from
$7E0D00onwards are large arrays that hold the state of all active entities in the game (16 sprites, ~40 ancillae). These are defined asstructsinCore/structs.asm. While there are dozens of variables for each sprite, the most important for general game logic are:SprState($7E0DD0,X): The sprite's main state (e.g.,0x09for active,0x0Bfor stunned).SprType($7E0E20,X): The sprite's ID number.SprX/SprY($0D10,X/$0D00,X): The sprite's coordinates.
The sprite engine in
bank_06.asmiterates through these arrays each frame, executing the logic for each active sprite.
5. Long-Term Progression: SRAM and Custom Flags
SRAM ($7EF000+) stores the player's save file and is the key to managing long-term quest progression. Oracle of Secrets heavily expands the vanilla save format to support its new data-driven systems.
-
OOSPROG($7EF3D6) andOOSPROG2($7EF3C6): These are the primary bitfields for tracking major and minor quest milestones. They are the heart of the game's custom progression.- Example Flow:
- The player talks to the
village_elderNPC for the first time. - The NPC's code in
Sprites/NPCs/village_elder.asmsets a specific bit inOOSPROG(e.g.,ORA.b #$10 : STA.l OOSPROG). - Later, the world map code in
Overworld/world_map.asmchecks this bit (LDA.l OOSPROG : AND.b #$10). If it's set, a new icon is displayed on the map.
- The player talks to the
- Example Flow:
-
Other Custom SRAM: The project adds many other custom variables to SRAM to track new systems, such as:
- New Inventory:
ZoraMask($7EF347),RocsFeather($7EF34D), etc. - Side-Quests:
MagicBeanProg($7EF39B) tracks the growth of a magic bean over time. - New Collectibles: A block starting at
$7EF38Btracks items likeBananasandSeashells.
- New Inventory:
This data-driven approach, centered on modifying and checking flags in SRAM, allows for complex, stateful quest design that persists across play sessions.