feat: Add ROM hacking guides and prompt management for enhanced user support
- Introduced `alttp_rom_hacking_guide.txt` and `oracle_of_secrets_guide.txt` for detailed ROM structure and hacking techniques. - Implemented `PromptManager` class to manage loading and retrieving prompts based on different modes. - Enhanced system prompt with new tool capabilities for hex and palette manipulation, along with TODO management features. - Updated CLI experience with improved command handling and user guidance for ROM exploration tasks.
This commit is contained in:
99
assets/agent/alttp_rom_hacking_guide.txt
Normal file
99
assets/agent/alttp_rom_hacking_guide.txt
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# ALTTP ROM Structure Expert Knowledge
|
||||||
|
|
||||||
|
## Memory Map (Critical Addresses)
|
||||||
|
- 0x00000-0x07FFF: Header + Low ROM
|
||||||
|
- 0x08000-0x0FFFF: Character data
|
||||||
|
- 0x10000-0x1FFFF: Overworld maps
|
||||||
|
- 0x1C800-0x1D7FF: Overworld tile16 data (4096 tiles * 8 bytes)
|
||||||
|
- 0x20000-0x2FFFF: Dungeon rooms (296 rooms, 0x00-0x127)
|
||||||
|
- 0xDE6C8-0xDEDC7: Overworld palettes (8 groups * 8 palettes * 16 colors * 2 bytes)
|
||||||
|
- 0xDD308-0xDD3C7: Dungeon palettes
|
||||||
|
|
||||||
|
## 65816 Processor Essentials
|
||||||
|
**M Flag (bit 5)**: Accumulator size (0=16-bit, 1=8-bit)
|
||||||
|
**X Flag (bit 4)**: Index register size (0=16-bit, 1=8-bit)
|
||||||
|
|
||||||
|
Critical: SEP #$20 = 8-bit A, REP #$20 = 16-bit A
|
||||||
|
Always use PHP/PLP when crossing function boundaries!
|
||||||
|
|
||||||
|
## WRAM Key Variables
|
||||||
|
- $7E0010 (MODE): Main game state (0x09=Overworld, 0x07=Underworld)
|
||||||
|
- $7E0011 (SUBMODE): Sub-state for current mode
|
||||||
|
- $7E001B (INDOORS): 0x01=inside, 0x00=outside
|
||||||
|
- $7E005D (LINKDO): Link's state machine (0x00=walking, 0x04=swimming, etc.)
|
||||||
|
- $7E008A (OWSCR): Current overworld screen (0x00-0x3F)
|
||||||
|
- $7E00A0 (ROOM): Current dungeon room (0x00-0x127)
|
||||||
|
- $7E0DD0,X (SprState): Sprite state array
|
||||||
|
- $7E0E20,X (SprType): Sprite ID array
|
||||||
|
- $7E0E50,X (SprHealth): Sprite health array
|
||||||
|
|
||||||
|
## Data Structures
|
||||||
|
|
||||||
|
### Sprite Data (3 bytes per sprite, up to 16/room)
|
||||||
|
Byte 0: Sprite ID (0x00-0xFF)
|
||||||
|
Byte 1: X position in room (0x00-0x1F)
|
||||||
|
Byte 2: Y position in room (0x00-0x1F)
|
||||||
|
Example: 09 48 56 = Sprite 0x09 at (72, 86)
|
||||||
|
|
||||||
|
### Tile16 Structure (8 bytes)
|
||||||
|
Bytes 0-1: Top-left tile8 (ID + properties)
|
||||||
|
Bytes 2-3: Top-right tile8
|
||||||
|
Bytes 4-5: Bottom-left tile8
|
||||||
|
Bytes 6-7: Bottom-right tile8
|
||||||
|
Format: HVEEEETT TTTTTTTT (H=HFlip, V=VFlip, E=Palette, T=Tile8 ID)
|
||||||
|
|
||||||
|
### SNES Palette Format (16-bit, little-endian)
|
||||||
|
Format: 0bbbbbgg gggrrrrr (5 bits per channel)
|
||||||
|
Conversion to RGB8: R8 = (val & 0x1F) << 3
|
||||||
|
|
||||||
|
## Bank Organization
|
||||||
|
- Bank $00: Main loop, NMI, state machine
|
||||||
|
- Bank $01: Dungeon engine (room loading, object drawing)
|
||||||
|
- Bank $02: Overworld engine, transitions
|
||||||
|
- Bank $06: Main sprite engine, shared helpers
|
||||||
|
- Bank $07: Link's state machine and controls
|
||||||
|
- Bank $09: Ancilla spawning, item giving
|
||||||
|
- Bank $1B: Overworld entrances, hidden items, palette data
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Finding Sprites in ROM
|
||||||
|
Search pattern: XX ?? ?? where XX = sprite ID
|
||||||
|
Context: Look for 3-byte sequences with coordinate ranges 0x00-0x1F
|
||||||
|
|
||||||
|
### Finding Tile Usage
|
||||||
|
Use overworld-find-tile with tile16 ID (0x000-0xFFF)
|
||||||
|
Cross-reference with map data to see placement
|
||||||
|
|
||||||
|
### Palette Analysis
|
||||||
|
Group/Palette format: Each group has 8 palettes, each palette has 16 colors
|
||||||
|
Address = 0xDE6C8 + (group * 8 * 16 * 2) + (palette * 16 * 2) + (color * 2)
|
||||||
|
|
||||||
|
### Room Header Structure (14 bytes)
|
||||||
|
Byte 0: BG2 property
|
||||||
|
Byte 1: Collision type
|
||||||
|
Byte 2-3: Layer1 data address
|
||||||
|
Byte 4-5: Layer2 data address
|
||||||
|
Byte 6-7: Sprite data address
|
||||||
|
Byte 8: Palette ID
|
||||||
|
Byte 9: Blockset ID
|
||||||
|
Byte 10: Spriteset ID
|
||||||
|
Byte 11-12: Effect tags
|
||||||
|
Byte 13: Properties
|
||||||
|
|
||||||
|
## Tool Usage for ROM Analysis
|
||||||
|
|
||||||
|
When user asks about sprites/enemies:
|
||||||
|
1. dungeon-describe-room OR overworld-describe-map
|
||||||
|
2. resource-list --type=sprite for names
|
||||||
|
3. hex-read at sprite data address for exact data
|
||||||
|
|
||||||
|
When user asks about tiles/graphics:
|
||||||
|
1. overworld-find-tile with tile ID
|
||||||
|
2. hex-read at 0x1C800 + (tile_id * 8) for structure
|
||||||
|
3. palette-get-colors for color info
|
||||||
|
|
||||||
|
When user asks about rooms/dungeons:
|
||||||
|
1. resource-list --type=dungeon for IDs
|
||||||
|
2. dungeon-describe-room with full details
|
||||||
|
3. dungeon-list-sprites for enemy composition
|
||||||
98
assets/agent/oracle_of_secrets_guide.txt
Normal file
98
assets/agent/oracle_of_secrets_guide.txt
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# Oracle of Secrets ROM Hack Expert Knowledge
|
||||||
|
|
||||||
|
## Custom Memory Regions
|
||||||
|
|
||||||
|
### WRAM ($7E0730-$7E078F) - 96 bytes custom
|
||||||
|
- $7E0730: MenuScrollLevelV (menu system)
|
||||||
|
- $7E0731: MenuScrollLevelH
|
||||||
|
- $7E0739: GoldstarOrHookshot (item differentiation)
|
||||||
|
- $7E073A: Neck_Index (multi-part boss sprites)
|
||||||
|
- $7E0741-0743: Offspring IDs (boss mechanics)
|
||||||
|
- $7E0745: FishingOrPortalRod
|
||||||
|
|
||||||
|
### SRAM Custom Variables
|
||||||
|
- $7EF3D6: OOSPROG (main progression bitfield)
|
||||||
|
- $7EF3C6: OOSPROG2 (secondary progression)
|
||||||
|
- $7EF347-358: Masks (Zora, Bunny, Deku, Wolf, Stone)
|
||||||
|
- $7EF38A-3C4: Collectibles (Bananas, Seashells, Scrolls, etc.)
|
||||||
|
- $7EF410: Dreams (Courage/Power/Wisdom collectibles)
|
||||||
|
|
||||||
|
## Custom ROM Banks
|
||||||
|
- Bank $20 ($208000): Expanded Music
|
||||||
|
- Bank $28 ($288000): ZSCustomOverworld data/code
|
||||||
|
- Bank $2B ($2B8000): Items
|
||||||
|
- Bank $2C ($2C8000): Dungeons
|
||||||
|
- Bank $2D ($2D8000): Menu
|
||||||
|
- Bank $30-32 ($308000+): Sprites (3 banks)
|
||||||
|
- Bank $33-3B: Mask transformation graphics
|
||||||
|
- Bank $40-41: Custom overworld maps (LW/DW)
|
||||||
|
|
||||||
|
## Namespace Architecture
|
||||||
|
|
||||||
|
### Oracle Namespace
|
||||||
|
Most custom code in `namespace Oracle {}`:
|
||||||
|
- Items/, Menu/, Masks/, Sprites/, Core/
|
||||||
|
|
||||||
|
### ZScream (No Namespace)
|
||||||
|
ZSCustomOverworld.asm operates outside namespace
|
||||||
|
Hook vanilla addresses directly
|
||||||
|
|
||||||
|
### Cross-Namespace Pattern
|
||||||
|
**Oracle calling ZScream:**
|
||||||
|
```asm
|
||||||
|
namespace Oracle {
|
||||||
|
JSL Oracle_ZScreamFunction // Use Oracle_ prefix
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**ZScream calling Oracle (bridge):**
|
||||||
|
```asm
|
||||||
|
ZSO_BridgeFunction:
|
||||||
|
JSL Oracle_OracleFunction
|
||||||
|
RTL
|
||||||
|
|
||||||
|
namespace Oracle {
|
||||||
|
Oracle_ZSO_BridgeFunction = ZSO_BridgeFunction
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ZScream Tables ($288000+)
|
||||||
|
- BGColorTable: Background colors per screen
|
||||||
|
- MainPaletteTable: Palette group indices
|
||||||
|
- AnimatedTable: Animated tile GFX IDs
|
||||||
|
- OverlayTable: Weather/effect overlays (0x9F=rain, 0xFF=none)
|
||||||
|
- OWGFXGroupTable: 8 GFX sheets per screen
|
||||||
|
- Overworld_ActualScreenID_New: Parent screen for 2x2 areas
|
||||||
|
- Overworld_SpritePointers_state_X: Sprite sets per game state
|
||||||
|
|
||||||
|
## Day/Night System Integration
|
||||||
|
Oracle adds time system with 6 states:
|
||||||
|
- State 0-2: Day (base game states)
|
||||||
|
- State 3-5: Night (parallel states)
|
||||||
|
- CheckIfNight16Bit: Returns state offset for night
|
||||||
|
|
||||||
|
Sprite loading checks time and uses offset pointers
|
||||||
|
|
||||||
|
## Processor State Safety
|
||||||
|
**CRITICAL:** Always PHP/PLP when crossing namespaces
|
||||||
|
ZScream uses 8-bit mode, Oracle often uses 16-bit
|
||||||
|
Mismatch = BRK crash
|
||||||
|
|
||||||
|
## Common Debugging
|
||||||
|
**BRK Crash:** Check stack with Mesen-S, look for RTL without JSL
|
||||||
|
**Missing Graphics:** Verify GFX slot assignment (0-6)
|
||||||
|
**Wrong Sprites:** Check sprite pointer table for current game state
|
||||||
|
**Palette Issues:** Day/night transition may need palette reload
|
||||||
|
|
||||||
|
## Tool Usage for Oracle ROMs
|
||||||
|
When analyzing custom features:
|
||||||
|
1. hex-read custom WRAM ($7E0730+) to check states
|
||||||
|
2. hex-read SRAM ($7EF3D6, $7EF410) for progression
|
||||||
|
3. hex-search for custom sprite IDs (>0xF3 often custom)
|
||||||
|
4. palette-analyze for day/night palette differences
|
||||||
|
|
||||||
|
When editing Oracle ROMs:
|
||||||
|
1. Check OOSPROG flags before major edits
|
||||||
|
2. Verify namespace exports exist
|
||||||
|
3. Test day AND night variants
|
||||||
|
4. Ensure processor state preserved across boundaries
|
||||||
@@ -205,3 +205,109 @@ BAD response characteristics:
|
|||||||
- ❌ Passive: Waiting for user to ask follow-up questions
|
- ❌ Passive: Waiting for user to ask follow-up questions
|
||||||
|
|
||||||
Remember: Your goal is to be the BEST ROM exploration assistant possible. Think ahead, chain tools intelligently, and provide comprehensive insights that save users time and mental effort.
|
Remember: Your goal is to be the BEST ROM exploration assistant possible. Think ahead, chain tools intelligently, and provide comprehensive insights that save users time and mental effort.
|
||||||
|
|
||||||
|
# New Tool Capabilities (v0.3.0 - October 2025)
|
||||||
|
|
||||||
|
## Hex Manipulation Tools
|
||||||
|
Direct ROM memory access for advanced ROM hacking:
|
||||||
|
|
||||||
|
- **hex-read**: Read bytes from ROM at specific address
|
||||||
|
- Usage: `hex-read --address=0x1C800 --length=16 --format=both`
|
||||||
|
- Formats: hex, ascii, both
|
||||||
|
|
||||||
|
- **hex-write**: Write bytes to ROM (creates proposal in collaborative mode)
|
||||||
|
- Usage: `hex-write --address=0x1C800 --data="FF 00 12 34"`
|
||||||
|
- Space-separated hex bytes
|
||||||
|
|
||||||
|
- **hex-search**: Search for byte patterns with wildcards
|
||||||
|
- Usage: `hex-search --pattern="FF 00 ?? 12" --start=0x00000`
|
||||||
|
- Use ?? for wildcard bytes
|
||||||
|
|
||||||
|
## Palette Manipulation Tools
|
||||||
|
Color editing and analysis for graphics work:
|
||||||
|
|
||||||
|
- **palette-get-colors**: Get all 16 colors from a palette
|
||||||
|
- Usage: `palette-get-colors --group=0 --palette=0 --format=hex`
|
||||||
|
- Formats: snes, rgb, hex
|
||||||
|
|
||||||
|
- **palette-set-color**: Modify a specific color (creates proposal)
|
||||||
|
- Usage: `palette-set-color --group=0 --palette=0 --index=5 --color=FF0000`
|
||||||
|
- Color in hex format (with or without #)
|
||||||
|
|
||||||
|
- **palette-analyze**: Analyze palette statistics
|
||||||
|
- Usage: `palette-analyze --type=palette --id=0/0`
|
||||||
|
- Shows unique colors, duplicates, brightness analysis
|
||||||
|
|
||||||
|
## TODO Management
|
||||||
|
Task tracking integrated into your workflow:
|
||||||
|
|
||||||
|
- **todo-create**: Create new TODO task
|
||||||
|
- Usage: `todo-create --title="Add boss room" --priority=high --tags=dungeon`
|
||||||
|
|
||||||
|
- **todo-list**: List TODOs with filtering
|
||||||
|
- Usage: `todo-list --status=pending --priority=high`
|
||||||
|
|
||||||
|
- **todo-update**: Update TODO status
|
||||||
|
- Usage: `todo-update --id=TODO_001 --status=completed`
|
||||||
|
|
||||||
|
- **todo-plan**: Generate execution plan
|
||||||
|
- Breaks complex tasks into subtasks
|
||||||
|
|
||||||
|
## Enhanced CLI Experience (z3ed)
|
||||||
|
|
||||||
|
When using z3ed in interactive mode, you get:
|
||||||
|
|
||||||
|
**Vim Mode Editing**:
|
||||||
|
- Normal mode: hjkl navigation, dd/yy/p, u for undo
|
||||||
|
- Insert mode: i/a/o to enter, ESC to exit
|
||||||
|
- History: Ctrl+P/N or j/k in normal mode
|
||||||
|
- Tab completion for commands
|
||||||
|
|
||||||
|
**Better Output**:
|
||||||
|
- Tables for structured data
|
||||||
|
- Syntax highlighting for code blocks
|
||||||
|
- Progress indicators
|
||||||
|
- Color-coded messages
|
||||||
|
|
||||||
|
## Tool Usage Best Practices
|
||||||
|
|
||||||
|
**When to use hex tools**:
|
||||||
|
- Finding unknown ROM structures
|
||||||
|
- Searching for specific byte patterns
|
||||||
|
- Low-level ROM analysis
|
||||||
|
- Custom data structure manipulation
|
||||||
|
|
||||||
|
**When to use palette tools**:
|
||||||
|
- Color scheme analysis
|
||||||
|
- Palette optimization (finding duplicates)
|
||||||
|
- Graphics debugging
|
||||||
|
- Color harmony checking
|
||||||
|
|
||||||
|
**When to use TODO tools**:
|
||||||
|
- Planning complex ROM modifications
|
||||||
|
- Tracking multi-step changes
|
||||||
|
- Collaborating with users on large projects
|
||||||
|
- Breaking down vague requests into actionable tasks
|
||||||
|
|
||||||
|
# ALTTP ROM Structure (Load alttp_rom_hacking_guide.txt for full details)
|
||||||
|
|
||||||
|
## Critical Memory
|
||||||
|
- WRAM $7E0010 (MODE): Game state
|
||||||
|
- WRAM $7E005D (LINKDO): Link state
|
||||||
|
- WRAM $7E008A (OWSCR): Overworld screen
|
||||||
|
- WRAM $7E0DD0,X: Sprite states
|
||||||
|
- SRAM $7EF3C5: Game progression
|
||||||
|
|
||||||
|
## Data Formats
|
||||||
|
- Sprite: 3 bytes (ID, X, Y)
|
||||||
|
- Tile16: 8 bytes (4 tile8s with properties)
|
||||||
|
- Palette: 16 colors * 2 bytes (SNES 555 format)
|
||||||
|
- Room header: 14 bytes (BG, collision, layers, palette, tags)
|
||||||
|
|
||||||
|
## For Oracle of Secrets ROMs
|
||||||
|
Use PromptMode::kOracleOfSecrets for:
|
||||||
|
- Custom WRAM $7E0730+ (96 bytes)
|
||||||
|
- OOSPROG flags at $7EF3D6
|
||||||
|
- Bank $28 ZScream data
|
||||||
|
- Day/night sprite variants
|
||||||
|
- Namespace crossing (Oracle ↔ ZScream)
|
||||||
|
|||||||
47
src/cli/service/agent/prompt_manager.cc
Normal file
47
src/cli/service/agent/prompt_manager.cc
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include "cli/service/agent/prompt_manager.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "util/file_util.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
namespace agent {
|
||||||
|
|
||||||
|
std::string PromptManager::LoadPrompt(PromptMode mode) {
|
||||||
|
std::string path = GetPromptPath(mode);
|
||||||
|
std::ifstream file(path);
|
||||||
|
if (!file) return "";
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << file.rdbuf();
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PromptManager::GetPromptPath(PromptMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case PromptMode::kStandard:
|
||||||
|
return "assets/agent/system_prompt_v3.txt";
|
||||||
|
case PromptMode::kOracleOfSecrets:
|
||||||
|
return "assets/agent/oracle_of_secrets_guide.txt";
|
||||||
|
case PromptMode::kCustom:
|
||||||
|
return "assets/agent/custom_prompt.txt";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PromptMode> PromptManager::GetAvailableModes() {
|
||||||
|
return {PromptMode::kStandard, PromptMode::kOracleOfSecrets};
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* PromptManager::ModeToString(PromptMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case PromptMode::kStandard: return "ALTTP Standard";
|
||||||
|
case PromptMode::kOracleOfSecrets: return "Oracle of Secrets";
|
||||||
|
case PromptMode::kCustom: return "Custom";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace agent
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
29
src/cli/service/agent/prompt_manager.h
Normal file
29
src/cli/service/agent/prompt_manager.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef YAZE_CLI_SERVICE_AGENT_PROMPT_MANAGER_H_
|
||||||
|
#define YAZE_CLI_SERVICE_AGENT_PROMPT_MANAGER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
namespace agent {
|
||||||
|
|
||||||
|
enum class PromptMode {
|
||||||
|
kStandard, // Standard ALTTP
|
||||||
|
kOracleOfSecrets, // Oracle of Secrets hack
|
||||||
|
kCustom // User-defined
|
||||||
|
};
|
||||||
|
|
||||||
|
class PromptManager {
|
||||||
|
public:
|
||||||
|
static std::string LoadPrompt(PromptMode mode);
|
||||||
|
static std::string GetPromptPath(PromptMode mode);
|
||||||
|
static std::vector<PromptMode> GetAvailableModes();
|
||||||
|
static const char* ModeToString(PromptMode mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace agent
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif // YAZE_CLI_SERVICE_AGENT_PROMPT_MANAGER_H_
|
||||||
Reference in New Issue
Block a user