use std::ffi::c_void; #[unsafe(no_mangle)] unsafe fn vbu_realloc_shim(ptr: *mut c_void, new_size: usize) -> *mut c_void { if !ptr.is_null() { // not supporting proper realloc because it needs bookkeeping and it's unnecessary return std::ptr::null_mut(); } let allocation = vec![0u8; new_size].into_boxed_slice(); Box::into_raw(allocation).cast() } #[link(name = "vb")] unsafe extern "C" { #[link_name = "vbuFromISX"] fn vbu_from_isx(bytes: *const c_void, length: usize, rom_length: *mut usize) -> *mut c_void; } pub fn rom_from_isx(bytes: &[u8]) -> Option> { if !bytes.starts_with(b"ISX") { return None; } let mut rom_length = 0; let raw_rom = unsafe { vbu_from_isx(bytes.as_ptr().cast(), bytes.len(), &mut rom_length) }; if raw_rom.is_null() { return None; } // SAFETY: the rom was allocated by vbu_realloc_shim, which created it from a Vec. let rom = unsafe { Vec::from_raw_parts(raw_rom.cast(), rom_length, rom_length) }; Some(rom) }