diff options
Diffstat (limited to 'src/script')
| -rw-r--r-- | src/script/wasm.rs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/script/wasm.rs b/src/script/wasm.rs new file mode 100644 index 0000000..96190f6 --- /dev/null +++ b/src/script/wasm.rs @@ -0,0 +1,121 @@ +use std::time::UNIX_EPOCH; + +use crossterm::{event::KeyCode, style::ContentStyle}; +use wasmi::{Caller, Engine, Linker}; + +use crate::{buffer::Cell, script::ScriptContext}; + +fn add_cell(mut caller: Caller<&mut ScriptContext>, character: u32, location: u32, z: u32) { + caller.data_mut().buffer.cells.push(Cell { + character: char::from_u32(character).unwrap_or_default(), + style: ContentStyle::new(), + x: (location >> 16) as u16, + y: (location & 0xffff) as u16, + z: z as u8, + }); +} + +fn window_size(caller: Caller<&mut ScriptContext>) -> u32 { + let window_size = &caller.data().buffer.window_size; + ((window_size.rows as u32) << 16) | (window_size.columns as u32) +} + +fn is_key_pressed_this_frame(caller: Caller<&mut ScriptContext>, key_code: u32) -> u32 { + const BACKSPACE: u32 = 1 << 24; + const ENTER: u32 = 2 << 24; + const LEFT: u32 = 3 << 24; + const RIGHT: u32 = 4 << 24; + const UP: u32 = 5 << 24; + const DOWN: u32 = 6 << 24; + const HOME: u32 = 7 << 24; + const END: u32 = 8 << 24; + const PAGE_UP: u32 = 9 << 24; + const PAGE_DOWN: u32 = 10 << 24; + const TAB: u32 = 11 << 24; + const BACK_TAB: u32 = 12 << 24; + const DELETE: u32 = 13 << 24; + const INSERT: u32 = 14 << 24; + const F: u32 = 15 << 24; + const CHAR: u32 = 16 << 24; + const ESC: u32 = 17 << 24; + let key_code = match key_code { + 0 => KeyCode::Null, + BACKSPACE => KeyCode::Backspace, + ENTER => KeyCode::Enter, + LEFT => KeyCode::Left, + RIGHT => KeyCode::Right, + UP => KeyCode::Up, + DOWN => KeyCode::Down, + HOME => KeyCode::Home, + END => KeyCode::End, + PAGE_UP => KeyCode::PageUp, + PAGE_DOWN => KeyCode::PageDown, + TAB => KeyCode::Tab, + BACK_TAB => KeyCode::BackTab, + DELETE => KeyCode::Delete, + INSERT => KeyCode::Insert, + F..CHAR => KeyCode::F((key_code & 0xff) as u8), + CHAR..ESC => KeyCode::Char(char::from_u32(key_code & 0xffffff).unwrap_or_default()), + ESC => KeyCode::Esc, + _ => KeyCode::Null, + }; + + if caller.data().input.is_key_pressed_this_frame(key_code) { + 1 + } else { + 0 + } +} + +fn exit(mut caller: Caller<&mut ScriptContext>) { + let _ = caller.data_mut().buffer.finish(); + std::process::exit(0); +} + +fn random_u64() -> u64 { + getrandom::u64().unwrap_or(4) +} + +fn system_now(caller: Caller<&mut ScriptContext>) -> u64 { + caller + .data() + .time + .system_now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos() as u64 +} + +fn monotonic_now(caller: Caller<&mut ScriptContext>) -> u64 { + caller.data().time.monotonic_now().as_nanos() as u64 +} + +fn delta_time(caller: Caller<&mut ScriptContext>) -> u64 { + caller.data().time.delta_time().as_nanos() as u64 +} + +pub fn linker<'ctx>( + engine: &Engine, +) -> Result<wasmi::Linker<&'ctx mut ScriptContext<'ctx>>, wasmi::Error> { + macro_rules! add_fns { + ($linker: expr, [$($func: ident),*]) => { + $($linker.func_wrap("tortuise", stringify!($func), $func)?;)* + }; + } + + let mut linker = Linker::new(engine); + add_fns!( + linker, + [ + add_cell, + window_size, + is_key_pressed_this_frame, + exit, + random_u64, + system_now, + monotonic_now, + delta_time + ] + ); + Ok(linker) +} |
