235 lines
9.1 KiB
Markdown
235 lines
9.1 KiB
Markdown
# AI Infrastructure Improvements Plan
|
|
|
|
**Status:** Active
|
|
**Owner (Agent ID):** ai-infra-architect
|
|
**Branch:** `feature/ai-infra-improvements`
|
|
**Created:** 2025-11-21
|
|
**Last Updated:** 2025-11-25
|
|
**Next Review:** 2025-12-02
|
|
**Coordination Board Entry:** link when claimed
|
|
|
|
## Overview
|
|
|
|
This document outlines the gaps in yaze's AI infrastructure (gRPC services, MCP integration) and the planned improvements to make yaze-mcp fully functional for AI-assisted SNES ROM hacking.
|
|
|
|
## Current State Analysis
|
|
|
|
### yaze-mcp Tools (28 Emulator + 10 ROM = 38 total)
|
|
|
|
| Category | Tools | Status |
|
|
|----------|-------|--------|
|
|
| Emulator Lifecycle | pause, resume, reset | Working |
|
|
| Execution Control | step_instruction, run_to_breakpoint | Working |
|
|
| Execution Control | step_over, step_out | Partial (step_over falls back to single-step) |
|
|
| Memory | read_memory, write_memory, get_game_state | Working |
|
|
| Breakpoints | add/remove/list/toggle | Working (execute only during emulation) |
|
|
| Watchpoints | add/remove/list/history | NOT WIRED (only called from RPC handlers) |
|
|
| Disassembly | get_disassembly | Partial (returns OPCODE_XX placeholders) |
|
|
| Tracing | get_execution_trace | BROKEN (returns FAILED_PRECONDITION) |
|
|
| Symbols | load/resolve/get_symbol_at | DISABLED (ASAR integration disabled) |
|
|
| ROM Basic | get_rom_info, read_rom_bytes | Working |
|
|
| ROM Advanced | overworld/dungeon/sprite reads | NOT IMPLEMENTED (stubs return errors) |
|
|
| ROM Versioning | create/list snapshots | Working |
|
|
| Input | press_buttons | Working |
|
|
|
|
### Critical Gaps
|
|
|
|
1. **gRPC Server Not Started** - `AgentControlServer` exists but is never instantiated
|
|
2. **Watchpoints Bypass Emulation** - Only triggered by RPC read/write, not CPU bus activity
|
|
3. **Disassembly Uses Placeholders** - No proper 65816 disassembler integration
|
|
4. **Execution Trace Not Buffered** - No ring buffer for instruction history
|
|
5. **Symbols Disabled** - ASAR integration commented out
|
|
6. **ROM Domain RPCs Stubbed** - Overworld/dungeon/sprite return "not yet implemented"
|
|
|
|
## Implementation Plan
|
|
|
|
### Phase 1: gRPC Server Hosting (Priority: Critical)
|
|
|
|
**Goal:** Stand up a unified gRPC server that registers EmulatorService + RomService
|
|
|
|
**Files to Modify:**
|
|
- `src/app/editor/editor_manager.cc` - Start AgentControlServer when YAZE_ENABLE_REMOTE_AUTOMATION
|
|
- `src/cli/service/agent/agent_control_server.cc` - Register both EmulatorService and RomService
|
|
- `src/app/service/unified_grpc_server.cc` - Consider merging with AgentControlServer
|
|
|
|
**Tasks:**
|
|
- [ ] Add `StartAgentServer()` method to EditorManager
|
|
- [ ] Wire startup to `YAZE_ENABLE_REMOTE_AUTOMATION` flag or `--enable-grpc` CLI flag
|
|
- [ ] Register EmulatorService and RomService on same server
|
|
- [ ] Add configurable port (default 50051)
|
|
- [ ] Test with yaze-mcp `check_status`
|
|
|
|
### Phase 2: Emulator Debug RPCs (Priority: High)
|
|
|
|
**Goal:** Flesh out disassembly, execution trace, and stepping
|
|
|
|
**2a. Proper Disassembly**
|
|
- Use DisassemblyViewer's existing instruction recording
|
|
- Or integrate a standalone 65816 disassembler (bsnes style)
|
|
- File: `src/cli/service/agent/emulator_service_impl.cc` lines 661-705
|
|
|
|
**2b. Execution Trace Buffer**
|
|
- Add ring buffer (1000-10000 entries) to DisassemblyViewer
|
|
- Record: address, opcode, operands, cycle count, register snapshot
|
|
- File: `src/app/emu/debug/disassembly_viewer.h`
|
|
|
|
**2c. StepOver Implementation**
|
|
- Detect JSR (0x20) and JSL (0x22) opcodes
|
|
- Set temporary breakpoint at return address (PC + instruction length)
|
|
- Run until breakpoint hit, then remove temporary BP
|
|
- File: `src/cli/service/agent/emulator_service_impl.cc` lines 598-607
|
|
|
|
**Tasks:**
|
|
- [ ] Integrate real 65816 disassembly into GetDisassembly RPC
|
|
- [ ] Add ExecutionTraceBuffer class with ring buffer
|
|
- [ ] Implement GetExecutionTrace from buffer
|
|
- [ ] Implement proper StepOver with JSR/JSL detection
|
|
|
|
### Phase 3: Breakpoint/Watchpoint Memory Integration (Priority: High)
|
|
|
|
**Goal:** Wire memory breakpoints and watchpoints into emulator memory bus
|
|
|
|
**Current State:**
|
|
- `BreakpointManager::ShouldBreakOnExecute()` IS called via CPU callback
|
|
- `BreakpointManager::ShouldBreakOnMemoryAccess()` IS NOT called during emulation
|
|
- `WatchpointManager::OnMemoryAccess()` IS NOT called during emulation
|
|
|
|
**Files to Modify:**
|
|
- `src/app/emu/snes.h` - Add read/write callbacks
|
|
- `src/app/emu/snes.cc` - Invoke breakpoint/watchpoint managers in CpuRead/CpuWrite
|
|
- `src/app/emu/emulator.cc` - Wire managers to callbacks
|
|
|
|
**Implementation:**
|
|
```cpp
|
|
// In Snes::CpuRead() or via callback:
|
|
if (debugging_enabled_) {
|
|
if (breakpoint_manager_.ShouldBreakOnMemoryAccess(addr, BreakpointManager::AccessType::READ)) {
|
|
running_ = false;
|
|
}
|
|
watchpoint_manager_.OnMemoryAccess(addr, /*is_write=*/false, value);
|
|
}
|
|
|
|
// In Snes::CpuWrite() or via callback:
|
|
if (debugging_enabled_) {
|
|
if (breakpoint_manager_.ShouldBreakOnMemoryAccess(addr, BreakpointManager::AccessType::WRITE)) {
|
|
running_ = false;
|
|
}
|
|
watchpoint_manager_.OnMemoryAccess(addr, /*is_write=*/true, value);
|
|
}
|
|
```
|
|
|
|
**Tasks:**
|
|
- [ ] Add `on_memory_read_` and `on_memory_write_` callbacks to CPU
|
|
- [ ] Invoke BreakpointManager from callbacks
|
|
- [ ] Invoke WatchpointManager from callbacks
|
|
- [ ] Add MCP tools for watchpoints: `add_watchpoint`, `list_watchpoints`, `get_watchpoint_history`
|
|
- [ ] Test memory breakpoints and watchpoints with yaze-mcp
|
|
|
|
### Phase 4: Symbol Loading & Resolution (Priority: Medium)
|
|
|
|
**Goal:** Load ASAR/WLA-DX/CA65 symbol files and enable label resolution
|
|
|
|
**Current State:**
|
|
- EmulatorServiceImpl has stubbed symbol methods returning "not available"
|
|
- ASAR wrapper exists in `src/core/asar_wrapper.h`
|
|
|
|
**Implementation Approach:**
|
|
1. Create `SymbolTable` class to store symbols (name -> address map)
|
|
2. Implement parsers for each format:
|
|
- ASAR: `.sym` files with `label = $XXXXXX` format
|
|
- WLA-DX: `.sym` files with different format
|
|
- CA65: `.dbg` or `.map` files
|
|
- Mesen: `.mlb` label files
|
|
3. Wire LoadSymbols RPC to parse and populate SymbolTable
|
|
4. Wire ResolveSymbol/GetSymbolAt to query SymbolTable
|
|
|
|
**Files to Create:**
|
|
- `src/app/emu/debug/symbol_table.h`
|
|
- `src/app/emu/debug/symbol_table.cc`
|
|
- `src/app/emu/debug/symbol_parser.h` - Format parsers
|
|
|
|
**Tasks:**
|
|
- [ ] Design SymbolTable class (bidirectional lookup)
|
|
- [ ] Implement ASAR .sym parser
|
|
- [ ] Implement WLA-DX parser
|
|
- [ ] Wire to EmulatorServiceImpl
|
|
- [ ] Test with Oracle of Secrets symbols
|
|
|
|
### Phase 5: ROM Domain RPCs (Priority: Medium)
|
|
|
|
**Goal:** Implement overworld/dungeon/sprite read/write RPCs
|
|
|
|
**Current State:**
|
|
- All domain RPCs return "not yet implemented"
|
|
- ROM class has raw access, but not structured zelda3 data
|
|
|
|
**Implementation:**
|
|
- Leverage `zelda3::Overworld`, `zelda3::Dungeon`, `zelda3::Sprite` classes
|
|
- Need to instantiate these in RomServiceImpl or get from shared state
|
|
|
|
**Files to Modify:**
|
|
- `src/app/net/rom_service_impl.cc` - Implement ReadOverworldMap, ReadDungeonRoom, ReadSprite
|
|
- Proto messages already defined in `rom_service.proto`
|
|
|
|
**Tasks:**
|
|
- [ ] Add zelda3::Overworld access to RomServiceImpl
|
|
- [ ] Implement ReadOverworldMap (tile16 data for 160 maps)
|
|
- [ ] Implement WriteOverworldTile
|
|
- [ ] Add zelda3::Dungeon access
|
|
- [ ] Implement ReadDungeonRoom (tile16 data for 296 rooms)
|
|
- [ ] Implement WriteDungeonTile
|
|
- [ ] Implement ReadSprite
|
|
|
|
### Phase 6: yaze-mcp Enhancements (Priority: Low)
|
|
|
|
**Goal:** Improve MCP error handling and add missing tools
|
|
|
|
**Tasks:**
|
|
- [ ] Add timeout/retry logic based on gRPC status codes
|
|
- [ ] Add clearer error messages for unimplemented RPCs
|
|
- [ ] Add watchpoint tools to server.py
|
|
- [ ] Document required build preset and port
|
|
- [ ] Add connection health monitoring
|
|
|
|
## File Reference
|
|
|
|
### Emulator Service
|
|
- **Header:** `src/cli/service/agent/emulator_service_impl.h`
|
|
- **Implementation:** `src/cli/service/agent/emulator_service_impl.cc` (822 lines)
|
|
- **Server:** `src/cli/service/agent/agent_control_server.cc`
|
|
|
|
### ROM Service
|
|
- **Header:** `src/app/net/rom_service_impl.h`
|
|
- **Implementation:** `src/app/net/rom_service_impl.cc`
|
|
- **Version Manager:** `src/app/net/rom_version_manager.h`
|
|
|
|
### Debug Managers
|
|
- **Breakpoints:** `src/app/emu/debug/breakpoint_manager.h|cc`
|
|
- **Watchpoints:** `src/app/emu/debug/watchpoint_manager.h|cc`
|
|
- **Disassembly:** `src/app/emu/debug/disassembly_viewer.h`
|
|
|
|
### Emulator Core
|
|
- **Emulator:** `src/app/emu/emulator.h|cc`
|
|
- **SNES:** `src/app/emu/snes.h|cc`
|
|
- **CPU:** `src/app/emu/cpu/cpu.h`
|
|
|
|
### MCP Server
|
|
- **Location:** `/Users/scawful/Code/yaze-mcp/server.py`
|
|
- **Proto Stubs:** `/Users/scawful/Code/yaze-mcp/protos/`
|
|
|
|
## Success Criteria
|
|
|
|
1. **yaze-mcp `check_status`** connects and returns full emulator state
|
|
2. **Memory breakpoints** pause emulation on WRAM/SRAM access
|
|
3. **Watchpoints** track and log all memory accesses in specified ranges
|
|
4. **`get_disassembly`** returns proper 65816 mnemonics
|
|
5. **`get_execution_trace`** returns last N instructions executed
|
|
6. **Symbol loading** works with ASAR output from Oracle of Secrets
|
|
7. **ROM domain RPCs** return structured overworld/dungeon/sprite data
|
|
|
|
## Notes
|
|
|
|
- Consider performance impact of memory access callbacks (may need optimization)
|
|
- May want debug mode toggle to enable/disable expensive instrumentation
|
|
- Future: Canvas automation service for GUI automation via MCP
|