use std::sync::mpsc::{channel, Sender}; use std::thread; use std::thread::{sleep, JoinHandle, Thread}; use std::time::{Duration, Instant}; use crate::chip8::computer::Chip8Computer; use crate::chip8::cpu_states::Chip8CpuStates; use crate::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction; pub enum ManagerDumpables { Video, Registers, Keyboard } pub struct Chip8ComputerManager { core_should_run: bool, one_step: bool, core_cycle_timer: bool, core_last_cycle_start: Instant, computer: Chip8Computer } impl Default for Chip8ComputerManager { fn default() -> Self { Chip8ComputerManager { core_should_run: false, one_step: true, core_cycle_timer: false, core_last_cycle_start: Instant::now() , computer: Chip8Computer::new() } } } impl Chip8ComputerManager { pub fn reset(&mut self) { self.computer.reset(); } pub fn new() -> Chip8ComputerManager { let core_handle = thread::spawn(move || { loop { let start_time = Instant::now(); // println!("Core Thread starting at {start_time:?}"); let sleep_time = Instant::now().duration_since(start_time).as_millis(); // println!("Core Thread sleeping for {sleep_time}ms"); sleep(Duration::from_millis((16 - sleep_time) as u64)); } }); Chip8ComputerManager::default() } pub fn start(&mut self) { self.core_should_run = true; } pub fn stop(&mut self) { self.core_should_run = false } pub fn step(&mut self) { self.one_step = true; } pub fn state(&mut self) -> &Chip8Computer { &self.computer } pub fn tick( &mut self) { // println!("STARTING TICK"); if self.one_step | self.core_should_run { match self.computer.state { WaitingForInstruction => { self.core_last_cycle_start = Instant::now(); self.computer.step_system(); // println!("SYSTEM STEP"); } _ => {} } }; if self.one_step { println!("SYSTEM HALTED AFTER 1 STEP"); // stop the CPU for the next cycle, we are only // wanting one step. self.one_step = false; } } pub fn press_key(&mut self, key_index: u8) { self.computer.keypad.push_key(key_index); if matches!(self.computer.state, Chip8CpuStates::WaitingForKey) { self.computer.state = WaitingForInstruction } } pub fn release_key(&mut self, key_index: u8) { self.computer.keypad.release_key(key_index); } pub fn sound(managed: &Chip8ComputerManager) -> bool { managed.computer.sound_timer.current() > 0 } pub fn wait_for_instruction(&mut self) { self.computer.state = WaitingForInstruction; } pub fn is_key_pressed(&self, key_index: u8) -> bool { self.computer.keypad.pressed(key_index) } pub fn num_cycles(&self) -> i32 { self.computer.num_cycles } pub fn load_bytes_to_system_memory(&mut self, bytes_to_load: Vec) { self.computer.load_bytes_to_memory(0x200, &bytes_to_load); } pub fn dump_to_string(&self, dump_type: ManagerDumpables) -> String { match dump_type { ManagerDumpables::Video => { self.computer.video_memory.format_as_string() } ManagerDumpables::Registers => { self.computer.registers.format_as_string() } ManagerDumpables::Keyboard => { self.computer.keypad.format_as_string() } } } }