rust8/chip8/cpu/
mod.rs

1pub mod execute;
2use thiserror::Error;
3
4use self::execute::InstructionExecutionError;
5use super::constants::INSTRUCTION_SIZE;
6use super::{Blocked, Chip8};
7use crate::chip8::Key;
8use crate::memory::ReadInstructionError;
9
10#[derive(Error, Debug)]
11pub enum CycleError {
12    #[error("instruction fetch error")]
13    FetchError(#[from] ReadInstructionError),
14    #[error("instruction execution error")]
15    ExecutionError(#[from] InstructionExecutionError),
16}
17
18impl Chip8 {
19    pub fn cycle(&mut self) -> Result<(), CycleError> {
20        if self.blocked != Blocked::No {
21            return Ok(());
22        }
23
24        let instruction = self.memory.read_instruction(self.program_counter)?;
25        self.execute_instruction(instruction)?;
26
27        // Auto-Increment only when not in jump
28        if !self.in_jump {
29            self.program_counter += INSTRUCTION_SIZE;
30        }
31        self.in_jump = false;
32
33        Ok(())
34    }
35
36    pub fn handle_key_up_interrupt(&mut self, key: Key) {
37        if let Blocked::WaitingOnKeyUp(vx) = self.blocked {
38            self.data_registers[vx] = u8::from(key);
39            self.blocked = Blocked::No;
40        }
41    }
42
43    pub fn update_timers(&mut self) {
44        if self.blocked != Blocked::No {
45            return;
46        }
47
48        // Should be called at a rate of 60hz
49        if self.delay_timer > 0 {
50            self.delay_timer -= 1;
51        }
52
53        if self.sound_timer > 0 {
54            self.sound_timer -= 1;
55        }
56    }
57}