1use std::cell::RefCell;
2
3use crate::ffi;
4
5pub type ReadDataHandler = Box<dyn Fn(ffi::AccessClass, u32, u32) -> Vec<u8>>;
6pub type WriteDataHandler = Box<dyn FnMut(ffi::AccessClass, u32, &[u8])>;
7pub type ExternalWriteHandler = Box<dyn FnMut(ffi::AccessClass, u32, u8)>;
8
9#[derive(Default)]
12pub struct InterfaceHandler {
13 pub advance_clock: Option<Box<dyn FnMut(i64) -> u8>>,
14 pub read_data: Option<ReadDataHandler>,
15 pub write_data: Option<WriteDataHandler>,
16 pub ymfm_external_read: Option<Box<dyn FnMut(ffi::AccessClass, u32) -> u8>>,
17 pub ymfm_external_write: Option<ExternalWriteHandler>,
18 pub ymfm_is_busy: Option<Box<dyn Fn() -> bool>>,
19 pub ymfm_set_busy_end: Option<Box<dyn FnMut(u32)>>,
20 pub ymfm_set_timer: Option<Box<dyn FnMut(u32, i32)>>,
21 pub ymfm_update_irq: Option<Box<dyn FnMut(bool)>>,
22}
23
24pub struct InterfaceCallbacks {
26 handler: RefCell<InterfaceHandler>,
27}
28
29impl InterfaceCallbacks {
30 pub fn new(handler: InterfaceHandler) -> Self {
32 Self {
33 handler: RefCell::new(handler),
34 }
35 }
36}
37
38pub(crate) fn default_callbacks() -> Box<InterfaceCallbacks> {
40 Box::new(InterfaceCallbacks::new(InterfaceHandler::default()))
41}
42
43pub(crate) fn ymfm_update_irq(callbacks: &InterfaceCallbacks, asserted: bool) {
45 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_update_irq.as_mut() {
46 handler(asserted);
47 }
48}
49
50pub(crate) fn advance_clock(callbacks: &InterfaceCallbacks, clocks: i64) -> u8 {
53 callbacks
54 .handler
55 .borrow_mut()
56 .advance_clock
57 .as_mut()
58 .map_or(0, |handler| handler(clocks))
59}
60
61pub(crate) fn ymfm_set_busy_end(callbacks: &InterfaceCallbacks, clocks: u32) {
63 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_set_busy_end.as_mut() {
64 handler(clocks);
65 }
66}
67
68pub(crate) fn ymfm_is_busy(callbacks: &InterfaceCallbacks) -> bool {
71 callbacks
72 .handler
73 .borrow()
74 .ymfm_is_busy
75 .as_ref()
76 .is_some_and(|handler| handler())
77}
78
79pub(crate) fn ymfm_set_timer(callbacks: &InterfaceCallbacks, tnum: u32, duration_in_clocks: i32) {
81 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_set_timer.as_mut() {
82 handler(tnum, duration_in_clocks);
83 }
84}
85
86pub(crate) fn ymfm_external_read(
89 callbacks: &InterfaceCallbacks,
90 access: ffi::AccessClass,
91 offset: u32,
92) -> u8 {
93 callbacks
94 .handler
95 .borrow_mut()
96 .ymfm_external_read
97 .as_mut()
98 .map_or(0, |handler| handler(access, offset))
99}
100
101pub(crate) fn read_data(
104 callbacks: &InterfaceCallbacks,
105 access: ffi::AccessClass,
106 base: u32,
107 length: u32,
108) -> Vec<u8> {
109 callbacks.handler.borrow().read_data.as_ref().map_or_else(
110 || vec![0; length as usize],
111 |handler| handler(access, base, length),
112 )
113}
114
115pub(crate) fn ymfm_external_write(
117 callbacks: &InterfaceCallbacks,
118 access: ffi::AccessClass,
119 offset: u32,
120 data: u8,
121) {
122 if let Some(handler) = callbacks.handler.borrow_mut().ymfm_external_write.as_mut() {
123 handler(access, offset, data);
124 }
125}
126
127pub(crate) fn write_data(
129 callbacks: &InterfaceCallbacks,
130 access: ffi::AccessClass,
131 base: u32,
132 data: &[u8],
133) {
134 if let Some(handler) = callbacks.handler.borrow_mut().write_data.as_mut() {
135 handler(access, base, data);
136 }
137}