add docs for asm style guide and oracle system architecture
This commit is contained in:
540
Docs/Core/StyleGuide.md
Normal file
540
Docs/Core/StyleGuide.md
Normal file
@@ -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
|
||||
472
Docs/Core/SystemArchitecture.md
Normal file
472
Docs/Core/SystemArchitecture.md
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user