use crate::emulator::{CpuError, System}; use std::sync::mpsc; use std::sync::{Arc, Mutex}; use std::thread; static TEST_CODE: &'static [u8; 0x10000] = include_bytes!("color.hex"); /* #region Commands */ #[derive(Copy, Clone, Debug, PartialEq)] pub enum Cmd { Step, Run, Stop, Get(GetType), Reset, } impl std::convert::From<&str> for Cmd { fn from(text: &str) -> Self { match text { "Step" => Self::Step, "Run" => Self::Run, "Stop" => Self::Stop, "Reset" => Self::Reset, _ => panic!("???"), } } } #[derive(Copy, Clone, Debug, PartialEq)] pub enum GetType { Range(usize, usize), Value(usize), Flags, } /* #endregion */ pub struct ThreadedEmulator { pub tcmd: mpsc::Sender, pub rdata: glib::Receiver>, pub system: Arc>, pub thread: thread::JoinHandle>, } impl ThreadedEmulator { pub fn new() -> Self { let (tcmd, rcmd) = mpsc::channel::(); let (tdata, rdata) = glib::MainContext::channel(glib::source::Priority::default()); let system = Arc::from(Mutex::from(System::new())); let thread = { let system = system.clone(); thread::spawn(move || Self::thread(rcmd, tdata, system)) }; Self { tcmd, rdata, system, thread, } } fn thread( rcmd: mpsc::Receiver, tdata: glib::Sender>, system: Arc>, ) -> Result<(), CpuError> { loop { if let Ok(cmd) = rcmd.recv() { let mut system = system.lock().unwrap_or_else(|e| { panic!("Error acquiring lock for the system. Error: {}", e) }); println!("Cmd: {:?}", cmd); match cmd { Cmd::Step => { system.step()?; let page_02 = Vec::from(&(*system.ram)[0x200..0x300]); tdata.send(page_02); } Cmd::Reset => { system.restart(); system.ram.load(*TEST_CODE); } Cmd::Run => loop { if let Err(e) = rcmd.recv_timeout(std::time::Duration::from_millis(1)) { if e == std::sync::mpsc::RecvTimeoutError::Timeout { system.step()?; let page_02 = Vec::from(&(*system.ram)[0x200..0x300]); tdata.send(page_02); } else { panic!("Controller mpsc disconnected: {}", e) } } else { break; } }, Cmd::Get(what) => match what { GetType::Flags => {} GetType::Range(start, end) => { let data = &(*system.ram)[start..end]; tdata .send(Vec::from(data)) .expect("Couldn't send requested value"); } GetType::Value(addr) => { tdata .send(vec![(*system.ram)[addr]]) .expect("Couldn't send requested value"); } }, _ => {} }; } } } }