diff --git a/src/emulator.rs b/src/emulator.rs index 7339c45..027df7b 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -114,6 +114,8 @@ impl Emulator { return Ok(()); }; self.load_rom(SimId::Player2, bytes)?; + let (first, second) = self.sims.split_at_mut(1); + first[0].link(&mut second[0]); Ok(()) } diff --git a/src/emulator/shrooms_vb_core.rs b/src/emulator/shrooms_vb_core.rs index 507085e..8a96ffe 100644 --- a/src/emulator/shrooms_vb_core.rs +++ b/src/emulator/shrooms_vb_core.rs @@ -62,6 +62,8 @@ extern "C" { fn vb_emulate_ex(sims: *mut *mut VB, count: c_uint, cycles: *mut u32) -> c_int; #[link_name = "vbGetCartROM"] fn vb_get_cart_rom(sim: *mut VB, size: *mut u32) -> *mut c_void; + #[link_name = "vbGetPeer"] + fn vb_get_peer(sim: *mut VB) -> *mut VB; #[link_name = "vbGetPixels"] fn vb_get_pixels( sim: *mut VB, @@ -93,6 +95,8 @@ extern "C" { fn vb_set_keys(sim: *mut VB, keys: u16) -> u16; #[link_name = "vbSetOption"] fn vb_set_option(sim: *mut VB, key: VBOption, value: c_int); + #[link_name = "vbSetPeer"] + fn vb_set_peer(sim: *mut VB, peer: *mut VB); #[link_name = "vbSetSamples"] fn vb_set_samples( sim: *mut VB, @@ -194,6 +198,10 @@ impl Sim { Some(vec) } + pub fn link(&mut self, peer: &mut Sim) { + unsafe { vb_set_peer(self.sim, peer.sim) }; + } + pub fn emulate_many(sims: &mut [Sim]) { let mut cycles = 20_000_000; let count = sims.len() as c_uint; @@ -269,6 +277,12 @@ impl Drop for Sim { // SAFETY: we made this pointer ourselves, we can for sure free it unsafe { drop(Box::from_raw(ptr)) }; + // If we're linked to another sim, unlink them from ourselves. + let peer = unsafe { vb_get_peer(self.sim) }; + if !peer.is_null() { + unsafe { vb_set_peer(peer, ptr::null_mut()) }; + } + let len = unsafe { vb_size_of() }.div_ceil(4); // SAFETY: the sim's memory originally came from a Vec let bytes: Vec = unsafe { Vec::from_raw_parts(self.sim.cast(), len, len) };