use crate::{M68000, Registers};
use crate::exception::{Exception, Vector};
use crate::memory_access::MemoryAccess;
use std::ffi::{c_void, CString};
use std::os::raw::c_char;
#[repr(C)]
pub struct ExceptionResult {
pub cycles: usize,
pub exception: u8,
}
#[repr(C)]
pub struct GetSetResult {
pub data: u32,
pub exception: u8,
}
#[repr(C)]
pub struct M68000Callbacks {
pub get_byte: extern "C" fn(addr: u32, user_data: *mut c_void) -> GetSetResult,
pub get_word: extern "C" fn(addr: u32, user_data: *mut c_void) -> GetSetResult,
pub get_long: extern "C" fn(addr: u32, user_data: *mut c_void) -> GetSetResult,
pub set_byte: extern "C" fn(addr: u32, data: u8, user_data: *mut c_void) -> GetSetResult,
pub set_word: extern "C" fn(addr: u32, data: u16, user_data: *mut c_void) -> GetSetResult,
pub set_long: extern "C" fn(addr: u32, data: u32, user_data: *mut c_void) -> GetSetResult,
pub reset_instruction: extern "C" fn(*mut c_void),
pub user_data: *mut c_void,
}
impl MemoryAccess for M68000Callbacks {
fn get_byte(&mut self, addr: u32) -> Option<u8> {
let res = (self.get_byte)(addr, self.user_data);
if res.exception == 0 {
Some(res.data as u8)
} else {
None
}
}
fn get_word(&mut self, addr: u32) -> Option<u16> {
let res = (self.get_word)(addr, self.user_data);
if res.exception == 0 {
Some(res.data as u16)
} else {
None
}
}
fn get_long(&mut self, addr: u32) -> Option<u32> {
let res = (self.get_long)(addr, self.user_data);
if res.exception == 0 {
Some(res.data)
} else {
None
}
}
fn set_byte(&mut self, addr: u32, value: u8) -> Option<()> {
let res = (self.set_byte)(addr, value, self.user_data);
if res.exception == 0 {
Some(())
} else {
None
}
}
fn set_word(&mut self, addr: u32, value: u16) -> Option<()> {
let res = (self.set_word)(addr, value, self.user_data);
if res.exception == 0 {
Some(())
} else {
None
}
}
fn set_long(&mut self, addr: u32, value: u32) -> Option<()> {
let res = (self.set_long)(addr, value, self.user_data);
if res.exception == 0 {
Some(())
} else {
None
}
}
fn reset_instruction(&mut self) {
(self.reset_instruction)(self.user_data)
}
}
#[no_mangle]
pub extern "C" fn m68000_new() -> *mut M68000 {
Box::into_raw(Box::new(M68000::new()))
}
#[no_mangle]
pub extern "C" fn m68000_new_no_reset() -> *mut M68000 {
Box::into_raw(Box::new(M68000::new_no_reset()))
}
#[no_mangle]
pub extern "C" fn m68000_delete(m68000: *mut M68000) {
unsafe {
std::mem::drop(Box::from_raw(m68000));
}
}
#[no_mangle]
pub extern "C" fn m68000_cycle(m68000: *mut M68000, memory: *mut M68000Callbacks, cycles: usize) -> usize {
unsafe {
(*m68000).cycle(&mut *memory, cycles)
}
}
#[no_mangle]
pub extern "C" fn m68000_cycle_until_exception(m68000: *mut M68000, memory: *mut M68000Callbacks, cycles: usize) -> ExceptionResult {
unsafe {
let (cycles, vector) = (*m68000).cycle_until_exception(&mut *memory, cycles);
ExceptionResult { cycles, exception: vector.unwrap_or(0) }
}
}
#[no_mangle]
pub extern "C" fn m68000_loop_until_exception_stop(m68000: *mut M68000, memory: *mut M68000Callbacks) -> ExceptionResult {
unsafe {
let (cycles, vector) = (*m68000).loop_until_exception_stop(&mut *memory);
ExceptionResult { cycles, exception: vector.unwrap_or(0) }
}
}
#[no_mangle]
pub extern "C" fn m68000_interpreter(m68000: *mut M68000, memory: *mut M68000Callbacks) -> usize {
unsafe {
(*m68000).interpreter(&mut *memory)
}
}
#[no_mangle]
pub extern "C" fn m68000_interpreter_exception(m68000: *mut M68000, memory: *mut M68000Callbacks) -> ExceptionResult {
unsafe {
let (cycles, vector) = (*m68000).interpreter_exception(&mut *memory);
ExceptionResult { cycles, exception: vector.unwrap_or(0) }
}
}
#[no_mangle]
pub extern "C" fn m68000_disassembler_interpreter(m68000: *mut M68000, memory: *mut M68000Callbacks, str: *mut c_char, len: usize) -> usize {
unsafe {
let (dis, cycles) = (*m68000).disassembler_interpreter(&mut *memory);
let cstring = CString::new(dis).expect("New CString for disassembler failed")
.into_bytes_with_nul();
let raw_cstring = std::mem::transmute::<*const u8, *const c_char>(cstring.as_ptr());
if cstring.len() <= len {
str.copy_from_nonoverlapping(raw_cstring, cstring.len());
} else {
str.copy_from_nonoverlapping(raw_cstring, len - 1);
*str.add(len - 1) = 0;
}
cycles
}
}
#[no_mangle]
pub extern "C" fn m68000_disassembler_interpreter_exception(m68000: *mut M68000, memory: *mut M68000Callbacks, str: *mut c_char, len: usize) -> ExceptionResult {
unsafe {
let (dis, cycles, vector) = (*m68000).disassembler_interpreter_exception(&mut *memory);
let cstring = CString::new(dis).expect("New CString for disassembler failed")
.into_bytes_with_nul();
let raw_cstring = std::mem::transmute::<*const u8, *const c_char>(cstring.as_ptr());
if cstring.len() <= len {
str.copy_from_nonoverlapping(raw_cstring, cstring.len());
} else {
str.copy_from_nonoverlapping(raw_cstring, len - 1);
*str.add(len - 1) = 0;
}
ExceptionResult { cycles, exception: vector.unwrap_or(0) }
}
}
#[no_mangle]
pub extern "C" fn m68000_exception(m68000: *mut M68000, vector: Vector) {
unsafe {
(*m68000).exception(Exception::from(vector))
}
}
#[no_mangle]
pub extern "C" fn m68000_peek_next_word(m68000: *mut M68000, memory: *mut M68000Callbacks) -> GetSetResult {
unsafe {
match (*m68000).peek_next_word(&mut *memory) {
Ok(data) => GetSetResult {
data: data as u32,
exception: 0,
},
Err(vec) => GetSetResult {
data: 0,
exception: vec,
},
}
}
}
#[no_mangle]
pub extern "C" fn m68000_registers(m68000: *mut M68000) -> *mut Registers {
unsafe {
&mut (*m68000).regs
}
}
#[no_mangle]
pub extern "C" fn m68000_get_registers(m68000: *const M68000) -> Registers {
unsafe {
(*m68000).regs
}
}
#[no_mangle]
pub extern "C" fn m68000_set_registers(m68000: *mut M68000, regs: Registers) {
unsafe {
(*m68000).regs = regs;
}
}