From 771245615464efcccbfa7c4e5e64ab3d4fb6963c Mon Sep 17 00:00:00 2001 From: scawful Date: Sun, 5 Oct 2025 01:45:19 -0400 Subject: [PATCH] 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. --- assets/agent/alttp_rom_hacking_guide.txt | 99 +++++++++++++++++++++ assets/agent/oracle_of_secrets_guide.txt | 98 +++++++++++++++++++++ assets/agent/system_prompt_v3.txt | 106 +++++++++++++++++++++++ src/cli/service/agent/prompt_manager.cc | 47 ++++++++++ src/cli/service/agent/prompt_manager.h | 29 +++++++ 5 files changed, 379 insertions(+) create mode 100644 assets/agent/alttp_rom_hacking_guide.txt create mode 100644 assets/agent/oracle_of_secrets_guide.txt create mode 100644 src/cli/service/agent/prompt_manager.cc create mode 100644 src/cli/service/agent/prompt_manager.h diff --git a/assets/agent/alttp_rom_hacking_guide.txt b/assets/agent/alttp_rom_hacking_guide.txt new file mode 100644 index 00000000..31d4ddae --- /dev/null +++ b/assets/agent/alttp_rom_hacking_guide.txt @@ -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 diff --git a/assets/agent/oracle_of_secrets_guide.txt b/assets/agent/oracle_of_secrets_guide.txt new file mode 100644 index 00000000..37d286e2 --- /dev/null +++ b/assets/agent/oracle_of_secrets_guide.txt @@ -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 diff --git a/assets/agent/system_prompt_v3.txt b/assets/agent/system_prompt_v3.txt index 18130a66..11c3e0b0 100644 --- a/assets/agent/system_prompt_v3.txt +++ b/assets/agent/system_prompt_v3.txt @@ -205,3 +205,109 @@ BAD response characteristics: - ❌ 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. + +# 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) diff --git a/src/cli/service/agent/prompt_manager.cc b/src/cli/service/agent/prompt_manager.cc new file mode 100644 index 00000000..8d0739bf --- /dev/null +++ b/src/cli/service/agent/prompt_manager.cc @@ -0,0 +1,47 @@ +#include "cli/service/agent/prompt_manager.h" +#include +#include +#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 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 diff --git a/src/cli/service/agent/prompt_manager.h b/src/cli/service/agent/prompt_manager.h new file mode 100644 index 00000000..558b3e0f --- /dev/null +++ b/src/cli/service/agent/prompt_manager.h @@ -0,0 +1,29 @@ +#ifndef YAZE_CLI_SERVICE_AGENT_PROMPT_MANAGER_H_ +#define YAZE_CLI_SERVICE_AGENT_PROMPT_MANAGER_H_ + +#include +#include + +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 GetAvailableModes(); + static const char* ModeToString(PromptMode mode); +}; + +} // namespace agent +} // namespace cli +} // namespace yaze + +#endif // YAZE_CLI_SERVICE_AGENT_PROMPT_MANAGER_H_