17 KiB
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
The GUI is built using eframe/egui (Rust immediate mode GUI framework):
use eframe::egui;
Key Structure:
GuiApp- Main GUI application structsystem: Option<Arc<Mutex<ConfigurableSystem>>>- Thread-safe system referencegui_state: state::GuiState- GUI state managementcomponents: components::GuiComponents- Component container
Entry Point: run_gui() function launches the GUI
1.2 State Management
Location: src/gui/state.rs
Key Structures:
| Structure | Purpose | Location |
|---|---|---|
GuiState |
Main UI state container | Lines 12-29 |
SystemInfo |
System metadata display | Lines 32-40 |
ComponentStates |
Component running states | Lines 43-49 |
MemoryState |
RAM contents display | Lines 52-57 |
RegisterState |
CPU register display | Lines 60-67 |
Current State Fields:
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()
1.3 GUI Components
Location: src/gui/components.rs
| Component | Purpose | Location |
|---|---|---|
GuiComponents |
Component container | Lines 72-84 |
ControlPanel |
Start/Stop/Reset buttons | Lines 180-303 |
MemoryViewer |
RAM display | Lines 305-428 |
RegisterViewer |
CPU registers display | Lines 430-574 |
RomLoader |
ROM file loading | Lines 576-671 |
StatusBar |
System status | Lines 673-804 |
Where to Add ROM Display:
- Create new
RomViewercomponent similar toMemoryViewer - Add to
GuiComponentsstruct - Render in
render_gui()
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_contentsexists but uses placeholder dataupdate_from_system()does NOT populate actual RAM data- Need to add RAM data extraction from Intel4002 components
CPU Register Status:
RegisterStateexists with all needed fieldsupdate_from_system()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
Framework: ratatui + crossterm (Terminal UI)
Key Structure:
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
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
2.3 Current Console Display
RAM Display: draw_ram_contents()
- Currently shows placeholder data (
00values) - Does NOT read actual RAM from Intel4002
CPU Register Display: draw_system_info()
- 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()
Current key bindings:
q/Q/Esc- Quitr/R- Run/Stop toggles/S- Stoph/H- HelpTab- Switch panesEnter- 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
Key Structures:
| Structure | Purpose | Location |
|---|---|---|
SystemConfig |
JSON system definition | Lines 58-67 |
ComponentConfig |
Component configuration enum | Lines 70-75 |
ConfigurableSystem |
Runtime system instance | Lines 362-428 |
Configuration Files:
configs/mcs4_basic.json- Basic MCS-4 systemconfigs/mcs4_max.json- Maximum configurationconfigs/mcs4_io_demo.json- I/O demonstration
3.2 Existing Configuration Options
JSON Configuration Structure:
{
"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
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
<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
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()
// 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()- Start systemstop()- Stop systemis_running()- Check running state
4.4 Keyboard Input Handling
Console: handle_key_event()
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() |
Add Ctrl-Q detection |
| GUI | GuiApp update loop |
Add keyboard shortcut |
| Traditional | run_system_demo() |
Add terminal input thread |
5. Component Data Access Analysis
5.1 Intel 4004 CPU
Location: src/components/cpu/intel_4004.rs
Register Access Methods:
| Method | Returns | Location |
|---|---|---|
get_accumulator() |
u8 |
Line 1142 |
get_carry() |
bool |
Line 1154 |
get_program_counter() |
u16 |
Line 1130 |
get_register(index) |
Option<u8> |
Line 1191 |
get_stack_pointer() |
u8 |
Line 1160 |
get_cycle_count() |
u64 |
Line 1166 |
5.2 Intel 4002 RAM
Location: src/components/memory/intel_4002.rs
Memory Access Methods:
| Method | Returns | Location |
|---|---|---|
read_ram_direct(addr) |
Option<u8> |
Line 818 |
get_io_port(port) |
Option<u8> |
Line 842 |
get_ram_size() |
usize |
Line 810 |
5.3 Intel 4001 ROM
Location: 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:
// 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/
| File | Size | Purpose |
|---|---|---|
fibonacci.bin |
33 bytes | Basic Fibonacci (RAM only) |
fibonacci_output.bin |
55 bytes | Fibonacci with output ports |
6.2 Expected Behavior
From programs/README.md:
- Calculates first 8 Fibonacci numbers
- Results stored in RAM locations 0-7
fibonacci_output.binalso 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
Changes Required:
- Add ROM display method (new ~50 lines after line 505):
fn draw_rom_contents(&self, f: &mut Frame, area: Rect) {
// Access ROM components and display contents
}
-
Update RAM display
draw_ram_contents():- Add actual RAM data retrieval from Intel4002
- Use
read_ram_direct()method
-
Update CPU display
draw_system_info():- Add actual register retrieval from Intel4004
- Use getter methods:
get_accumulator(),get_program_counter(), etc.
-
Add component downcasting helper (new method):
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
Changes Required:
- Extend
MemoryState(line 52-57):
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
}
- 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
- Add
RomViewercomponent (new ~100 lines after line 428):- Similar to
MemoryViewer - Display ROM contents in hex grid
- Similar to
7.3 Display Configuration
File: src/gui/console.rs
Extend ConsoleConfig:
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
Add display options:
<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
Add in handle_key_event():
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
Add in update() method:
// 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
Add terminal input thread in run_system_demo():
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 |
draw_ram_contents() |
Modify |
| Console CPU display | src/gui/console.rs |
draw_system_info() |
Modify |
| Console ROM display | src/gui/console.rs |
New method | Add |
| GUI state update | src/gui/state.rs |
update_from_system() |
Modify |
| GUI ROM viewer | src/gui/components.rs |
New component | Add |
| Console config | src/gui/console.rs |
ConsoleConfig |
Extend |
| XML config | configs/console_config.xml |
Add display options | Extend |
| Console Ctrl-Q | src/gui/console.rs |
handle_key_event() |
Modify |
| GUI Ctrl-Q | src/gui/mod.rs |
update() |
Modify |
| Traditional Ctrl-Q | src/main.rs |
run_system_demo() |
Modify |
9. Architecture Diagram
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 |
234-259 |
| GUI State | src/gui/state.rs |
12-176 |
| GUI Components | src/gui/components.rs |
72-804 |
| Console Entry | src/gui/console.rs |
509-515 |
| Console Config | src/gui/console.rs |
35-58 |
| Console Keys | src/gui/console.rs |
142-202 |
| System Config | src/system_config.rs |
58-629 |
| Main Entry | src/main.rs |
102-279 |
| CPU Getters | src/components/cpu/intel_4004.rs |
1130-1197 |
| RAM Getters | src/components/memory/intel_4002.rs |
810-866 |