Files
oracle-of-secrets/Docs/Core/Ram.md
scawful 6ba634caa4 Add comprehensive documentation for sprites and systems
- Introduced detailed analysis for the Minecart system, highlighting its state machine, track system, and areas for improvement.
- Created an NPCs analysis document, summarizing various NPC sprites and their functionalities.
- Added an Objects analysis document, covering interactive elements like collectibles, ice blocks, and minecarts.
- Documented the Overlord sprite system, detailing its role in spawning other sprites and managing events.
- Compiled a Dungeons & Indoor Areas document, outlining custom room tags, enhanced mechanics, and advanced collision systems.
- Developed an Overworld Systems Analysis, focusing on the ZSCustomOverworld architecture and its core features.
- Added a Time System document, explaining the in-game clock and day/night cycle management.
- Documented the ZScream Custom Overworld, detailing its data-driven approach and key features.
2025-10-02 12:44:30 -04:00

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 in bank_00.asm reads this value every frame and jumps to the corresponding module in the Module_MainRouting table.
  • SUBMODE ($7E0011): Many modules have their own internal state machines. This variable holds the sub-state for the current MODE.

This MODE/SUBMODE pattern is the fundamental driver of the game's flow. For example:

  • When Link opens the menu, the game sets MODE to 0x0E (Interface), which gives control to the menu engine.
  • When Link talks to a character, Interface_PrepAndDisplayMessage is called, which saves the current game state to MODECACHE ($7E010C) and then sets MODE to 0x0E to 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 MODE to 0x08 (Overworld Load) or 0x06 (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 (0x01 for indoors, 0x00 for outdoors). This variable is checked by numerous systems to alter their behavior. For instance, the ZSCustomOverworld system 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) and ROOM ($7E00A0): These variables store the player's current location. OWSCR holds the Overworld screen ID, while ROOM holds 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:

  1. The game looks up the entrance data for that tile in Overworld/entrances.asm.
  2. This data specifies the destination ROOM ID (e.g., 0x0104).
  3. The INDOORS flag is set to 0x01.
  4. The main game MODE is set to 0x06 (Underworld Load).
  5. The dungeon engine in bank_01.asm takes over. It reads the ROOM ID and uses it to look up the room's header in ALTTP/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 in Dungeons/custom_tag.asm. For example, a kill room tag will cause the Underworld_HandleRoomTags routine to check if all sprites in the room ($7E0E20+) have been defeated.

  • UWDEATH ($7FDF80) and OWDEATH ($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 in LINKDO ($7E005D). This is covered in detail in Docs/Link.md.

  • Sprites and Ancillae: The WRAM regions from $7E0D00 onwards are large arrays that hold the state of all active entities in the game (16 sprites, ~40 ancillae). These are defined as structs in Core/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., 0x09 for active, 0x0B for 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.asm iterates 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) and OOSPROG2 ($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:
      1. The player talks to the village_elder NPC for the first time.
      2. The NPC's code in Sprites/NPCs/village_elder.asm sets a specific bit in OOSPROG (e.g., ORA.b #$10 : STA.l OOSPROG).
      3. Later, the world map code in Overworld/world_map.asm checks this bit (LDA.l OOSPROG : AND.b #$10). If it's set, a new icon is displayed on the map.
  • 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 $7EF38B tracks items like Bananas and Seashells.

This data-driven approach, centered on modifying and checking flags in SRAM, allows for complex, stateful quest design that persists across play sessions.