1use alloc::rc::Rc;
2use core::cell::{Ref, RefCell, RefMut};
3
4use crate::mmu::{MemHandler, MemRead, MemWrite, Mmu};
5
6pub struct Device<T>(Rc<RefCell<T>>, bool);
8
9impl<T> Device<T> {
10    pub fn new(inner: T) -> Self {
12        Self::inner(inner, false)
13    }
14
15    pub fn mediate(inner: T) -> Self {
17        Self::inner(inner, true)
18    }
19
20    fn inner(inner: T, debug: bool) -> Self {
21        Self(Rc::new(RefCell::new(inner)), debug)
22    }
23
24    pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
26        self.0.borrow()
27    }
28
29    pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
31        self.0.borrow_mut()
32    }
33}
34
35impl<T: IoHandler> Device<T> {
36    pub fn handler(&self) -> IoMemHandler<T> {
38        IoMemHandler(self.0.clone(), self.1)
39    }
40}
41
42pub trait IoHandler {
44    fn on_read(&mut self, mmu: &Mmu, addr: u16) -> MemRead;
46
47    fn on_write(&mut self, mmu: &Mmu, addr: u16, value: u8) -> MemWrite;
49}
50
51pub struct IoMemHandler<T>(Rc<RefCell<T>>, bool);
53
54impl<T: IoHandler> MemHandler for IoMemHandler<T> {
55    fn on_read(&self, mmu: &Mmu, addr: u16) -> MemRead {
56        match self.0.try_borrow_mut() {
58            Ok(mut inner) => inner.on_read(mmu, addr),
59            Err(e) => {
60                if self.1 {
61                    MemRead::PassThrough
63                } else {
64                    panic!("Recursive read from {:04x}: {}", addr, e)
65                }
66            }
67        }
68    }
69
70    fn on_write(&self, mmu: &Mmu, addr: u16, value: u8) -> MemWrite {
71        match self.0.try_borrow_mut() {
73            Ok(mut inner) => inner.on_write(mmu, addr, value),
74            Err(e) => {
75                if self.1 {
76                    MemWrite::PassThrough
78                } else {
79                    panic!("Recursive write to {:04x}: {}", addr, e)
80                }
81            }
82        }
83    }
84}