Skip to main content

MacMemoryBus

Struct MacMemoryBus 

Source
pub struct MacMemoryBus { /* private fields */ }
Expand description

Flat guest RAM with low-memory globals, a process heap adapter, and diagnostics.

Implementations§

Source§

impl MacMemoryBus

Source

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.

Source

pub fn new(ram_size: usize) -> Self

Create a new memory bus with the given RAM size

Source

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.

Source

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.

Source

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.

Source

pub fn alloc(&mut self, size: u32) -> u32

Source

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.

Source

pub fn get_alloc_size(&self, addr: u32) -> Option<u32>

Return the allocated size for a given address, or None if unknown.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn load(&mut self, address: u32, data: &[u8])

Load data into memory at the given address

Source

pub fn globals(&self) -> &LowMemGlobals

Get reference to low-memory globals

Source

pub fn globals_mut(&mut self) -> &mut LowMemGlobals

Get mutable reference to low-memory globals

Source

pub fn ram_size(&self) -> u32

Get RAM size

Source

pub fn set_addressing_32_bit(&mut self, enabled: bool)

Select the guest MMU address width. The default is 32-bit addressing.

Source

pub fn addressing_32_bit(&self) -> bool

Whether guest memory accesses currently use all 32 address bits.

Source

pub fn translate_guest_address(&self, address: u32) -> u32

Source

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

Source§

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 read_byte(&mut self, addr: u32) -> u8

Read one byte from address.
Source§

fn write_byte(&mut self, addr: u32, val: u8)

Write one byte to address.
Source§

fn read_word(&mut self, addr: u32) -> u16

Read one big-endian 16-bit word from address.
Source§

fn write_word(&mut self, addr: u32, val: u16)

Write one big-endian 16-bit word to address.
Source§

fn read_long(&mut self, addr: u32) -> u32

Read one big-endian 32-bit longword from address.
Source§

fn write_long(&mut self, addr: u32, val: u32)

Write one big-endian 32-bit longword to address.
Source§

fn sync(&mut self, _cpu_clocks: u32)

Precise-timing callback (Part E.2): called immediately before each bus access with the number of CPU clocks of internal (non-bus) processing the core performed since its previous access. The access itself then takes the standard 4 CPU clocks of a 68000 bus cycle. Read more
Source§

fn try_read_byte(&mut self, address: u32) -> Result<u8, BusFault>

Fallible read variants used to surface bus/MMU faults to the CPU core. Read more
Source§

fn try_read_word(&mut self, address: u32) -> Result<u16, BusFault>

Fallible word read used for bus/MMU fault delivery. Read more
Source§

fn try_read_long(&mut self, address: u32) -> Result<u32, BusFault>

Fallible longword read used for bus/MMU fault delivery. Read more
Source§

fn try_write_byte(&mut self, address: u32, value: u8) -> Result<(), BusFault>

Fallible byte write used for bus/MMU fault delivery. Read more
Source§

fn try_write_word(&mut self, address: u32, value: u16) -> Result<(), BusFault>

Fallible word write used for bus/MMU fault delivery. Read more
Source§

fn try_write_long(&mut self, address: u32, value: u32) -> Result<(), BusFault>

Fallible longword write used for bus/MMU fault delivery. Read more
Source§

fn read_three_bytes(&mut self, address: u32) -> u32

Read a big-endian three-byte operand from address, returned in the low 24 bits. Read more
Source§

fn write_three_bytes(&mut self, address: u32, value: u32)

Write the low 24 bits of value as a big-endian three-byte operand. Read more
Source§

fn try_read_three_bytes(&mut self, address: u32) -> Result<u32, BusFault>

Fallible three-byte read used for bus/MMU fault delivery. This is the variant the core calls, so a host that bills bus cycles must override it (as well as AddressBus::read_three_bytes) for the billing to take effect. Read more
Source§

fn try_write_three_bytes( &mut self, address: u32, value: u32, ) -> Result<(), BusFault>

Fallible three-byte write used for bus/MMU fault delivery. Read more
Source§

fn read_immediate_word(&mut self, address: u32) -> u16

Read an instruction-stream word. Read more
Source§

fn read_immediate_long(&mut self, address: u32) -> u32

Read an instruction-stream longword. Read more
Source§

fn try_read_immediate_word(&mut self, address: u32) -> Result<u16, BusFault>

Instruction-stream reads with bus-fault reporting, used by the non-prefetch (68010+) opcode/immediate path so hosts can tell fetches from data reads (e.g. to model a 32-bit fetch path).
Source§

fn try_read_immediate_long(&mut self, address: u32) -> Result<u32, BusFault>

Fallible instruction-stream longword read. Read more
Source§

fn last_fetch_was_cached(&self) -> bool

Whether the most recent instruction-stream read was served from the CPU’s instruction cache. The 68060 timing model gates superscalar pairing and branch folding on a cached fetch stream; plain test buses default to true (pair freely).
Source§

fn begin_instruction_fetches(&mut self)

Start tracking cache residency for one complete instruction. The MC68020 timing tables define their cache case for an instruction that is in the cache, including extension and immediate words rather than only the opcode word. Hosts with an instruction-cache model use this hook to reset their per-instruction hit accumulator.
Source§

fn instruction_fetches_were_cached(&self) -> bool

Whether every instruction-stream access since 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

Take a pending request to return from cycle-scheduled execution at the next completed instruction or interrupt-entry boundary. Read more
Source§

fn interrupt_acknowledge(&mut self, _level: u8) -> u32

Perform an interrupt-acknowledge cycle for level. Read more
Source§

fn ipl_hold_sample(&mut self)

IPL poll-point marker. The 68000/68010 sample their IPL pins at ONE microcode-determined point per instruction, and the take-interrupt decision at the next instruction boundary consumes that sample. A timing-accurate host latches the IPL level at the start of every bus access and, by default, lets the instruction’s LAST access provide the boundary sample. For instructions whose poll point is NOT the last access (e.g. read-modify-write instructions poll during the final prefetch that precedes the writeback), the core calls this right after the polling access: the host must keep that access’s sample and ignore later accesses until the boundary decision consumes it. Functional-only buses can ignore it.
Source§

fn ipl_release_sample(&mut self)

Release an 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)

Notify attached devices that the CPU asserted the external RESET line.
Source§

impl MemoryBus for MacMemoryBus

Source§

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

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)

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)

Big-endian 32-bit write.

Same fast-path optimisation as write_word.

Source§

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])

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])

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, )

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 read_byte(&self, address: u32) -> u8

Read a byte from memory
Source§

fn write_byte(&mut self, address: u32, value: u8)

Write a byte to memory
Source§

fn fill_zeros(&mut self, address: u32, len: u32)

Zero-fill a region of memory. Default impl is a byte-by-byte loop; the 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)

Fill a region of memory with a repeated byte.
Source§

fn ram_size(&self) -> u32

Get the total RAM size
Source§

fn application_memory_limit(&self) -> u32

Highest address available to the application heap, globals, and stack. Implementations may reserve RAM above this boundary for emulated hardware and host-owned callback code.
Source§

fn read_pstring(&self, address: u32) -> Vec<u8>

Read a Pascal string (length-prefixed) from memory. Delegates to 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])

Write a Pascal string (length-prefixed) to memory. Clamps to the Pascal-string max of 255 bytes (the length byte’s range) and routes the data through Self::write_bytes so the slice fast path on MacMemoryBus applies.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more