diff --git a/Docs/Core/StyleGuide.md b/Docs/Core/StyleGuide.md new file mode 100644 index 0000000..1b86572 --- /dev/null +++ b/Docs/Core/StyleGuide.md @@ -0,0 +1,540 @@ +# Oracle of Secrets: 65816 ASM Style Guide + +**Version**: 1.0 +**Purpose**: Reduce AI errors and ensure consistent code quality across the codebase. + +--- + +## Quick Reference Card + +### Label Naming + +| Type | Pattern | Example | +|------|---------|---------| +| Sprite function | `Sprite_{Name}_{Type}` | `Sprite_Booki_Main`, `Sprite_Darknut_Draw` | +| Menu function | `Menu_{Purpose}` | `Menu_InitGraphics`, `Menu_DrawBackground` | +| Link/Player | `Link_{Action}` | `Link_ConsumeMagicBagItem`, `Link_HandleYItem` | +| Oracle namespace | `Oracle_{Function}` | `Oracle_CheckIfNight`, `Oracle_MainEntry` | +| Local labels | `.lowercase_with_underscores` | `.not_being_pushed`, `.nextTile` | +| Constants (macro) | `!UPPERCASE` | `!SPRID`, `!Health`, `!Damage` | +| Memory addresses | `CamelCase` | `SprAction`, `LinkState`, `OOSPROG` | + +### Processor State Checklist + +- [ ] Always use size suffixes (`.b`, `.w`, `.l`) for ambiguous operations +- [ ] Use `PHP`/`PLP` for functions called from unknown context +- [ ] `REP #$30` = 16-bit A and X/Y, `SEP #$30` = 8-bit +- [ ] `REP #$20` / `SEP #$20` = A only +- [ ] `REP #$10` / `SEP #$10` = X/Y only + +### Call Convention Checklist + +- [ ] `JSL`/`RTL` for cross-bank calls (3-byte return address) +- [ ] `JSR`/`RTS` for same-bank calls (2-byte return address) +- [ ] **NEVER MIX** - mismatch causes crashes +- [ ] External hooks use `JSL`, internal helpers use `JSR` + +--- + +## 1. File Structure + +### 1.1 File Header (Required for new files) + +```asm +; ========================================================= +; File: sprites/enemies/my_enemy.asm +; Purpose: [Brief description of what this file implements] +; Author: [Your name or handle] +; ========================================================= +``` + +### 1.2 Section Organization + +```asm +; ========================================================= +; Sprite Properties +; ========================================================= +!SPRID = $XX +!NbrTiles = 02 +; ... (30 properties in standard order) + +; ========================================================= +; Entry Points +; ========================================================= +Sprite_MyEnemy_Long: +{ ... } + +Sprite_MyEnemy_Prep: +{ ... } + +; ========================================================= +; Main Logic +; ========================================================= +Sprite_MyEnemy_Main: +{ ... } + +; ========================================================= +; Drawing +; ========================================================= +Sprite_MyEnemy_Draw: +{ ... } +``` + +--- + +## 2. Naming Conventions + +### 2.1 Labels + +**PascalCase with underscores for hierarchy:** + +```asm +; Good +Sprite_Booki_Main +Menu_InitGraphics +Link_ConsumeMagicBagItem +Oracle_CheckIfNight + +; Bad +spriteBookiMain ; No underscores +sprite_booki_main ; All lowercase +SPRITE_BOOKI_MAIN ; All uppercase +``` + +### 2.2 Local Labels + +**Lowercase with dot prefix:** + +```asm +Sprite_Move: +{ + LDA.w SprAction, X : BNE .already_moving + ; Start movement + INC.w SprAction, X + .already_moving + RTS +} +``` + +### 2.3 Constants and Macros + +```asm +; Macro parameters: !UPPERCASE +!SPRID = $D5 +!Health = 08 +!Damage = 02 + +; Debug flags: !UPPERCASE with LOG prefix +!DEBUG = 1 +!LOG_MUSIC = 1 +!LOG_SPRITES = 0 + +; Memory addresses: CamelCase (matching vanilla convention) +SprAction = $0D80 +LinkState = $5D +OOSPROG = $7EF3D6 +``` + +### 2.4 Sprite Property Standard Order + +All sprites MUST define properties in this order: + +```asm +!SPRID = Sprite_MyEnemyID +!NbrTiles = 02 +!Harmless = 00 +!Health = 08 +!Damage = 02 +!DeathAnimation = 00 +!ImperviousArrow = 00 +!ImperviousSword = 00 +!Boss = 00 +!Shadow = 01 +!Palette = 00 +!Hitbox = $00 +!Persist = 00 +!Statis = 00 +!CollisionLayer = 00 +!CanFall = 01 +!DeflectProjectiles = 00 +!WaterSprite = 00 +!Blockable = 00 +!Prize = 00 +!Sound = $00 +!Interaction = $00 +!Subtype2 = 00 +%Set_Sprite_Properties(Sprite_MyEnemy_Prep, Sprite_MyEnemy_Long) +``` + +--- + +## 3. Scoping and Indentation + +### 3.1 Bracket Scoping + +**ALL functions use `{ }` brackets** (NOT `subroutine`/`endsubroutine`): + +```asm +Sprite_Booki_Main: +{ + LDA.w SprAction, X + JSL JumpTableLocal + dw StalkPlayer + dw HideFromPlayer + dw ApproachPlayer + + StalkPlayer: + { + %PlayAnimation(0,1,16) + JSR Sprite_Booki_Move + RTS + } + + HideFromPlayer: + { + ; Nested content indented 2 spaces + LDA.b #$00 + STA.w SprAction, X + RTS + } +} +``` + +### 3.2 Indentation Rules + +- **2-space indentation** for all nested content +- Local labels at same indentation as containing block +- Conditional code indented under branch: + +```asm + JSL Sprite_CheckActive : BCC .inactive + ; Active sprite code (indented) + JSR DoActiveStuff + .inactive + PLB + RTL +``` + +--- + +## 4. Processor State Management + +### 4.1 Size Suffixes (REQUIRED) + +Always use explicit size suffixes when processor state matters: + +```asm +; Good - explicit sizes +LDA.w #$1234 ; 16-bit load +LDA.b #$12 ; 8-bit load +STA.l $7E0000 ; Long address + +; Bad - ambiguous +LDA #$12 ; Is this 8-bit or 16-bit? +``` + +### 4.2 State Preservation + +```asm +; Functions called from unknown context +SomePublicFunction: +{ + PHP ; Save caller's state + SEP #$30 ; Set known state (8-bit A, X/Y) + + ; ... function body ... + + PLP ; Restore caller's state + RTL +} + +; Internal helpers can assume state from caller +.helper: + ; Assume 8-bit A from caller + LDA.b #$00 + RTS +``` + +### 4.3 Processor Mode Macros + +Use these macros for clarity: + +```asm +%m8() ; SEP #$20 - 8-bit accumulator +%m16() ; REP #$20 - 16-bit accumulator +%a8() ; SEP #$20 - 8-bit A (alias) +%a16() ; REP #$20 - 16-bit A (alias) +%index8() ; SEP #$10 - 8-bit X/Y +%index16() ; REP #$10 - 16-bit X/Y +``` + +--- + +## 5. Hook and Patch Patterns + +### 5.1 Small Patches (pushpc/pullpc) + +```asm +pushpc +org $1EF27D +ShopItem_Banana: +{ + JSR $F4CE ; SpriteDraw_ShopItem + ; Custom code here + RTS +} +assert pc() <= $1EF2AB ; Ensure we fit +pullpc +``` + +### 5.2 Hook Pattern + +```asm +; In patches.asm or near related code +pushpc +org $02XXXX ; Vanilla address + JSL MyCustomHook ; 4-byte JSL + NOP ; Pad if needed +pullpc + +; The hook implementation +MyCustomHook: +{ + ; Preserve any clobbered code + JSL OriginalRoutine + + ; Add custom logic + LDA.w CustomFlag : BEQ .skip + JSL DoCustomThing + .skip + + RTL +} +``` + +### 5.3 Hook Documentation + +```asm +; ========================================================= +; Hook: $02XXXX - Link's Y-Button Handler +; Purpose: Add custom item handling for Magic Bag +; Vanilla Code Replaced: JSL $07F44C +; Side Effects: Clobbers A +; ========================================================= +``` + +--- + +## 6. Comments and Documentation + +### 6.1 Section Dividers + +Use exactly 57 equal signs: + +```asm +; ========================================================= +; Section Name +; ========================================================= +``` + +### 6.2 Bitfield Documentation + +```asm +; Bitfield: hmwo oooo +; o - OAM slot count (bits 0-4) +; w - Wall-seeking behavior +; m - Master sword ceremony flag +; h - Harmless (no contact damage) +SprNbrOAM = $0E40 +``` + +### 6.3 TODO Comments + +```asm +; TODO: Add chase animation when player is detected +; TODO(scawful): Refactor this to use lookup table +``` + +### 6.4 Magic Number Documentation + +```asm +LDA.b #$08 ; 8-frame animation delay +CMP.w #$0100 ; Check if past screen boundary (256px) +``` + +--- + +## 7. Memory and Data Structures + +### 7.1 Struct Definitions + +```asm +struct TimeState $7EE000 +{ + .Hours: skip 1 + .Minutes: skip 1 + .Speed: skip 1 + .Padding: skip 13 + .BlueVal: skip 2 + .GreenVal: skip 2 + .RedVal: skip 2 +} +endstruct +``` + +### 7.2 Inline Data Tables + +```asm +Sprite_Draw: +{ + ; ... draw code ... + RTS + + ; Data tables use dot notation + .start_index + db $00, $04, $08, $0C + .nbr_of_tiles + db 3, 3, 3, 3 + .x_offsets + dw 4, -4, 4, -4 +} +``` + +--- + +## 8. Error Prevention Checklist + +### Before Submitting Code + +- [ ] All labels use correct PascalCase_With_Underscores +- [ ] All local labels use .dot_notation +- [ ] Size suffixes on all ambiguous loads/stores +- [ ] JSL/RTL and JSR/RTS pairs matched correctly +- [ ] Hooks have `assert` statements to prevent overflow +- [ ] Magic numbers have inline comments explaining purpose +- [ ] Sprite properties in standard order +- [ ] Section dividers between major code blocks + +### Common Crash Causes + +1. **JSL/JSR mismatch** - Using RTL with JSR or RTS with JSL +2. **Bank crossing** - Forgetting to set DBR with PHK:PLB +3. **Processor state** - Assuming 8-bit when 16-bit or vice versa +4. **Hook overflow** - Patch exceeds available space +5. **Missing pullpc** - Stack imbalance from pushpc + +--- + +## 9. Oracle of Secrets Specific Patterns + +### 9.1 Sprite Entry Point Pattern + +```asm +Sprite_MyEnemy_Long: +{ + PHB : PHK : PLB ; Set data bank to current bank + JSR Sprite_MyEnemy_Draw + JSL Sprite_DrawShadow + JSL Sprite_CheckActive : BCC .inactive + JSR Sprite_MyEnemy_Main + .inactive + PLB + RTL +} +``` + +### 9.2 State Machine Pattern + +```asm +Sprite_MyEnemy_Main: +{ + LDA.w SprAction, X + JSL JumpTableLocal + dw State_Idle + dw State_Chase + dw State_Attack + dw State_Retreat + + State_Idle: + { + %PlayAnimation(0,1,16) + ; Check for player proximity + JSL Sprite_CheckDamageToLink + BCC .stay_idle + INC.w SprAction, X ; Transition to Chase + .stay_idle + RTS + } + ; ... more states ... +} +``` + +### 9.3 SRAM Flag Checking + +```asm +; Check Oracle progression flag +LDA.l OOSPROG : AND.b #$01 : BEQ .not_complete + ; Player has completed this milestone +.not_complete + +; Bitfield reference for OOSPROG ($7EF3D6): +; .fmp h.i. +; i = Intro complete +; h = Hall of Secrets visited +; p = Pendant progress +; m = Master Sword acquired +; f = Fortress of Secrets +``` + +--- + +## 10. AI Agent Instructions + +### 10.1 Before Writing Code + +1. **Read existing patterns** - Search for similar implementations +2. **Check memory map** - Verify address usage won't conflict +3. **Identify hook points** - Use Hyrule Historian to find vanilla code +4. **Verify bank space** - Check MemoryMap.md for free space + +### 10.2 When Modifying Code + +1. **Always read the file first** - Never assume structure +2. **Match existing style** - Follow patterns in the same file +3. **Use explicit sizes** - Never rely on assumed processor state +4. **Add assert statements** - Prevent silent overflow errors + +### 10.3 After Writing Code + +1. **Run build** - Use `mcp__book-of-mudora__run_build()` +2. **Run lint** - Use `mcp__book-of-mudora__lint_asm()` +3. **Verify in emulator** - Test before marking complete + +--- + +## Appendix: Common Macro Reference + +### Animation and Drawing +- `%PlayAnimation(start, end, speed)` - Animate sprite frames +- `%DrawSprite(...)` - Draw sprite OAM +- `%SetFrame(n)` - Set current animation frame + +### Sprite Control +- `%GotoAction(n)` - Change sprite state +- `%SetTimer*(n)` - Set various timers +- `%SetSpriteSpeed*(n)` - Set movement speed +- `%SetHarmless()` / `%SetImpervious()` - Damage flags + +### Player +- `%PreventPlayerMovement()` / `%AllowPlayerMovement()` +- `%GetPlayerRupees()` - Return rupee count +- `%ShowUnconditionalMessage(id)` - Display dialogue +- `%ShowSolicitedMessage(id)` - Display on interaction + +### Audio +- `%PlaySFX1(id)` / `%PlaySFX2(id)` - Sound effects +- `%PlayMusic(id)` - Change music + +### Debugging +- `%print_debug(msg)` - Build-time debug output +- `%log_section(name, flag)` - Conditional section logging diff --git a/Docs/Core/SystemArchitecture.md b/Docs/Core/SystemArchitecture.md new file mode 100644 index 0000000..4d33c28 --- /dev/null +++ b/Docs/Core/SystemArchitecture.md @@ -0,0 +1,472 @@ +# 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: + +```asm +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 Oracle` become `Oracle.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 + +```asm +; 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**: +```asm +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**: +```asm +%ShowUnconditionalMessage($20) ; Force display +%ShowSolicitedMessage($20) ; On interaction only +``` + +--- + +## 5. Hook Architecture + +### 5.1 Hook Types + +**Type 1: Inline Patch** (replace vanilla code) +```asm +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) +```asm +pushpc +org $07F000+($ID*2) ; Jump table for sprite $ID + dw Sprite_Custom_Prep +pullpc +``` + +**Type 3: Extended Logic** (call original + extend) +```asm +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: + +```asm +; ========================================================= +; 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 + +```bash +# 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): +```python +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**: +```python +mcp__hyrule-historian__lookup_address("02XXXX") +mcp__hyrule-historian__search_oracle_code("Sprite_Booki") +mcp__hyrule-historian__get_ram_info("SprAction") +``` + +### 7.3 Logging + +```asm +; 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 + +1. Create file: `Sprites/Enemies/my_sprite.asm` +2. Define properties using standard order +3. Implement `_Long`, `_Prep`, `_Main`, `_Draw` +4. Add include to `Sprites/all_sprites.asm` +5. Add to sprite table with `org` directive +6. Build and test + +### 8.2 Adding a Quest Flag + +1. Find free bit in OOSPROG/OOSPROG2 +2. Document in `Core/sram.asm` +3. Update this file's SRAM section +4. Use in code: + ```asm + LDA.l OOSPROG : ORA.b #$XX : STA.l OOSPROG + ``` + +### 8.3 Adding a New Hook + +1. Find vanilla address with Hyrule Historian +2. Document what original code does +3. Create hook with `pushpc`/`pullpc` +4. Add `assert` to verify space +5. 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: + +1. [ ] Check `oracle.org` for related tasks +2. [ ] Read existing code in affected files +3. [ ] Verify memory map for conflicts +4. [ ] Use Hyrule Historian for vanilla lookups +5. [ ] Follow StyleGuide.md conventions +6. [ ] Run build after changes +7. [ ] Document any new hooks +8. [ ] Update this file if adding new systems