e29ac45c84
scroll left and right work in stdef and hidef adds octo test roms adds schip fonts to memory
133 lines
3.7 KiB
Rust
133 lines
3.7 KiB
Rust
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<u8>) {
|
|
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()
|
|
}
|
|
}
|
|
}
|
|
} |