pub struct MacMemoryBus { /* private fields */ }Expand description
Flat guest RAM with low-memory globals, a process heap adapter, and diagnostics.
Implementations§
Source§impl MacMemoryBus
impl MacMemoryBus
Sourcepub fn block_move(&mut self, src: u32, dst: u32, count: u32)
pub fn block_move(&mut self, src: u32, dst: u32, count: u32)
BlockMove fast path. Copies count bytes from src to
dst, handling overlap correctly. When both ranges are fully
inside RAM and no watchpoint is armed, uses slice::copy_within
— one bounds check, memmove-grade throughput. Falls back to
byte-at-a-time (preserving the overlap-handling order from
Inside Macintosh II-44) when the fast path doesn’t apply.
Sourcepub unsafe fn wrap_external(
ram_ptr: *mut u8,
ram_size: usize,
globals: LowMemGlobals,
) -> Self
pub unsafe fn wrap_external( ram_ptr: *mut u8, ram_size: usize, globals: LowMemGlobals, ) -> Self
Create a memory bus wrapping an external RAM slice
§Safety
The RAM slice must remain valid for the lifetime of this bus.
Sourcepub fn reserve_heap(&mut self, size: u32)
pub fn reserve_heap(&mut self, size: u32)
Allocate memory from heap. Reuses freed blocks via best-fit (smallest free block >= request), otherwise bump-allocates. Returns 0 on OOM; callers must set memFullErr. Reserve space at the start of the heap without returning it. Used to protect zone headers from being overwritten by alloc(). Idempotent so callers can reserve before resources are loaded and later write the zone header during application initialization.
Sourcepub fn reserve_heap_until(&mut self, end_addr: u32)
pub fn reserve_heap_until(&mut self, end_addr: u32)
Advance the heap bump pointer past an absolute guest address.
Loader-owned regions are written directly rather than allocated through the Memory Manager shim, so the runner uses this before materializing Toolbox heap objects that must not overlap the loaded application image.
pub fn alloc(&mut self, size: u32) -> u32
Sourcepub fn alloc_aligned(&mut self, size: u32, alignment: u32) -> u32
pub fn alloc_aligned(&mut self, size: u32, alignment: u32) -> u32
Allocate memory from the heap with a stronger start-address alignment.
This keeps the same user-visible size and free-list behavior as
Self::alloc, but lets Toolbox managers request stable record
placement without making every heap allocation pay that cost.
Sourcepub fn get_alloc_size(&self, addr: u32) -> Option<u32>
pub fn get_alloc_size(&self, addr: u32) -> Option<u32>
Return the allocated size for a given address, or None if unknown.
Sourcepub fn set_alloc_size(&mut self, addr: u32, new_size: u32)
pub fn set_alloc_size(&mut self, addr: u32, new_size: u32)
Update the logical size of an existing allocation. Used by SetPtrSize / SetHandleSize for in-place resize. Caller is responsible for ensuring the new size fits within the original 4-byte-aligned capacity — see trap/memory.rs SetPtrSize.
No-op for unknown addresses.
Sourcepub fn free(&mut self, addr: u32)
pub fn free(&mut self, addr: u32)
Return a previously allocated block to the free list for reuse. Does nothing for null pointers or unknown addresses.
Sourcepub fn ram_slice(&self, start: u32, len: u32) -> &[u8] ⓘ
pub fn ram_slice(&self, start: u32, len: u32) -> &[u8] ⓘ
Return a read-only slice of contiguous RAM. Useful for bulk reads (e.g. framebuffer rendering) without per-byte method-call overhead.
Sourcepub fn copy_ram_bytes(&mut self, src: u32, dst: u32, len: u32) -> bool
pub fn copy_ram_bytes(&mut self, src: u32, dst: u32, len: u32) -> bool
Copy a RAM range to another RAM range with one bounds/tracing gate. Falls back to byte writes when debug watchpoints or framebuffer-write tracing are active so diagnostics still observe each destination byte.
Sourcepub fn copy_mapped_ram_bytes(
&mut self,
src: u32,
dst: u32,
len: u32,
map: &[u8; 256],
) -> bool
pub fn copy_mapped_ram_bytes( &mut self, src: u32, dst: u32, len: u32, map: &[u8; 256], ) -> bool
Copy a RAM range through an 8-bit lookup table into another RAM range. Used by indexed blitters that need source-palette to destination-palette translation without allocating a scratch row.
Sourcepub fn globals(&self) -> &LowMemGlobals
pub fn globals(&self) -> &LowMemGlobals
Get reference to low-memory globals
Sourcepub fn globals_mut(&mut self) -> &mut LowMemGlobals
pub fn globals_mut(&mut self) -> &mut LowMemGlobals
Get mutable reference to low-memory globals
Sourcepub fn set_addressing_32_bit(&mut self, enabled: bool)
pub fn set_addressing_32_bit(&mut self, enabled: bool)
Select the guest MMU address width. The default is 32-bit addressing.
Sourcepub fn addressing_32_bit(&self) -> bool
pub fn addressing_32_bit(&self) -> bool
Whether guest memory accesses currently use all 32 address bits.
pub fn translate_guest_address(&self, address: u32) -> u32
Sourcepub fn dump_stack(&self, sp: u32, label: &str)
pub fn dump_stack(&self, sp: u32, label: &str)
Dump stack contents around the given SP for debugging
Trait Implementations§
Source§impl AddressBus for MacMemoryBus
impl AddressBus for MacMemoryBus
Source§fn fast_mem(&mut self) -> Option<FastMem>
fn fast_mem(&mut self) -> Option<FastMem>
Guest RAM is one flat side-effect-free array, so expose it all to
the m68k batch loop. Returns None while bus-access diagnostics
(tracers/watchpoints) are active so they keep seeing every access.
Source§fn write_byte(&mut self, addr: u32, val: u8)
fn write_byte(&mut self, addr: u32, val: u8)
address.Source§fn write_word(&mut self, addr: u32, val: u16)
fn write_word(&mut self, addr: u32, val: u16)
address.Source§fn write_long(&mut self, addr: u32, val: u32)
fn write_long(&mut self, addr: u32, val: u32)
address.Source§fn sync(&mut self, _cpu_clocks: u32)
fn sync(&mut self, _cpu_clocks: u32)
Source§fn try_read_byte(&mut self, address: u32) -> Result<u8, BusFault>
fn try_read_byte(&mut self, address: u32) -> Result<u8, BusFault>
Source§fn try_read_word(&mut self, address: u32) -> Result<u16, BusFault>
fn try_read_word(&mut self, address: u32) -> Result<u16, BusFault>
Source§fn try_read_long(&mut self, address: u32) -> Result<u32, BusFault>
fn try_read_long(&mut self, address: u32) -> Result<u32, BusFault>
Source§fn try_write_byte(&mut self, address: u32, value: u8) -> Result<(), BusFault>
fn try_write_byte(&mut self, address: u32, value: u8) -> Result<(), BusFault>
Source§fn try_write_word(&mut self, address: u32, value: u16) -> Result<(), BusFault>
fn try_write_word(&mut self, address: u32, value: u16) -> Result<(), BusFault>
Source§fn try_write_long(&mut self, address: u32, value: u32) -> Result<(), BusFault>
fn try_write_long(&mut self, address: u32, value: u32) -> Result<(), BusFault>
Source§fn read_three_bytes(&mut self, address: u32) -> u32
fn read_three_bytes(&mut self, address: u32) -> u32
address, returned in the
low 24 bits. Read moreSource§fn write_three_bytes(&mut self, address: u32, value: u32)
fn write_three_bytes(&mut self, address: u32, value: u32)
value as a big-endian three-byte operand. Read moreSource§fn try_read_three_bytes(&mut self, address: u32) -> Result<u32, BusFault>
fn try_read_three_bytes(&mut self, address: u32) -> Result<u32, BusFault>
AddressBus::read_three_bytes) for the
billing to take effect. Read moreSource§fn try_write_three_bytes(
&mut self,
address: u32,
value: u32,
) -> Result<(), BusFault>
fn try_write_three_bytes( &mut self, address: u32, value: u32, ) -> Result<(), BusFault>
Source§fn read_immediate_word(&mut self, address: u32) -> u16
fn read_immediate_word(&mut self, address: u32) -> u16
Source§fn read_immediate_long(&mut self, address: u32) -> u32
fn read_immediate_long(&mut self, address: u32) -> u32
Source§fn try_read_immediate_word(&mut self, address: u32) -> Result<u16, BusFault>
fn try_read_immediate_word(&mut self, address: u32) -> Result<u16, BusFault>
Source§fn try_read_immediate_long(&mut self, address: u32) -> Result<u32, BusFault>
fn try_read_immediate_long(&mut self, address: u32) -> Result<u32, BusFault>
Source§fn last_fetch_was_cached(&self) -> bool
fn last_fetch_was_cached(&self) -> bool
Source§fn begin_instruction_fetches(&mut self)
fn begin_instruction_fetches(&mut self)
Source§fn instruction_fetches_were_cached(&self) -> bool
fn instruction_fetches_were_cached(&self) -> bool
begin_instruction_fetches hit the instruction cache. Functional test
buses without a cache model default to the most recent fetch result.Source§fn take_boundary_request(&mut self) -> bool
fn take_boundary_request(&mut self) -> bool
Source§fn interrupt_acknowledge(&mut self, _level: u8) -> u32
fn interrupt_acknowledge(&mut self, _level: u8) -> u32
level. Read moreSource§fn ipl_hold_sample(&mut self)
fn ipl_hold_sample(&mut self)
Source§fn ipl_release_sample(&mut self)
fn ipl_release_sample(&mut self)
ipl_hold_sample poll-point hold before the instruction
boundary consumes it. Called on exception dispatch: the vector jump’s
handler-entry prefetch is a fresh poll point on real silicon (Moira
jumpToVector polls during the final refill read), so a hold placed
earlier in the faulted instruction must not survive into the handler.Source§fn reset_devices(&mut self)
fn reset_devices(&mut self)
Source§impl MemoryBus for MacMemoryBus
impl MemoryBus for MacMemoryBus
Source§fn read_word(&self, address: u32) -> u16
fn read_word(&self, address: u32) -> u16
Big-endian 16-bit read.
Fast path uses one bounds check + direct slice index instead of
two read_byte calls (each with its own bounds check + branch
on the RamStorage variant). This is on the M68K instruction-
fetch hot path, so per-call overhead dominates. Falls back to
the byte-by-byte path when the read straddles self.ram_size.
Source§fn read_long(&self, address: u32) -> u32
fn read_long(&self, address: u32) -> u32
Big-endian 32-bit read.
Same optimisation as read_word — one bounds check + direct
slice index when the 4 bytes lie wholly within self.ram_size.
Source§fn write_word(&mut self, address: u32, value: u16)
fn write_word(&mut self, address: u32, value: u16)
Big-endian 16-bit write.
Fast-path slice write (one bounds check + direct write) instead
of two write_byte calls. Falls back to byte-at-a-time when
(a) the write straddles ram_size, (b) a debug watchpoint is
armed, or (c) the FB-write tracer is enabled — any of those
needs per-byte dispatch through write_byte.
Source§fn write_long(&mut self, address: u32, value: u32)
fn write_long(&mut self, address: u32, value: u32)
Big-endian 32-bit write.
Same fast-path optimisation as write_word.
Source§fn read_bytes(&self, address: u32, len: usize) -> Vec<u8> ⓘ
fn read_bytes(&self, address: u32, len: usize) -> Vec<u8> ⓘ
Bulk read fast path — one slice_at instead of len byte
reads (each with its own bounds check + RamStorage dispatch).
Used by BlockMove, resource-fork loads, and any other caller
that pulls more than a few bytes at once.
Source§fn read_bytes_into(&self, address: u32, dst: &mut [u8])
fn read_bytes_into(&self, address: u32, dst: &mut [u8])
Zero-alloc bulk read fast path — slice_at + copy_from_slice
directly into the caller’s buffer. Lets per-row readers pre-
allocate one Vec and write row-by-row instead of allocating +
copying twice per row.
Source§fn write_bytes(&mut self, address: u32, data: &[u8])
fn write_bytes(&mut self, address: u32, data: &[u8])
Bulk write fast path — one slice_at_mut + copy_from_slice
instead of per-byte writes. Watchpoint-armed debug builds keep
the byte-at-a-time fallback so per-address watchpoints still
trigger; same for the FB-write tracer.
Source§fn fill_bytes_strided(
&mut self,
address: u32,
stride: u32,
count: u32,
value: u8,
)
fn fill_bytes_strided( &mut self, address: u32, stride: u32, count: u32, value: u8, )
Strided fill fast path: one translation and bounds check for the span from the first to the last byte written, then a stride loop over the RAM slice. Falls back to byte writes — which skip exactly the protected bytes and journal each write — when the span touches read-only code, a write probe is armed, or a tracer is active.
Source§fn write_byte(&mut self, address: u32, value: u8)
fn write_byte(&mut self, address: u32, value: u8)
Source§fn fill_zeros(&mut self, address: u32, len: u32)
fn fill_zeros(&mut self, address: u32, len: u32)
MacMemoryBus override uses a single slice fill on
the underlying RAM. Used by Memory Manager _NewPtrClear /
_NewHandleClear allocators to avoid an intermediate
vec![0u8; size] allocation.Source§fn fill_bytes(&mut self, address: u32, len: u32, value: u8)
fn fill_bytes(&mut self, address: u32, len: u32, value: u8)
Source§fn application_memory_limit(&self) -> u32
fn application_memory_limit(&self) -> u32
Source§fn read_pstring(&self, address: u32) -> Vec<u8> ⓘ
fn read_pstring(&self, address: u32) -> Vec<u8> ⓘ
Self::read_bytes for the data so the underlying slice
fast path on MacMemoryBus applies.Source§fn write_pstring(&mut self, address: u32, data: &[u8])
fn write_pstring(&mut self, address: u32, data: &[u8])
Self::write_bytes so the
slice fast path on MacMemoryBus applies.