#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
use core::ffi::c_void;
#[repr(u32)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Button {
B = 0,
Y = 1,
Select = 2,
Start = 3,
Up = 4,
Down = 5,
Left = 6,
Right = 7,
A = 8,
X = 9,
L1 = 10,
R1 = 11,
L2 = 12,
R2 = 13,
L3 = 14,
R3 = 15,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct TextSize {
pub width: u32,
pub height: u32,
}
#[allow(non_camel_case_types)]
pub mod sys {
unsafe extern "C" {
#[link_name = "wasm96_graphics_set_size"]
pub fn graphics_set_size(width: u32, height: u32);
#[link_name = "wasm96_graphics_set_color"]
pub fn graphics_set_color(r: u32, g: u32, b: u32, a: u32);
#[link_name = "wasm96_graphics_background"]
pub fn graphics_background(r: u32, g: u32, b: u32);
#[link_name = "wasm96_graphics_point"]
pub fn graphics_point(x: i32, y: i32);
#[link_name = "wasm96_graphics_line"]
pub fn graphics_line(x1: i32, y1: i32, x2: i32, y2: i32);
#[link_name = "wasm96_graphics_rect"]
pub fn graphics_rect(x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_rect_outline"]
pub fn graphics_rect_outline(x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_circle"]
pub fn graphics_circle(x: i32, y: i32, r: u32);
#[link_name = "wasm96_graphics_circle_outline"]
pub fn graphics_circle_outline(x: i32, y: i32, r: u32);
#[link_name = "wasm96_graphics_image"]
pub fn graphics_image(x: i32, y: i32, w: u32, h: u32, ptr: u32, len: u32);
#[link_name = "wasm96_graphics_image_png"]
pub fn graphics_image_png(x: i32, y: i32, ptr: u32, len: u32);
#[link_name = "wasm96_graphics_image_jpeg"]
pub fn graphics_image_jpeg(x: i32, y: i32, ptr: u32, len: u32);
#[link_name = "wasm96_graphics_mtl_register_texture"]
pub fn graphics_mtl_register_texture(
texture_key: u64,
mtl_ptr: u32,
mtl_len: u32,
tex_filename_ptr: u32,
tex_filename_len: u32,
tex_ptr: u32,
tex_len: u32,
) -> u32;
#[link_name = "wasm96_graphics_svg_register"]
pub fn graphics_svg_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
#[link_name = "wasm96_graphics_svg_draw_key"]
pub fn graphics_svg_draw_key(key: u64, x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_svg_unregister"]
pub fn graphics_svg_unregister(key: u64);
#[link_name = "wasm96_graphics_gif_register"]
pub fn graphics_gif_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
#[link_name = "wasm96_graphics_gif_draw_key"]
pub fn graphics_gif_draw_key(key: u64, x: i32, y: i32);
#[link_name = "wasm96_graphics_gif_draw_key_scaled"]
pub fn graphics_gif_draw_key_scaled(key: u64, x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_gif_unregister"]
pub fn graphics_gif_unregister(key: u64);
#[link_name = "wasm96_graphics_png_register"]
pub fn graphics_png_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
#[link_name = "wasm96_graphics_png_draw_key"]
pub fn graphics_png_draw_key(key: u64, x: i32, y: i32);
#[link_name = "wasm96_graphics_png_draw_key_scaled"]
pub fn graphics_png_draw_key_scaled(key: u64, x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_png_unregister"]
pub fn graphics_png_unregister(key: u64);
#[link_name = "wasm96_graphics_jpeg_register"]
pub fn graphics_jpeg_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
#[link_name = "wasm96_graphics_jpeg_draw_key"]
pub fn graphics_jpeg_draw_key(key: u64, x: i32, y: i32);
#[link_name = "wasm96_graphics_jpeg_draw_key_scaled"]
pub fn graphics_jpeg_draw_key_scaled(key: u64, x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_jpeg_unregister"]
pub fn graphics_jpeg_unregister(key: u64);
#[link_name = "wasm96_graphics_font_register_ttf"]
pub fn graphics_font_register_ttf(key: u64, data_ptr: u32, data_len: u32) -> u32;
#[link_name = "wasm96_graphics_font_register_bdf"]
pub fn graphics_font_register_bdf(key: u64, data_ptr: u32, data_len: u32) -> u32;
#[link_name = "wasm96_graphics_font_register_spleen"]
pub fn graphics_font_register_spleen(key: u64, size: u32) -> u32;
#[link_name = "wasm96_graphics_font_unregister"]
pub fn graphics_font_unregister(key: u64);
#[link_name = "wasm96_graphics_text_key"]
pub fn graphics_text_key(x: i32, y: i32, font_key: u64, text_ptr: u32, text_len: u32);
#[link_name = "wasm96_graphics_text_measure_key"]
pub fn graphics_text_measure_key(font_key: u64, text_ptr: u32, text_len: u32) -> u64;
#[link_name = "wasm96_graphics_triangle"]
pub fn graphics_triangle(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32);
#[link_name = "wasm96_graphics_triangle_outline"]
pub fn graphics_triangle_outline(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32);
#[link_name = "wasm96_graphics_bezier_quadratic"]
pub fn graphics_bezier_quadratic(
x1: i32,
y1: i32,
cx: i32,
cy: i32,
x2: i32,
y2: i32,
segments: u32,
);
#[link_name = "wasm96_graphics_bezier_cubic"]
pub fn graphics_bezier_cubic(
x1: i32,
y1: i32,
cx1: i32,
cy1: i32,
cx2: i32,
cy2: i32,
x2: i32,
y2: i32,
segments: u32,
);
#[link_name = "wasm96_graphics_pill"]
pub fn graphics_pill(x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_pill_outline"]
pub fn graphics_pill_outline(x: i32, y: i32, w: u32, h: u32);
#[link_name = "wasm96_graphics_set_3d"]
pub fn graphics_set_3d(enable: u32);
#[link_name = "wasm96_graphics_camera_look_at"]
pub fn graphics_camera_look_at(
eye_x: f32,
eye_y: f32,
eye_z: f32,
target_x: f32,
target_y: f32,
target_z: f32,
up_x: f32,
up_y: f32,
up_z: f32,
);
#[link_name = "wasm96_graphics_camera_perspective"]
pub fn graphics_camera_perspective(fovy: f32, aspect: f32, near: f32, far: f32);
#[link_name = "wasm96_graphics_mesh_create"]
pub fn graphics_mesh_create(
key: u64,
v_ptr: *const f32,
v_len: usize,
i_ptr: *const u32,
i_len: usize,
) -> u32;
#[link_name = "wasm96_graphics_mesh_create_obj"]
pub fn graphics_mesh_create_obj(key: u64, ptr: *const u8, len: usize) -> u32;
#[link_name = "wasm96_graphics_mesh_create_stl"]
pub fn graphics_mesh_create_stl(key: u64, ptr: *const u8, len: usize) -> u32;
#[link_name = "wasm96_graphics_mesh_set_texture"]
pub fn graphics_mesh_set_texture(mesh_key: u64, image_key: u64) -> u32;
#[link_name = "wasm96_graphics_mesh_draw"]
pub fn graphics_mesh_draw(
key: u64,
x: f32,
y: f32,
z: f32,
rx: f32,
ry: f32,
rz: f32,
sx: f32,
sy: f32,
sz: f32,
);
#[link_name = "wasm96_input_is_button_down"]
pub fn input_is_button_down(port: u32, btn: u32) -> u32;
#[link_name = "wasm96_input_is_key_down"]
pub fn input_is_key_down(key: u32) -> u32;
#[link_name = "wasm96_input_get_mouse_x"]
pub fn input_get_mouse_x() -> i32;
#[link_name = "wasm96_input_get_mouse_y"]
pub fn input_get_mouse_y() -> i32;
#[link_name = "wasm96_input_is_mouse_down"]
pub fn input_is_mouse_down(btn: u32) -> u32;
#[link_name = "wasm96_audio_init"]
pub fn audio_init(sample_rate: u32) -> u32;
#[link_name = "wasm96_audio_push_samples"]
pub fn audio_push_samples(ptr: u32, len: u32);
#[link_name = "wasm96_audio_play_wav"]
pub fn audio_play_wav(ptr: u32, len: u32);
#[link_name = "wasm96_audio_play_qoa"]
pub fn audio_play_qoa(ptr: u32, len: u32);
#[link_name = "wasm96_audio_play_xm"]
pub fn audio_play_xm(ptr: u32, len: u32);
#[link_name = "wasm96_storage_save"]
pub fn storage_save(key: u64, data_ptr: u32, data_len: u32);
#[link_name = "wasm96_storage_load"]
pub fn storage_load(key: u64) -> u64;
#[link_name = "wasm96_storage_free"]
pub fn storage_free(ptr: u32, len: u32);
#[link_name = "wasm96_system_log"]
pub fn system_log(ptr: u32, len: u32);
#[link_name = "wasm96_system_millis"]
pub fn system_millis() -> u64;
}
}
pub mod graphics {
use super::sys;
use crate::TextSize;
pub(crate) fn hash_key(key: &str) -> u64 {
let mut hash: u64 = 0xcbf29ce484222325;
for byte in key.bytes() {
hash ^= byte as u64;
hash = hash.wrapping_mul(0x100000001b3);
}
hash
}
pub fn set_size(width: u32, height: u32) {
unsafe { sys::graphics_set_size(width, height) }
}
pub fn set_color(r: u8, g: u8, b: u8, a: u8) {
unsafe { sys::graphics_set_color(r as u32, g as u32, b as u32, a as u32) }
}
pub fn background(r: u8, g: u8, b: u8) {
unsafe { sys::graphics_background(r as u32, g as u32, b as u32) }
}
pub fn point(x: i32, y: i32) {
unsafe { sys::graphics_point(x, y) }
}
pub fn line(x1: i32, y1: i32, x2: i32, y2: i32) {
unsafe { sys::graphics_line(x1, y1, x2, y2) }
}
pub fn rect(x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_rect(x, y, w, h) }
}
pub fn rect_outline(x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_rect_outline(x, y, w, h) }
}
pub fn circle(x: i32, y: i32, r: u32) {
unsafe { sys::graphics_circle(x, y, r) }
}
pub fn circle_outline(x: i32, y: i32, r: u32) {
unsafe { sys::graphics_circle_outline(x, y, r) }
}
pub fn image(x: i32, y: i32, w: u32, h: u32, data: &[u8]) {
unsafe { sys::graphics_image(x, y, w, h, data.as_ptr() as u32, data.len() as u32) }
}
pub fn image_png(x: i32, y: i32, data: &[u8]) {
unsafe { sys::graphics_image_png(x, y, data.as_ptr() as u32, data.len() as u32) }
}
pub fn image_jpeg(x: i32, y: i32, data: &[u8]) {
unsafe { sys::graphics_image_jpeg(x, y, data.as_ptr() as u32, data.len() as u32) }
}
pub fn gif_register(key: &str, gif_bytes: &[u8]) -> bool {
unsafe {
sys::graphics_gif_register(
hash_key(key),
gif_bytes.as_ptr() as u32,
gif_bytes.len() as u32,
) != 0
}
}
pub fn gif_draw_key(key: &str, x: i32, y: i32) {
unsafe { sys::graphics_gif_draw_key(hash_key(key), x, y) }
}
pub fn gif_draw_key_scaled(key: &str, x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_gif_draw_key_scaled(hash_key(key), x, y, w, h) }
}
pub fn gif_unregister(key: &str) {
unsafe { sys::graphics_gif_unregister(hash_key(key)) }
}
pub fn triangle(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
unsafe { sys::graphics_triangle(x1, y1, x2, y2, x3, y3) }
}
pub fn triangle_outline(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
unsafe { sys::graphics_triangle_outline(x1, y1, x2, y2, x3, y3) }
}
pub fn bezier_quadratic(x1: i32, y1: i32, cx: i32, cy: i32, x2: i32, y2: i32, segments: u32) {
unsafe { sys::graphics_bezier_quadratic(x1, y1, cx, cy, x2, y2, segments) }
}
pub fn bezier_cubic(
x1: i32,
y1: i32,
cx1: i32,
cy1: i32,
cx2: i32,
cy2: i32,
x2: i32,
y2: i32,
segments: u32,
) {
unsafe { sys::graphics_bezier_cubic(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments) }
}
pub fn pill(x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_pill(x, y, w, h) }
}
pub fn pill_outline(x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_pill_outline(x, y, w, h) }
}
pub fn set_3d(enable: bool) {
unsafe { sys::graphics_set_3d(enable as u32) }
}
pub fn camera_look_at(eye: (f32, f32, f32), target: (f32, f32, f32), up: (f32, f32, f32)) {
unsafe {
sys::graphics_camera_look_at(
eye.0, eye.1, eye.2, target.0, target.1, target.2, up.0, up.1, up.2,
)
}
}
pub fn camera_perspective(fovy: f32, aspect: f32, near: f32, far: f32) {
unsafe { sys::graphics_camera_perspective(fovy, aspect, near, far) }
}
pub fn mesh_create(key: &str, vertices: &[f32], indices: &[u32]) -> bool {
let k = hash_key(key);
unsafe {
sys::graphics_mesh_create(
k,
vertices.as_ptr(),
vertices.len(),
indices.as_ptr(),
indices.len(),
) != 0
}
}
pub fn mesh_create_obj(key: &str, obj_data: &[u8]) -> bool {
let k = hash_key(key);
unsafe { sys::graphics_mesh_create_obj(k, obj_data.as_ptr(), obj_data.len()) != 0 }
}
pub fn mesh_create_stl(key: &str, stl_data: &[u8]) -> bool {
let k = hash_key(key);
unsafe { sys::graphics_mesh_create_stl(k, stl_data.as_ptr(), stl_data.len()) != 0 }
}
pub fn mesh_draw(
key: &str,
pos: (f32, f32, f32),
rot: (f32, f32, f32),
scale: (f32, f32, f32),
) {
let k = hash_key(key);
unsafe {
sys::graphics_mesh_draw(
k, pos.0, pos.1, pos.2, rot.0, rot.1, rot.2, scale.0, scale.1, scale.2,
)
}
}
pub fn mesh_set_texture(mesh_key: &str, image_key: &str) -> bool {
unsafe { sys::graphics_mesh_set_texture(hash_key(mesh_key), hash_key(image_key)) != 0 }
}
pub fn svg_register(key: &str, svg_bytes: &[u8]) -> bool {
unsafe {
sys::graphics_svg_register(
hash_key(key),
svg_bytes.as_ptr() as u32,
svg_bytes.len() as u32,
) != 0
}
}
pub fn svg_draw_key(key: &str, x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_svg_draw_key(hash_key(key), x, y, w, h) }
}
pub fn svg_unregister(key: &str) {
unsafe { sys::graphics_svg_unregister(hash_key(key)) }
}
pub fn png_register(key: &str, png_bytes: &[u8]) -> bool {
unsafe {
sys::graphics_png_register(
hash_key(key),
png_bytes.as_ptr() as u32,
png_bytes.len() as u32,
) != 0
}
}
pub fn mtl_register_texture(
texture_key: &str,
mtl_bytes: &[u8],
tex_filename: &str,
tex_bytes: &[u8],
) -> bool {
unsafe {
sys::graphics_mtl_register_texture(
hash_key(texture_key),
mtl_bytes.as_ptr() as u32,
mtl_bytes.len() as u32,
tex_filename.as_ptr() as u32,
tex_filename.len() as u32,
tex_bytes.as_ptr() as u32,
tex_bytes.len() as u32,
) != 0
}
}
pub fn jpeg_register(key: &str, jpeg_bytes: &[u8]) -> bool {
unsafe {
sys::graphics_jpeg_register(
hash_key(key),
jpeg_bytes.as_ptr() as u32,
jpeg_bytes.len() as u32,
) != 0
}
}
pub fn png_draw_key(key: &str, x: i32, y: i32) {
unsafe { sys::graphics_png_draw_key(hash_key(key), x, y) }
}
pub fn jpeg_draw_key(key: &str, x: i32, y: i32) {
unsafe { sys::graphics_jpeg_draw_key(hash_key(key), x, y) }
}
pub fn png_draw_key_scaled(key: &str, x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_png_draw_key_scaled(hash_key(key), x, y, w, h) }
}
pub fn jpeg_draw_key_scaled(key: &str, x: i32, y: i32, w: u32, h: u32) {
unsafe { sys::graphics_jpeg_draw_key_scaled(hash_key(key), x, y, w, h) }
}
pub fn png_unregister(key: &str) {
unsafe { sys::graphics_png_unregister(hash_key(key)) }
}
pub fn jpeg_unregister(key: &str) {
unsafe { sys::graphics_jpeg_unregister(hash_key(key)) }
}
pub fn font_register_ttf(key: &str, data: &[u8]) -> bool {
unsafe {
sys::graphics_font_register_ttf(hash_key(key), data.as_ptr() as u32, data.len() as u32)
!= 0
}
}
pub fn font_register_bdf(key: &str, data: &[u8]) -> bool {
unsafe {
sys::graphics_font_register_bdf(hash_key(key), data.as_ptr() as u32, data.len() as u32)
!= 0
}
}
pub fn font_register_spleen(key: &str, size: u32) -> bool {
unsafe { sys::graphics_font_register_spleen(hash_key(key), size) != 0 }
}
pub fn font_unregister(key: &str) {
unsafe { sys::graphics_font_unregister(hash_key(key)) }
}
pub fn text_key(x: i32, y: i32, font_key: &str, text: &str) {
unsafe {
sys::graphics_text_key(
x,
y,
hash_key(font_key),
text.as_ptr() as u32,
text.len() as u32,
)
}
}
pub fn text_measure_key(font_key: &str, text: &str) -> TextSize {
let packed = unsafe {
sys::graphics_text_measure_key(
hash_key(font_key),
text.as_ptr() as u32,
text.len() as u32,
)
};
TextSize {
width: (packed >> 32) as u32,
height: (packed & 0xFFFF_FFFF) as u32,
}
}
}
pub mod input {
use super::{Button, sys};
pub fn is_button_down(port: u32, btn: Button) -> bool {
unsafe { sys::input_is_button_down(port, btn as u32) != 0 }
}
pub fn is_key_down(key: u32) -> bool {
unsafe { sys::input_is_key_down(key) != 0 }
}
pub fn get_mouse_x() -> i32 {
unsafe { sys::input_get_mouse_x() }
}
pub fn get_mouse_y() -> i32 {
unsafe { sys::input_get_mouse_y() }
}
pub fn is_mouse_down(btn: u32) -> bool {
unsafe { sys::input_is_mouse_down(btn) != 0 }
}
}
pub mod audio {
use super::sys;
pub fn init(sample_rate: u32) -> u32 {
unsafe { sys::audio_init(sample_rate) }
}
pub fn push_samples(samples: &[i16]) {
unsafe { sys::audio_push_samples(samples.as_ptr() as u32, samples.len() as u32) }
}
pub fn play_wav(data: &[u8]) {
unsafe { sys::audio_play_wav(data.as_ptr() as u32, data.len() as u32) }
}
pub fn play_qoa(data: &[u8]) {
unsafe { sys::audio_play_qoa(data.as_ptr() as u32, data.len() as u32) }
}
pub fn play_xm(data: &[u8]) {
unsafe { sys::audio_play_xm(data.as_ptr() as u32, data.len() as u32) }
}
}
pub mod storage {
use super::sys;
pub fn save(key: &str, data: &[u8]) {
unsafe {
sys::storage_save(
super::graphics::hash_key(key),
data.as_ptr() as u32,
data.len() as u32,
)
}
}
pub fn load(key: &str) -> Option<Vec<u8>> {
let packed = unsafe { sys::storage_load(super::graphics::hash_key(key)) };
if packed == 0 {
return None;
}
let ptr = (packed >> 32) as u32;
let len = packed as u32;
let mut data = Vec::with_capacity(len as usize);
unsafe {
core::ptr::copy_nonoverlapping(ptr as *const u8, data.as_mut_ptr(), len as usize);
data.set_len(len as usize);
}
unsafe { sys::storage_free(ptr, len) };
Some(data)
}
}
pub mod system {
use super::sys;
pub fn log(message: &str) {
unsafe { sys::system_log(message.as_ptr() as u32, message.len() as u32) }
}
pub fn millis() -> u64 {
unsafe { sys::system_millis() }
}
}
pub mod prelude {
pub use crate::Button;
pub use crate::TextSize;
pub use crate::audio;
pub use crate::graphics;
pub use crate::input;
pub use crate::storage;
pub use crate::system;
}
#[allow(dead_code)]
const _C_VOID: *const c_void = core::ptr::null();