Skip to content

Commit 47332e0

Browse files
committed
ffi support
1 parent 3aa634d commit 47332e0

File tree

3 files changed

+98
-1
lines changed

3 files changed

+98
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ lint:
1313

1414
build-wasm:
1515
cargo build --release --target wasm32-unknown-unknown
16-
wasm-opt -O4 ./target/wasm32-unknown-unknown/release/lr35902.wasm -o gameboy.wasm && du -h gameboy.wasm
16+
wasm-opt -O4 ./target/wasm32-unknown-unknown/release/gameboy.wasm -o gameboy.wasm && du -h gameboy.wasm
1717

1818
test:
1919
cargo test --release

src/input.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub struct Keypad {
66
}
77

88
#[derive(Copy, Clone)]
9+
#[repr(C)]
910
pub enum KeypadKey {
1011
Right,
1112
Left,

src/lib.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::sync::Mutex;
2+
use std::sync::OnceLock;
3+
14
#[cfg(target_arch = "wasm32")]
25
use wasm_bindgen::prelude::*;
36

@@ -10,9 +13,102 @@ mod mmu;
1013
mod mode;
1114
mod screen;
1215

16+
pub use crate::input::KeypadKey;
17+
1318
#[cfg(target_arch = "wasm32")]
1419
#[wasm_bindgen(start)]
1520
pub async fn start() {
1621
// screen::web::render().await
1722
// TODO: Process GL
1823
}
24+
25+
#[no_mangle]
26+
pub static GAMEBOY: OnceLock<Mutex<Option<crate::gameboy::Gameboy>>> = OnceLock::new();
27+
28+
#[cfg(target_vendor = "apple")]
29+
unsafe impl Send for crate::gameboy::Gameboy {}
30+
#[cfg(target_vendor = "apple")]
31+
unsafe impl Sync for crate::gameboy::Gameboy {}
32+
33+
#[no_mangle]
34+
pub extern "C" fn load_rom(bytes: *const std::ffi::c_uchar, bytes_length: usize) {
35+
let bytes = unsafe { std::slice::from_raw_parts(bytes, bytes_length) };
36+
let bytes: Vec<u8> = Vec::from(bytes);
37+
GAMEBOY
38+
.get_or_init(|| Some(crate::gameboy::Gameboy::new(bytes.to_vec(), None)).into());
39+
}
40+
41+
#[no_mangle]
42+
pub extern "C" fn frame() {
43+
if let Some(gb) = GAMEBOY.get() {
44+
if let Ok(mut locked_gb) = gb.lock() {
45+
locked_gb.as_mut().unwrap().frame();
46+
}
47+
}
48+
}
49+
50+
#[no_mangle]
51+
pub extern "C" fn keydown(key: KeypadKey) {
52+
if let Some(gb) = GAMEBOY.get() {
53+
if let Ok(mut locked_gb) = gb.lock() {
54+
locked_gb.as_mut().unwrap().keydown(key);
55+
}
56+
}
57+
}
58+
59+
#[no_mangle]
60+
pub extern "C" fn keyup(key: KeypadKey) {
61+
if let Some(gb) = GAMEBOY.get() {
62+
if let Ok(mut locked_gb) = gb.lock() {
63+
locked_gb.as_mut().unwrap().keyup(key);
64+
}
65+
}
66+
}
67+
68+
#[no_mangle]
69+
pub extern "C" fn width() -> u32 {
70+
if let Some(gb) = GAMEBOY.get() {
71+
if let Ok(mut locked_gb) = gb.lock() {
72+
return locked_gb.as_mut().unwrap().width;
73+
}
74+
}
75+
76+
0
77+
}
78+
79+
#[no_mangle]
80+
pub extern "C" fn height() -> u32 {
81+
if let Some(gb) = GAMEBOY.get() {
82+
if let Ok(mut locked_gb) = gb.lock() {
83+
return locked_gb.as_mut().unwrap().height;
84+
}
85+
}
86+
87+
0
88+
}
89+
90+
#[repr(C)]
91+
pub struct ImageBuffer {
92+
len: i32,
93+
data: *const u8,
94+
}
95+
96+
#[no_mangle]
97+
pub extern "C" fn image() -> ImageBuffer {
98+
if let Some(gb) = GAMEBOY.get() {
99+
if let Ok(mut locked_gb) = gb.lock() {
100+
let image: &[u8] = locked_gb.as_mut().unwrap().image();
101+
let data = image.as_ptr();
102+
let len = image.len() as i32;
103+
// std::mem::forget(image);
104+
// My guess image will be dropped but let's test
105+
106+
return ImageBuffer { len, data };
107+
}
108+
}
109+
110+
ImageBuffer {
111+
len: 0,
112+
data: std::ptr::null_mut(),
113+
}
114+
}

0 commit comments

Comments
 (0)