1use std::cell::RefCell;
2
3use crate::ffi;
4
5#[derive(Default)]
8pub struct InterfaceHandler {
9 pub advance_clock: Option<Box<dyn FnMut(i64) -> u8>>,
10 pub read_data: Option<Box<dyn Fn(ffi::AccessClass, u32, u32) -> Vec<u8>>>,
11 pub write_data: Option<Box<dyn FnMut(ffi::AccessClass, u32, &[u8])>>,
12 pub ymfm_external_read: Option<Box<dyn FnMut(ffi::AccessClass, u32) -> u8>>,
13 pub ymfm_external_write: Option<Box<dyn FnMut(ffi::AccessClass, u32, u8)>>,
14 pub ymfm_is_busy: Option<Box<dyn Fn() -> bool>>,
15 pub ymfm_set_busy_end: Option<Box<dyn FnMut(u32)>>,
16 pub ymfm_set_timer: Option<Box<dyn FnMut(u32, i32)>>,
17 pub ymfm_update_irq: Option<Box<dyn FnMut(bool)>>,
18}
19
20pub struct InterfaceCallbacks {
22 handler: RefCell<InterfaceHandler>,
23}
24
25impl InterfaceCallbacks {
26 pub fn new(handler: InterfaceHandler) -> Self {
28 Self {
29 handler: RefCell::new(handler),
30 }
31 }
32}
33
34pub(crate) fn default_callbacks() -> Box<InterfaceCallbacks> {
36 Box::new(InterfaceCallbacks::new(InterfaceHandler::default()))
37}
38
39pub(crate) fn ymfm_update_irq(callbacks: &InterfaceCallbacks, asserted: bool) {
41 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_update_irq.as_mut() {
42 handler(asserted);
43 }
44}
45
46pub(crate) fn advance_clock(callbacks: &InterfaceCallbacks, clocks: i64) -> u8 {
49 callbacks
50 .handler
51 .borrow_mut()
52 .advance_clock
53 .as_mut()
54 .map_or(0, |handler| handler(clocks))
55}
56
57pub(crate) fn ymfm_set_busy_end(callbacks: &InterfaceCallbacks, clocks: u32) {
59 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_set_busy_end.as_mut() {
60 handler(clocks);
61 }
62}
63
64pub(crate) fn ymfm_is_busy(callbacks: &InterfaceCallbacks) -> bool {
67 callbacks
68 .handler
69 .borrow()
70 .ymfm_is_busy
71 .as_ref()
72 .map_or(false, |handler| handler())
73}
74
75pub(crate) fn ymfm_set_timer(callbacks: &InterfaceCallbacks, tnum: u32, duration_in_clocks: i32) {
77 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_set_timer.as_mut() {
78 handler(tnum, duration_in_clocks);
79 }
80}
81
82pub(crate) fn ymfm_external_read(
85 callbacks: &InterfaceCallbacks,
86 access: ffi::AccessClass,
87 offset: u32,
88) -> u8 {
89 callbacks
90 .handler
91 .borrow_mut()
92 .ymfm_external_read
93 .as_mut()
94 .map_or(0, |handler| handler(access, offset))
95}
96
97pub(crate) fn read_data(
100 callbacks: &InterfaceCallbacks,
101 access: ffi::AccessClass,
102 base: u32,
103 length: u32,
104) -> Vec<u8> {
105 callbacks.handler.borrow().read_data.as_ref().map_or_else(
106 || vec![0; length as usize],
107 |handler| handler(access, base, length),
108 )
109}
110
111pub(crate) fn ymfm_external_write(
113 callbacks: &InterfaceCallbacks,
114 access: ffi::AccessClass,
115 offset: u32,
116 data: u8,
117) {
118 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_external_write.as_mut() {
119 handler(access, offset, data);
120 }
121}
122
123pub(crate) fn write_data(
125 callbacks: &InterfaceCallbacks,
126 access: ffi::AccessClass,
127 base: u32,
128 data: &[u8],
129) {
130 if let Some(handler) = callbacks.handler.borrow_mut().write_data.as_mut() {
131 handler(access, base, data);
132 }
133}