Files
trevors_chip8_toy/gemma/src/chip8/computer_manager.rs
T
tmerritt e29ac45c84 scroll down works on CHIP-8 and High-Res modes
scroll left and right work in stdef and hidef
adds octo test roms
adds schip fonts to memory
2024-10-27 11:41:25 -04:00

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()
}
}
}
}