pub mod bus;
pub mod globals;
pub use bus::{
arm_watchpoint, disarm_watchpoint, get_step, increment_step, set_current_pc,
set_watch_registers, watchpoint_armed, STEP_COUNTER,
};
pub use bus::{MacMemoryBus, MemoryBus};
pub use globals::LowMemGlobals;
pub(crate) const APP_HEAP_COMPAT_FREE_FLOOR: u32 = 24 * 1024 * 1024;
pub(crate) const APP_HEAP_COMPAT_FREE_CAP: u32 = 64 * 1024 * 1024;
const EXPLICIT_PARTITION_HEADROOM: u32 = 1024 * 1024;
pub(crate) fn app_heap_free_bytes(bus: &MacMemoryBus) -> u32 {
let heap_end = bus.read_long(globals::addr::HEAP_END);
let appl_limit = bus.read_long(globals::addr::APPL_LIMIT);
let raw_span = appl_limit.saturating_sub(heap_end);
let raw = app_zone_free_bytes(bus).unwrap_or(raw_span);
let mem_top = bus.read_long(globals::addr::MEM_TOP);
let explicitly_partitioned = mem_top != 0
&& appl_limit != 0
&& appl_limit.saturating_add(EXPLICIT_PARTITION_HEADROOM) < mem_top;
if explicitly_partitioned {
raw.min(APP_HEAP_COMPAT_FREE_CAP)
} else {
raw.clamp(APP_HEAP_COMPAT_FREE_FLOOR, APP_HEAP_COMPAT_FREE_CAP)
}
}
fn app_zone_free_bytes(bus: &MacMemoryBus) -> Option<u32> {
let app_zone = bus.read_long(globals::addr::APP_L_ZONE);
let appl_limit = bus.read_long(globals::addr::APPL_LIMIT);
if app_zone == 0 || appl_limit <= app_zone {
return None;
}
let bk_lim = bus.read_long(app_zone);
let zcb_free = bus.read_long(app_zone + 12);
let zone_size = appl_limit.saturating_sub(app_zone);
if bk_lim == appl_limit && zcb_free > 0 && zcb_free <= zone_size {
Some(zcb_free)
} else {
None
}
}
pub(crate) fn app_partition_size_bytes(bus: &MacMemoryBus) -> u32 {
let app_zone = bus.read_long(globals::addr::APP_L_ZONE);
let appl_limit = bus.read_long(globals::addr::APPL_LIMIT);
if app_zone != 0 && appl_limit > app_zone {
appl_limit - app_zone
} else {
bus.ram_size()
}
}
impl m68k::AddressBus for MacMemoryBus {
#[inline]
fn read_byte(&mut self, addr: u32) -> u8 {
MemoryBus::read_byte(self, addr)
}
#[inline]
fn write_byte(&mut self, addr: u32, val: u8) {
MemoryBus::write_byte(self, addr, val)
}
#[inline]
fn read_word(&mut self, addr: u32) -> u16 {
MemoryBus::read_word(self, addr)
}
#[inline]
fn write_word(&mut self, addr: u32, val: u16) {
MemoryBus::write_word(self, addr, val)
}
#[inline]
fn read_long(&mut self, addr: u32) -> u32 {
MemoryBus::read_long(self, addr)
}
#[inline]
fn write_long(&mut self, addr: u32, val: u32) {
MemoryBus::write_long(self, addr, val)
}
}