1use crate::debug::Z80Debugger;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
5pub enum InterruptLine {
6    High,
7    Low,
8}
9
10pub trait BusInterface {
11    type DebugView<'a>: Z80Debugger
12    where
13        Self: 'a;
14
15    /// Read a byte from the given memory address.
16    fn read_memory(&mut self, address: u16) -> u8;
17
18    /// Write the given byte to the given memory address.
19    fn write_memory(&mut self, address: u16, value: u8);
20
21    /// Read a byte from the given I/O port. Most hardware only uses the lower 8 bits of the address.
22    fn read_io(&mut self, address: u16) -> u8;
23
24    /// Write the given byte to the given I/O port. Most hardware only uses the lower 8 bits of the address.
25    fn write_io(&mut self, address: u16, value: u8);
26
27    /// Poll the NMI interrupt line.
28    fn nmi(&self) -> InterruptLine;
29
30    /// Poll the INT interrupt line.
31    fn int(&self) -> InterruptLine;
32
33    /// Poll the BUSREQ line; setting this halts the Z80
34    fn busreq(&self) -> bool;
35
36    /// Poll the RESET line; setting this resets and halts the Z80
37    fn reset(&self) -> bool;
38
39    fn debug_view(&mut self) -> Option<Self::DebugView<'_>> {
40        None
41    }
42}
43
44#[cfg(test)]
45#[derive(Debug, Clone)]
46pub(crate) struct InMemoryBus {
47    pub(crate) memory: [u8; 0x10000],
48    pub(crate) io_ports: [u8; 0x100],
49    pub(crate) nmi: InterruptLine,
50    pub(crate) int: InterruptLine,
51    pub(crate) reset: bool,
52}
53
54#[cfg(test)]
55impl InMemoryBus {
56    pub(crate) fn new() -> Self {
57        use std::array;
58
59        Self {
60            memory: array::from_fn(|_| 0),
61            io_ports: array::from_fn(|_| 0),
62            nmi: InterruptLine::High,
63            int: InterruptLine::High,
64            reset: false,
65        }
66    }
67}
68
69#[cfg(test)]
70impl BusInterface for InMemoryBus {
71    type DebugView<'a>
72        = crate::debug::DummyZ80Debugger
73    where
74        Self: 'a;
75
76    fn read_memory(&mut self, address: u16) -> u8 {
77        self.memory[address as usize]
78    }
79
80    fn write_memory(&mut self, address: u16, value: u8) {
81        self.memory[address as usize] = value;
82    }
83
84    fn read_io(&mut self, address: u16) -> u8 {
85        self.io_ports[(address & 0xFF) as usize]
86    }
87
88    fn write_io(&mut self, address: u16, value: u8) {
89        self.io_ports[(address & 0xFF) as usize] = value;
90    }
91
92    fn nmi(&self) -> InterruptLine {
93        self.nmi
94    }
95
96    fn int(&self) -> InterruptLine {
97        self.int
98    }
99
100    fn busreq(&self) -> bool {
101        false
102    }
103
104    fn reset(&self) -> bool {
105        self.reset
106    }
107}