pub struct EmuCore { /* private fields */ }Expand description
The pure emulation-core facade: load a ROM, step a frame, expose the framebuffer + audio.
For the present path. Lives behind an Arc<Mutex<…>> when a consumer drives it from a
dedicated thread; stepped synchronously otherwise.
Implementations§
Source§impl EmuCore
impl EmuCore
Sourcepub fn new(seed: u64, region: Region) -> Self
pub fn new(seed: u64, region: Region) -> Self
Power on with a determinism seed and a region. No ROM is loaded yet.
Sourcepub fn load_rom(&mut self, rom: &[u8]) -> Result<(), EmuError>
pub fn load_rom(&mut self, rom: &[u8]) -> Result<(), EmuError>
Load a raw ROM image, transparently unwrapping a zip archive first if rom is one (the
common case of a .sfc/.smc distributed zipped). Header detection + board selection
happen in rustysnes-cart. On success the cart is installed
in a fresh Bus and the system is left ready to boot from the cart’s reset vector on the
first Self::run_frame.
§Errors
Returns an EmuError if the image is empty, is a zip archive that can’t be opened or
contains no recognizable ROM entry, or no valid SNES header is found.
Sourcepub fn firmware_candidates(&self) -> &'static [&'static str]
pub fn firmware_candidates(&self) -> &'static [&'static str]
The coprocessor firmware dumps this cart will accept (filenames), in try order. Empty when the cart needs no external firmware. A host uses this to locate + install the dump.
Sourcepub fn needs_firmware(&self) -> bool
pub fn needs_firmware(&self) -> bool
Whether the loaded cart carries a coprocessor that needs a (not-yet-installed) firmware dump
to function. The honesty posture of docs/adr/0003: without the dump the coprocessor is
non-functional, so a host should prompt for it.
Sourcepub fn install_firmware(&mut self, bytes: &[u8]) -> bool
pub fn install_firmware(&mut self, bytes: &[u8]) -> bool
Supply a coprocessor firmware dump. Returns true if the cart’s board accepted it (right
coprocessor + size); on success the bytes are retained for Power-Cycle.
Sourcepub fn load_sram(&mut self, data: &[u8])
pub fn load_sram(&mut self, data: &[u8])
Restore battery SRAM from a .srm image (truncated/zero-padded to the board’s SRAM size).
Sourcepub fn save_sram(&self) -> &[u8] ⓘ
pub fn save_sram(&self) -> &[u8] ⓘ
The current battery SRAM contents (empty when the cart has no SRAM), for a .srm save.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Soft reset: re-run the cart’s reset vector without clearing RAM (the SNES front-panel Reset button). A no-op when no ROM is loaded.
Sourcepub fn power_cycle(&mut self)
pub fn power_cycle(&mut self)
Power-cycle (hard reset): rebuild a clean machine from the retained ROM + firmware. Battery
SRAM is NOT preserved here (the caller reloads .srm if desired).
Sourcepub const fn rom_loaded(&self) -> bool
pub const fn rom_loaded(&self) -> bool
Whether a ROM is loaded.
Sourcepub fn cart_name(&self) -> Option<&'static str>
pub fn cart_name(&self) -> Option<&'static str>
The loaded cartridge’s board name (for a status display), if any.
Sourcepub fn rom(&self) -> &[u8] ⓘ
pub fn rom(&self) -> &[u8] ⓘ
The raw ROM byte image currently loaded (empty if none) — for TAS movie recording’s
ROM-identity hash (crate::movie::hash_rom/crate::movie::Movie::verify_rom), which
needs the exact bytes rather than Cart’s parsed/header-stripped internal representation.
Sourcepub fn system_mut(&mut self) -> &mut System
pub fn system_mut(&mut self) -> &mut System
Direct mutable access to the deterministic core, for TAS movie record/playback
(crate::movie), Lua scripting, or a debugger overlay — all need genuine read/write
reach into the running System/Bus.
Sourcepub fn set_pad(&mut self, player: usize, buttons: u16)
pub fn set_pad(&mut self, player: usize, buttons: u16)
Latch the controller state for a player (0 = P1, 1 = P2), applied to the Bus at the
top of the next Self::run_frame/Self::apply_pads. Taken as a raw button-state
word, same as crate::bus::Bus::set_joypad — a host is responsible for any input
hygiene it wants (e.g. the frontend’s Buttons::sanitize_dpad clearing illegal opposite
D-pad directions before calling this), matching the honest “this facade stores what it’s
told” posture the rest of its setters already have.
Sourcepub fn apply_pads(&mut self)
pub fn apply_pads(&mut self)
Push the latched pad state to the Bus without running a frame — split out of
Self::run_frame so a host that needs to interleave conditional stepping (a debugger’s
pause/breakpoint gate) can latch input once and then choose how to advance the System.
Sourcepub fn set_port_device(&mut self, port: usize, device: PortDevice)
pub fn set_port_device(&mut self, port: usize, device: PortDevice)
Select which peripheral is attached to controller port port — see
crate::bus::Bus::set_port_device.
Sourcepub fn set_mouse(
&mut self,
port: usize,
dx: i32,
dy: i32,
left: bool,
right: bool,
)
pub fn set_mouse( &mut self, port: usize, dx: i32, dy: i32, left: bool, right: bool, )
Feed one frame’s worth of SNES Mouse input for port port — see
crate::bus::Bus::set_mouse.
Sourcepub fn set_voice_mutes(&mut self, mutes: [bool; 8])
pub fn set_voice_mutes(&mut self, mutes: [bool; 8])
Set the 8 per-voice audio mute toggles — see crate::bus::Bus::set_voice_mutes’s doc.
Sourcepub fn set_superscope(&mut self, port: usize, x: i32, y: i32, buttons: u8)
pub fn set_superscope(&mut self, port: usize, x: i32, y: i32, buttons: u8)
Feed one frame’s worth of Super Scope input for port port — see
crate::bus::Bus::set_superscope.
Sourcepub fn set_multitap_pad(&mut self, port: usize, sub_index: usize, buttons: u16)
pub fn set_multitap_pad(&mut self, port: usize, sub_index: usize, buttons: u16)
Feed one frame’s worth of input for Super Multitap sub-pad sub_index of port port —
see crate::bus::Bus::set_multitap_pad.
Sourcepub fn run_frame(&mut self)
pub fn run_frame(&mut self)
Advance one full video frame unconditionally: latch pads, run the scheduler to the next
frame boundary, then decode the PPU framebuffer + drain the S-DSP audio. A host that needs
conditional stepping (pause/breakpoints) should call Self::apply_pads +
Self::system_mut + Self::present_current_frame directly instead.
Sourcepub fn present_current_frame(&mut self)
pub fn present_current_frame(&mut self)
Decode the PPU framebuffer + drain the S-DSP audio from the System’s CURRENT state,
without advancing it — the second half of Self::run_frame, split out for a host that
drives System::run_frame (or step_instruction) directly (netplay rollback, a debugger’s
single-step) and needs to pick up the result afterward.
Sourcepub fn framebuffer(&self) -> &[u8] ⓘ
pub fn framebuffer(&self) -> &[u8] ⓘ
The current RGBA8 framebuffer slice (the active mode’s w*h*4 bytes), for the present path.
Sourcepub fn audio(&self) -> &[(i16, i16)]
pub fn audio(&self) -> &[(i16, i16)]
The audio samples (32 kHz stereo) produced during the most recent Self::run_frame.
Sourcepub fn save_state(&self) -> Vec<u8> ⓘ
pub fn save_state(&self) -> Vec<u8> ⓘ
Snapshot the full deterministic core state (System::save_state, docs/adr/0006) for
rewind/run-ahead/quick-save. Host-only state (the decoded RGBA8 framebuffer, the retained
ROM/firmware bytes for Power-Cycle, latched pads) is NOT part of this — it’s outside the
deterministic core and is re-derived after Self::load_state.
Sourcepub fn load_state(&mut self, bytes: &[u8]) -> Result<(), SaveStateError>
pub fn load_state(&mut self, bytes: &[u8]) -> Result<(), SaveStateError>
Restore a snapshot taken by Self::save_state from a System with the SAME cart
already loaded (a save-state never embeds ROM bytes, docs/adr/0006) — the caller must
have already load_rom’d the matching ROM. Re-renders the framebuffer immediately so a
host reflects the restored frame without waiting for the next Self::run_frame, and
clears the audio FIFO (a state load jumps time discontinuously; there is no continuous
audio stream to drain across that jump).
§Errors
Propagates rustysnes_savestate::SaveStateError if bytes is truncated/corrupt, from
an incompatible format version, or doesn’t match this System’s currently-loaded cart
(SRAM size, coprocessor presence) — the state is left unchanged on error.