extern crate clap; use std::fs; use std::io; use std::io::prelude::*; use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread; use std::time::Duration; mod core; mod rom; use self::core::Core; enum Control { Run(bool), } enum SimData {} struct BoundController { tx: Sender, _rx: Receiver, } struct BoundCore { _tx: Sender, rx: Receiver, } fn new_bound_pair() -> (BoundCore, BoundController) { let (tx_c, rx_c): (Sender, Receiver) = channel(); let (tx_d, rx_d): (Sender, Receiver) = channel(); return ( BoundCore { _tx: tx_d, rx: rx_c, }, BoundController { tx: tx_c, _rx: rx_d, }, ); } fn cli_controller(bound: BoundController) { let stdin = io::stdin(); for line in stdin.lock().lines() { let line = line.unwrap(); match line.as_ref() { "stop" => { println!("stop"); bound.tx.send(Control::Run(false)).unwrap(); } "start" => { println!("start"); bound.tx.send(Control::Run(true)).unwrap(); } _ => (), } } } fn ws_controller(_bound: BoundController) { // TODO implement println!("AAA"); } fn new_controller(name: &str) -> Result<&dyn Fn(BoundController), i32> { match name { "cli" => Ok(&cli_controller), "ws" => Ok(&ws_controller), _ => Err(1), } } fn core_worker(mut core: Core, bound: BoundCore) { let mut should_stop = false; loop { if should_stop == true { if let Ok(msg) = bound.rx.recv() { match msg { Control::Run(run) => should_stop = !run, } } } else { println!("0x{:08x}: {}", core.pc(), core.op()); core.step(); if let Ok(msg) = bound.rx.recv_timeout(Duration::from_millis(1000)) { match msg { Control::Run(run) => should_stop = !run, } } } } } fn main() { /* Parse args*/ let cli_args_matches = clap::App::new("x51emu") .version("0.1.0") .author("oxore") .about("MCS51 emulator") .arg( clap::Arg::with_name("file") .short("f") .long("file") .value_name("FILE") .help("Sets a file with program to load") .takes_value(true) .required(true), ) .arg( clap::Arg::with_name("interface") .short("i") .long("interface") .value_name("INTERFACE") .help("Sets a controlling and I/O interface") .takes_value(true) .default_value("cli") .possible_values(&["cli", "ws"]), ) .get_matches(); let filename = cli_args_matches .value_of("file") .expect("No file name provided"); let controller = { let controller_type_name = cli_args_matches .value_of("interface") .expect("No interface type specified"); new_controller(controller_type_name).expect(&format!( "Unknown controller type \"{}\"", controller_type_name )) }; /* Read program and instantiate a simulator */ let data = fs::read_to_string(filename).unwrap_or_else(|_| panic!("Unable to read file {}", filename)); let core = match Core::new_with_rom_from_hex(data) { Ok(value) => value, Err(err_string) => { println!("{}", err_string); return; } }; /* Run core worker and controller */ let (bound_core, bound_controller) = new_bound_pair(); thread::spawn(move || { core_worker(core, bound_core); }); controller(bound_controller); }