Files
yaze/docs/internal/agents/archive/plans-2025-11/emulator-debug-api-design.md

517 lines
15 KiB
Markdown

# Emulator Debug API Design for AI Agent Integration
**Status:** Active
**Owner (Agent ID):** snes-emulator-expert
**Last Updated:** 2025-11-25
**Next Review:** 2025-12-02
**Coordination Board Entry:** link when claimed
## Executive Summary
This document outlines the design for a comprehensive debugging API that enables AI agents to debug Zelda ROM hacks through the yaze emulator. The API provides execution control, memory inspection, disassembly, and analysis capabilities specifically tailored for 65816 and SPC700 debugging.
## Architecture Overview
```
┌──────────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ AI Agent │◄────►│ Tool Dispatcher │◄────►│ gRPC Service │
│ (Claude/GPT) │ │ │ │ │
└──────────────────┘ └─────────────────┘ └──────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Tool Handlers │ │ Emulator Service │
│ │ │ Implementation │
└─────────────────┘ └──────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────┐
│ Debug Infrastructure │
├─────────────────┬───────────────────────┤
│ Disassembler │ Step Controller │
│ Symbol Provider │ Breakpoint Manager │
│ Memory Tracker │ State Snapshots │
└─────────────────┴───────────────────────┘
```
## Phase 1 (MVP) Features
### 1. Execution Control API
```cpp
// Tool Dispatcher Commands
enum class EmulatorDebugTool {
// Basic execution
kDebugRun, // Run until breakpoint or pause
kDebugStep, // Single instruction step
kDebugStepOver, // Step over JSR/JSL calls
kDebugStepOut, // Step out of current subroutine
kDebugPause, // Pause execution
kDebugReset, // Reset to power-on state
// Breakpoint management
kDebugSetBreak, // Set execution breakpoint
kDebugClearBreak, // Clear breakpoint by ID
kDebugListBreaks, // List all breakpoints
kDebugToggleBreak, // Enable/disable breakpoint
};
```
#### Example Tool Call Structure:
```cpp
struct DebugStepRequest {
enum StepType {
SINGLE, // One instruction
OVER, // Step over calls
OUT, // Step out of routine
TO_ADDRESS // Run to specific address
};
StepType type;
uint32_t target_address; // For TO_ADDRESS
uint32_t max_steps; // Timeout protection
};
struct DebugStepResponse {
bool success;
uint32_t pc; // New program counter
uint32_t instruction_count;
DisassembledInstruction current_instruction;
std::vector<std::string> call_stack;
std::string message;
};
```
### 2. Memory Inspection API
```cpp
enum class MemoryDebugTool {
kMemoryRead, // Read memory region
kMemoryWrite, // Write memory (for patching)
kMemoryWatch, // Set memory watchpoint
kMemoryCompare, // Compare two memory regions
kMemorySearch, // Search for byte pattern
kMemorySnapshot, // Save memory state
kMemoryDiff, // Diff against snapshot
};
```
#### Memory Region Types:
```cpp
enum class MemoryRegion {
WRAM, // Work RAM ($7E0000-$7FFFFF)
SRAM, // Save RAM ($700000-$77FFFF)
ROM, // ROM banks ($008000-$FFFFFF)
VRAM, // Video RAM (PPU)
OAM, // Sprite data
CGRAM, // Palette data
APU_RAM, // Audio RAM ($0000-$FFFF in SPC700 space)
};
struct MemoryReadRequest {
MemoryRegion region;
uint32_t address; // 24-bit SNES address
uint32_t size; // Bytes to read
bool as_hex; // Format as hex dump
bool with_symbols; // Include symbol annotations
};
struct MemoryReadResponse {
std::vector<uint8_t> data;
std::string hex_dump;
std::map<uint32_t, std::string> symbols; // Address -> symbol name
std::string interpretation; // AI-friendly interpretation
};
```
### 3. Disassembly API
```cpp
enum class DisassemblyTool {
kDisassemble, // Disassemble at address
kDisassembleRange, // Disassemble N instructions
kDisassembleContext, // Show surrounding code
kFindInstruction, // Search for instruction pattern
kGetCallStack, // Get current call stack
kTraceExecution, // Get execution history
};
```
#### Disassembly Request/Response:
```cpp
struct DisassemblyRequest {
uint32_t address;
uint32_t instruction_count;
uint32_t context_before; // Instructions before target
uint32_t context_after; // Instructions after target
bool include_symbols;
bool include_execution_counts;
bool track_branches; // Show branch targets
};
struct DisassemblyResponse {
struct Line {
uint32_t address;
std::string hex_bytes; // "20 34 80"
std::string mnemonic; // "JSR"
std::string operands; // "$8034"
std::string symbol; // "MainGameLoop"
std::string comment; // "; Initialize game state"
bool is_breakpoint;
bool is_current_pc;
uint32_t execution_count;
uint32_t branch_target; // For jumps/branches
};
std::vector<Line> lines;
std::string formatted_text; // Human-readable disassembly
std::vector<std::string> referenced_symbols;
};
```
### 4. Analysis API
```cpp
enum class AnalysisTool {
kAnalyzeRoutine, // Analyze subroutine behavior
kFindReferences, // Find references to address
kDetectPattern, // Detect common bug patterns
kCompareRom, // Compare with original ROM
kProfileExecution, // Performance profiling
kTrackDataFlow, // Track value propagation
};
```
## Tool Dispatcher Integration
### New Tool Definitions
```cpp
// In tool_dispatcher.h
enum class ToolCallType {
// ... existing tools ...
// Debugger - Execution Control
kDebugRun,
kDebugStep,
kDebugStepOver,
kDebugStepOut,
kDebugRunToAddress,
// Debugger - Breakpoints
kDebugSetBreakpoint,
kDebugSetWatchpoint,
kDebugClearBreakpoint,
kDebugListBreakpoints,
kDebugEnableBreakpoint,
// Debugger - Memory
kDebugReadMemory,
kDebugWriteMemory,
kDebugSearchMemory,
kDebugCompareMemory,
kDebugSnapshotMemory,
// Debugger - Disassembly
kDebugDisassemble,
kDebugGetCallStack,
kDebugGetExecutionTrace,
kDebugFindInstruction,
// Debugger - Analysis
kDebugAnalyzeRoutine,
kDebugFindReferences,
kDebugDetectBugs,
kDebugProfileCode,
};
```
### Tool Handler Implementation
```cpp
class DebuggerToolHandler {
public:
explicit DebuggerToolHandler(EmulatorServiceImpl* service);
absl::StatusOr<ToolResponse> HandleDebugStep(const nlohmann::json& params);
absl::StatusOr<ToolResponse> HandleDebugSetBreakpoint(const nlohmann::json& params);
absl::StatusOr<ToolResponse> HandleDebugDisassemble(const nlohmann::json& params);
absl::StatusOr<ToolResponse> HandleDebugReadMemory(const nlohmann::json& params);
absl::StatusOr<ToolResponse> HandleDebugAnalyze(const nlohmann::json& params);
private:
EmulatorServiceImpl* emulator_service_;
Disassembler65816 disassembler_;
SymbolProvider symbol_provider_;
MemoryAnalyzer analyzer_;
};
```
## Example AI Agent Interactions
### Example 1: Debugging a Crash
**Agent Query:**
```json
{
"tool": "debug_analyze",
"params": {
"problem": "Game crashes when entering dungeon room 15",
"context": {
"room_id": 15,
"entrance_id": 3
}
}
}
```
**System Response:**
```json
{
"analysis": {
"crash_location": {
"address": "0x008A45",
"instruction": "LDA [$00],Y",
"symbol": "LoadRoomHeader+0x15"
},
"cause": "Null pointer dereference",
"explanation": "Direct page location $00 contains $0000, causing invalid long pointer access",
"registers_at_crash": {
"Y": "0x0010",
"DP": "0x1E00",
"$1E00": "0x0000"
},
"suggested_fix": "Check room header pointer before dereferencing",
"call_stack": [
"Module_Dungeon",
"Dungeon_LoadRoom",
"LoadRoomHeader"
]
}
}
```
### Example 2: Step-by-Step Debugging
**Agent Query:**
```json
{
"tool": "debug_step",
"params": {
"type": "over",
"with_context": true,
"show_memory": ["$7E0010", "$7E0012"]
}
}
```
**Response:**
```json
{
"pc_before": "0x008034",
"pc_after": "0x008037",
"instruction_executed": {
"address": "0x008034",
"mnemonic": "JSR",
"operand": "$8520",
"symbol": "UpdateSprites",
"cycles": 6
},
"context": {
"before": [
{"address": "0x008031", "instruction": "LDA $10", "value": "0x07"}
],
"after": [
{"address": "0x008037", "instruction": "BEQ $8045"}
]
},
"memory_values": {
"$7E0010": "0x07",
"$7E0012": "0x00"
},
"call_depth": 2
}
```
### Example 3: Finding Bug Patterns
**Agent Query:**
```json
{
"tool": "debug_detect_bugs",
"params": {
"patterns": ["stack_overflow", "invalid_bank", "dma_collision"],
"range": {
"start": "0x008000",
"end": "0x00FFFF"
}
}
}
```
**Response:**
```json
{
"bugs_found": [
{
"type": "potential_stack_overflow",
"location": "0x009A23",
"description": "Recursive JSR without stack check",
"severity": "high",
"suggestion": "Add stack pointer validation before recursive call"
},
{
"type": "invalid_bank_switch",
"location": "0x00B456",
"description": "PHB without corresponding PLB",
"severity": "medium",
"suggestion": "Ensure data bank is restored after operation"
}
]
}
```
### Example 4: Memory Watchpoint
**Agent Query:**
```json
{
"tool": "debug_set_watchpoint",
"params": {
"address": "0x7E0020",
"size": 2,
"type": "write",
"condition": "value > 0x00FF",
"description": "Monitor game state overflow"
}
}
```
**Response:**
```json
{
"watchpoint_id": 5,
"status": "active",
"message": "Watchpoint set on $7E0020-$7E0021 for writes > 0x00FF"
}
```
## Phase 2 (Full) Features
### Advanced Analysis
- **Control Flow Graphs**: Generate CFG for routines
- **Data Flow Analysis**: Track value propagation through code
- **Symbolic Execution**: Analyze possible execution paths
- **Pattern Matching**: Detect specific code patterns (e.g., DMA setup, HDMA tables)
- **Performance Profiling**: Cycle-accurate performance analysis
### Enhanced Debugging
- **Conditional Breakpoints**: Complex expressions (e.g., "A > 0x10 && X == 0")
- **Trace Recording**: Record full execution traces to file
- **Reverse Debugging**: Step backwards through recorded execution
- **Memory Diffing**: Visual diff between memory states
- **SPC700 Debugging**: Full audio processor debugging support
### AI-Specific Features
- **Semantic Analysis**: Understanding game logic from assembly
- **Bug Pattern Database**: ML-trained bug detection
- **Automated Fix Suggestions**: Propose assembly patches for bugs
- **Test Case Generation**: Generate test scenarios for ROM hacks
- **Documentation Generation**: Auto-document assembly routines
## Implementation Priority
### Phase 1A (Immediate - Week 1-2)
1. Basic step control (single, over, out)
2. Simple breakpoints (address-based)
3. Memory read/write operations
4. Basic disassembly at address
### Phase 1B (Short-term - Week 3-4)
1. Call stack tracking
2. Symbol resolution
3. Memory watchpoints
4. Execution trace (last N instructions)
### Phase 1C (Medium-term - Week 5-6)
1. Pattern-based bug detection
2. Memory snapshots and comparison
3. Advanced breakpoint conditions
4. Performance metrics
### Phase 2 (Long-term - Month 2+)
1. Full analysis suite
2. SPC700 debugging
3. Reverse debugging
4. AI-specific enhancements
## Success Metrics
### Technical Metrics
- Response time < 100ms for step operations
- Support for 100+ simultaneous breakpoints without performance impact
- Accurate disassembly for 100% of valid 65816 opcodes
- Symbol resolution for all loaded ASM files
### User Experience Metrics
- AI agents can identify crash causes in < 5 interactions
- Step debugging provides sufficient context without overwhelming
- Memory inspection clearly shows relevant game state
- Bug detection has < 10% false positive rate
## Integration Points
### With Existing yaze Components
- **Rom Class**: Read-only access to ROM data
- **Emulator Core**: Direct CPU/PPU/APU state access
- **Symbol Files**: Integration with usdasm output
- **Canvas System**: Visual debugging overlays (Phase 2)
### With AI Infrastructure
- **Tool Dispatcher**: Seamless tool call routing
- **Prompt Builder**: Context-aware debugging prompts
- **Agent Memory**: Persistent debugging session state
- **Response Formatter**: Human-readable debug output
## Security Considerations
1. **Read-Only by Default**: Prevent accidental ROM corruption
2. **Sandboxed Execution**: Limit memory access to emulated space
3. **Rate Limiting**: Prevent runaway debugging loops
4. **Audit Logging**: Track all debugging operations
5. **Session Isolation**: Separate debug sessions per agent
## Testing Strategy
### Unit Tests
- Disassembler accuracy for all opcodes
- Step controller call stack tracking
- Breakpoint manager hit detection
- Symbol provider resolution
### Integration Tests
- Full debugging session workflows
- gRPC service communication
- Tool dispatcher routing
- Memory state consistency
### End-to-End Tests
- AI agent debugging scenarios
- Bug detection accuracy
- Performance under load
- Error recovery paths
## Documentation Requirements
1. **API Reference**: Complete gRPC service documentation
2. **Tool Guide**: How to use each debugging tool
3. **Assembly Primer**: 65816 basics for AI agents
4. **Common Patterns**: Debugging patterns for Zelda3
5. **Troubleshooting**: Common issues and solutions
## Conclusion
This debugging API design provides a comprehensive foundation for AI agents to effectively debug SNES ROM hacks. The phased approach ensures quick delivery of core features while building toward advanced analysis capabilities. The integration with existing yaze infrastructure and focus on 65816-specific debugging makes this a powerful tool for ROM hacking assistance.
The API balances technical depth with usability, providing both low-level control for precise debugging and high-level analysis for pattern recognition. This enables AI agents to assist with everything from simple crash debugging to complex performance optimization.