# System Interactions & Coordination **Version:** 2.0 **Last Updated:** October 3, 2025 **Purpose:** Document how major systems coordinate and interact in Oracle of Secrets **Cross-References:** - `Docs/World/Overworld/ZSCustomOverworldAdvanced.md` - ZScream technical details - `Docs/General/Troubleshooting.md` - System conflict debugging - `Docs/Core/MemoryMap.md` - Shared memory regions --- ## 1. Overview This document analyzes interactions between major systems in Oracle of Secrets, including: - **ZSCustomOverworld** (custom overworld engine) - **Time System** (day/night cycle) - **Mask System** (Link transformations) - **Sprite Engine** (dynamic sprite loading) - **Menu System** (UI and item management) Each section includes: - πŸ“Š **Interaction flow diagrams** - πŸ”§ **Implementation details** - ⚠️ **Known conflicts and solutions** - 🎯 **Coordination points** --- ## Table of Contents 1. [Overview](#1-overview) 2. [System Coordination Map](#2-system-coordination-map) 3. [ZSCustomOverworld Γ— Time System](#3-zscustomoverworld--time-system) 4. [ZSCustomOverworld Γ— Lost Woods](#4-zscustomoverworld--lost-woods) 5. [ZSCustomOverworld Γ— Song of Storms](#5-zscustomoverworld--song-of-storms) 6. [ZSCustomOverworld Γ— Day/Night Sprites](#6-zscustomoverworld--daynight-sprites) 7. [Mask System Γ— All Systems](#7-mask-system--all-systems) 8. [Overworld Transition Sequence](#8-overworld-transition-sequence) 9. [Frame-by-Frame Coordination](#9-frame-by-frame-coordination) --- ## 2. System Coordination Map ### High-Level Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Main Game Loop (Bank $00) β”‚ β”‚ Module_MainRouting ($0080B5) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β–Ό β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Module09 β”‚ β”‚ Module07 β”‚ β”‚ Module0E β”‚ β”‚Overworld β”‚ β”‚Underworldβ”‚ β”‚ Menu β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ZSCustom β”‚ β”‚ Time System β”‚ β”‚ Overworld │◄──── (Clock) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Palettes β”‚ β”‚ β€’ Hours β”‚ β”‚ β€’ Graphics β”‚ β”‚ β€’ Day/Night β”‚ β”‚ β€’ Overlays β”‚ β”‚ β€’ Palette β”‚ β”‚ β€’ Sprites β”‚ β”‚ Filter β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Sprite Engine (Bank $06) β”‚ β”‚ β€’ Load sprites for area β”‚ β”‚ β€’ Apply day/night set β”‚ β”‚ β€’ Initialize sprite state β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Mask System (Bank $3A) β”‚ β”‚ β€’ Transform Link β”‚ β”‚ β€’ Override abilities β”‚ β”‚ β€’ Custom physics β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Shared Memory Regions | Address | System | Purpose | Conflicts | |---------|--------|---------|-----------| | `$7E008A` | All | Current overworld area | Read-only | | `$7E0010` | All | Game module/mode | Read-only | | `$7E008C` | ZSO, Storms | Overlay register | Write conflict βœ“ Resolved | | `$7EE000` | Time, Sprites | Current hour | Read-only | | `$7EF3C5` | Sprites, Time | Game state | Read/Write | | `$7EF39D` | Storms, ZSO | Storm active flag | Coordination | --- --- ## 3. ZSCustomOverworld Γ— Time System **Systems:** - `Overworld/ZSCustomOverworld.asm` - `Overworld/time_system.asm` **Interaction Type:** βœ… Compatible by Design ### 3.1. Coordination Point: Palette Modulation Both systems modify overworld palettes: - **ZSCustomOverworld:** Sets base palette from area-specific tables - **Time System:** Applies color transformation for lighting effects ### 3.2. Interaction Flow ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Area Transition Begins β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ZSCustomOverworld: Load Area Palette β”‚ β”‚ β€’ Read area ID from $8A β”‚ β”‚ β€’ Lookup in Pool_OverworldPaletteSet β”‚ β”‚ β€’ Write base colors to CGRAM β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό (Each color write intercepted) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Time System: LoadDayNightPaletteEffect Hook β”‚ β”‚ β€’ Intercepts ALL writes to $2122 (CGRAM) β”‚ β”‚ β€’ Checks current hour ($7EE000) β”‚ β”‚ β€’ Applies color subtraction based on time: β”‚ β”‚ - Dawn (06:00-07:59): Gradual brightening β”‚ β”‚ - Day (08:00-17:59): No modification β”‚ β”‚ - Dusk (18:00-19:59): Gradual darkening β”‚ β”‚ - Night (20:00-05:59): Heavy darkening β”‚ β”‚ β€’ Writes modified color to CGRAM β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Final Palette Applied to Screen β”‚ β”‚ (Base colors + Time-of-Day modulation) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 3.3. Implementation Details **Time System Hook Location:** ```asm ; In time_system.asm pushpc org $0ED32F ; Vanilla palette load routine JSL LoadDayNightPaletteEffect ; Intercept color writes pullpc LoadDayNightPaletteEffect: { ; Save original color PHA ; Check time of day LDA.l $7EE000 ; Current hour CMP.b #$12 ; 18:00 (6 PM) BCS .night CMP.b #$06 ; 06:00 (6 AM) BCC .night ; Day: No modification PLA STA $2122 ; Write to CGRAM RTL .night ; Night: Apply darkening PLA JSR ApplyDarkeningEffect STA $2122 RTL } ``` **ZSCustomOverworld Palette Loading:** ```asm ; In ZSCustomOverworld.asm LoadAreaPalette: { LDA.b $8A ; Current area ASL A : ASL A TAX ; Load palette set index LDA.l Pool_OverworldPaletteSet, X TAY ; Load colors (each write goes through Time System hook) LDA.l PaletteData, Y STA $2122 ; ← Hook intercepts here ; ... load remaining colors ... } ``` ### 3.4. Status & Recommendations βœ… **Status:** Compatible - No code changes needed **How it works:** 1. ZSCustomOverworld writes base palette colors 2. Each write is intercepted by Time System hook 3. Time System modifies the color based on hour 4. Modified color is written to CGRAM 5. Result: Area-specific palette with time-of-day lighting **Recommendations:** - βœ… No compatibility fixes required - πŸ“ Code organization: Consider moving Time System hooks to `Core/patches.asm` - 🎨 Design consideration: Ensure base palettes are designed for darkening (avoid pure black) --- ## 4. ZSCustomOverworld Γ— Lost Woods Puzzle **Systems:** - `Overworld/ZSCustomOverworld.asm` - `Overworld/lost_woods.asm` **Interaction Type:** ⚠️ Direct Conflict - Integration Required ### 4.1. Coordination Point: Screen Transitions The Lost Woods creates a maze by intercepting transitions and looping the player back until they follow the correct path sequence. ### 4.2. Conflict Analysis **Lost Woods Mechanism:** 1. Detects player in area `$29` (Lost Woods) 2. Tracks exit direction (N/S/E/W) 3. Compares against solution sequence 4. If wrong: Overrides Link's coordinates to loop back 5. If correct: Allows normal transition **ZSCustomOverworld Mechanism:** 1. Hooks `OverworldHandleTransitions` at `$02A9C4` 2. Implements custom transition logic 3. Uses expanded area tables 4. Handles multiple transition types **Conflict:** ZSCustomOverworld's hook runs before Lost Woods check, potentially bypassing the puzzle logic. ### 4.3. Interaction Flow (Proposed Solution) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Player Reaches Screen Edge β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ZSCustomOverworld: OverworldHandleTransitions β”‚ β”‚ β€’ Detect transition trigger β”‚ β”‚ β€’ Calculate new area/coordinates β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Check Area ID β”‚ β”‚ Is $8A == $29? β”‚ β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”˜ β”‚ YES β”‚ NO β”‚ β”‚ β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Lost Woods Active β”‚ β”‚ Normal Transition β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–Ό β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ JSL LostWoods_ β”‚ β”‚ β”‚ PuzzleHandler β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ Check Direction β”‚ β”‚ β”‚ Against Sequence β”‚ β”‚ β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”˜ β”‚ β”‚ CORRECT β”‚ WRONG β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Override Coords β”‚ β”‚ β”‚ β”‚ Loop Back β”‚ β”‚ β”‚ β”‚ Return Carry=1 β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Transition β”‚ β”‚ β”‚ β”‚ Handled β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Execute Standard β”‚ β”‚ ZS Transition β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 4.4. Implementation Solution **Step 1: Modify ZSCustomOverworld Transition Handler** ```asm ; In ZSCustomOverworld.asm at OverworldHandleTransitions OverworldHandleTransitions: { ; ... existing transition detection logic ... ; After determining new area but BEFORE applying transition: LDA.b $8A ; Current Area ID CMP.b #$29 ; Lost Woods area? BNE .normal_transition ; Check if we're actually transitioning (not just moving within screen) LDA.b $20 ; Link X low ; ... boundary check ... ; Call Lost Woods handler JSL LostWoods_PuzzleHandler BCS .transition_handled ; Carry set = puzzle handled transition .normal_transition ; ... execute standard ZS transition logic ... .transition_handled RTL } ``` **Step 2: Create Lost Woods Handler Subroutine** ```asm ; In Overworld/lost_woods.asm LostWoods_PuzzleHandler: { ; Input: Transition direction in progress ; Output: Carry set if puzzle handled transition, clear if allowing normal ; Determine exit direction JSR GetExitDirection ; Returns direction in A ; Check against sequence LDX.w LostWoodsSolutionProgress ; Current step in sequence CMP.l LostWoodsSolution, X ; Check if correct direction BNE .wrong_direction ; Correct direction INX STX.w LostWoodsSolutionProgress CPX.b #$04 ; Sequence length BNE .continue_puzzle ; Sequence complete! Allow normal transition STZ.w LostWoodsSolutionProgress ; Reset for next time CLC ; Clear carry = allow normal transition RTL .wrong_direction ; Override coordinates to loop back STZ.w LostWoodsSolutionProgress ; Reset sequence ; Calculate loop-back coordinates based on direction JSR CalculateLoopbackCoords SEC ; Set carry = transition handled by puzzle RTL .continue_puzzle ; Mid-sequence, allow transition but stay in Lost Woods CLC RTL } LostWoodsSolution: db $00, $02, $01, $03 ; N, E, S, W (example) ``` ### 4.5. Status & Recommendations ⚠️ **Status:** Requires Integration **Action Items:** 1. βœ… Design: Integration pattern documented above 2. ⏳ Implementation: Add Lost Woods check to ZS transition handler 3. ⏳ Refactor: Convert Lost Woods to subroutine with carry flag return 4. ⏳ Testing: Verify puzzle still works with ZS transitions **Testing Checklist:** - [ ] Wrong sequence loops player back correctly - [ ] Correct sequence allows escape - [ ] Sequence resets on wrong direction - [ ] Works with all 4 exit directions - [ ] No crashes or graphical glitches --- ## 5. ZSCustomOverworld Γ— Song of Storms **Systems:** - `Overworld/ZSCustomOverworld.asm` - `Items/ocarina.asm` - `Overworld/time_system.asm` **Interaction Type:** βœ… Resolved - Persistent State Solution ### 5.1. Coordination Point: Weather Overlays Both systems control the weather overlay register (`$8C`): - **ZSCustomOverworld:** Sets area default overlay on transitions - **Song of Storms:** Summons/dismisses rain effect ### 5.2. Conflict Analysis **Original Problem:** 1. Player plays Song of Storms β†’ Rain overlay (`$9F`) applied 2. Player transitions to new screen β†’ ZS reloads default overlay 3. Rain disappears immediately (lost state) 4. If player dismisses storm, might remove natural weather effects ### 5.3. Solution Architecture **Implemented Solution: Persistent SRAM Flag** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Player Plays Song of Storms Ocarina β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ OcarinaEffect_SummonStorms (Items/ocarina.asm) β”‚ β”‚ β€’ Read area ID ($8A) β”‚ β”‚ β€’ Lookup default overlay in Pool_OverlayTable β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Default = Rain? β”‚ β”‚ (Overlay $9F) β”‚ β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”˜ β”‚ YES β”‚ NO β”‚ β”‚ β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Do Nothing β”‚ β”‚ Toggle Storm Flag β”‚ β”‚ (Natural rain) β”‚ β”‚ XOR $7EF39D, #$01 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Storm Active Flag Set β”‚ β”‚ $7EF39D (SRAM) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Every Frame (if in Overworld) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ HandleStormsOverlay (time_system.asm) β”‚ β”‚ Called from RunClock each frame β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Storm Active? β”‚ β”‚ $7EF39D == 1 β”‚ β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”˜ β”‚ YES β”‚ NO β”‚ β”‚ β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Force Rain β”‚ β”‚ Allow ZS Default β”‚ β”‚ LDA #$9F β”‚ β”‚ Overlay to Apply β”‚ β”‚ STA $8C β”‚ β”‚ (Do Nothing) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Screen Transition or Area Change β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ZSCustomOverworld: Load Area Defaults β”‚ β”‚ β€’ Loads default overlay from Pool_OverlayTable β”‚ β”‚ β€’ Writes to $8C β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό (Next frame) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ HandleStormsOverlay: Check Storm Flag β”‚ β”‚ β€’ If SRAM_StormsActive = 1, override with rain β”‚ β”‚ β€’ Rain persists across transitions! β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 5.4. Implementation Details **SRAM Variable Definition:** ```asm ; In Core/sram.asm SRAM_StormsActive = $7EF39D ; 1 byte: 0=off, 1=active ``` **Ocarina Effect (Modified):** ```asm ; In Items/ocarina.asm OcarinaEffect_SummonStorms: { ; Check if natural rain is already present LDA.b $8A ; Current area ASL A TAX LDA.l Pool_OverlayTable, X CMP.b #$9F ; Is default overlay rain? BEQ .exit ; If yes, don't toggle (natural rain) ; Toggle storm active flag LDA.l $7EF39D EOR.b #$01 ; Toggle bit STA.l $7EF39D ; Play sound effect LDA.b #$20 ; Storm sound STA.w $012E .exit RTL } ``` **Storm Overlay Handler:** ```asm ; In Overworld/time_system.asm HandleStormsOverlay: { ; Only run in overworld LDA.b $1B ; INDOORS flag BNE .exit ; Skip if indoors ; Check storm flag LDA.l $7EF39D ; Storm active? BEQ .exit ; No storm, let ZS handle overlay ; Force rain overlay LDA.b #$9F ; Rain overlay ID STA.b $8C ; Overlay register .exit RTS } ; Called from RunClock main loop: RunClock: { ; ... time system logic ... JSR HandleStormsOverlay ; Check storm state every frame ; ... rest of clock logic ... } ``` ### 5.5. Status & Benefits βœ… **Status:** Fully Implemented and Tested **Benefits:** 1. βœ… Rain persists across screen transitions 2. βœ… Rain persists when entering/exiting dungeons 3. βœ… Prevents accidental cancellation of natural rain 4. βœ… Works seamlessly with ZS overlay system 5. βœ… State saved in SRAM (survives save/load) **Edge Cases Handled:** - Natural rain areas: Song does nothing (no toggle) - Transition to dungeon: Flag preserved, reapplied on return - Save/load: Storm state persists via SRAM - Multiple plays: Toggle on/off correctly --- ## 6. ZSCustomOverworld Γ— Day/Night Sprites **Systems:** - `Overworld/ZSCustomOverworld.asm` - `Overworld/time_system.asm` **Interaction Type:** βœ… Resolved - Integrated Solution ### 6.1. Coordination Point: Sprite Set Loading The sprite loading system must select different sprite sets based on time of day: - **Day (06:00-17:59):** Normal enemy sprites - **Night (18:00-05:59):** Nocturnal enemy sprites (different IDs) ### 6.2. Solution: Oracle_ZSO_CheckIfNight Bridge Function **Problem:** ZScream hooks vanilla `Overworld_LoadSprites` at `$09C4C7`, but needs to access Oracle's time system (`$7EE000`) which is in a different namespace. **Solution:** Bridge function that combines game state with time check. ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Area Transition / Sprite Reload Triggered β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ZSCustomOverworld: LoadOverworldSprites_Interupt ($09C4C7)β”‚ β”‚ β€’ Calculate screen size β”‚ β”‚ β€’ Get area ID from $040A β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ JSL Oracle_ZSO_CheckIfNight (Bridge Function) β”‚ β”‚ β€’ Checks special peacetime areas (Tail Palace, Zora) β”‚ β”‚ β€’ Reads hour from $7EE000 β”‚ β”‚ β€’ Returns GameState or GameState+1 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό (Returns phase index) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Calculate Sprite Pointer Offset β”‚ β”‚ β€’ Base = AreaID * 2 β”‚ β”‚ β€’ Offset = PhaseOffsetTable[Phase] β”‚ β”‚ β€’ FinalIndex = Base + Offset β”‚ β”‚ β”‚ β”‚ PhaseOffsetTable: β”‚ β”‚ .phaseOffset β”‚ β”‚ dw $0000, $0000 ; State 0: Day, Night β”‚ β”‚ dw $0140, $0280 ; State 1: Day, Night β”‚ β”‚ dw $04C0, $0600 ; State 2: Day, Night β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Load Sprite Data from Pool_Overworld_SpritePointers β”‚ β”‚ β€’ Reads pointer at FinalIndex β”‚ β”‚ β€’ Loads sprite list for area+time β”‚ β”‚ β€’ Initializes sprites β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 6.3. Implementation Details **Bridge Function (time_system.asm):** ```asm ; This function lives OUTSIDE Oracle namespace ; So ZScream can call it via JSL ZSO_CheckIfNight: { PHB : PHK : PLB ; Check special peacetime areas first LDA $8A ; Current area CMP.b #$2E : BEQ .tail_palace CMP.b #$2F : BEQ .tail_palace CMP.b #$1E : BEQ .zora_sanctuary JMP .continue_check .tail_palace ; If crystal collected, load peacetime sprites LDA.l $7EF37A ; Crystals SRAM AND #$10 BNE .load_peacetime JMP .continue_check .zora_sanctuary LDA.l $7EF37A AND #$20 BNE .load_peacetime JMP .continue_check .load_peacetime ; Return normal game state (day sprites) LDA.l $7EF3C5 PLB RTL .continue_check REP #$30 ; Don't change during intro LDA.l $7EF3C5 : AND.w #$00FF CMP.w #$0002 : BCC .day_time ; Check time LDA.l $7EE000 : AND.w #$00FF CMP.w #$0012 : BCS .night_time ; >= 18:00 CMP.w #$0006 : BCC .night_time ; < 06:00 .day_time LDA.l $7EF3C5 BRA .done .night_time LDA.l $7EF3C5 INC A ; GameState + 1 for night .done SEP #$30 PLB RTL } ; Export to Oracle namespace namespace Oracle { Oracle_ZSO_CheckIfNight = ZSO_CheckIfNight } ``` **ZSCustomOverworld Hook:** ```asm ; In ZSCustomOverworld.asm at $09C4C7 org $09C4C7 LoadOverworldSprites_Interupt: { LDX.w $040A ; Area ID LDA.l Pool_BufferAndBuildMap16Stripes_overworldScreenSize, X : TAY LDA.w .xSize, Y : STA.w $0FB9 : STZ.w $0FB8 LDA.w .ySize, Y : STA.w $0FBB : STZ.w $0FBA ; Get phase (day/night + game state) JSL Oracle_ZSO_CheckIfNight ; Returns phase in A ASL : TAY ; * 2 for word table REP #$30 ; Calculate final pointer index TXA : ASL ; AreaID * 2 CLC : ADC.w .phaseOffset, Y ; Add phase offset TAX ; Get sprite pointer LDA.l Pool_Overworld_SpritePointers_state_0_New, X STA.b $00 SEP #$20 BRA .skip .xSize db $02, $04, $04, $02 .ySize db $02, $04, $02, $04 .phaseOffset dw $0000, $0000 ; State 0: Day, Night dw $0140, $0280 ; State 1: Day, Night (160 areas * 2 bytes) dw $04C0, $0600 ; State 2: Day, Night NOP : NOP : NOP org $09C50D .skip } ``` ### 6.4. Status & Remaining Issues βœ… **Status:** Sprite Loading Logic Complete ⚠️ **Known Issue:** Sprite graphics (tilesets) not updating **What Works:** - Correct sprite IDs load for day/night - Game state + time properly combined - Peacetime areas handled correctly - Transition logic integrated **What Doesn't Work:** - Sprite graphics remain from previous set - Results in "gargoyle" effect (wrong tiles for sprite) - Need to trigger sprite GFX reload on time change **Proposed Solution:** Add graphics reload hook in time transition: ```asm ; In time_system.asm when hour changes TimeTransition_NightToDayOrDayToNight: { ; ... existing time change logic ... ; Reload sprite graphics if in overworld LDA.b $1B ; INDOORS flag BNE .skip JSL Overworld_ReloadSpriteGFX ; Force GFX update .skip RTL } ``` See `Docs/World/Overworld/ZSCustomOverworldAdvanced.md` Section 4 for complete day/night sprite loading documentation. --- ## 7. Mask System Γ— All Systems **System:** `Masks/all_masks.asm` **Interaction Type:** πŸ”„ Complex Multi-System Coordination ### 7.1. Overview The Mask System transforms Link, affecting nearly every game system: - **Physics:** Custom movement, swimming, climbing - **Graphics:** Different Link sprite sets (banks $33-$3B) - **Abilities:** Unique powers per mask - **Menu:** Item restrictions, HUD changes - **Sprites:** Different collision/interaction ### 7.2. System Impact Map ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Mask System β”‚ β”‚ (Bank $3A) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β–Ό β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Player Engine β”‚ β”‚ Sprite System β”‚ β”‚ Menu System β”‚ β”‚ (Bank $07) β”‚ β”‚ (Bank $06) β”‚ β”‚ (Bank $2D) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Movement β”‚ β”‚ β€’ Collision β”‚ β”‚ β€’ Inventory β”‚ β”‚ β€’ Physics β”‚ β”‚ β€’ Damage β”‚ β”‚ β€’ HUD β”‚ β”‚ β€’ Actions β”‚ β”‚ β€’ Interactions β”‚ β”‚ β€’ Abilities β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Graphics System β”‚ β”‚ └──────────►│ (Banks $33-$3B) β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β€’ Deku ($35) β”‚ β”‚ β€’ Zora ($36) β”‚ β”‚ β€’ Bunny ($37) β”‚ β”‚ β€’ Wolf ($38) β”‚ β”‚ β€’ Minish ($39) β”‚ β”‚ β€’ Moosh ($33) β”‚ β”‚ β€’ GBC ($3B) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 7.3. Coordination Points **A. Transform Sequence** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Player Equips Mask from Menu β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Link_TransformMask (Masks/mask_routines.asm) β”‚ β”‚ β€’ Read mask ID from equipment slot β”‚ β”‚ β€’ Validate can transform (not indoors, etc.) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Save Original State β”‚ β”‚ β€’ Store vanilla Link properties to WRAM backup β”‚ β”‚ β€’ $7E0730+: Original movement speed, abilities β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Load Mask Graphics β”‚ β”‚ β€’ DMA mask-specific Link graphics from banks $33-$3B β”‚ β”‚ β€’ Replace Link's OAM tileset β”‚ β”‚ β€’ Update palette to CGRAM β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Override Player State Machine β”‚ β”‚ β€’ Hook Link_Main ($078000) β”‚ β”‚ β€’ Redirect to mask-specific handlers β”‚ β”‚ β€’ Custom physics, movement, actions β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Update Collision & Sprites β”‚ β”‚ β€’ Set custom hitbox size β”‚ β”‚ β€’ Modify sprite interaction flags β”‚ β”‚ β€’ Update damage tables β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Set Menu/HUD State β”‚ β”‚ β€’ Update ability icons β”‚ β”‚ β€’ Restrict/enable items β”‚ β”‚ β€’ Show transformation indicator β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **B. De-Transform Sequence** When mask is removed or expires: 1. Restore original Link properties from backup 2. Reload vanilla Link graphics 3. Restore normal hitbox/collision 4. Re-enable all items 5. Clear transformation flags ### 7.4. Mask-Specific Interactions **Deku Mask (Masks/deku_mask.asm):** - **Movement:** Hop-based instead of walk - **Water:** Cannot swim (sinks immediately) - **Combat:** Deku Bubble projectile - **Special:** Can use Deku Flowers - **Graphics:** Bank $35 **Zora Mask (Masks/zora_mask.asm):** - **Movement:** Fast underwater swimming - **Combat:** Boomerang fins - **Breathing:** Infinite underwater - **Special:** Electric barrier - **Graphics:** Bank $36 **Bunny Hood (Masks/bunny_hood.asm):** - **Movement:** 2x speed boost - **Jump:** Increased jump height - **Special:** Dash attack - **Graphics:** Bank $37 **Wolf Mask (Masks/wolf_mask.asm):** - **Movement:** Quadruped locomotion - **Combat:** Bite attack - **Special:** Enhanced sense (see hidden) - **Graphics:** Bank $38 **Minish Mask (Masks/minish_form.asm):** - **Size:** Reduced hitbox (access small spaces) - **Combat:** Weak attacks - **Special:** Talk to Minish NPCs - **Graphics:** Bank $39 ### 7.5. Memory Coordination **Mask State Variables (WRAM):** ``` $7E0730: Mask_CurrentForm ; 0=Normal, 1=Deku, 2=Zora, etc. $7E0731: Mask_TransformTimer ; Countdown for timed masks $7E0732: Mask_AbilityFlags ; Bitfield for active abilities $7E0733: Mask_BackupSpeed ; Original Link speed $7E0734: Mask_BackupJump ; Original jump power ``` **Equipment Slots (SRAM):** ``` $7EF347: ZoraMask ; Owned: 0=No, 1=Yes $7EF348: BunnyHood $7EF349: DekuMask $7EF34A: WolfMask $7EF34B: MinishMask ``` ### 7.6. Known Issues & Solutions **Issue 1: Menu Access While Transformed** - Problem: Some masks prevent menu access - Solution: Hook menu open, allow "safe" transformations (Bunny) but block risky ones (Minish) **Issue 2: Death While Transformed** - Problem: Death sequence uses vanilla Link graphics - Solution: Force de-transform before death animation **Issue 3: Dungeon Restrictions** - Problem: Some dungeons shouldn't allow transformations - Solution: Check dungeon ID before transform, deny with message --- ## 8. Overworld Transition Sequence **Complete Frame-by-Frame Breakdown** This section documents the exact order of operations during an overworld area transition, showing how all systems coordinate. ### 8.1. Transition Trigger (Frame 0) ``` Player Reaches Screen Edge ↓ Link_Main (Bank $07) detects boundary ↓ Sets $11 (submodule) = $01 (transition start) ↓ Module remains $09 (Overworld) ``` ### 8.2. Transition Sequence (Frames 1-30) **Frame 1-2: State Setup** ``` Module09_Overworld (Bank $00) ↓ Checks $11 submodule ↓ Submodule $01: Begin Transition ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Store current state: β”‚ β”‚ β€’ Camera position β†’ $7EC180 β”‚ β”‚ β€’ Link coordinates β†’ $7EC184 β”‚ β”‚ β€’ BG scroll β†’ $7EC188 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Frame 3-8: Scroll Animation** ``` Every frame: ↓ Increment camera offset ↓ Update BG1/BG2 scroll registers ↓ Move Link sprite position ↓ Check if scroll complete (8 tiles) ``` **Frame 9: New Area Load Start** ``` Scroll complete ↓ Calculate new area ID ↓ Store in $8A (new area) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ZSCustomOverworld Hook Triggers β”‚ β”‚ OverworldHandleTransitions ($02A9C4) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ Lost Woods check (if area $29) ↓ Normal transition continues ``` **Frame 10-15: Graphics & Data Load** ``` ZSCustomOverworld_LoadArea: ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Load in sequence: β”‚ β”‚ 1. Map16 data from pool β”‚ β”‚ 2. Tile32 layout β”‚ β”‚ 3. Collision data β”‚ β”‚ 4. Base palette β”‚ β”‚ 5. Overlay data β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Frame 16-20: Palette & Overlay Processing** ``` Palette loading: ↓ Each color write β†’ $2122 ↓ Time System hook intercepts ↓ Applies day/night modulation ↓ Final color written to CGRAM β”‚ β”œβ”€ Check Storm Flag ($7EF39D) └─ If active, override overlay with rain ``` **Frame 21-25: Sprite System** ``` LoadOverworldSprites_Interupt: ↓ JSL Oracle_ZSO_CheckIfNight ↓ Calculate sprite pointer offset ↓ Load sprite data for area+time ↓ Initialize sprite slots (16 total) ↓ Set initial sprite states ``` **Frame 26-28: Mask System Check** ``` If Link transformed: ↓ Verify mask valid in new area ↓ Maintain transformation state ↓ Update custom physics for terrain ``` **Frame 29-30: Finalization** ``` Set $11 = $00 (submodule complete) ↓ Enable player control ↓ Resume normal gameplay ``` --- ## 9. Frame-by-Frame Coordination **Every Frame (60 FPS) Execution Order** ### 9.1. NMI (Interrupt_NMI - $0080C9) ``` Hardware Interrupt (VBlank starts) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ NMI_ReadJoypads β”‚ β”‚ β€’ Read controller input β”‚ β”‚ β€’ Store in $F0-$F7 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ NMI_DoUpdates β”‚ β”‚ β€’ DMA stripe data to VRAM β”‚ β”‚ β€’ Update OAM (sprite positions) β”‚ β”‚ β€’ Upload palettes if changed β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ NMI_PrepareSprites β”‚ β”‚ β€’ Calculate sprite priority β”‚ β”‚ β€’ Build OAM buffer β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ RTI (Return from interrupt) ``` ### 9.2. Main Loop (MainGameLoop - $008034) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Module_MainRouting ($0080B5) β”‚ β”‚ β€’ Read $10 (module) β”‚ β”‚ β€’ Jump to current module handler β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ If Module $09 (Overworld): ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Module09_Overworld β”‚ β”‚ β€’ Read $11 (submodule) β”‚ β”‚ β€’ Execute current overworld submodule β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Time System: RunClock β”‚ β”‚ β€’ Increment frame counter β”‚ β”‚ β€’ Update hour if needed β”‚ β”‚ β€’ Handle day/night transitions β”‚ β”‚ β€’ Call HandleStormsOverlay β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Link_Main (Bank $07) β”‚ β”‚ β€’ Read $5D (Link state) β”‚ β”‚ β€’ Execute state handler β”‚ β”‚ β€’ Update position, velocity β”‚ β”‚ β€’ Check mask transformations β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Sprite_Main (Bank $06) β”‚ β”‚ β€’ Loop through 16 sprite slots β”‚ β”‚ β€’ Execute each active sprite's AI β”‚ β”‚ β€’ Check collisions with Link β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Ancilla_Main (Bank $08) β”‚ β”‚ β€’ Update projectiles β”‚ β”‚ β€’ Handle particle effects β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ Loop back to Module_MainRouting ``` ### 9.3. System Priority Order When multiple systems need to modify the same resource: **Priority 1 (Highest): Player Safety** - Mask de-transform on death - Collision damage - State machine locks **Priority 2: Weather/Environment** - Storm overlay override - Time-based palette - Dynamic weather effects **Priority 3: Normal Gameplay** - Standard sprite behavior - Menu access - Item usage **Priority 4 (Lowest): Visual Polish** - Animated tiles - Particle effects - HUD animations --- ## 10. Troubleshooting System Interactions **Common Issues:** ### 10.1. "System X overwrites System Y's changes" **Diagnosis:** 1. Check execution order in main loop 2. Verify which system runs last 3. Look for missing coordination flags **Solution:** - Add SRAM/WRAM flag for coordination - Use priority system (see 9.3) - Implement callback/hook pattern ### 10.2. "Changes don't persist across transitions" **Diagnosis:** 1. Check if state is in WRAM (volatile) or SRAM (persistent) 2. Verify state is restored during area load 3. Look for reset code that clears flags **Solution:** - Move important state to SRAM - Add save/restore routines - Check ZS transition hooks ### 10.3. "Namespace can't call function in other namespace" **Diagnosis:** 1. Check if function is exported with Oracle_ prefix 2. Verify build order in Oracle_main.asm 3. Look for missing export block **Solution:** - Add export: `namespace Oracle { Oracle_Function = Function }` - Use bridge function pattern (see Section 6.2) - Verify calling syntax with prefix See `Docs/General/Troubleshooting.md` for comprehensive debugging guide. --- ## 11. References **Core Documentation:** - `Docs/World/Overworld/ZSCustomOverworldAdvanced.md` - ZScream internals - `Docs/General/Troubleshooting.md` - Problem-solving guide - `Docs/General/DevelopmentGuidelines.md` - Best practices - `Docs/Core/MemoryMap.md` - Memory layout **System-Specific:** - `Overworld/ZSCustomOverworld.asm` - Custom overworld engine - `Overworld/time_system.asm` - Day/night cycle - `Masks/mask_routines.asm` - Transformation system - `Items/ocarina.asm` - Song effects **Vanilla Reference:** - `ALTTP/bank_00.asm` - Main loop and modules - `ALTTP/bank_02.asm` - Overworld transitions - `ALTTP/bank_06.asm` - Sprite engine - `ALTTP/bank_07.asm` - Player engine --- **Document Version:** 2.0 **Last Updated:** October 3, 2025 **Maintained By:** Oracle of Secrets Development Team