Add sprite analysis documentation for various bosses and mini-bosses

- Created detailed documentation for the Kydrog Boss sprite, outlining its phases, behaviors, and mechanics.
- Added analysis for the Manhandla sprite, including its transformation into Big Chuchu and phase management.
- Documented the Octoboss sprite, highlighting its unique mechanics and interactions with a "brother" Octoboss.
- Provided an overview of the Twinrova boss sprite, detailing its transformation and phase-based attacks.
- Included analysis for the Vampire Bat mini-boss, emphasizing its enhanced behavior compared to standard Keese.
- Documented the Wolfos mini-boss, focusing on its integration into a mask quest and unique pacification mechanics.
This commit is contained in:
scawful
2025-10-02 21:24:44 -04:00
parent 0f1e0a8c75
commit 6780dd0d45
14 changed files with 771 additions and 26 deletions

View File

@@ -90,3 +90,38 @@ This section details the layout of the save file memory.
| `$7EF34D` | `RocsFeather` | Flag indicating if the player has obtained Roc's Feather. | | `$7EF34D` | `RocsFeather` | Flag indicating if the player has obtained Roc's Feather. |
| `$7EF352` | `StoneMask` | Flag indicating if the player has obtained the Stone Mask. | | `$7EF352` | `StoneMask` | Flag indicating if the player has obtained the Stone Mask. |
| `$7EF358` | `WolfMask` | Flag indicating if the player has obtained the Wolf Mask. | | `$7EF358` | `WolfMask` | Flag indicating if the player has obtained the Wolf Mask. |
## 3. Custom Code and Data Layout (ROM Banks)
This section details the allocation of custom code and data within the ROM banks, as defined by `org` directives in the project's assembly files. The order of `incsrc` directives in `Oracle_main.asm` is crucial for the final ROM layout.
| Bank (Hex) | Address Range (PC) | Purpose / Contents |
|------------|--------------------|--------------------------------------------------------|
| $20 | `$208000` - `$20FFFF` | Expanded Music |
| $21-$27 | | ZScream Reserved |
| $28 | `$288000` - `$28FFFF` | ZSCustomOverworld data and code |
| $29-$2A | | ZScream Reserved |
| $2B | `$2B8000` - `$2BFFFF` | Items |
| $2C | `$2C8000` - `$2CFFFF` | Underworld/Dungeons |
| $2D | `$2D8000` - `$2DFFFF` | Menu |
| $2E | `$2E8000` - `$2EFFFF` | HUD |
| $2F | `$2F8000` - `$2FFFFF` | Expanded Message Bank |
| $30 | `$308000` - `$30FFFF` | Sprites |
| $31 | `$318000` - `$31FFFF` | Sprites |
| $32 | `$328000` - `$32FFFF` | Sprites |
| $33 | `$338000` - `$33FFFF` | Moosh Form Gfx and Palette |
| $34 | `$348000` - `$34FFFF` | Time System, Custom Overworld Overlays, Gfx |
| $35 | `$358000` - `$35FFFF` | Deku Link Gfx and Palette |
| $36 | `$368000` - `$36FFFF` | Zora Link Gfx and Palette |
| $37 | `$378000` - `$37FFFF` | Bunny Link Gfx and Palette |
| $38 | `$388000` - `$38FFFF` | Wolf Link Gfx and Palette |
| $39 | `$398000` - `$39FFFF` | Minish Link Gfx |
| $3A | `$3A8000` - `$3AFFFF` | Mask Routines, Custom Ancillae (Deku Bubble) |
| $3B | `$3B8000` - `$3BFFFF` | GBC Link Gfx |
| $3C | | Unused |
| $3D | | ZS Tile16 |
| $3E | | LW ZS Tile32 |
| $3F | | DW ZS Tile32 |
| $40 | `$408000` - `$40FFFF` | LW World Map |
| $41 | `$418000` - `$41FFFF` | DW World Map |
| Patches | Various | Targeted modifications within vanilla ROM addresses | `Core/patches.asm`, `Util/item_cheat.asm` |

View File

@@ -129,11 +129,11 @@ With ZSOW v3, the vanilla sprite loading hook (`Overworld_LoadSprites` at `$09C4
### Conclusion & Solution ### Conclusion & Solution
This is an **unresolved conflict**. The original day/night sprite logic is not being called by ZSOW's custom sprite loading routine, preventing day/night-specific sprites from appearing. This is a **partially resolved conflict**. The integration of day/night logic into ZSOW's custom sprite loading routine now correctly switches the active sprite set based on the time of day. However, the corresponding sprite graphics are not being loaded, leading to incorrect visual representation of sprites.
**Status:** **Status:**
- An initial attempt was made to integrate the `CheckIfNight` logic into ZSOW's `LoadOverworldSprites_Interupt` routine. - The logic to determine day/night and adjust the `GameState` for sprite set loading has been successfully integrated into `ZSCustomOverworld.asm` (via `ZSO_CheckIfNight` called from `LoadOverworldSprites_Interupt`).
- This attempt introduced severe regressions, including game crashes (`BRK`) and build failures. - This resolves the issue of day/night-specific sprites *appearing* (i.e., the correct sprite data is now referenced).
- The changes have been **reverted** to restore stability. - **New Issue:** The sprite *graphics* (tilesets) are not being updated to match the new day/night sprite sets. This results in "gargoyle" sprites (graphical corruption) for sprites that change between day and night.
- As a result, the conflict remains, and a new solution is needed to make the two systems compatible. - A new solution is needed to ensure the correct sprite graphics are loaded when the sprite set changes due to day/night transitions.

View File

@@ -95,6 +95,7 @@ The 65816 is an 8/16-bit microprocessor used in the Super Nintendo Entertainment
- When hooking or modifying vanilla code, it is essential to understand the original context. The `usdasm` disassembly is the primary reference for this. - When hooking or modifying vanilla code, it is essential to understand the original context. The `usdasm` disassembly is the primary reference for this.
- To find the original code for a patch at a given address (e.g., `$07A3DB`), you can search for the SNES address in the `usdasm` files (e.g., `#_07A3DB:`). - To find the original code for a patch at a given address (e.g., `$07A3DB`), you can search for the SNES address in the `usdasm` files (e.g., `#_07A3DB:`).
- **Vanilla labels are not included by default.** The `usdasm` project is a reference, not part of the build. If you need to call a vanilla routine, you must find its implementation in the disassembly and explicitly copy or recreate it within the `Oracle of Secrets` source, giving it a new label (e.g., inside the `Oracle` namespace). - **Vanilla labels are not included by default.** The `usdasm` project is a reference, not part of the build. If you need to call a vanilla routine, you must find its implementation in the disassembly and explicitly copy or recreate it within the `Oracle of Secrets` source, giving it a new label (e.g., inside the `Oracle` namespace).
- **Disassembly files are for reference only.** Never modify any files within the `usdasm` directory. All changes must be made within the `Oracle of Secrets` project files.
### 3.5. Namespacing ### 3.5. Namespacing
@@ -444,3 +445,20 @@ ZScream reserves:
| `0x1E0000 - 0x1E7FFF` | 1 Bank | Custom ASM patches | | `0x1E0000 - 0x1E7FFF` | 1 Bank | Custom ASM patches |
| `0x1E8000 - 0x1EFFFF` | 1 Bank | Expanded Tile16 space | | `0x1E8000 - 0x1EFFFF` | 1 Bank | Expanded Tile16 space |
| `0x1F0000 - 0x1FFFFF` | 2 Banks | Expanded Tile32 space | | `0x1F0000 - 0x1FFFFF` | 2 Banks | Expanded Tile32 space |
## 10. Oracle of Secrets Specific Guidelines for Gemini
To ensure accurate and consistent modifications within the Oracle of Secrets project, adhere to the following guidelines regarding memory management and code placement:
- **Understand `incsrc` Order:** The order of `incsrc` directives in `Oracle_main.asm` is paramount. It dictates the final ROM layout, especially for code and data placed using `org`. Always consult `Oracle_main.asm` and `Docs/Core/MemoryMap.md` to understand the current memory allocation before introducing new `org` directives.
- **`org` for New Features:** When implementing new features that require significant code or data, use `org $XXXXXX` to place them in an appropriate free bank. Refer to the detailed memory map in `Docs/Core/MemoryMap.md` and the `Oracle_main.asm` comment for available and designated banks. If a new bank is needed, ensure it does not conflict with existing allocations or ZScream reserved space.
- **`pushpc`/`pullpc` for Patches:** For small, targeted modifications to vanilla code or data (e.g., changing a few bytes, hooking a jump), use `pushpc`/`pullpc`. These directives are ideal for non-intrusive patches that don't require a dedicated bank. Examine `Core/patches.asm` and `Util/item_cheat.asm` for examples of this usage.
- **Consult Memory Map:** Before any code modification involving `org` or `pushpc`/`pullpc`, always cross-reference with `Docs/Core/MemoryMap.md` and the `Oracle_main.asm` comment to prevent memory conflicts and ensure proper placement.
- **Prioritize Existing Conventions:** Mimic the existing style and structure of the codebase. If a new feature is similar to an existing one, follow its implementation pattern, including how it manages memory.
- **Avoid Arbitrary `org`:** Never use `org` without a clear understanding of the target address and its implications for the overall ROM layout. Unplanned `org` directives can lead to crashes or unexpected behavior.
'''

View File

@@ -23,7 +23,8 @@ The project makes extensive use of both WRAM and SRAM to store custom data and g
To ensure modern and maintainable assembly code, the project adheres to the following `asar` best practices: To ensure modern and maintainable assembly code, the project adheres to the following `asar` best practices:
* **`pushpc`/`pullpc` vs. `org`:** Use `pushpc`/`pullpc` for small, targeted patches. For larger blocks of new code, use `org` to place them in designated free space banks. Avoid using `org` to modify existing vanilla code directly, as this can lead to conflicts. * **`org` for New Code and Data:** Use `org $XXXXXX` to place larger blocks of new code or data into designated free space banks. The `incsrc` order in `Oracle_main.asm` is critical when using `org`, as it directly determines the final ROM layout. Moving `org` blocks or changing the `incsrc` order can lead to memory conflicts or incorrect addressing.
* **`pushpc`/`pullpc` for Targeted Patches:** Use `pushpc`/`pullpc` for small, targeted modifications to existing vanilla code or data. This directive temporarily changes the program counter, allowing a small patch to be inserted at a specific address without affecting the surrounding `org` context. Files like `Core/patches.asm` and `Util/item_cheat.asm` extensively use `pushpc`/`pullpc` for this purpose.
* **Scoping:** Use labels followed by `{}` to define local scopes for new logic blocks. This is the established convention, and `subroutine`/`endsubroutine` are not used. * **Scoping:** Use labels followed by `{}` to define local scopes for new logic blocks. This is the established convention, and `subroutine`/`endsubroutine` are not used.
* **Data Structures:** Use `struct` for complex, related data (e.g., sprite state) and `table` for jump tables or data arrays. This improves readability and reduces errors from manual offset calculations. * **Data Structures:** Use `struct` for complex, related data (e.g., sprite state) and `table` for jump tables or data arrays. This improves readability and reduces errors from manual offset calculations.
* **Constants:** Use `!` or `define()` to create named constants for RAM/SRAM addresses, item IDs, sprite states, and other "magic numbers." This makes the code self-documenting and easier to maintain. * **Constants:** Use `!` or `define()` to create named constants for RAM/SRAM addresses, item IDs, sprite states, and other "magic numbers." This makes the code self-documenting and easier to maintain.
@@ -103,14 +104,42 @@ Macros are used extensively to simplify common tasks and improve code readabilit
## 6. ROM Map & Memory Layout ## 6. ROM Map & Memory Layout
Oracle of Secrets uses the ZScream expanded ROM map, which provides additional space for new code and data. The following is a brief overview of the key bank allocations: Oracle of Secrets utilizes the ZScream expanded ROM map, providing significant additional space for new code and data. The allocation of custom code and data within these banks is managed through `org` directives in the assembly files. The `incsrc` order in `Oracle_main.asm` is crucial, as it dictates the final placement of these blocks in the ROM.
* **`$2B8000+`:** Free space for new code and data. Here is a detailed overview of the custom ROM bank allocations:
* **`$288000+`:** `ZSCustomOverworld` configuration tables.
* **`$7E0730+`:** Custom WRAM region for new features.
* **`$7EF3D6+`:** Custom SRAM region for new progress flags and item data.
For a more detailed breakdown of the ROM map, refer to the `ZS ROM MAP.txt` file in the `Core/` directory. | Bank (Hex) | Address Range (PC) | Purpose / Contents | Defining File(s) |
|------------|--------------------|--------------------------------------------------------|---------------------------------------|
| $20 | `$208000` - `$20FFFF` | Expanded Music | `Music/all_music.asm` |
| $21-$27 | | ZScream Reserved | |
| $28 | `$288000` - `$28FFFF` | ZSCustomOverworld data and code | `Overworld/ZSCustomOverworld.asm` |
| $29-$2A | | ZScream Reserved | |
| $2B | `$2B8000` - `$2BFFFF` | Items | `Items/all_items.asm` |
| $2C | `$2C8000` - `$2CFFFF` | Underworld/Dungeons | `Dungeons/dungeons.asm` |
| $2D | `$2D8000` - `$2DFFFF` | Menu | `Menu/menu.asm` |
| $2E | `$2E8000` - `$2EFFFF` | HUD | `Menu/menu.asm` |
| $2F | `$2F8000` - `$2FFFFF` | Expanded Message Bank | `Core/message.asm` |
| $30 | `$308000` - `$30FFFF` | Sprites | `Sprites/all_sprites.asm` |
| $31 | `$318000` - `$31FFFF` | Sprites | `Sprites/all_sprites.asm` |
| $32 | `$328000` - `$32FFFF` | Sprites | `Sprites/all_sprites.asm` |
| $33 | `$338000` - `$33FFFF` | Moosh Form Gfx and Palette | `Masks/all_masks.asm` |
| $34 | `$348000` - `$34FFFF` | Time System, Custom Overworld Overlays, Gfx | `Masks/all_masks.asm` |
| $35 | `$358000` - `$35FFFF` | Deku Link Gfx and Palette | `Masks/all_masks.asm` |
| $36 | `$368000` - `$36FFFF` | Zora Link Gfx and Palette | `Masks/all_masks.asm` |
| $37 | `$378000` - `$37FFFF` | Bunny Link Gfx and Palette | `Masks/all_masks.asm` |
| $38 | `$388000` - `$38FFFF` | Wolf Link Gfx and Palette | `Masks/all_masks.asm` |
| $39 | `$398000` - `$39FFFF` | Minish Link Gfx | `Masks/all_masks.asm` |
| $3A | `$3A8000` - `$3AFFFF` | Mask Routines, Custom Ancillae (Deku Bubble) | `Masks/all_masks.asm` |
| $3B | `$3B8000` - `$3BFFFF` | GBC Link Gfx | `Masks/all_masks.asm` |
| $3C | | Unused | |
| $3D | | ZS Tile16 | |
| $3E | | LW ZS Tile32 | |
| $3F | | DW ZS Tile32 | |
| $40 | `$408000` - `$40FFFF` | LW World Map | `Overworld/overworld.asm` |
| $41 | `$418000` - `$41FFFF` | DW World Map | `Overworld/overworld.asm` |
| Patches | Various | Targeted modifications within vanilla ROM addresses | `Core/patches.asm`, `Util/item_cheat.asm` |
For a more detailed breakdown of the ROM map, refer to the `ZS ROM MAP.txt` file in the `Core/` directory, and `Docs/Core/MemoryMap.md` for a comprehensive overview of all custom memory regions.
--- ---
@@ -118,7 +147,7 @@ For a more detailed breakdown of the ROM map, refer to the `ZS ROM MAP.txt` file
The following documents have been generated by analyzing the codebase and project files. They serve as key references for understanding the project's architecture and gameplay systems. The following documents have been generated by analyzing the codebase and project files. They serve as key references for understanding the project's architecture and gameplay systems.
* **`Docs/MemoryMap.md`:** A comprehensive map of all custom WRAM and SRAM variables. See [MemoryMap.md](MemoryMap.md) for details. * **`Docs/MemoryMap.md`:** A comprehensive map of all custom WRAM and SRAM variables. See [MemoryMap.md](Core/MemoryMap.md) for details.
* **`Docs/QuestFlow.md`:** A detailed guide to the main story and side-quest progression, including trigger conditions and progression flags. See [QuestFlow.md](QuestFlow.md) for details. * **`Docs/QuestFlow.md`:** A detailed guide to the main story and side-quest progression, including trigger conditions and progression flags. See [QuestFlow.md](QuestFlow.md) for details.

View File

@@ -31,6 +31,11 @@ At the top of your new sprite file, define its core properties using the provide
!Prize = 01 ; Prize pack dropped on death (0-15) !Prize = 01 ; Prize pack dropped on death (0-15)
; ... and so on for all properties ... ; ... and so on for all properties ...
; --- Design Considerations ---
; * **Multi-purpose Sprite IDs:** A single `!SPRID` can be used for multiple distinct behaviors (e.g., Dark Link and Ganon) through the use of `SprSubtype`. This is a powerful technique for reusing sprite slots and creating multi-phase bosses or variations of enemies.
; * **Damage Handling for Bosses:** For boss sprites, `!Damage = 0` is acceptable if damage is applied through other means, such as spawned projectiles or direct contact logic within the main routine.
; * **Custom Boss Logic:** Setting `!Boss = 00` for a boss sprite indicates that custom boss logic is being used, rather than relying on vanilla boss flags. This is important for understanding how boss-specific behaviors are implemented.
; This macro MUST be called after the properties ; This macro MUST be called after the properties
%Set_Sprite_Properties(Sprite_MyNewEnemy_Prep, Sprite_MyNewEnemy_Long) %Set_Sprite_Properties(Sprite_MyNewEnemy_Prep, Sprite_MyNewEnemy_Long)
``` ```
@@ -103,13 +108,16 @@ Sprite_MyNewEnemy_Main:
RTS RTS
} }
State_Hurt: ; State_Hurt:
{ ; {
; Sprite was hit, flash and get knocked back ; ; Sprite was hit, flash and get knocked back
JSL Sprite_DamageFlash_Long ; JSL Sprite_DamageFlash_Long
RTS ; RTS
} ; }
} ; }
;
; --- Code Readability Note ---
; For improved readability and maintainability, always prefer using named constants for hardcoded values (e.g., timers, speeds, health, magic numbers) and named labels for `JSL` calls to project-specific functions instead of direct numerical addresses.
``` ```
## 6. Drawing (`_Draw` routine) ## 6. Drawing (`_Draw` routine)
@@ -135,11 +143,66 @@ Sprite_MyNewEnemy_Draw:
db $C0, $C2, $C4, $C6, $C8, $CA, $CC, $CE db $C0, $C2, $C4, $C6, $C8, $CA, $CC, $CE
.properties ; OAM properties (palette, priority, flips) .properties ; OAM properties (palette, priority, flips)
db $3B, $7B, $3B, $7B, $3B, $7B, $3B, $7B db $3B, $7B, $3B, $7B, $3B, $7B, $3B, $7B
.sizes ; Size of each tile (e.g., $02 for 16x16) ; .sizes ; Size of each tile (e.g., $02 for 16x16)
db $02, $02, $02, $02, $02, $02, $02, $02 ; db $02, $02, $02, $02, $02, $02, $02, $02
} ; }
;
; --- Code Readability Note ---
; For improved readability and maintainability, always prefer using named constants for hardcoded values (e.g., OAM properties, tile numbers) and named labels for `JSL` calls to project-specific functions instead of direct numerical addresses.
``` ```
## 7. Final Integration ## 7. Final Integration
The `%Set_Sprite_Properties()` macro you added in Step 2 handles the final integration. It automatically adds your sprite's `_Prep` and `_Long` routines to the game's sprite tables in `Core/sprite_new_table.asm`. Your sprite is now ready to be placed in the game world! The %Set_Sprite_Properties() macro you added in Step 2 handles the final integration. It automatically adds your sprite's _Prep and _Long routines to the game's sprite tables in Core/sprite_new_table.asm. Your sprite is now ready to be placed in the game world!
## 8. Advanced Sprite Design Patterns
### 8.1. Multi-Part Sprites and Child Sprites
For complex bosses or entities, you can break them down into a main parent sprite and multiple child sprites.
* **Parent Sprite Responsibilities:**
* Spawns and manages its child sprites (e.g., Kydreeok spawning `kydreeok_head` instances).
* Monitors the state/health of its child sprites to determine its own phases, actions, or defeat conditions.
* Often handles overall movement, phase transitions, and global effects.
* Uses global variables (e.g., `Offspring1_Id`, `Offspring2_Id`) to store the sprite IDs of its children for easy referencing.
* **Child Sprite Responsibilities:**
* Handles its own independent logic, movement, and attacks.
* May be positioned relative to the parent sprite.
* Can use `SprSubtype` to differentiate between multiple instances of the same child sprite ID (e.g., left head vs. right head).
* **Shared Sprite IDs for Variations:** A single `!SPRID` can also be used for different enemy variations (e.g., Keese, Fire Keese, Ice Keese, Vampire Bat) by assigning unique `SprSubtype` values. This is an efficient way to reuse sprite slots and base logic.
### 8.2. Multi-Phase Bosses and Dynamic Health Management
Boss fights can be made more engaging by implementing multiple phases and dynamic health management.
* **Phase Transitions:** Trigger new phases based on health thresholds, timers, or the defeat of child sprites. Phases can involve:
* Changing the boss's graphics or palette.
* Altering movement patterns and attack routines.
* Spawning new entities or environmental hazards.
* **Health Management:** Boss health can be managed in various ways:
* Directly via the parent sprite's `SprHealth`.
* Indirectly by monitoring the health or state of child sprites (e.g., Kydreeok's main body health is tied to its heads).
* Using custom variables (e.g., `!KydrogPhase`) to track overall boss progression.
* **Quest Integration and Pacification:** Sprites can be integrated into quests where "defeat" might mean pacification rather than outright killing. This can involve refilling health and changing the sprite's state to a subdued or quest-complete action (e.g., Wolfos granting a mask after being subdued by the Song of Healing).
### 8.3. Code Reusability and Modularity
When designing multiple sprites, especially bosses, look for opportunities to reuse code and create modular components.
* **Shared Logic:** If multiple sprites perform similar actions (e.g., spawning stalfos, specific movement patterns), consider creating common functions or macros that can be called by different sprites. This reduces code duplication and improves maintainability.
* **Refactoring:** Regularly refactor duplicated code into reusable components. This makes it easier to apply changes consistently across related sprites.
### 8.4. Configurability and Avoiding Hardcoded Values
To improve sprite reusability and ease of placement in different maps, avoid hardcoding values that might change.
* **Activation Triggers:** Instead of hardcoding specific screen coordinates or camera values for activation (e.g., Octoboss's Y-coordinate trigger), consider using:
* Sprite properties (`SprMiscA`, `SprMiscB`, etc.) to store configurable trigger values.
* Room-specific flags or events that can be set externally.
* Relative positioning or distance checks to Link.
* **Timers, Speeds, Offsets:** Always prefer using named constants (`!CONSTANT_NAME = value`) for numerical values that control behavior (timers, speeds, offsets, health thresholds). This significantly improves readability and makes it easier to adjust parameters without searching through code.
* **Function Calls:** Use named labels for `JSL` calls to project-specific functions instead of direct numerical addresses.
### 8.5. Overriding Vanilla Behavior
When creating new boss sequences or modifying existing enemies, it's common to override vanilla sprite behavior.
* **Hooking Entry Points:** Identify the entry points of vanilla sprites (e.g., `Sprite_Blind_Long`, `Sprite_Blind_Prep`) and use `org` directives to redirect execution to your custom routines.
* **Contextual Checks:** Within your custom routines, perform checks (e.g., `LDA.l $7EF3CC : CMP.b #$06`) to determine if the vanilla behavior should be executed or if your custom logic should take over.
* **SRAM Flags:** Utilize SRAM flags (`$7EF3XX`) to track quest progression or conditions that dictate whether vanilla or custom behavior is active.

31
Docs/Sprites/DarkLink.md Normal file
View File

@@ -0,0 +1,31 @@
# Dark Link Sprite Analysis
## Overview
Dark Link (Sprite ID: `$C1`) is a boss sprite known for its dynamic and challenging combat. It features a variety of attacks, including sword slashes, jump attacks, and projectile spawning. A notable aspect of this sprite is its ability to transform into a Ganon-like entity via a subtype, suggesting a multi-phase boss encounter.
## Key Properties:
* **Sprite ID:** `$C1`
* **Number of Tiles:** 4
* **Health:** 34 (decimal)
* **Damage:** 0 (Damage is handled by spawned attacks or direct contact logic, not directly by the sprite's `!Damage` property.)
* **Special Properties:**
* `!DeflectProjectiles = 01` (Deflects all projectiles)
* `!ImperviousArrow = 01` (Impervious to arrows)
* `!Boss = 00` (Despite being a boss, this flag is not set, indicating custom boss logic rather than reliance on vanilla boss flags.)
## Subtypes:
* **Subtype `$05` (Ganon):** This subtype completely alters Dark Link's behavior to that of a Ganon boss, executing `Sprite_Ganon_Main` and `Sprite_Ganon_Draw`. This mechanism allows for a multi-stage boss fight or an entirely different boss using the same sprite slot.
* **Subtype `$01` (Sword Damage):** This subtype is used for a temporary sprite spawned during Dark Link's sword attacks to handle collision and damage detection.
## In-Game Behavior:
Dark Link is an active and engaging boss. It moves strategically towards Link, performs various sword attacks (including a jump attack with screen shake), can utilize a cape for evasion, and throws bombs. It reacts to damage with visual recoil and flashing, and enters an "enraging" state (indicated by a red palette change) which likely alters its attack patterns or aggression. The Ganon subtype suggests a significant shift in combat during the fight.
## Original Sprite Replaced:
The code does not explicitly state which vanilla sprite `dark_link` replaces. However, the integration of `GanonInit` and Ganon-related logic strongly suggests it either heavily modifies an existing Ganon boss fight or is a completely new boss utilizing a custom sprite ID.
## Development Goals for Oracle of Secrets:
* **Variety in Attacks:** Introduce more diverse attack patterns and abilities to enhance the fight's complexity and challenge.
* **Unique Oracle of Secrets Attacks:** Implement attacks that are thematic and unique to the Oracle of Secrets project, moving beyond standard ALTTP boss mechanics.
## Code Quality Notes:
The code, while functional and effective in creating a competent boss, is noted to be somewhat "messy" due to its origin from Zarby89's ZScream project. This implies that while it works, future modifications might require careful navigation through its structure.

65
Docs/Sprites/Kydreeok.md Normal file
View File

@@ -0,0 +1,65 @@
# Kydreeok Sprite Analysis
## Overview
The `kydreeok` sprite (ID: `Sprite_Kydreeok`, which is `$7A`) represents the main Kydreeok boss. It orchestrates the entire boss fight, including spawning and managing its child head sprites (`kydreeok_head`), controlling its own movement phases, and handling its overall defeat. This is a multi-headed boss where the heads are separate sprites.
## Key Properties:
* **Sprite ID:** `Sprite_Kydreeok` (`$7A`)
* **Description:** The main Kydreeok boss, controlling the overall fight and its child heads.
* **Number of Tiles:** 8
* **Health:** `00` (The boss's health is managed through its child heads and custom logic, not directly by this sprite's `!Health` property.)
* **Damage:** `00` (Damage dealt to Link is likely handled by its heads or custom logic.)
* **Special Properties:**
* `!Boss = 01` (This sprite is correctly identified as a boss.)
* `!Hitbox = $07`
## Main States/Actions (`Sprite_Kydreeok_Main` Jump Table):
The boss's behavior is divided into several phases:
* **`Kydreeok_Start` (0x00):** Initial state. Applies graphics and palette, prevents Link from passing through, and transitions to `Kydreeok_StageControl` after a timer. Stores its own sprite index in `Kydreeok_Id`.
* **`Kydreeok_StageControl` (0x01):** Manages the boss's movement stage, setting velocities and checking boundaries.
* **`Kydreeok_MoveXandY` (0x02):** Moves the boss in both X and Y directions towards Link, checking boundaries and handling damage.
* **`Kydreeok_MoveXorY` (0x03):** Moves the boss in either X or Y direction towards Link, checking boundaries and handling damage.
* **`Kydreeok_KeepWalking` (0x04):** Continues walking, with a random chance to transition to a flying state.
* **`Kydreeok_Dead` (0x05):** Handles the boss's death sequence, including visual effects (flickering, explosions) and eventually despawning the sprite.
* **`Kydreeok_Flying` (0x06):** The boss enters a flying state, moving towards Link at a set height, checking boundaries and handling damage.
## Initialization (`Sprite_Kydreeok_Prep`):
* Sets initial timers and movement speeds.
* Caches its own origin position.
* **Spawns its child heads:** Calls `JSR SpawnLeftHead` and `JSR SpawnRightHead`. A `SpawnCenterHead` routine is commented out, suggesting a potential for a three-headed boss.
* Initializes neck offsets to zero.
* Applies a custom palette (`JSR ApplyPalette`).
* Sets the boss theme music.
## Death and Respawn Logic (`Sprite_Kydreeok_CheckIfDead`, `MaybeRespawnHead`):
* **`Sprite_Kydreeok_CheckIfDead`:** This crucial routine checks the state of its child heads (`Offspring1_Id`, `Offspring2_Id`). If both heads are defeated, it triggers a "dead" phase, changes its graphics, respawns both heads, and then transitions to the `Kydreeok_Dead` state. This indicates a multi-phase boss where heads can be temporarily defeated.
* **`MaybeRespawnHead`:** Randomly respawns a head if its corresponding child sprite is dead, adding a dynamic challenge to the fight.
## Head Spawning (`SpawnLeftHead`, `SpawnRightHead`):
* These routines spawn `Sprite_KydreeokHead` (`$CF`) sprites.
* They assign `SprSubtype` to the spawned heads (`$00` for left, `$01` for right), allowing the child sprites to differentiate their behavior.
* They store the IDs of the spawned heads in global variables (`Offspring1_Id`, `Offspring2_Id`).
* They set the initial position of the heads relative to the main boss and initialize neck segment coordinates.
## Movement (`MoveBody`, `StopIfOutOfBounds`):
* **`MoveBody`:** Manages the main body's movement, calling `JSL Sprite_Move` and updating background scrolling based on its movement. It reuses logic from `Trinexx_MoveBody`.
* **`StopIfOutOfBounds`:** Prevents the boss from moving beyond screen boundaries. It also subtly adjusts the neck positions when hitting a boundary, creating a visual "pushing" effect.
## Palette Management (`ApplyPalette`, `ApplyEndPalette`):
* **`ApplyPalette`:** Sets the initial palette for the boss.
* **`ApplyEndPalette`:** Sets a different palette, likely for a defeated state or phase change.
## Graphics Transfer (`ApplyKydreeokGraphics`):
* Handles DMA transfer of graphics data (`kydreeok.bin`, `kydreeok_phase2.bin`) to VRAM, allowing for different graphical appearances across phases.
## Global Variables for Neck Control:
* `LeftNeck1_X` to `LeftNeck3_Y`, `RightNeck1_X` to `RightNeck3_Y`: Global RAM addresses used to store the coordinates of the neck segments, enabling the heads to track them.
* `Kydreeok_Id`: Stores the sprite index of the main Kydreeok boss.
* `Offspring1_Id`, `Offspring2_Id`: Store the sprite indices of the spawned heads.
## Discrepancies/Notes:
* The `!Health` and `!Damage` properties are `00`, confirming that the boss's health and damage are managed through its heads (`Sprite_KydreeokHead`) and custom logic within `Sprite_Kydreeok_CheckIfDead`.
* The `Sprite_Kydreeok_CheckIfDead` routine clearly defines a multi-phase fight where the heads can be defeated, respawned, and ultimately lead to the main boss's defeat.
* The commented-out `SpawnCenterHead` suggests a potential for a three-headed Kydreeok that was either removed or is an unimplemented feature.
* Reusing movement logic from `Trinexx_MoveBody` is efficient but should be considered for unique boss feel.
* Hardcoded addresses for `JSL` calls could be replaced with named labels for better maintainability.

View File

@@ -0,0 +1,68 @@
# Kydreeok Head Sprite Analysis
## Overview
The `kydreeok_head` sprite (ID: `Sprite_KydreeokHead`, which is `$CF`) is a child sprite of the main `Kydreeok` boss. It represents one of the multi-headed boss's individual heads, possessing independent movement, attack patterns, and damage handling. Its primary role is to move, rotate, and attack Link, contributing to the overall boss encounter.
## Key Properties:
* **Sprite ID:** `Sprite_KydreeokHead` (`$CF`)
* **Description:** Child sprite of the Kydreeok boss, responsible for individual head behavior.
* **Number of Tiles:** 7
* **Health:** `$C8` (200 decimal) - This high health value indicates it's a significant component of the boss fight.
* **Damage:** `00` (Damage is likely applied through its spawned attacks.)
* **Special Properties:**
* `!Boss = 00` (Not marked as a boss itself, as it's a component of a larger boss.)
* `!Hitbox = 09`
## Subtypes:
The `SprSubtype, X` register is crucial for differentiating the heads and their behavior:
* **Subtype `$00`:** Controls the "Left Head" via `Neck1_Control`.
* **Subtype `$01`:** Controls the "Right Head" via `Neck2_Control`.
This allows the same sprite ID to manage multiple distinct heads.
## Main States/Actions (`Sprite_KydreeokHead_Main` Jump Table):
The head's behavior is governed by a state machine:
* **`KydreeokHead_ForwardAnim` (0x00):** Default state, plays forward animation, handles damage, performs rotational movement, and randomly attacks. Transitions to other directional states based on Link's position.
* **`KydreeokHead_RightAnim` (0x01):** Plays right-facing animation, handles damage, rotation, and attacks.
* **`KydreeokHead_LeftAnim` (0x02):** Plays left-facing animation, handles damage, rotation, and attacks.
* **`KydreeokHead_FarRight` (0x03):** Plays far-right animation, moves towards Link, handles damage, rotation, and attacks.
* **`KydreeokHead_FarLeft` (0x04):** Plays far-left animation, moves towards Link, handles damage, rotation, and attacks.
* **`KydreeokHead_SummonFire` (0x05):** Moves towards Link, checks damage, and utilizes `JSL Sprite_Twinrova_FireAttack` to deal damage. The head sprite is then killed after a timer.
## Initialization (`Sprite_KydreeokHead_Prep`):
* Sets initial health to `$FF` (255 decimal), though the `!Health` property is `$C8`. This discrepancy might be overridden by the parent `Kydreeok` sprite or is a temporary value.
* Sets `SprBump = $09` (bump damage type).
* Initializes `SprMiscE, X` to `0`.
## Drawing (`Sprite_KydreeokHead_Draw`):
* Uses standard OAM allocation routines.
* The main drawing routine calls `JMP Sprite_KydreeokHead_DrawNeck`, indicating that the neck segments are drawn after the head.
* Includes logic for flashing when damaged.
## Neck Control (`KydreeokHead_NeckControl`, `Neck1_Control`, `Neck2_Control`, `Sprite_KydreeokHead_DrawNeck`, `DrawNeckPart`):
This is a sophisticated system for managing the multi-segmented neck:
* `KydreeokHead_NeckControl` dispatches to `Neck1_Control` (for the left head) or `Neck2_Control` (for the right head) based on `SprSubtype, X`.
* `Neck1_Control` and `Neck2_Control` manage the movement and positioning of three neck segments, ensuring they follow the head while maintaining specific distances.
* `Sprite_KydreeokHead_DrawNeck` and `DrawNeckPart` handle the rendering of these segments.
## Movement and Rotation (`KydreeokHead_RotationMove`, `RotateHeadUsingSpeedValues`, `MoveWithBody`):
* **`KydreeokHead_RotationMove`:** Generates random speeds, dispatches to neck control, moves with the main body, and applies rotational movement.
* **`RotateHeadUsingSpeedValues`:** Uses sine/cosine tables (`XSpeedSin`, `YSpeedSin`) to apply smooth rotational movement.
* **`MoveWithBody`:** Ensures the head's position is correctly offset and relative to the main `Kydreeok` boss, adjusting for left or right heads.
## Attacks (`RandomlyAttack`, `KydreeokHead_SummonFire`):
* **`RandomlyAttack`:** Randomly spawns a fire-based projectile (which is actually the `Sprite_KydreeokHead` itself entering the `SummonFire` state).
* **`KydreeokHead_SummonFire`:** This state is entered when a fire projectile is spawned. It moves towards Link and uses `JSL Sprite_Twinrova_FireAttack` to deal damage, after which the head sprite is killed.
## Key Macros/Functions Used:
* `%Set_Sprite_Properties`, `%GotoAction`, `%StartOnFrame`, `%PlayAnimation`, `%MoveTowardPlayer`
* `JSL JumpTableLocal`, `JSL Sprite_CheckDamageFromPlayer`, `JSL Sprite_CheckDamageToPlayer`, `JSL Sprite_DamageFlash_Long`
* `JSL GetRandomInt`, `JSL Sprite_MoveLong`, `JSL Sprite_IsToRightOfPlayer`
* `JSL Sprite_SpawnDynamically`, `JSL Sprite_SetSpawnedCoords`
* `JSL Sprite_Twinrova_FireAttack`, `JSL Fireball_SpawnTrailGarnish`
* `JSR GetDistance8bit`
## Discrepancies/Notes:
* The `!Health` property is `$C8`, but `Sprite_KydreeokHead_Prep` sets `SprHealth, X` to `$FF`. This needs clarification.
* The reuse of `JSL Sprite_Twinrova_FireAttack` for Kydreeok's head is an example of code reuse, but it's important to ensure it fits the thematic design of Kydreeok.
* The neck control system is quite intricate, highlighting advanced sprite design.
* Several hardcoded addresses for `JSL` calls could be replaced with named labels for better maintainability.

View File

@@ -0,0 +1,90 @@
# Kydrog Boss Sprite Analysis
## Overview
The `kydrog_boss` sprite (ID: `Sprite_KydrogBoss`, which is `$CB`) represents the main Kydrog boss. This boss features multiple phases, dynamic movement, and the ability to summon stalfos offspring. It's a complex encounter designed to challenge the player through varied attack patterns and phase transitions.
## Key Properties:
* **Sprite ID:** `Sprite_KydrogBoss` (`$CB`)
* **Description:** The main Kydrog boss, controlling its own movement, phases, and spawning stalfos offspring.
* **Number of Tiles:** 11
* **Health:** `00` (The boss's health is managed through `CheckForNextPhase` and `Sprite_KydrogBoss_CheckIfDead`, not directly by this property.)
* **Damage:** `00` (Damage dealt to Link is likely handled by its attacks or spawned offspring.)
* **Special Properties:**
* `!Boss = $01` (Correctly identified as a boss.)
* `!Shadow = 01` (Draws a shadow.)
* `!Hitbox = 03`
## Custom Variables:
* `!ConsecutiveHits = $AC`: Tracks consecutive hits on the boss, influencing its behavior.
* `!KydrogPhase = $7A`: Manages the current phase of the boss fight.
* `!WalkSpeed = 10`: Defines the boss's walking speed.
## Main States/Actions (`Sprite_KydrogBoss_Main` Jump Table):
The boss's behavior is governed by a detailed state machine:
* **`KydrogBoss_Init` (0x00):** Initial state, plays an "Arms Crossed" animation, and transitions to `KydrogBoss_WalkState` after an intro timer.
* **`KydrogBoss_WalkState` (0x01):** The primary walking state. Manages phase transitions, handles damage, taunting, and determines the next walking direction (forward, backward, left, right) based on Link's position and proximity.
* **`KydrogBoss_WalkForward` (0x02), `KydrogBoss_WalkLeft` (0x03), `KydrogBoss_WalkRight` (0x04), `KydrogBoss_WalkBackward` (0x05):** These states handle movement in specific directions, playing corresponding animations and executing core movement logic.
* **`KydrogBoss_TakeDamage` (0x06):** Manages the boss taking damage. Increments `!ConsecutiveHits`, plays a damage animation, spawns stalfos offspring, and can trigger an ascend action.
* **`KydrogBoss_TauntPlayer` (0x07):** Plays a taunting animation, handles damage, and transitions to `KydrogBoss_SummonStalfos`.
* **`KydrogBoss_SummonStalfos` (0x08):** Plays a summoning animation, handles damage, spawns stalfos offspring, and can throw a bone projectile at Link.
* **`KydrogBoss_Death` (0x09):** Handles the boss's death sequence, including killing spawned friends, playing a flickering animation, and despawning.
* **`KydrogBoss_Ascend` (0x0A):** The boss ascends off-screen, increasing its `SprHeight` and spawning stalfos offspring. Transitions to `KydrogBoss_Descend`.
* **`KydrogBoss_Descend` (0x0B):** The boss descends, tracking Link's position, decreasing its `SprHeight`, and spawning stalfos offspring. Transitions back to `KydrogBoss_WalkState`.
* **`KydrogBoss_Abscond` (0x0C):** The boss moves away from Link, increasing its speed, and transitions back to `KydrogBoss_WalkState`.
## Initialization (`Sprite_KydrogBoss_Prep`):
* Initializes `!KydrogPhase` to `00`.
* Sets initial health to `$A0` (160 decimal).
* Configures deflection (`SprDefl`), hitbox (`SprHitbox`), and bump damage (`SprBump`).
* Sets `SprGfxProps` to not invincible.
* Calls `JSR KydrogBoss_Set_Damage` to define its damage vulnerabilities.
* Sets initial sprite speeds and `!Harmless = 00`.
* Sets an intro timer (`SprTimerD = $80`).
## Death Check (`Sprite_KydrogBoss_CheckIfDead`):
* Monitors `SprHealth, X`. If health is zero or negative, it triggers the boss's death sequence, setting `SprState = $04` (kill sprite boss style) and `SprAction = $09` (KydrogBoss_Death stage).
## Phase Management (`CheckForNextPhase`):
This routine dynamically manages the boss's phases based on its current health:
* **Phase One (`!KydrogPhase = $00`):** Transitions to Phase Two when health drops below `$20`.
* **Phase Two (`!KydrogPhase = $01`):** Transitions to Phase Three when health drops below `$20`. Resets health to `$80`, sets action to `KydrogBoss_WalkState`, and increments `SprFlash, X`.
* **Phase Three (`!KydrogPhase = $02`):** Transitions to Phase Four when health drops below `$20`. Resets health to `$80`, sets action to `KydrogBoss_WalkState`.
* **Phase Four (`!KydrogPhase = $03`):** Sets action to `KydrogBoss_WalkState`.
## Damage Table (`KydrogBoss_Set_Damage`):
* Defines how KydrogBoss reacts to various attack types (Boomerang, Sword, Arrow, Bomb, etc.), stored in a damage properties table.
## Offspring Spawning (`RandomStalfosOffspring`, `Sprite_Offspring_Spawn`, `Sprite_Offspring_SpawnHead`):
* **`RandomStalfosOffspring`:** Randomly spawns either a normal stalfos offspring (`Sprite_Offspring_Spawn`) or a stalfos head offspring (`Sprite_Offspring_SpawnHead`), with a limit of 4 active stalfos.
* **`Sprite_Offspring_Spawn`:** Spawns a stalfos offspring (Sprite ID `$A7` or `$85`).
* **`Sprite_Offspring_SpawnHead`:** Spawns a stalfos head offspring (Sprite ID `$7C` or `$02`).
## Attacks (`Kydrog_ThrowBoneAtPlayer`):
* **`Kydrog_ThrowBoneAtPlayer`:** Spawns a bone projectile (Sprite ID `$A7`) that moves towards Link.
## Movement (`KydrogBoss_DoMovement`, `BounceBasedOnPhase`):
* **`KydrogBoss_DoMovement`:** Handles damage checks, applies damage to Link on contact, flashes when damaged, and incorporates phase-based bouncing and stalfos spawning.
* **`BounceBasedOnPhase`:** Adjusts the boss's bounce speed based on the current `!KydrogPhase`.
## Drawing (`Sprite_KydrogBoss_Draw`):
* Uses standard OAM allocation routines.
* Handles complex animation frames, x/y offsets, character data, properties, and sizes for drawing the boss.
* Utilizes 16-bit operations (`REP #$30`, `SEP #$30`) for precise drawing calculations.
## Other Routines:
* **`StopIfTooClose()` macro:** Prevents the boss from getting too close to Link.
* **`Sprite_CheckIfFrozen`:** Checks if the sprite is frozen and unfreezes it after a timer.
* **`GetNumberSpawnStalfos`:** Counts the number of active stalfos offspring.
* **`SpawnSplash`:** Spawns a splash effect.
* **`SpawnBossPoof`:** Spawns a boss poof effect.
* **`HandleMovingSplash`:** Handles splash effects during movement.
* **`SpawnMedallion` / `SpawnMedallionAlt`:** Spawns a medallion.
## Discrepancies/Notes:
* The main boss's health is intricately managed through `SprHealth, X` and `!KydrogPhase`, requiring a clear understanding of their interplay.
* The stalfos offspring are spawned using specific sprite IDs, which should be cross-referenced for full understanding.
* Many hardcoded values for timers, speeds, and offsets could be replaced with named constants for improved readability and maintainability.
* The code includes direct calls to sound effect functions (`JSL $0DBB8A`) and a commented-out call to `JSL $01F3EC` (Light Torch), which might be a leftover or an unimplemented feature.
## Hardcoded Activation Trigger:
* As noted by the user, the activation trigger for KydrogBoss is hardcoded. Specifically, in the `WaitForPlayerToApproach` routine, the boss checks `LDA.b $20 : CMP #$08C8`. `$20` represents Link's Y position, and `$08C8` is a hardcoded Y-coordinate. This means the boss will only activate when Link reaches this specific Y-coordinate, making it difficult to relocate the boss to other overworld maps without modifying this value.

79
Docs/Sprites/Manhandla.md Normal file
View File

@@ -0,0 +1,79 @@
# Manhandla / Big Chuchu Sprite Analysis
## Overview
The `manhandla` sprite (ID: `Sprite_Manhandla`, which is `$88`) is a multi-phase boss. It begins as Manhandla, a multi-headed plant-like enemy, and upon the defeat of its individual heads, it transforms into a Big Chuchu. This design creates a dynamic and evolving boss encounter.
## Key Properties:
* **Sprite ID:** `Sprite_Manhandla` (`$88`)
* **Description:** A multi-phase boss that transforms from Manhandla to Big Chuchu.
* **Number of Tiles:** 3
* **Health:** `00` (Health is managed by its spawned heads in the first phase and then by its own `SprHealth` in the second phase.)
* **Damage:** `00` (Damage dealt to Link is likely handled by its heads or spawned projectiles.)
* **Special Properties:**
* `!Boss = 01` (Correctly identified as a boss.)
* `!DeathAnimation = 01` (Indicates custom death handling rather than a standard animation.)
* `!Hitbox = 00`
## Custom Variables:
* `Offspring1_Id`, `Offspring2_Id`, `Offspring3_Id`: Global variables used to track the sprite indices of the spawned Manhandla heads.
## Main States/Actions (`Sprite_Manhandla_Main` Jump Table):
The boss's behavior is governed by a detailed state machine across its phases:
* **`Manhandla_Intro` (0x00):** Initial state. Spawns the three Manhandla heads (`SpawnLeftManhandlaHead`, `SpawnRightManhandlaHead`, `SpawnCenterMandhandlaHead`) and transitions to `Manhandla_Body`.
* **`Manhandla_FrontHead` (0x01), `Manhandla_LeftHead` (0x02), `Manhandla_RightHead` (0x03):** These states are likely executed by the individual Manhandla head child sprites, managing their movement, damage, and contact with Link.
* **`BigChuchu_Main` (0x04):** The primary state for the Big Chuchu phase. Handles movement, damage, and can spawn Chuchu blasts.
* **`Flower_Flicker` (0x05):** A transitional state that flickers the background (BG2) and spawns a new `Sprite_Manhandla` (with `SprSubtype = $08`, representing the Big Chuchu head) after a timer, as part of the transformation.
* **`Manhandla_Body` (0x06):** The main state for the Manhandla body. Handles movement, damage, updates the positions of its spawned heads, and can spawn Mothula beams.
* **`BigChuchu_Emerge` (0x07):** Manages the emergence animation of the Big Chuchu.
* **`BigChuchu_Flower` (0x08):** A state for the Big Chuchu, possibly related to its visual appearance or an attack.
* **`BigChuchu_Dead` (0x09):** Handles the death sequence of the Big Chuchu.
* **`ChuchuBlast` (0x0A):** Manages the movement and damage of the spawned Chuchu blast projectile.
## Initialization (`Sprite_Manhandla_Prep`):
* Sets initial movement speeds and enables BG1 movement.
* Configures deflection properties (`SprDefl = $80`).
* Sets initial health to `$80`.
* Initializes `SprAction, X` based on `SprSubtype, X`.
## Phase Transition and Death Check (`Sprite_Manhandla_CheckForNextPhaseOrDeath`):
This critical routine orchestrates the boss's transformation:
* It checks if all three Manhandla heads (`Offspring1_Id`, `Offspring2_Id`, `Offspring3_Id`) are dead.
* If all heads are defeated, it triggers the transition to the Big Chuchu phase:
* Sets `SprMiscD, X = $01` (phase flag).
* Refills health (`SprHealth = $40`).
* Adjusts OAM entries (`SprNbrOAM = $08`).
* Sets `SprAction = $07` (BigChuchu_Emerge).
* It also manages the Big Chuchu's defeat, transitioning to `BigChuchu_Dead` when its health drops below `$04`.
## Head Spawning (`SpawnLeftManhandlaHead`, `SpawnRightManhandlaHead`, `SpawnCenterMandhandlaHead`):
* These routines spawn `Sprite_Manhandla` (`$88`) sprites as child heads.
* They assign specific `SprSubtype` values (`$03` for left, `$02` for right, `$01` for center) to differentiate the heads.
* They store the IDs of the spawned heads in global variables (`Offspring1_Id`, `Offspring2_Id`, `Offspring3_Id`).
* They set the initial position, health, and properties for each head.
## Head Positioning (`SetLeftHeadPos`, `SetRightHeadPos`, `SetCenterHeadPos`):
* These routines dynamically calculate and set the positions of the spawned heads relative to the main Manhandla body.
## Movement (`Sprite_Manhandla_Move`, `Manhandla_StopIfOutOfBounds`):
* **`Sprite_Manhandla_Move`:** The core movement logic for the Manhandla body, utilizing a jump table for `StageControl`, `MoveXandY`, `MoveXorY`, and `KeepWalking` states.
* **`Manhandla_StopIfOutOfBounds`:** Prevents the boss from moving beyond predefined screen boundaries.
## Attacks (`Chuchu_SpawnBlast`, `Mothula_SpawnBeams`):
* **`Chuchu_SpawnBlast`:** Spawns a Chuchu blast projectile (Sprite ID `$88` with `SprSubtype = $0A`).
* **`Mothula_SpawnBeams`:** Spawns beam projectiles (Sprite ID `$89`), called from `Manhandla_Body`.
## Drawing (`Sprite_Manhandla_Draw`, `Sprite_BigChuchu_Draw`):
* **`Sprite_Manhandla_Draw`:** Renders the Manhandla body and its heads.
* **`Sprite_BigChuchu_Draw`:** Renders the Big Chuchu form.
* Both utilize standard OAM allocation routines and handle animation frames, offsets, character data, properties, and sizes.
## Graphics and Palette (`ApplyManhandlaGraphics`, `ApplyManhandlaPalette`):
* **`ApplyManhandlaGraphics`:** Handles DMA transfer of graphics data (`manhandla.bin`) to VRAM.
* **`ApplyManhandlaPalette`:** Sets the custom palette for Manhandla.
## Discrepancies/Notes:
* The `!Health` property is `00`, indicating that the boss's health is managed by its heads in the first phase and then by its own `SprHealth` in the Big Chuchu phase.
* The `Sprite_Manhandla` ID (`$88`) is efficiently reused for the main boss, its heads, and the Chuchu blast projectile, with `SprSubtype` differentiating their roles.
* The reuse of `Mothula_SpawnBeams` for Manhandla is an example of code reuse.
* Hardcoded values for timers, speeds, and offsets could be replaced with named constants for improved readability and maintainability.
* A commented-out `org` for `Sprite_DoTheDeath#PrepareEnemyDrop.post_death_stuff` suggests potential modifications to the death routine.

79
Docs/Sprites/Octoboss.md Normal file
View File

@@ -0,0 +1,79 @@
# Octoboss Sprite Analysis
## Overview
The `octoboss` sprite (ID: `Sprite_Octoboss`, which is `$3C`) is a multi-phase boss, likely an octopus-like creature. It features a unique mechanic involving a "brother" Octoboss, and can summon stalfos offspring. The fight progresses through distinct phases including emergence, movement, taunting, ascending, submerging, and a surrender sequence.
## Key Properties:
* **Sprite ID:** `Sprite_Octoboss` (`$3C`)
* **Description:** A multi-phase boss with a "brother" Octoboss, capable of summoning stalfos and engaging in various movement and attack patterns.
* **Number of Tiles:** 11
* **Health:** `00` (Health is managed by `ReturnTotalHealth` and `CheckForNextPhase`, combining the health of both Octobosses.)
* **Damage:** `00` (Damage dealt to Link is likely handled by its attacks or spawned offspring.)
* **Special Properties:**
* `!Boss = $01` (Correctly identified as a boss.)
* `!Shadow = 01` (Draws a shadow.)
* `!Hitbox = 03`
## Custom Variables:
* `!ConsecutiveHits = $AC`: Tracks consecutive hits on the boss.
* `!KydrogPhase = $7A`: Tracks the current phase of the boss fight. (Note: This variable name is `KydrogPhase`, suggesting shared logic or a copy-paste from the Kydrog boss.)
* `!WalkSpeed = 10`: Defines the boss's walking speed.
* `BrotherSpr = $0EB0`: Stores the sprite index of the "brother" Octoboss.
## Main Logic Flow (`Sprite_Octoboss_Main` and `Sprite_Octoboss_Secondary`):
The Octoboss has two primary main routines, `Sprite_Octoboss_Main` and `Sprite_Octoboss_Secondary`, which are called based on `SprMiscF, X`. This suggests different forms or behaviors for the two Octobosses.
**`Sprite_Octoboss_Main` Jump Table (for the primary Octoboss):**
* **`WaitForPlayerToApproach` (0x00):** Waits for Link to reach a specific Y-coordinate (`$08C8`) to trigger activation.
* **`Emerge` (0x01):** Emerges from the water, preventing Link's movement.
* **`EmergedShowMessage` (0x02):** Displays an introductory message.
* **`SpawnAndAwakeHisBrother` (0x03):** Spawns a "brother" Octoboss (`Sprite_Octoboss` with `SprMiscF = $01`) and stores its ID in `BrotherSpr`.
* **`WaitForBrotherEmerge` (0x04):** Waits for the brother to emerge and displays a message.
* **`SpawnPirateHats` (0x05):** Spawns "boss poof" effects for both Octobosses, changes their frames, and spawns walls using `Overworld_DrawMap16_Persist` macros.
* **`IdlePhase` (0x06):** Idles, can spawn fireballs, and checks total health (`ReturnTotalHealth`) to potentially trigger surrender.
* **`PickDirection` (0x07):** Picks a random direction and speed for movement.
* **`Moving` (0x08):** Moves around, handles boundary checks, spawns splash effects, and checks total health to potentially trigger surrender.
* **`WaitMessageBeforeSurrender` (0x09):** Displays a surrender message (`$004A`), sets the brother's action, and transitions to `RemoveHat`.
* **`RemoveHat` (0x0A):** Removes hats from both Octobosses with "boss poof" effects, displays a message (`$004B`), and transitions to `Submerge`.
* **`Submerge` (0x0B):** Submerges, playing an animation and spawning a splash effect.
* **`SubmergeWaitWall` (0x0C):** Submerges further, drawing walls using `Overworld_DrawMap16_Persist` macros.
* **`EmergeWaitGiveItem` (0x0D):** Emerges, spawns a medallion (`SpawnMedallion`), and sets an SRAM flag.
* **`SubmergeForeverKill` (0x0E):** Submerges completely, despawns, and allows Link to move again.
**`Sprite_Octoboss_Secondary` Jump Table (for the secondary/brother Octoboss, when `SprMiscF, X` is set):**
This routine largely mirrors `Sprite_Octoboss_Main` but includes specific states like `WaitDialog` and `Moving2`, suggesting slight behavioral differences.
## Initialization (`Sprite_Octoboss_Long` and `Sprite_Octoboss_Prep`):
* **`Sprite_Octoboss_Long`:** Main entry point. Handles sprite initialization, including setting OAM properties, bulletproofing, frame, and palette values. It also checks for boss defeat and medallion spawning.
* **`Sprite_Octoboss_Prep`:** Initializes `!KydrogPhase` to `00`, sets initial health (`$A0`), configures deflection, hitbox, bump damage, and calls `JSR KydrogBoss_Set_Damage` to set up the damage table. Sets initial sprite speeds and an intro timer.
## Health Management (`Sprite_Octoboss_CheckIfDead`, `ReturnTotalHealth`, `CheckForNextPhase`):
* **`Sprite_Octoboss_CheckIfDead`:** Monitors `SprHealth, X`. If health is zero or negative, it triggers the boss's death sequence.
* **`ReturnTotalHealth`:** Calculates the combined health of both Octobosses (`SprHealth, X` and `SprHealth, Y` of `BrotherSpr`).
* **`CheckForNextPhase`:** Manages the boss's phases based on health thresholds, similar to the Kydrog boss.
## Offspring Spawning (`RandomStalfosOffspring`, `Sprite_Offspring_Spawn`, `Sprite_Offspring_SpawnHead`):
* These routines are identical to those found in `kydrog_boss.asm`, spawning stalfos offspring.
## Attacks (`Chuchu_SpawnBlast`, `Mothula_SpawnBeams`, `Kydrog_ThrowBoneAtPlayer`):
* **`Chuchu_SpawnBlast`:** Spawns a Chuchu blast projectile.
* **`Mothula_SpawnBeams`:** Spawns beam projectiles.
* **`Kydrog_ThrowBoneAtPlayer`:** Spawns a bone projectile (reused from Kydrog).
## Drawing (`Sprite_Octoboss_Draw`, `Sprite_Octoboss_Draw2`):
* **`Sprite_Octoboss_Draw`:** Draws the primary Octoboss.
* **`Sprite_Octoboss_Draw2`:** Draws the secondary/brother Octoboss.
* Both use standard OAM allocation routines and handle complex animation frames, offsets, character data, properties, and sizes.
## Other Routines:
* **`SpawnSplash`:** Spawns a splash effect.
* **`SpawnBossPoof`:** Spawns a boss poof effect.
* **`HandleMovingSplash`:** Handles splash effects during movement.
* **`SpawnMedallion` / `SpawnMedallionAlt`:** Spawns a medallion.
## Discrepancies/Notes:
* **Shared Variables/Code with Kydrog:** The extensive use of `!KydrogPhase`, `KydrogBoss_Set_Damage`, and `Kydrog_ThrowBoneAtPlayer` suggests significant code reuse or copy-pasting from the Kydrog boss. This could lead to unexpected interactions or make maintenance challenging if changes are made to one boss but not the other. Refactoring shared logic into common functions or macros would be beneficial.
* **`Sprite_Octoboss_Secondary`:** The existence of a separate main routine for the "brother" Octoboss indicates that the two Octobosses might have slightly different behaviors or phases.
## Hardcoded Activation Trigger:
* As noted by the user, the activation trigger for Octoboss is hardcoded. In the `WaitForPlayerToApproach` routine, the boss checks `LDA.b $20 : CMP #$08C8`. `$20` represents Link's Y position, and `$08C8` is a hardcoded Y-coordinate. This means the boss will only activate when Link reaches this specific Y-coordinate, making it difficult to relocate the boss to other overworld maps without modifying this value. This hardcoded dependency needs to be addressed for improved reusability.

80
Docs/Sprites/Twinrova.md Normal file
View File

@@ -0,0 +1,80 @@
# Twinrova Boss Sprite Analysis
## Overview
The `twinrova` sprite (ID: `Sprite_Twinrova`, which is `$CE`) is a complex, multi-phase boss designed to override the vanilla Blind and Blind Maiden sprites. It features a dramatic transformation from Blind Maiden into Twinrova, followed by alternating phases where Twinrova switches between Koume (fire) and Kotake (ice) forms, each possessing distinct attacks and environmental interactions.
## Key Properties:
* **Sprite ID:** `Sprite_Twinrova` (`$CE`)
* **Description:** A multi-phase boss that transforms from Blind Maiden, then alternates between fire (Koume) and ice (Kotake) forms.
* **Number of Tiles:** 6
* **Health:** `00` (Health is managed by `Sprite_Twinrova_CheckIfDead` and phase transitions.)
* **Damage:** `00` (Damage dealt to Link is likely handled by its attacks.)
* **Special Properties:**
* `!Boss = 01` (Correctly identified as a boss.)
* `!Shadow = 01` (Draws a shadow.)
* `!Hitbox = 03`
* `!CollisionLayer = 01` (Checks both layers for collision.)
## Custom Variables/Macros:
* `!AnimSpeed = 8`: Defines the animation speed for various states.
* `Twinrova_Front()`, `Twinrova_Back()`, `Twinrova_Ready()`, `Twinrova_Attack()`, `Show_Koume()`, `Show_Kotake()`, `Twinrova_Hurt()`: Macros for playing specific animations, enhancing code readability.
* `$AC`: A RAM address used to store the current attack type (Fire or Ice).
## Main Logic Flow (`Sprite_Twinrova_Main`):
The boss's behavior is governed by a detailed state machine:
* **`Twinrova_Init` (0x00):** Initial state. Displays an introductory message and transitions to `Twinrova_MoveState`.
* **`Twinrova_MoveState` (0x01):** The core movement and phase management state. It checks `SprHealth, X` to determine if Twinrova is in Phase 1 (single entity) or Phase 2 (alternating forms).
* **Phase 1:** Twinrova moves around, randomly spawning Fire/Ice Keese, or preparing Fire/Ice attacks.
* **Phase 2:** Twinrova alternates between `Twinrova_KoumeMode` (fire) and `Twinrova_KotakeMode` (ice) forms.
* **`Twinrova_MoveForwards` (0x02), `Twinrova_MoveBackwards` (0x03):** Handles movement using `Sprite_FloatTowardPlayer` and `Sprite_CheckTileCollision`.
* **`Twinrova_PrepareAttack` (0x04):** Prepares either a Fire or Ice attack based on the value in `$AC`.
* **`Twinrova_FireAttack` (0x05):** Executes a Fire attack. Restores floor tiles, uses `JSL Sprite_Twinrova_FireAttack` (a shared function for the actual attack), and randomly releases fireballs (`ReleaseFireballs`).
* **`Twinrova_IceAttack` (0x06):** Executes an Ice attack using `JSL Sprite_Twinrova_IceAttack` (a shared function).
* **`Twinrova_Hurt` (0x07):** Manages Twinrova taking damage. Plays a hurt animation and, after a timer, determines whether to dodge or retaliate with a fire or ice attack.
* **`Twinrova_KoumeMode` (0x08):** Koume (fire) form. Spawns pit hazards (`AddPitHazard`), falling tiles (`Ganon_SpawnFallingTilesOverlord`), and fireballs (`Sprite_SpawnFireball`). Uses `RageModeMove` for dynamic movement.
* **`Twinrova_KotakeMode` (0x09):** Kotake (ice) form. Can spawn lightning (`JSL $1DE612`) and uses `RageModeMove` for dynamic movement.
* **`Twinrova_Dead` (0x0A):** Handles Twinrova's death sequence, killing all spawned friends and playing a hurt animation.
## Initialization (`Sprite_Twinrova_Prep`):
* Checks for the presence of the Blind Maiden (`$7EF3CC = $06`). If the Maiden is present, Twinrova is killed, indicating that Twinrova spawns *from* the Blind Maiden.
* Sets initial health to `$5A` (90 decimal).
* Configures deflection (`SprDefl = $80`), bump damage (`SprBump = $04`), and ensures Twinrova is not invincible.
* Configures Blind Boss startup parameters and initializes various timers and `SprMisc` variables.
## Death Check (`Sprite_Twinrova_CheckIfDead`):
* Monitors `SprHealth, X`. If health is zero or negative, it triggers the boss's death sequence, setting `SprState = $04` (kill sprite boss style) and `SprAction = $0A` (Twinrova_Dead stage).
## Movement (`RageModeMove`, `DoRandomStrafe`, `VelocityOffsets`):
* **`RageModeMove`:** A sophisticated routine for dynamic, floaty movement. It randomly determines a movement mode (predictive movement towards player, random strafe, random dodge, stay in place) based on timers and probabilities. It also handles evasive actions.
* **`DoRandomStrafe`:** Generates random strafing movement.
* **`VelocityOffsets`:** A table defining X and Y speed offsets for movement.
## Environmental Interactions (`Twinrova_RestoreFloorTile`, `RestoreFloorTile`, `AddPitHazard`, `Ganon_SpawnFallingTilesOverlord`):
* **`Twinrova_RestoreFloorTile` / `RestoreFloorTile`:** Restores floor tiles, likely after they have been modified by an attack.
* **`AddPitHazard`:** Adds a pit hazard to the floor.
* **`Ganon_SpawnFallingTilesOverlord`:** Spawns falling tiles (reused from Ganon's mechanics).
## Drawing (`Sprite_Twinrova_Draw`):
* Uses standard OAM allocation routines.
* Handles complex animation frames, x/y offsets, character data, properties, and sizes for drawing Twinrova.
* Utilizes 16-bit operations for precise drawing calculations.
## Graphics Transfer (`ApplyTwinrovaGraphics`):
* Handles DMA transfer of graphics data (`twinrova.bin`) to VRAM.
## Attack Spawning (`Fireball_Configure`, `ReleaseFireballs`, `Sprite_SpawnFireKeese`, `Sprite_SpawnIceKeese`, `JSL Sprite_SpawnFireball`, `JSL $1DE612` (Sprite_SpawnLightning)):
* Twinrova can spawn various projectiles and enemies, including fireballs, Fire Keese, Ice Keese, and lightning.
## Blind Maiden Integration:
Twinrova's fight is deeply integrated with the Blind Maiden mechanics:
* **`Follower_BasicMover`:** This routine is hooked to check if the follower is the Blind Maiden, triggering the transformation to Twinrova.
* **`Follower_CheckBlindTrigger`:** Checks if the Blind Maiden follower is within a specific trigger area.
* **`Blind_SpawnFromMaiden`:** This is the core routine for the transformation. It applies Twinrova graphics, sets Twinrova's initial state and position based on the Maiden's, and sets various timers and properties.
* **`SpritePrep_Blind_PrepareBattle`:** This routine is overridden to handle Twinrova's prep or to despawn if a room flag is set.
## Discrepancies/Notes:
* **Health Management:** The `!Health` property is `00`. The boss's health is managed by `Sprite_Twinrova_CheckIfDead` and phase transitions.
* **Code Reuse:** There is extensive code reuse from other sprites/bosses (e.g., `Sprite_Twinrova_FireAttack` is also used by KydreeokHead, `Ganon_SpawnFallingTilesOverlord` in Koume mode, `Sprite_SpawnFireKeese`/`Sprite_SpawnIceKeese` in MoveState). This is an efficient practice but requires careful management to ensure thematic consistency and avoid unintended side effects.
* **Hardcoded Addresses:** Several `JSL` calls are to hardcoded addresses (e.g., `JSL $1DE612` for lightning). These should ideally be replaced with named labels for better maintainability.
* **Blind Maiden Overrides:** The boss heavily relies on overriding vanilla Blind Maiden behavior, which is a common ROM hacking technique but requires careful understanding of the original game's code.
* **`TargetPositions`:** This table is defined but appears unused in the provided code.

View File

@@ -0,0 +1,46 @@
# Vampire Bat Mini-Boss Sprite Analysis
## Overview
The `vampire_bat` sprite is a mini-boss, a specialized enemy that utilizes the generic Keese sprite ID (`$11`) but differentiates its behavior through `SprSubtype = 02`. It features more complex movement patterns and attacks compared to a standard Keese, including ascending, flying around, descending, and spawning other Keese.
## Key Properties:
* **Sprite ID:** `0x11` (Custom Keese Subtype 02)
* **Description:** A mini-boss variant of the Keese, with enhanced movement and attack capabilities.
* **Number of Tiles:** 8 (Inherited from the base Keese sprite.)
* **Health:** `32` (decimal, set in `Sprite_Keese_Prep` based on subtype.)
* **Damage:** `00` (Damage dealt to Link is likely handled by its attacks.)
* **Special Properties:**
* `!Boss = 00` (Not marked as a boss, but functions as a mini-boss/special enemy.)
* `!Shadow = 01` (Draws a shadow.)
## Main Logic Flow (`Sprite_VampireBat_Main`):
The Vampire Bat's behavior is governed by a state machine:
* **`VampireBat_Idle` (0x00):** Waits for Link to approach within a specified distance (`$24`). Transitions to `VampireBat_Ascend`.
* **`VampireBat_Ascend` (0x01):** Plays an ascending animation, increases its `SprHeight` to `$50`, and randomly spawns a Fire Keese (`Sprite_SpawnFireKeese`). Transitions to `VampireBat_FlyAround`.
* **`VampireBat_FlyAround` (0x02):** Plays a flying animation, moves towards Link (`Sprite_ProjectSpeedTowardsPlayer`), and randomly selects new directions (`Sprite_SelectNewDirection`). Transitions to `VampireBat_Descend` after a timer.
* **`VampireBat_Descend` (0x03):** Plays a descending animation, decreases its `SprHeight` until it's on the ground, and randomly uses `Sprite_Twinrova_FireAttack`. Transitions back to `VampireBat_Idle` after a timer.
## Initialization (from `Sprite_Keese_Prep` in `keese.asm`):
The Vampire Bat does not have its own `_Prep` routine and relies on the generic `Sprite_Keese_Prep` routine in `keese.asm`. When `SprSubtype = 02`:
* `SprHealth` is set to `$20` (32 decimal).
* `SprDefl` is set to `$80`.
* `SprTimerC` is set to `$30`.
## Drawing (`Sprite_VampireBat_Draw`):
* This routine is called from `Sprite_Keese_Long` in `keese.asm` when `SprSubtype = 02`.
* Uses standard OAM allocation routines.
* Handles animation frames, x/y offsets, character data, properties, and sizes specific to the Vampire Bat's appearance.
## Attack Spawning (`Sprite_SpawnFireKeese`, `Sprite_SpawnIceKeese`):
* **`Sprite_SpawnFireKeese`:** Spawns a Keese sprite (`$11`) with `SprSubtype = $01` (Fire Keese).
* **`Sprite_SpawnIceKeese`:** Spawns a Keese sprite (`$11`) with `SprSubtype = $00` (Ice Keese).
## Interactions:
* **Damage:** Responds to damage from Link, including flashing and bouncing from tile collisions.
* **Attacks:** Can spawn Fire Keese and utilize `Sprite_Twinrova_FireAttack` (a shared attack function).
## Discrepancies/Notes:
* **Shared Sprite ID:** The Vampire Bat efficiently reuses the generic Keese sprite ID (`$11`), with `SprSubtype = 02` serving as the primary differentiator for its unique behavior.
* **Health Management:** Its health is configured within the generic `Sprite_Keese_Prep` routine based on its subtype.
* **Code Reuse:** It reuses `Sprite_Twinrova_FireAttack`, demonstrating efficient code sharing across different boss/mini-boss sprites.
* **Hardcoded Values:** Many numerical values for timers, speeds, and offsets are hardcoded. Replacing these with named constants would improve readability and maintainability.

62
Docs/Sprites/Wolfos.md Normal file
View File

@@ -0,0 +1,62 @@
# Wolfos Mini-Boss Sprite Analysis
## Overview
The `wolfos` sprite (ID: `Sprite_Wolfos`, which is `$A9`) functions as a mini-boss or special enemy. It engages Link in combat with various movement and attack patterns. A key aspect of this sprite is its integration into a mask quest, where it can be subdued and, under specific conditions, grants Link the Wolf Mask.
## Key Properties:
* **Sprite ID:** `Sprite_Wolfos` (`$A9`)
* **Description:** A mini-boss/special enemy that fights Link and is part of a mask quest.
* **Number of Tiles:** 4
* **Health:** `30` (decimal)
* **Damage:** `00` (Damage dealt to Link is likely handled by its attacks.)
* **Special Properties:**
* `!Boss = 00` (Not marked as a boss, but functions as a mini-boss/special enemy.)
* `!ImperviousArrow = 01` (Impervious to arrows.)
## Custom Variables/Macros:
* `WolfosDialogue = SprMiscD`: Stores a flag to control Wolfos dialogue.
* `Wolfos_AnimateAction = SprMiscE`: Stores the current animation action.
* `AttackForward()`, `AttackBack()`, `WalkRight()`, `WalkLeft()`, `AttackRight()`, `AttackLeft()`, `Subdued()`, `GrantMask()`, `Dismiss()`: Macros for setting `SprAction` and `Wolfos_AnimateAction`, improving code clarity.
* `!NormalSpeed = $08`, `!AttackSpeed = $0F`: Constants for movement speeds.
## Main Logic Flow (`Sprite_Wolfos_Main`):
The Wolfos's behavior is governed by a state machine:
* **`Wolfos_AttackForward` (0x00), `Wolfos_AttackBack` (0x01), `Wolfos_WalkRight` (0x02), `Wolfos_WalkLeft` (0x03), `Wolfos_AttackRight` (0x04), `Wolfos_AttackLeft` (0x05):** These states manage the Wolfos's movement and attacks. They call `Wolfos_Move` and can randomly trigger attack actions with increased speed and temporary imperviousness.
* **`Wolfos_Subdued` (0x06):** In this state, the Wolfos stops moving, displays dialogue (`$23`), and waits for Link to play the Song of Healing (`SongFlag = $01`). If the song is played, it transitions to `Wolfos_GrantMask`.
* **`Wolfos_GrantMask` (0x07):** Displays the Wolfos mask graphic, shows a message (`$10F`), grants Link the `WolfMask` item, and transitions to `Wolfos_Dismiss`.
* **`Wolfos_Dismiss` (0x08):** Stops moving, kills the sprite, and clears Link's `BRANDISH` flag.
## Initialization (`Sprite_Wolfos_Prep`):
* Checks if Link is outdoors (`$1B`). If so, it further checks if the Wolfos has already been defeated (`$7EF303 = $01`). If defeated, the sprite is killed to prevent respawning.
* Sets initial timers (`SprTimerA = $40`, `SprTimerC = $40`).
* Configures deflection properties (`SprDefl = $82`, making it impervious to arrows).
* Sets `SprNbrOAM = $08` and initializes `SprMiscG, X` and `SprMiscE, X` to `0`.
## Defeat Check (`Sprite_Wolfos_CheckIfDefeated`):
* Checks if Link is outdoors. If `SprHealth, X` drops below `$04`, the Wolfos is considered "defeated."
* Upon defeat, it sets `SprAction = $06` (Wolfos_Subdued), `SprState = $09` (normal state, avoiding a full death animation), refills its health to `$40`, and clears `WolfosDialogue`. This indicates pacification rather than outright killing.
## Movement (`Wolfos_Move`, `Wolfos_DecideAction`, `Wolfos_MoveAction_Basic`, `Wolfos_MoveAction_CirclePlayer`, `Wolfos_MoveAction_Dodge`):
* **`Wolfos_Move`:** Handles damage flash, checks damage from player, prevents player from passing through, bounces from tile collision, checks for recoiling, moves the sprite, and calls `Wolfos_DecideAction`.
* **`Wolfos_DecideAction`:** Determines the Wolfos's next movement action based on timers and random chance. It uses a jump table to select between `Wolfos_MoveAction_Basic`, `Wolfos_MoveAction_CirclePlayer`, and `Wolfos_MoveAction_Dodge`.
* **`Wolfos_MoveAction_Basic`:** Basic movement towards or away from Link based on distance.
* **`Wolfos_MoveAction_CirclePlayer`:** Attempts to circle the player.
* **`Wolfos_MoveAction_Dodge`:** Dodges by applying speed towards the player.
## Animation (`Sprite_Wolfos_Animate`):
* This routine is called from `Sprite_Wolfos_Main`.
* It uses `Wolfos_AnimateAction` (stored in `SprMiscE, X`) to determine which animation to play.
* It has separate animation routines for `AttackForward`, `AttackBack`, `WalkRight`, `WalkLeft`, `AttackRight`, `AttackLeft`, and `Subdued`.
* It also spawns sparkle garnishes (`JSL Sprite_SpawnSparkleGarnish`).
## Drawing (`Sprite_Wolfos_Draw`):
* Uses standard OAM allocation routines.
* Handles animation frames, x/y offsets, character data, properties, and sizes for drawing the Wolfos.
* Includes a special frame for the Wolf Mask (`$CC`) when granting the item.
## Discrepancies/Notes:
* **Mask Quest Integration:** The Wolfos is directly integrated into a mask quest, where playing the Song of Healing subdues it and leads to receiving the Wolf Mask.
* **Health Refill on Defeat:** When defeated, its health is refilled to `$40`, and its state is set to `Wolfos_Subdued`, indicating it's not truly killed but rather pacified.
* **Hardcoded Values:** Many numerical values for timers, speeds, and offsets are hardcoded. Replacing these with named constants would improve readability and maintainability.
* **`JSL Link_ReceiveItem`:** This is a standard function for giving items to Link.
* **`JSL Sprite_SpawnSparkleGarnish`:** This is a generic garnish spawning function.