14 KiB
14 KiB
Oracle of Secrets: System Architecture
Purpose: Document how major systems interact to help AI agents understand the codebase structure.
1. High-Level Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Oracle_main.asm │
│ (Master include file - controls ROM layout and build order) │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────┼─────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Core/ │ │ Sprites/ │ │ Overworld/ │
│ - link.asm │ │ - all_sprites│ │ - ZSCustomOW │
│ - sram.asm │ │ - Bosses/ │ │ - time_system│
│ - symbols.asm│ │ - NPCs/ │ │ - overlays │
│ - patches.asm│ │ - Enemies/ │ │ - lost_woods │
│ - message.asm│ │ - Objects/ │ └───────────────┘
└───────────────┘ └───────────────┘
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ Items/ │ │ Menu/ │
│ - all_items │ │ - menu.asm │
│ - ocarina │ │ - menu_select│
│ - magic_bag │ │ - menu_journal│
└───────────────┘ └───────────────┘
2. Namespace Organization
2.1 Oracle Namespace
All custom Oracle of Secrets code lives inside the Oracle namespace:
namespace Oracle
{
; Core systems
incsrc "Core/link.asm"
incsrc "Core/sram.asm"
incsrc "Core/symbols.asm"
; Content
incsrc "Music/all_music.asm"
incsrc "Sprites/all_sprites.asm"
incsrc "Items/all_items.asm"
; Patches go last
incsrc "Core/patches.asm"
}
namespace off
; ZScream code is OUTSIDE the namespace
incsrc "Overworld/ZSCustomOverworld.asm"
2.2 Why This Matters
- Labels inside
namespace OraclebecomeOracle.LabelName - ZScream uses its own conventions and must be outside
- Patches at end to ensure all labels are defined
3. Memory Map Overview
3.1 Bank Organization
| Bank Range | Purpose | Notes |
|---|---|---|
| $00-$1F | Vanilla ALTTP + small patches | Limited free space |
| $20-$29 | ZScream Overworld Data | ~1.5MB reserved |
| $30 | Sprite prep/initialization | Oracle sprites start here |
| $31 | Main sprite logic | Enemy/NPC behavior |
| $32 | Boss logic | Complex sprite code |
| $33-$3F | Free space | Available for expansion |
3.2 RAM Regions
| Region | Purpose |
|---|---|
| $7E0000-$7E1FFF | Scratch RAM (volatile) |
| $7E2000-$7EFFFF | Game state RAM |
| $7EE000-$7EE0FF | TimeState struct |
| $7EF000-$7EFFFF | SRAM (saved data) |
| $7EF3C5-$7EF3D6 | Oracle progression flags |
| $7EF410 | Dreams bitfield |
3.3 Key SRAM Variables
; GameState ($7EF3C5) - Overall progression
; 0x00 = Very start
; 0x01 = Uncle reached
; 0x02 = Zelda rescued / Farore intro
; 0x03 = Agahnim defeated
; OOSPROG ($7EF3D6) - Oracle progression bitfield
; .fmp h.i.
; i = Intro complete, Maku Tree met
; h = Hall of Secrets visited
; p = Pendant quest progress
; m = Master Sword acquired
; f = Fortress of Secrets
; OOSPROG2 ($7EF3C6) - Secondary progression
; .fbh .zsu
; u = Uncle visited
; s = Priest visited in sanctuary
; z = Zelda brought to sanctuary
; h = Uncle left house
; b = Book of Mudora obtained
; f = Fortune teller flag
; Dreams ($7EF410) - Dream sequence tracking
; .dts fwpb
; (Individual dream completion flags)
4. System Interactions
4.1 ZScream Custom Overworld (ZSOW) Integration
ZSOW manages:
- Overworld map transitions
- Palette events
- Overlay data
- Custom collision
Hook Points:
OverworldHandleTransitions ($028000 area)
└── Oracle_CheckIfNight (time-based sprite loading)
└── LostWoods_PuzzleHandler (navigation puzzle)
└── SongOfStorms overlay effects
Known Conflicts:
- Lost Woods puzzle directly modifies transition logic
- Day/Night sprites must check
Oracle_CheckIfNight - Song of Storms overlays need coordination with ZSOW
4.2 Time System
File: Overworld/time_system.asm
Structure:
struct TimeState $7EE000
{
.Hours, .Minutes, .Speed
.BlueVal, .GreenVal, .RedVal
.TempColor, .SubColor
}
Flow:
RunClock (called each frame)
├── TimeSystem_CheckCanRun
│ └── Check game mode, indoors status
├── TimeSystem_IncrementTime
│ └── Update Hours/Minutes based on Speed
└── TimeSystem_UpdatePalettes
└── Apply color tinting based on time
Integration Points:
Oracle_CheckIfNight- Called by ZSOW for sprite loading- Palette system - Affects overworld colors
- NPC behavior - Some NPCs react to time
4.3 Sprite System
Entry Points (standard pattern):
Sprite_*_Long (JSL entry from sprite table)
├── PHB : PHK : PLB (set data bank)
├── Sprite_*_Draw (JSR - render)
├── Sprite_CheckActive (JSL - is active?)
│ └── Sprite_*_Main (JSR - if active)
├── PLB
└── RTL
State Machine:
SprAction (per-sprite state variable)
└── JumpTableLocal dispatches to state handlers
├── State_Idle
├── State_Chase
├── State_Attack
└── State_Retreat
Key Variables (indexed by X):
| Address | Name | Purpose |
|---|---|---|
| $0D00 | SprY | Y position (low byte) |
| $0D10 | SprX | X position (low byte) |
| $0D80 | SprAction | Current state |
| $0DA0 | SprHealth | Hit points remaining |
| $0E40 | SprNbrOAM | OAM slot count |
4.4 Menu System
File: Menu/menu.asm
State Machine:
MenuMode ($0200) - Current menu state
├── $00 = Not in menu
├── $01 = Opening animation
├── $02 = Item select
├── $0C = Magic Bag submenu
├── $0D = Ring Box submenu
└── $0E = Song select submenu
Flow:
Menu_Entry (from pause input)
├── Menu_InitGraphics
├── Menu_Upload* (VRAM transfers)
└── Menu_MainLoop
├── Handle input
├── Update selection
└── Menu_Draw*
4.5 Dialogue System
Files: Core/message.asm, Core/messages.org
Message Format (in messages.org):
** 20 - Maku Tree Part1
[W:02][S:03]Ah, [L]!
[2]Thank the Goddesses you are
[3]alright. I feared the worst.
[V]A dark shadow has befallen us.[K]
Control Codes:
| Code | Meaning |
|---|---|
[2], [3] |
Line 2, Line 3 |
[K] |
Wait for button press |
[V] |
Continue on same line |
[W:XX] |
Wait time |
[S:XX] |
Text speed |
[SFX:XX] |
Play sound effect |
[CH2I] |
2-choice prompt |
[CH3] |
3-choice prompt |
[L] |
Player name |
Display Macros:
%ShowUnconditionalMessage($20) ; Force display
%ShowSolicitedMessage($20) ; On interaction only
5. Hook Architecture
5.1 Hook Types
Type 1: Inline Patch (replace vanilla code)
pushpc
org $02XXXX ; Vanilla address
JSL MyHook ; Replace original instruction
NOP : NOP ; Pad to match original size
pullpc
Type 2: Table Override (jump table entry)
pushpc
org $07F000+($ID*2) ; Jump table for sprite $ID
dw Sprite_Custom_Prep
pullpc
Type 3: Extended Logic (call original + extend)
MyHook:
{
JSL OriginalRoutine ; Preserve original behavior
; Add custom logic
LDA.w CustomFlag
BEQ .skip
JSL CustomHandler
.skip
RTL
}
5.2 Hook Documentation Pattern
Every hook should document:
; =========================================================
; Hook: $XXBANK:ADDR
; Purpose: [What this hook adds/changes]
; Vanilla Code: [What original code did]
; Clobbered: [Registers modified]
; Dependencies: [Other systems affected]
; =========================================================
6. Build System
6.1 Build Order (Critical)
1. Core/symbols.asm - Memory declarations
2. Core/sram.asm - SRAM layout
3. Core/link.asm - Player modifications
4. Music/all_music.asm - SPC700 data
5. Sprites/all_sprites.asm - All sprite code
6. Items/all_items.asm - Item handlers
7. Menu/menu.asm - Menu system
8. Dungeons/ - Dungeon-specific code
9. Core/patches.asm - Vanilla patches (LAST)
10. Overworld/ZSCustomOverworld.asm - ZSOW (OUTSIDE namespace)
6.2 Build Commands
# Fast build
./run.sh
# MCP tools
mcp__book-of-mudora__run_build() # Build ROM
mcp__book-of-mudora__lint_asm() # Check style
mcp__book-of-mudora__analyze_patches() # Review patches
7. Debugging Workflow
7.1 Common Debug Points
| Symptom | Check First |
|---|---|
| Crash on room enter | Sprite prep routine, invalid JSL target |
| Wrong graphics | SprGfx assignment, DMA timing |
| Frozen game | Infinite loop in Main, missing RTS/RTL |
| Black screen | Palette loading, HDMA setup |
| Corrupt saves | SRAM address conflict, missing bank setup |
7.2 Debug Tools
Yaze MCP (in-development):
mcp__yaze_mcp__read_memory("7E0010", 2) # Read RAM
mcp__yaze_mcp__add_breakpoint("02XXXX") # Set breakpoint
mcp__yaze_mcp__get_game_state() # Dump current state
Hyrule Historian:
mcp__hyrule-historian__lookup_address("02XXXX")
mcp__hyrule-historian__search_oracle_code("Sprite_Booki")
mcp__hyrule-historian__get_ram_info("SprAction")
7.3 Logging
; Build-time logging
%log_section("Sprites", !LOG_SPRITES)
; Enable in build:
!LOG_SPRITES = 1 ; Set in config
; Output appears in build log
8. Common Integration Patterns
8.1 Adding a New Sprite
- Create file:
Sprites/Enemies/my_sprite.asm - Define properties using standard order
- Implement
_Long,_Prep,_Main,_Draw - Add include to
Sprites/all_sprites.asm - Add to sprite table with
orgdirective - Build and test
8.2 Adding a Quest Flag
- Find free bit in OOSPROG/OOSPROG2
- Document in
Core/sram.asm - Update this file's SRAM section
- Use in code:
LDA.l OOSPROG : ORA.b #$XX : STA.l OOSPROG
8.3 Adding a New Hook
- Find vanilla address with Hyrule Historian
- Document what original code does
- Create hook with
pushpc/pullpc - Add
assertto verify space - Test vanilla behavior still works
9. System Dependency Graph
┌─────────────┐
│ TimeSystem │
└──────┬──────┘
│ Oracle_CheckIfNight
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Lost Woods │────▶│ ZSOW │◀────│ Overlays │
│ Puzzle │ │ Transitions │ │ System │
└─────────────┘ └──────┬──────┘ └─────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Sprites │ │ Events │
│ (Loading) │ │ (Triggers) │
└──────┬──────┘ └──────┬──────┘
│ │
└───────────┬─────────────┘
▼
┌─────────────┐
│ Player │
│ (Link) │
└─────────────┘
10. AI Agent Checklist
When working on Oracle of Secrets:
- Check
oracle.orgfor related tasks - Read existing code in affected files
- Verify memory map for conflicts
- Use Hyrule Historian for vanilla lookups
- Follow StyleGuide.md conventions
- Run build after changes
- Document any new hooks
- Update this file if adding new systems