extern crate clap; use std::fs; use std::io; use std::io::prelude::*; use std::sync::{Arc, Condvar, Mutex}; use std::thread::sleep; use std::{thread, time}; mod core; mod rom; use self::core::Core; fn core_worker(mut core: Core, should_stop: &Mutex, cvar: &Condvar) { loop { while !(*should_stop.lock().unwrap()) { println!("0x{:08x}: {}", core.pc(), core.op()); core.step(); sleep(time::Duration::from_millis(1000)); } while *should_stop.lock().unwrap() { let _ = cvar.wait(should_stop.lock().unwrap()).unwrap(); } } } fn cli_controller(asyncpair: Arc<(Mutex, Condvar)>) { let &(ref should_stop, ref cvar) = &*asyncpair; let stdin = io::stdin(); for line in stdin.lock().lines() { let line = line.unwrap(); match line.as_ref() { "stop" => { println!("stop"); *should_stop.lock().unwrap() = true; } "start" => { println!("start"); *should_stop.lock().unwrap() = false; cvar.notify_one(); } _ => (), } } } fn main() { 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) .possible_values(&["cli", "ws"]), ) .get_matches(); let filename = cli_args_matches .value_of("file") .expect("No file name provided"); let data = fs::read_to_string(filename).unwrap_or_else(|_| panic!("Unable to read file {}", filename)); let asyncpair = Arc::new((Mutex::new(false), Condvar::new())); let asyncpair2 = asyncpair.clone(); let core = match Core::new_with_rom_from_hex(data) { Ok(value) => value, Err(err_string) => { println!("{}", err_string); return; } }; thread::spawn(move || { let (ref should_stop, ref condvar) = *asyncpair2; core_worker(core, should_stop, condvar); }); cli_controller(asyncpair); }