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