rusty_emu/plans/codebase_analysis.md

589 lines
17 KiB
Markdown

# MCS-4 Emulator Codebase Analysis
## Executive Summary
This document provides a comprehensive analysis of the MCS-4 emulator codebase structure, focusing on GUI, console output, configuration systems, and entry points. The analysis identifies specific locations for implementing ROM/RAM/CPU register display and Ctrl-Q keyboard handling.
---
## 1. GUI Structure Analysis
### 1.1 Framework and Architecture
**Location:** [`src/gui/mod.rs`](src/gui/mod.rs:1-259)
The GUI is built using **eframe/egui** (Rust immediate mode GUI framework):
```rust
use eframe::egui;
```
**Key Structure:**
- [`GuiApp`](src/gui/mod.rs:21-29) - Main GUI application struct
- `system: Option<Arc<Mutex<ConfigurableSystem>>>` - Thread-safe system reference
- `gui_state: state::GuiState` - GUI state management
- `components: components::GuiComponents` - Component container
**Entry Point:** [`run_gui()`](src/gui/mod.rs:234-259) function launches the GUI
### 1.2 State Management
**Location:** [`src/gui/state.rs`](src/gui/state.rs:1-176)
**Key Structures:**
| Structure | Purpose | Location |
|-----------|---------|----------|
| [`GuiState`](src/gui/state.rs:12-29) | Main UI state container | Lines 12-29 |
| [`SystemInfo`](src/gui/state.rs:32-40) | System metadata display | Lines 32-40 |
| [`ComponentStates`](src/gui/state.rs:43-49) | Component running states | Lines 43-49 |
| [`MemoryState`](src/gui/state.rs:52-57) | RAM contents display | Lines 52-57 |
| [`RegisterState`](src/gui/state.rs:60-67) | CPU register display | Lines 60-67 |
**Current State Fields:**
```rust
pub struct MemoryState {
pub ram_contents: Vec<[u8; 4]>, // 4 banks of RAM data
pub selected_bank: usize,
pub selected_address: usize,
}
pub struct RegisterState {
pub accumulator: u8,
pub carry_flag: bool,
pub program_counter: u16,
pub index_registers: [u8; 16], // R0-R15
pub stack_pointer: u8,
}
```
**State Update Method:** [`update_from_system()`](src/gui/state.rs:100-118)
### 1.3 GUI Components
**Location:** [`src/gui/components.rs`](src/gui/components.rs:1-804)
| Component | Purpose | Location |
|-----------|---------|----------|
| [`GuiComponents`](src/gui/components.rs:72-84) | Component container | Lines 72-84 |
| [`ControlPanel`](src/gui/components.rs:180-303) | Start/Stop/Reset buttons | Lines 180-303 |
| [`MemoryViewer`](src/gui/components.rs:305-428) | RAM display | Lines 305-428 |
| [`RegisterViewer`](src/gui/components.rs:430-574) | CPU registers display | Lines 430-574 |
| [`RomLoader`](src/gui/components.rs:576-671) | ROM file loading | Lines 576-671 |
| [`StatusBar`](src/gui/components.rs:673-804) | System status | Lines 673-804 |
**Where to Add ROM Display:**
- Create new `RomViewer` component similar to `MemoryViewer`
- Add to [`GuiComponents`](src/gui/components.rs:72-84) struct
- Render in [`render_gui()`](src/gui/mod.rs:171-185)
### 1.4 Current Display Gaps
**Missing ROM Display:**
- No ROM content viewer exists
- Need to add ROM data retrieval from Intel4001 components
**RAM Display Status:**
- [`MemoryState.ram_contents`](src/gui/state.rs:54) exists but uses placeholder data
- [`update_from_system()`](src/gui/state.rs:100-118) does NOT populate actual RAM data
- Need to add RAM data extraction from Intel4002 components
**CPU Register Status:**
- [`RegisterState`](src/gui/state.rs:60-67) exists with all needed fields
- [`update_from_system()`](src/gui/state.rs:100-118) does NOT populate actual CPU data
- Need to add CPU data extraction from Intel4004 component
---
## 2. Console Output Analysis
### 2.1 Console Interface
**Location:** [`src/gui/console.rs`](src/gui/console.rs:1-515)
**Framework:** ratatui + crossterm (Terminal UI)
**Key Structure:**
```rust
pub struct ConsoleApp {
system: Arc<Mutex<ConfigurableSystem>>,
config: ConsoleConfig,
running: bool,
command_buffer: String,
show_help: bool,
selected_pane: usize,
}
```
### 2.2 Console Configuration
**Location:** [`src/gui/console.rs:35-58`](src/gui/console.rs:35-58)
```rust
pub struct ConsoleConfig {
pub enabled: bool,
pub refresh_rate_ms: u64,
pub show_ram: bool,
pub show_registers: bool,
pub show_system_info: bool,
pub ram_banks_per_row: usize,
pub max_ram_rows: usize,
}
```
**XML Config File:** [`configs/console_config.xml`](configs/console_config.xml:1-45)
### 2.3 Current Console Display
**RAM Display:** [`draw_ram_contents()`](src/gui/console.rs:472-505)
- Currently shows placeholder data (`00` values)
- Does NOT read actual RAM from Intel4002
**CPU Register Display:** [`draw_system_info()`](src/gui/console.rs:401-470)
- Shows placeholder text: "see DEBUG output"
- Does NOT read actual registers from Intel4004
**ROM Display:**
- NOT implemented in console
- Would need new `draw_rom_contents()` method
### 2.4 Input Handling
**Location:** [`handle_key_event()`](src/gui/console.rs:142-202)
Current key bindings:
- `q/Q/Esc` - Quit
- `r/R` - Run/Stop toggle
- `s/S` - Stop
- `h/H` - Help
- `Tab` - Switch panes
- `Enter` - Execute command
**Ctrl-Q NOT currently handled** - Need to add `KeyCode::Char('q')` with Ctrl modifier check
---
## 3. Configuration System Analysis
### 3.1 System Configuration
**Location:** [`src/system_config.rs`](src/system_config.rs:1-629)
**Key Structures:**
| Structure | Purpose | Location |
|-----------|---------|----------|
| [`SystemConfig`](src/system_config.rs:58-67) | JSON system definition | Lines 58-67 |
| [`ComponentConfig`](src/system_config.rs:70-75) | Component configuration enum | Lines 70-75 |
| [`ConfigurableSystem`](src/system_config.rs:362-363) | Runtime system instance | Lines 362-428 |
**Configuration Files:**
- [`configs/mcs4_basic.json`](configs/mcs4_basic.json:1-167) - Basic MCS-4 system
- [`configs/mcs4_max.json`](configs/mcs4_max.json) - Maximum configuration
- [`configs/mcs4_io_demo.json`](configs/mcs4_io_demo.json) - I/O demonstration
### 3.2 Existing Configuration Options
**JSON Configuration Structure:**
```json
{
"name": "IntelMcs4",
"description": "Basic MCS-4 System",
"version": "1.0",
"metadata": {
"cpu_speed": 750000,
"rom_count": 2,
"ram_count": 1
},
"components": { ... },
"connections": { ... }
}
```
### 3.3 Where Display Configuration Fits
**Option 1: Extend ConsoleConfig** in [`src/gui/console.rs:35-58`](src/gui/console.rs:35-58)
```rust
pub struct ConsoleConfig {
// Existing fields...
pub show_rom: bool, // NEW: ROM display toggle
pub rom_address_range: String, // NEW: ROM address range to display
pub display_format: String, // NEW: hex/decimal/ascii
}
```
**Option 2: Extend XML Config** [`configs/console_config.xml`](configs/console_config.xml:1-45)
```xml
<interface>
<!-- Existing options -->
<show_rom>true</show_rom>
<rom_bytes_per_row>16</rom_bytes_per_row>
<display_format>hex</display_format>
</interface>
```
**Option 3: Create New DisplayConfig** structure for unified GUI/Console settings
---
## 4. Main Entry Point Analysis
### 4.1 Application Flow
**Location:** [`src/main.rs`](src/main.rs:1-676)
```mermaid
flowchart TD
A[main] --> B[Parse CLI Args]
B --> C{Mode?}
C -->|--console| D[Launch Console]
C -->|--gui| E[Launch GUI]
C -->|default| F[Traditional Mode]
D --> G[run_console]
E --> H[run_gui]
F --> I[run_system_demo]
```
### 4.2 Mode Selection
**Location:** [`main()`](src/main.rs:102-279)
```rust
// Interface mode selection and launch
if use_console {
// Launch interactive console interface
let console_config = ConsoleConfig::default();
run_console(system_arc, console_config)
} else if use_gui {
// Launch graphical user interface
run_gui(Some(system_arc))
} else {
// Traditional mode
run_system_demo(system)
}
```
### 4.3 System Start/Stop
**ConfigurableSystem Methods:**
- [`run()`](src/system_config.rs:380-428) - Start system
- [`stop()`](src/system_config.rs:538-540) - Stop system
- [`is_running()`](src/system_config.rs:542-544) - Check running state
### 4.4 Keyboard Input Handling
**Console:** [`handle_key_event()`](src/gui/console.rs:142-202)
**GUI:** Uses egui event system - no explicit keyboard handler
**Traditional Mode:** No keyboard handling (Ctrl+C only)
**Where Ctrl-Q Fits:**
| Mode | Location | Implementation |
|------|----------|----------------|
| Console | [`handle_key_event()`](src/gui/console.rs:142) | Add Ctrl-Q detection |
| GUI | [`GuiApp`](src/gui/mod.rs:21) update loop | Add keyboard shortcut |
| Traditional | [`run_system_demo()`](src/main.rs:460) | Add terminal input thread |
---
## 5. Component Data Access Analysis
### 5.1 Intel 4004 CPU
**Location:** [`src/components/cpu/intel_4004.rs`](src/components/cpu/intel_4004.rs:1-1602)
**Register Access Methods:**
| Method | Returns | Location |
|--------|---------|----------|
| [`get_accumulator()`](src/components/cpu/intel_4004.rs:1142-1144) | `u8` | Line 1142 |
| [`get_carry()`](src/components/cpu/intel_4004.rs:1154-1156) | `bool` | Line 1154 |
| [`get_program_counter()`](src/components/cpu/intel_4004.rs:1130-1132) | `u16` | Line 1130 |
| [`get_register(index)`](src/components/cpu/intel_4004.rs:1191-1197) | `Option<u8>` | Line 1191 |
| [`get_stack_pointer()`](src/components/cpu/intel_4004.rs:1160-1162) | `u8` | Line 1160 |
| [`get_cycle_count()`](src/components/cpu/intel_4004.rs:1166-1168) | `u64` | Line 1166 |
### 5.2 Intel 4002 RAM
**Location:** [`src/components/memory/intel_4002.rs`](src/components/memory/intel_4002.rs:1-1140)
**Memory Access Methods:**
| Method | Returns | Location |
|--------|---------|----------|
| [`read_ram_direct(addr)`](src/components/memory/intel_4002.rs:818-824) | `Option<u8>` | Line 818 |
| [`get_io_port(port)`](src/components/memory/intel_4002.rs:842-848) | `Option<u8>` | Line 842 |
| [`get_ram_size()`](src/components/memory/intel_4002.rs:810-813) | `usize` | Line 810 |
### 5.3 Intel 4001 ROM
**Location:** [`src/components/memory/intel_4001.rs`](src/components/memory/intel_4001.rs)
**Expected Methods (need verification):**
- ROM data read/access
- I/O port access
### 5.4 Component Access Pattern
**From ConfigurableSystem:**
```rust
// Access components HashMap
let components = system.get_components();
// Get CPU
if let Some(cpu_component) = components.get("CPU_4004") {
if let Ok(cpu) = cpu_component.lock() {
// Access CPU methods - but need downcast to Intel4004
}
}
```
**Challenge:** Components are stored as `Box<dyn Component>` - need downcasting to access type-specific methods.
---
## 6. Fibonacci Example Analysis
### 6.1 Program Files
**Location:** [`programs/`](programs/)
| File | Size | Purpose |
|------|------|---------|
| [`fibonacci.bin`](programs/fibonacci.bin) | 33 bytes | Basic Fibonacci (RAM only) |
| [`fibonacci_output.bin`](programs/fibonacci_output.bin) | 55 bytes | Fibonacci with output ports |
### 6.2 Expected Behavior
**From [`programs/README.md`](programs/README.md:7-13):**
- Calculates first 8 Fibonacci numbers
- Results stored in RAM locations 0-7
- `fibonacci_output.bin` also outputs to ports for visibility
### 6.3 Where Results Appear
**RAM Locations:** 0x00-0x07 (first 8 Fibonacci numbers: 0, 1, 1, 2, 3, 5, 8, 13)
**Output Ports:** Port values visible during execution with `fibonacci_output.bin`
---
## 7. Implementation Recommendations
### 7.1 ROM/RAM/CPU Display - Console
**File:** [`src/gui/console.rs`](src/gui/console.rs)
**Changes Required:**
1. **Add ROM display method** (new ~50 lines after line 505):
```rust
fn draw_rom_contents(&self, f: &mut Frame, area: Rect) {
// Access ROM components and display contents
}
```
2. **Update RAM display** [`draw_ram_contents()`](src/gui/console.rs:472-505):
- Add actual RAM data retrieval from Intel4002
- Use `read_ram_direct()` method
3. **Update CPU display** [`draw_system_info()`](src/gui/console.rs:401-470):
- Add actual register retrieval from Intel4004
- Use getter methods: `get_accumulator()`, `get_program_counter()`, etc.
4. **Add component downcasting helper** (new method):
```rust
fn get_cpu_state(&self) -> Option<CpuState> { ... }
fn get_ram_state(&self) -> Option<RamState> { ... }
fn get_rom_state(&self) -> Option<RomState> { ... }
```
### 7.2 ROM/RAM/CPU Display - GUI
**File:** [`src/gui/state.rs`](src/gui/state.rs)
**Changes Required:**
1. **Extend `MemoryState`** (line 52-57):
```rust
pub struct MemoryState {
pub ram_contents: Vec<[u8; 4]>,
pub rom_contents: Vec<u8>, // NEW: ROM data
pub rom_address_range: (u16, u16), // NEW: Address range
// ...existing fields
}
```
2. **Update `update_from_system()`** (line 100-118):
- Add actual CPU register retrieval
- Add actual RAM data retrieval
- Add ROM data retrieval
**File:** [`src/gui/components.rs`](src/gui/components.rs)
3. **Add `RomViewer` component** (new ~100 lines after line 428):
- Similar to `MemoryViewer`
- Display ROM contents in hex grid
### 7.3 Display Configuration
**File:** [`src/gui/console.rs`](src/gui/console.rs:35-58)
**Extend `ConsoleConfig`:**
```rust
pub struct ConsoleConfig {
// Existing...
pub show_rom: bool, // NEW
pub display_refresh_rate: u64, // NEW
pub address_format: String, // NEW: hex/decimal
}
```
**File:** [`configs/console_config.xml`](configs/console_config.xml)
**Add display options:**
```xml
<display>
<show_rom>true</show_rom>
<show_rom_addresses>true</show_rom_addresses>
</display>
```
### 7.4 Ctrl-Q Keyboard Handling
**Console - File:** [`src/gui/console.rs`](src/gui/console.rs:142)
**Add in `handle_key_event()`:**
```rust
KeyCode::Char('q') if key.modifiers.contains(KeyModifiers::CONTROL) => {
self.running = false;
if let Ok(mut system) = self.system.lock() {
system.stop();
}
}
```
**GUI - File:** [`src/gui/mod.rs`](src/gui/mod.rs:141)
**Add in `update()` method:**
```rust
// Check for Ctrl-Q shortcut
if ui.input(|i| i.key_pressed(egui::Key::Q) && i.modifiers.ctrl) {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
```
**Traditional Mode - File:** [`src/main.rs`](src/main.rs:460)
**Add terminal input thread in `run_system_demo()`**:
```rust
thread::spawn(move || {
let stdin = std::io::stdin();
for line in stdin.lock().lines() {
if line.unwrap() == "\x11" { // Ctrl-Q
*running.lock().unwrap() = false;
break;
}
}
});
```
---
## 8. Summary of Required Changes
| Task | File | Location | Type |
|------|------|----------|------|
| Console RAM display | [`src/gui/console.rs`](src/gui/console.rs:472) | `draw_ram_contents()` | Modify |
| Console CPU display | [`src/gui/console.rs`](src/gui/console.rs:401) | `draw_system_info()` | Modify |
| Console ROM display | [`src/gui/console.rs`](src/gui/console.rs:505) | New method | Add |
| GUI state update | [`src/gui/state.rs`](src/gui/state.rs:100) | `update_from_system()` | Modify |
| GUI ROM viewer | [`src/gui/components.rs`](src/gui/components.rs:428) | New component | Add |
| Console config | [`src/gui/console.rs`](src/gui/console.rs:35) | `ConsoleConfig` | Extend |
| XML config | [`configs/console_config.xml`](configs/console_config.xml) | Add display options | Extend |
| Console Ctrl-Q | [`src/gui/console.rs`](src/gui/console.rs:142) | `handle_key_event()` | Modify |
| GUI Ctrl-Q | [`src/gui/mod.rs`](src/gui/mod.rs:141) | `update()` | Modify |
| Traditional Ctrl-Q | [`src/main.rs`](src/main.rs:460) | `run_system_demo()` | Modify |
---
## 9. Architecture Diagram
```mermaid
graph TB
subgraph Entry
main[main.rs]
end
subgraph Modes
console[Console Mode]
gui[GUI Mode]
traditional[Traditional Mode]
end
subgraph Console Components
console_app[ConsoleApp]
console_config[ConsoleConfig]
draw_ram[draw_ram_contents]
draw_cpu[draw_system_info]
handle_keys[handle_key_event]
end
subgraph GUI Components
gui_app[GuiApp]
gui_state[GuiState]
gui_components[GuiComponents]
mem_viewer[MemoryViewer]
reg_viewer[RegisterViewer]
end
subgraph System
config_sys[ConfigurableSystem]
components[Component HashMap]
end
subgraph Hardware Components
cpu[Intel4004 CPU]
ram[Intel4002 RAM]
rom[Intel4001 ROM]
end
main --> console
main --> gui
main --> traditional
console --> console_app
console_app --> draw_ram
console_app --> draw_cpu
console_app --> handle_keys
gui --> gui_app
gui_app --> gui_state
gui_app --> gui_components
gui_components --> mem_viewer
gui_components --> reg_viewer
console_app --> config_sys
gui_state --> config_sys
config_sys --> components
components --> cpu
components --> ram
components --> rom
```
---
## 10. Key Code Locations Reference
| Component | File | Key Lines |
|-----------|------|-----------|
| GUI Entry | [`src/gui/mod.rs`](src/gui/mod.rs:234) | 234-259 |
| GUI State | [`src/gui/state.rs`](src/gui/state.rs:12) | 12-176 |
| GUI Components | [`src/gui/components.rs`](src/gui/components.rs:72) | 72-804 |
| Console Entry | [`src/gui/console.rs`](src/gui/console.rs:509) | 509-515 |
| Console Config | [`src/gui/console.rs`](src/gui/console.rs:35) | 35-58 |
| Console Keys | [`src/gui/console.rs`](src/gui/console.rs:142) | 142-202 |
| System Config | [`src/system_config.rs`](src/system_config.rs:58) | 58-629 |
| Main Entry | [`src/main.rs`](src/main.rs:102) | 102-279 |
| CPU Getters | [`src/components/cpu/intel_4004.rs`](src/components/cpu/intel_4004.rs:1130) | 1130-1197 |
| RAM Getters | [`src/components/memory/intel_4002.rs`](src/components/memory/intel_4002.rs:810) | 810-866 |