77 lines
6.4 KiB
Markdown
77 lines
6.4 KiB
Markdown
# Custom Menu & HUD System
|
|
|
|
This document provides a detailed analysis of the custom menu and Heads-Up Display (HUD) systems in Oracle of Secrets, based on the code in the `Menu/` directory.
|
|
|
|
## 1. Overview
|
|
|
|
The project features a completely custom menu and HUD, replacing the vanilla systems. The menu is a robust, multi-screen system, while the HUD provides a clean, modern interface for in-game stats.
|
|
|
|
- **Menu System**: A two-page design that separates selectable items from quest status and equipment. It is accessible by pressing the Start button.
|
|
- **HUD System**: A persistent on-screen display for health, magic, rupees, and the currently equipped item.
|
|
|
|
## 2. Menu System Architecture
|
|
|
|
The entire menu operates as a large state machine, with the main entry point being `Menu_Entry` in `Menu/menu.asm`. The flow is controlled by the value in WRAM `$0200`.
|
|
|
|
### 2.1. Main State Machine
|
|
|
|
The `Menu_Entry` routine uses a jump table (`.vectors`) to execute different subroutines based on the state in `$0200`. This modular approach allows for a clean separation of tasks like initialization, drawing, input handling, and screen transitions.
|
|
|
|
**Key States in `$0200`:**
|
|
|
|
| State ID | Label | Purpose |
|
|
|----------|----------------------------|-------------------------------------------------------------------------|
|
|
| `0x00` | `Menu_InitGraphics` | Initializes the menu, clears player state, and prepares for drawing. |
|
|
| `0x01` | `Menu_UploadRight` | Draws the entire right-hand screen (Quest Status). |
|
|
| `0x02` | `Menu_UploadLeft` | Draws the entire left-hand screen (Item Selection). |
|
|
| `0x04` | `Menu_ItemScreen` | The main interactive state for the Item screen. Handles cursor movement. |
|
|
| `0x05` | `Menu_ScrollTo` | Handles the smooth scrolling animation when moving from Items to Quest. |
|
|
| `0x06` | `Menu_StatsScreen` | The main interactive state for the Quest Status screen. |
|
|
| `0x0A` | `Menu_Exit` | Exits the menu, restores the game state, and updates the equipped item. |
|
|
| `0x0C` | `Menu_MagicBag` | A sub-menu for viewing collectible items. |
|
|
| `0x0D` | `Menu_SongMenu` | A sub-menu for selecting Ocarina songs. |
|
|
| `0x0E` | `Menu_Journal` | A sub-menu for reading the player's journal. |
|
|
| `0x09` | `Menu_RingBox` | A sub-menu for managing magic rings. |
|
|
|
|
### 2.2. Item Selection Screen (Left Page)
|
|
|
|
This is the primary interactive screen where the player selects their Y-button item.
|
|
|
|
- **Drawing (`DrawYItems`):** This routine is responsible for rendering all 24 item slots. It reads the SRAM address for each slot from `Menu_AddressIndex` (`menu_select_item.asm`), checks if the player owns the item, and then calls `DrawMenuItem`.
|
|
- **`DrawMenuItem`:** This generic function is the core of the drawing system. It takes an item's SRAM value (e.g., Sword level 0-4) and uses it to look up the correct 16x16 tile data from a large graphics table in `Menu/menu_gfx_table.asm`. This makes the menu highly data-driven.
|
|
- **Selection (`menu_select_item.asm`):** Cursor movement is handled by `Menu_FindNextItem`, `Menu_FindPrevItem`, etc. These routines intelligently skip over empty slots, ensuring the cursor always lands on a valid item. The currently selected slot index is stored in `$0202`.
|
|
|
|
### 2.3. Quest Status Screen (Right Page)
|
|
|
|
This screen is a static display of the player's overall progress.
|
|
|
|
- **Drawing:** It is rendered by a series of functions in `menu_draw.asm`, including:
|
|
- `Menu_DrawQuestItems`: Draws equipped sword, shield, tunic, etc.
|
|
- `Menu_DrawPendantIcons` & `Menu_DrawTriforceIcons`: Reads SRAM flags to draw collected pendants and crystals.
|
|
- `Menu_DrawCharacterName`: Reads the player's name from SRAM and renders it.
|
|
- `DrawLocationName`: Reads the current overworld area (`$008A`) or underworld room (`$00A0`) and looks up the corresponding name from the tables in `menu_map_names.asm`.
|
|
|
|
## 3. HUD System Architecture
|
|
|
|
The HUD is a separate system that hooks the vanilla game's NMI rendering routines. Its main entry point is `HUD_Update` in `Menu/menu_hud.asm`.
|
|
|
|
- **Functionality:** The `HUD_Update` routine runs every frame during gameplay. It reads player stats directly from SRAM and WRAM and draws them to the VRAM buffer for the top of the screen.
|
|
- **Key Drawing Logic:**
|
|
- **Hearts:** `HUD_UpdateHearts` is a loop that draws empty hearts based on `MAXHP` (`$7EF36C`) and then overlays full/partial hearts based on `CURHP` (`$7EF36D`).
|
|
- **Magic Meter:** It reads `MagicPower` (`$7EF36E`) and uses the `MagicTilemap` lookup table to find the correct tiles to display the green bar.
|
|
- **Counters:** It uses a `HexToDecimal` routine to convert the values for Rupees, Bombs, and Arrows into drawable digits.
|
|
- **Equipped Item:** `HUD_UpdateItemBox` reads the currently equipped item index (`$0202`), finds its graphics data in the `HudItems` table, and draws the icon in the top-left box.
|
|
|
|
## 4. Data-Driven Design & Areas for Improvement
|
|
|
|
The entire menu and HUD are heavily data-driven, which is a major strength.
|
|
|
|
- **Graphics:** All item icons for both the menu and HUD are defined in data tables in `menu_gfx_table.asm` and `menu_hud.asm`, not hardcoded.
|
|
- **Item Layout:** The position and SRAM address of every item in the menu are defined in the `Menu_ItemCursorPositions` and `Menu_AddressIndex` tables, allowing the layout to be easily changed.
|
|
- **Text:** Item names, location names, and other text are all stored in data tables in `menu_text.asm` and `menu_map_names.asm`.
|
|
|
|
This analysis confirms the suggestions in the placeholder `Menu.md` file:
|
|
|
|
1. **Refactor Redundant Code:** The input handling logic for the Magic Bag, Song Menu, and Ring Box is nearly identical and is a prime candidate for being refactored into a single, reusable subroutine.
|
|
2. **Use `table` for Jump Tables:** The main `Menu_Entry` jump table is created with manual `dw` directives and would be cleaner and safer if generated with asar's `table` directive.
|
|
3. **Replace Hardcoded Values:** Hardcoded state values (e.g., `LDA.b #$0C : STA.w $0200`) should be replaced with named constants (`!MENU_STATE_MAGIC_BAG = $0C`) for readability and maintainability. |