- Introduced comprehensive documentation covering internal hook architecture, memory management, graphics loading pipeline, sprite loading system, cross-namespace integration, performance considerations, and debugging strategies. - Detailed sections on adding custom features and modifying existing behaviors, including examples and code snippets. - Included a complete hook list and memory map quick reference for developers.
1321 lines
52 KiB
Markdown
1321 lines
52 KiB
Markdown
# 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
|
||
|