aboutsummaryrefslogtreecommitdiff
path: root/src/interrupts_timers.rs
blob: 95a0757a1f869c01ed8343fa9c4bf30fb35b10d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use crate::display::DisplayInterrupt;
use crate::state::{GBState, MemError};

const TIMA_TIMER_SPEEDS: [u64; 4] = [1024, 16, 64, 256];

impl GBState {
    pub fn check_interrupts(&mut self) -> Result<(), MemError> {
        if self.mem.ime {
            let interrupts = self.mem.io[0x0f] & self.mem.interrupts_register & 0b11111;
            for i in 0..5 {
                if interrupts & (1 << i) != 0 {
                    self.push(self.cpu.pc)?;

                    self.mem.ime = false;
                    self.cpu.pc = 0x40 + (i << 3);
                    self.mem.halt = false;

                    self.mem.io[0x0f] &= !(1 << i);
                    break;
                }
            }
        }
        Ok(())
    }

    pub fn tima_timer(&mut self, c: u64) {
        if self.mem.timer_enabled
            && self.tima_cycles >= TIMA_TIMER_SPEEDS[self.mem.timer_speed as usize]
        {
            if self.mem.tima == 0xff {
                self.mem.io[0x0f] |= 0b100;
                self.mem.tima = self.mem.tma;
            } else {
                self.mem.tima += 1;
            }
            self.tima_cycles %= TIMA_TIMER_SPEEDS[self.mem.timer_speed as usize];
        }
        self.tima_cycles += c;
    }

    pub fn update_display_interrupts(&mut self, c: u64) {
        let interrupt = self.mem.display.update_display(c);

        match interrupt {
            DisplayInterrupt::Vblank => {
                self.mem.io[0x0f] |= 1;
            }
            DisplayInterrupt::Stat => {
                self.mem.io[0xf] |= 2;
            }
            DisplayInterrupt::Both => {
                self.mem.io[0xf] |= 3;
            }
            _ => {}
        }
    }

    pub fn div_timer(&mut self, c: u64) {
        if self.div_cycles >= 256 {
            self.mem.div += 1;

            self.div_cycles = 0;
        }
        self.div_cycles += c;
    }
}