summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 1ec5174d602ed35393ecaa710054cc4970baf75b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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<bool>, 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<bool>, 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);
}