1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(not(feature = "std"))]
92extern crate alloc;
93
94use core::ffi::c_void;
95
96#[repr(u32)]
98#[derive(Copy, Clone, Debug, Eq, PartialEq)]
99pub enum Button {
100 B = 0,
101 Y = 1,
102 Select = 2,
103 Start = 3,
104 Up = 4,
105 Down = 5,
106 Left = 6,
107 Right = 7,
108 A = 8,
109 X = 9,
110 L1 = 10,
111 R1 = 11,
112 L2 = 12,
113 R2 = 13,
114 L3 = 14,
115 R3 = 15,
116}
117
118#[repr(C)]
120#[derive(Copy, Clone, Debug, Eq, PartialEq)]
121pub struct TextSize {
122 pub width: u32,
123 pub height: u32,
124}
125
126#[allow(non_camel_case_types)]
128pub mod sys {
129 unsafe extern "C" {
130 #[link_name = "wasm96_graphics_set_size"]
132 pub fn graphics_set_size(width: u32, height: u32);
133 #[link_name = "wasm96_graphics_set_color"]
134 pub fn graphics_set_color(r: u32, g: u32, b: u32, a: u32);
135 #[link_name = "wasm96_graphics_background"]
136 pub fn graphics_background(r: u32, g: u32, b: u32);
137 #[link_name = "wasm96_graphics_point"]
138 pub fn graphics_point(x: i32, y: i32);
139 #[link_name = "wasm96_graphics_line"]
140 pub fn graphics_line(x1: i32, y1: i32, x2: i32, y2: i32);
141 #[link_name = "wasm96_graphics_rect"]
142 pub fn graphics_rect(x: i32, y: i32, w: u32, h: u32);
143 #[link_name = "wasm96_graphics_rect_outline"]
144 pub fn graphics_rect_outline(x: i32, y: i32, w: u32, h: u32);
145 #[link_name = "wasm96_graphics_circle"]
146 pub fn graphics_circle(x: i32, y: i32, r: u32);
147 #[link_name = "wasm96_graphics_circle_outline"]
148 pub fn graphics_circle_outline(x: i32, y: i32, r: u32);
149 #[link_name = "wasm96_graphics_image"]
150 pub fn graphics_image(x: i32, y: i32, w: u32, h: u32, ptr: u32, len: u32);
151
152 #[link_name = "wasm96_graphics_image_png"]
154 pub fn graphics_image_png(x: i32, y: i32, ptr: u32, len: u32);
155 #[link_name = "wasm96_graphics_image_jpeg"]
156 pub fn graphics_image_jpeg(x: i32, y: i32, ptr: u32, len: u32);
157
158 #[link_name = "wasm96_graphics_mtl_register_texture"]
163 pub fn graphics_mtl_register_texture(
164 texture_key: u64,
165 mtl_ptr: u32,
166 mtl_len: u32,
167 tex_filename_ptr: u32,
168 tex_filename_len: u32,
169 tex_ptr: u32,
170 tex_len: u32,
171 ) -> u32;
172
173 #[link_name = "wasm96_graphics_svg_register"]
176 pub fn graphics_svg_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
177 #[link_name = "wasm96_graphics_svg_draw_key"]
178 pub fn graphics_svg_draw_key(key: u64, x: i32, y: i32, w: u32, h: u32);
179 #[link_name = "wasm96_graphics_svg_unregister"]
180 pub fn graphics_svg_unregister(key: u64);
181
182 #[link_name = "wasm96_graphics_gif_register"]
184 pub fn graphics_gif_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
185 #[link_name = "wasm96_graphics_gif_draw_key"]
186 pub fn graphics_gif_draw_key(key: u64, x: i32, y: i32);
187 #[link_name = "wasm96_graphics_gif_draw_key_scaled"]
188 pub fn graphics_gif_draw_key_scaled(key: u64, x: i32, y: i32, w: u32, h: u32);
189 #[link_name = "wasm96_graphics_gif_unregister"]
190 pub fn graphics_gif_unregister(key: u64);
191
192 #[link_name = "wasm96_graphics_png_register"]
194 pub fn graphics_png_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
195 #[link_name = "wasm96_graphics_png_draw_key"]
196 pub fn graphics_png_draw_key(key: u64, x: i32, y: i32);
197 #[link_name = "wasm96_graphics_png_draw_key_scaled"]
198 pub fn graphics_png_draw_key_scaled(key: u64, x: i32, y: i32, w: u32, h: u32);
199 #[link_name = "wasm96_graphics_png_unregister"]
200 pub fn graphics_png_unregister(key: u64);
201
202 #[link_name = "wasm96_graphics_jpeg_register"]
204 pub fn graphics_jpeg_register(key: u64, data_ptr: u32, data_len: u32) -> u32;
205 #[link_name = "wasm96_graphics_jpeg_draw_key"]
206 pub fn graphics_jpeg_draw_key(key: u64, x: i32, y: i32);
207 #[link_name = "wasm96_graphics_jpeg_draw_key_scaled"]
208 pub fn graphics_jpeg_draw_key_scaled(key: u64, x: i32, y: i32, w: u32, h: u32);
209 #[link_name = "wasm96_graphics_jpeg_unregister"]
210 pub fn graphics_jpeg_unregister(key: u64);
211
212 #[link_name = "wasm96_graphics_font_register_ttf"]
226 pub fn graphics_font_register_ttf(key: u64, data_ptr: u32, data_len: u32) -> u32;
227 #[link_name = "wasm96_graphics_font_register_bdf"]
228 pub fn graphics_font_register_bdf(key: u64, data_ptr: u32, data_len: u32) -> u32;
229 #[link_name = "wasm96_graphics_font_register_spleen"]
230 pub fn graphics_font_register_spleen(key: u64, size: u32) -> u32;
231 #[link_name = "wasm96_graphics_font_unregister"]
232 pub fn graphics_font_unregister(key: u64);
233
234 #[link_name = "wasm96_graphics_text_key"]
238 pub fn graphics_text_key(x: i32, y: i32, font_key: u64, text_ptr: u32, text_len: u32);
239
240 #[link_name = "wasm96_graphics_text_measure_key"]
244 pub fn graphics_text_measure_key(font_key: u64, text_ptr: u32, text_len: u32) -> u64;
245
246 #[link_name = "wasm96_graphics_triangle"]
247 pub fn graphics_triangle(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32);
248
249 #[link_name = "wasm96_graphics_triangle_outline"]
250 pub fn graphics_triangle_outline(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32);
251
252 #[link_name = "wasm96_graphics_bezier_quadratic"]
253 pub fn graphics_bezier_quadratic(
254 x1: i32,
255 y1: i32,
256 cx: i32,
257 cy: i32,
258 x2: i32,
259 y2: i32,
260 segments: u32,
261 );
262
263 #[link_name = "wasm96_graphics_bezier_cubic"]
264 pub fn graphics_bezier_cubic(
265 x1: i32,
266 y1: i32,
267 cx1: i32,
268 cy1: i32,
269 cx2: i32,
270 cy2: i32,
271 x2: i32,
272 y2: i32,
273 segments: u32,
274 );
275
276 #[link_name = "wasm96_graphics_pill"]
277 pub fn graphics_pill(x: i32, y: i32, w: u32, h: u32);
278
279 #[link_name = "wasm96_graphics_pill_outline"]
280 pub fn graphics_pill_outline(x: i32, y: i32, w: u32, h: u32);
281
282 #[link_name = "wasm96_graphics_set_3d"]
284 pub fn graphics_set_3d(enable: u32);
285
286 #[link_name = "wasm96_graphics_camera_look_at"]
287 pub fn graphics_camera_look_at(
288 eye_x: f32,
289 eye_y: f32,
290 eye_z: f32,
291 target_x: f32,
292 target_y: f32,
293 target_z: f32,
294 up_x: f32,
295 up_y: f32,
296 up_z: f32,
297 );
298
299 #[link_name = "wasm96_graphics_camera_perspective"]
300 pub fn graphics_camera_perspective(fovy: f32, aspect: f32, near: f32, far: f32);
301
302 #[link_name = "wasm96_graphics_mesh_create"]
303 pub fn graphics_mesh_create(
304 key: u64,
305 v_ptr: *const f32,
306 v_len: usize,
307 i_ptr: *const u32,
308 i_len: usize,
309 ) -> u32;
310
311 #[link_name = "wasm96_graphics_mesh_create_obj"]
312 pub fn graphics_mesh_create_obj(key: u64, ptr: *const u8, len: usize) -> u32;
313
314 #[link_name = "wasm96_graphics_mesh_create_stl"]
315 pub fn graphics_mesh_create_stl(key: u64, ptr: *const u8, len: usize) -> u32;
316
317 #[link_name = "wasm96_graphics_mesh_set_texture"]
318 pub fn graphics_mesh_set_texture(mesh_key: u64, image_key: u64) -> u32;
319
320 #[link_name = "wasm96_graphics_mesh_draw"]
321 pub fn graphics_mesh_draw(
322 key: u64,
323 x: f32,
324 y: f32,
325 z: f32,
326 rx: f32,
327 ry: f32,
328 rz: f32,
329 sx: f32,
330 sy: f32,
331 sz: f32,
332 );
333
334 #[link_name = "wasm96_input_is_button_down"]
336 pub fn input_is_button_down(port: u32, btn: u32) -> u32;
337 #[link_name = "wasm96_input_is_key_down"]
338 pub fn input_is_key_down(key: u32) -> u32;
339 #[link_name = "wasm96_input_get_mouse_x"]
340 pub fn input_get_mouse_x() -> i32;
341 #[link_name = "wasm96_input_get_mouse_y"]
342 pub fn input_get_mouse_y() -> i32;
343 #[link_name = "wasm96_input_is_mouse_down"]
344 pub fn input_is_mouse_down(btn: u32) -> u32;
345
346 #[link_name = "wasm96_audio_init"]
348 pub fn audio_init(sample_rate: u32) -> u32;
349 #[link_name = "wasm96_audio_push_samples"]
350 pub fn audio_push_samples(ptr: u32, len: u32);
351
352 #[link_name = "wasm96_audio_play_wav"]
353 pub fn audio_play_wav(ptr: u32, len: u32);
354
355 #[link_name = "wasm96_audio_play_qoa"]
356 pub fn audio_play_qoa(ptr: u32, len: u32);
357
358 #[link_name = "wasm96_audio_play_xm"]
359 pub fn audio_play_xm(ptr: u32, len: u32);
360
361 #[link_name = "wasm96_storage_save"]
363 pub fn storage_save(key: u64, data_ptr: u32, data_len: u32);
364 #[link_name = "wasm96_storage_load"]
365 pub fn storage_load(key: u64) -> u64;
366 #[link_name = "wasm96_storage_free"]
367 pub fn storage_free(ptr: u32, len: u32);
368
369 #[link_name = "wasm96_system_log"]
371 pub fn system_log(ptr: u32, len: u32);
372 #[link_name = "wasm96_system_millis"]
373 pub fn system_millis() -> u64;
374 }
375}
376
377pub mod graphics {
379 use super::sys;
380 use crate::TextSize;
381
382 pub(crate) fn hash_key(key: &str) -> u64 {
383 let mut hash: u64 = 0xcbf29ce484222325;
384 for byte in key.bytes() {
385 hash ^= byte as u64;
386 hash = hash.wrapping_mul(0x100000001b3);
387 }
388 hash
389 }
390
391 pub fn set_size(width: u32, height: u32) {
393 unsafe { sys::graphics_set_size(width, height) }
394 }
395
396 pub fn set_color(r: u8, g: u8, b: u8, a: u8) {
398 unsafe { sys::graphics_set_color(r as u32, g as u32, b as u32, a as u32) }
399 }
400
401 pub fn background(r: u8, g: u8, b: u8) {
403 unsafe { sys::graphics_background(r as u32, g as u32, b as u32) }
404 }
405
406 pub fn point(x: i32, y: i32) {
408 unsafe { sys::graphics_point(x, y) }
409 }
410
411 pub fn line(x1: i32, y1: i32, x2: i32, y2: i32) {
413 unsafe { sys::graphics_line(x1, y1, x2, y2) }
414 }
415
416 pub fn rect(x: i32, y: i32, w: u32, h: u32) {
418 unsafe { sys::graphics_rect(x, y, w, h) }
419 }
420
421 pub fn rect_outline(x: i32, y: i32, w: u32, h: u32) {
423 unsafe { sys::graphics_rect_outline(x, y, w, h) }
424 }
425
426 pub fn circle(x: i32, y: i32, r: u32) {
428 unsafe { sys::graphics_circle(x, y, r) }
429 }
430
431 pub fn circle_outline(x: i32, y: i32, r: u32) {
433 unsafe { sys::graphics_circle_outline(x, y, r) }
434 }
435
436 pub fn image(x: i32, y: i32, w: u32, h: u32, data: &[u8]) {
439 unsafe { sys::graphics_image(x, y, w, h, data.as_ptr() as u32, data.len() as u32) }
440 }
441
442 pub fn image_png(x: i32, y: i32, data: &[u8]) {
444 unsafe { sys::graphics_image_png(x, y, data.as_ptr() as u32, data.len() as u32) }
445 }
446
447 pub fn image_jpeg(x: i32, y: i32, data: &[u8]) {
449 unsafe { sys::graphics_image_jpeg(x, y, data.as_ptr() as u32, data.len() as u32) }
450 }
451
452 pub fn gif_register(key: &str, gif_bytes: &[u8]) -> bool {
456 unsafe {
457 sys::graphics_gif_register(
458 hash_key(key),
459 gif_bytes.as_ptr() as u32,
460 gif_bytes.len() as u32,
461 ) != 0
462 }
463 }
464
465 pub fn gif_draw_key(key: &str, x: i32, y: i32) {
467 unsafe { sys::graphics_gif_draw_key(hash_key(key), x, y) }
468 }
469
470 pub fn gif_draw_key_scaled(key: &str, x: i32, y: i32, w: u32, h: u32) {
472 unsafe { sys::graphics_gif_draw_key_scaled(hash_key(key), x, y, w, h) }
473 }
474
475 pub fn gif_unregister(key: &str) {
477 unsafe { sys::graphics_gif_unregister(hash_key(key)) }
478 }
479
480 pub fn triangle(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
482 unsafe { sys::graphics_triangle(x1, y1, x2, y2, x3, y3) }
483 }
484
485 pub fn triangle_outline(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
487 unsafe { sys::graphics_triangle_outline(x1, y1, x2, y2, x3, y3) }
488 }
489
490 pub fn bezier_quadratic(x1: i32, y1: i32, cx: i32, cy: i32, x2: i32, y2: i32, segments: u32) {
492 unsafe { sys::graphics_bezier_quadratic(x1, y1, cx, cy, x2, y2, segments) }
493 }
494
495 pub fn bezier_cubic(
497 x1: i32,
498 y1: i32,
499 cx1: i32,
500 cy1: i32,
501 cx2: i32,
502 cy2: i32,
503 x2: i32,
504 y2: i32,
505 segments: u32,
506 ) {
507 unsafe { sys::graphics_bezier_cubic(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments) }
508 }
509
510 pub fn pill(x: i32, y: i32, w: u32, h: u32) {
512 unsafe { sys::graphics_pill(x, y, w, h) }
513 }
514
515 pub fn pill_outline(x: i32, y: i32, w: u32, h: u32) {
517 unsafe { sys::graphics_pill_outline(x, y, w, h) }
518 }
519
520 pub fn set_3d(enable: bool) {
525 unsafe { sys::graphics_set_3d(enable as u32) }
526 }
527
528 pub fn camera_look_at(eye: (f32, f32, f32), target: (f32, f32, f32), up: (f32, f32, f32)) {
529 unsafe {
530 sys::graphics_camera_look_at(
531 eye.0, eye.1, eye.2, target.0, target.1, target.2, up.0, up.1, up.2,
532 )
533 }
534 }
535
536 pub fn camera_perspective(fovy: f32, aspect: f32, near: f32, far: f32) {
537 unsafe { sys::graphics_camera_perspective(fovy, aspect, near, far) }
538 }
539
540 pub fn mesh_create(key: &str, vertices: &[f32], indices: &[u32]) -> bool {
541 let k = hash_key(key);
542 unsafe {
543 sys::graphics_mesh_create(
544 k,
545 vertices.as_ptr(),
546 vertices.len(),
547 indices.as_ptr(),
548 indices.len(),
549 ) != 0
550 }
551 }
552
553 pub fn mesh_create_obj(key: &str, obj_data: &[u8]) -> bool {
554 let k = hash_key(key);
555 unsafe { sys::graphics_mesh_create_obj(k, obj_data.as_ptr(), obj_data.len()) != 0 }
556 }
557
558 pub fn mesh_create_stl(key: &str, stl_data: &[u8]) -> bool {
559 let k = hash_key(key);
560 unsafe { sys::graphics_mesh_create_stl(k, stl_data.as_ptr(), stl_data.len()) != 0 }
561 }
562
563 pub fn mesh_draw(
564 key: &str,
565 pos: (f32, f32, f32),
566 rot: (f32, f32, f32),
567 scale: (f32, f32, f32),
568 ) {
569 let k = hash_key(key);
570 unsafe {
571 sys::graphics_mesh_draw(
572 k, pos.0, pos.1, pos.2, rot.0, rot.1, rot.2, scale.0, scale.1, scale.2,
573 )
574 }
575 }
576
577 pub fn mesh_set_texture(mesh_key: &str, image_key: &str) -> bool {
584 unsafe { sys::graphics_mesh_set_texture(hash_key(mesh_key), hash_key(image_key)) != 0 }
585 }
586
587 pub fn svg_register(key: &str, svg_bytes: &[u8]) -> bool {
591 unsafe {
592 sys::graphics_svg_register(
593 hash_key(key),
594 svg_bytes.as_ptr() as u32,
595 svg_bytes.len() as u32,
596 ) != 0
597 }
598 }
599
600 pub fn svg_draw_key(key: &str, x: i32, y: i32, w: u32, h: u32) {
602 unsafe { sys::graphics_svg_draw_key(hash_key(key), x, y, w, h) }
603 }
604
605 pub fn svg_unregister(key: &str) {
607 unsafe { sys::graphics_svg_unregister(hash_key(key)) }
608 }
609
610 pub fn png_register(key: &str, png_bytes: &[u8]) -> bool {
613 unsafe {
614 sys::graphics_png_register(
615 hash_key(key),
616 png_bytes.as_ptr() as u32,
617 png_bytes.len() as u32,
618 ) != 0
619 }
620 }
621
622 pub fn mtl_register_texture(
633 texture_key: &str,
634 mtl_bytes: &[u8],
635 tex_filename: &str,
636 tex_bytes: &[u8],
637 ) -> bool {
638 unsafe {
639 sys::graphics_mtl_register_texture(
640 hash_key(texture_key),
641 mtl_bytes.as_ptr() as u32,
642 mtl_bytes.len() as u32,
643 tex_filename.as_ptr() as u32,
644 tex_filename.len() as u32,
645 tex_bytes.as_ptr() as u32,
646 tex_bytes.len() as u32,
647 ) != 0
648 }
649 }
650
651 pub fn jpeg_register(key: &str, jpeg_bytes: &[u8]) -> bool {
654 unsafe {
655 sys::graphics_jpeg_register(
656 hash_key(key),
657 jpeg_bytes.as_ptr() as u32,
658 jpeg_bytes.len() as u32,
659 ) != 0
660 }
661 }
662
663 pub fn png_draw_key(key: &str, x: i32, y: i32) {
665 unsafe { sys::graphics_png_draw_key(hash_key(key), x, y) }
666 }
667
668 pub fn jpeg_draw_key(key: &str, x: i32, y: i32) {
670 unsafe { sys::graphics_jpeg_draw_key(hash_key(key), x, y) }
671 }
672
673 pub fn png_draw_key_scaled(key: &str, x: i32, y: i32, w: u32, h: u32) {
675 unsafe { sys::graphics_png_draw_key_scaled(hash_key(key), x, y, w, h) }
676 }
677
678 pub fn jpeg_draw_key_scaled(key: &str, x: i32, y: i32, w: u32, h: u32) {
680 unsafe { sys::graphics_jpeg_draw_key_scaled(hash_key(key), x, y, w, h) }
681 }
682
683 pub fn png_unregister(key: &str) {
685 unsafe { sys::graphics_png_unregister(hash_key(key)) }
686 }
687
688 pub fn jpeg_unregister(key: &str) {
690 unsafe { sys::graphics_jpeg_unregister(hash_key(key)) }
691 }
692
693 pub fn font_register_ttf(key: &str, data: &[u8]) -> bool {
710 unsafe {
711 sys::graphics_font_register_ttf(hash_key(key), data.as_ptr() as u32, data.len() as u32)
712 != 0
713 }
714 }
715
716 pub fn font_register_bdf(key: &str, data: &[u8]) -> bool {
730 unsafe {
731 sys::graphics_font_register_bdf(hash_key(key), data.as_ptr() as u32, data.len() as u32)
732 != 0
733 }
734 }
735
736 pub fn font_register_spleen(key: &str, size: u32) -> bool {
753 unsafe { sys::graphics_font_register_spleen(hash_key(key), size) != 0 }
754 }
755
756 pub fn font_unregister(key: &str) {
766 unsafe { sys::graphics_font_unregister(hash_key(key)) }
767 }
768
769 pub fn text_key(x: i32, y: i32, font_key: &str, text: &str) {
784 unsafe {
785 sys::graphics_text_key(
786 x,
787 y,
788 hash_key(font_key),
789 text.as_ptr() as u32,
790 text.len() as u32,
791 )
792 }
793 }
794
795 pub fn text_measure_key(font_key: &str, text: &str) -> TextSize {
816 let packed = unsafe {
817 sys::graphics_text_measure_key(
818 hash_key(font_key),
819 text.as_ptr() as u32,
820 text.len() as u32,
821 )
822 };
823
824 TextSize {
825 width: (packed >> 32) as u32,
826 height: (packed & 0xFFFF_FFFF) as u32,
827 }
828 }
829}
830
831pub mod input {
833 use super::{Button, sys};
834
835 pub fn is_button_down(port: u32, btn: Button) -> bool {
837 unsafe { sys::input_is_button_down(port, btn as u32) != 0 }
838 }
839
840 pub fn is_key_down(key: u32) -> bool {
842 unsafe { sys::input_is_key_down(key) != 0 }
843 }
844
845 pub fn get_mouse_x() -> i32 {
847 unsafe { sys::input_get_mouse_x() }
848 }
849
850 pub fn get_mouse_y() -> i32 {
852 unsafe { sys::input_get_mouse_y() }
853 }
854
855 pub fn is_mouse_down(btn: u32) -> bool {
858 unsafe { sys::input_is_mouse_down(btn) != 0 }
859 }
860}
861
862pub mod audio {
864 use super::sys;
865
866 pub fn init(sample_rate: u32) -> u32 {
868 unsafe { sys::audio_init(sample_rate) }
869 }
870
871 pub fn push_samples(samples: &[i16]) {
874 unsafe { sys::audio_push_samples(samples.as_ptr() as u32, samples.len() as u32) }
875 }
876
877 pub fn play_wav(data: &[u8]) {
880 unsafe { sys::audio_play_wav(data.as_ptr() as u32, data.len() as u32) }
881 }
882
883 pub fn play_qoa(data: &[u8]) {
886 unsafe { sys::audio_play_qoa(data.as_ptr() as u32, data.len() as u32) }
887 }
888
889 pub fn play_xm(data: &[u8]) {
893 unsafe { sys::audio_play_xm(data.as_ptr() as u32, data.len() as u32) }
894 }
895}
896
897pub mod storage {
899 use super::sys;
900
901 pub fn save(key: &str, data: &[u8]) {
903 unsafe {
904 sys::storage_save(
905 super::graphics::hash_key(key),
906 data.as_ptr() as u32,
907 data.len() as u32,
908 )
909 }
910 }
911
912 pub fn load(key: &str) -> Option<Vec<u8>> {
915 let packed = unsafe { sys::storage_load(super::graphics::hash_key(key)) };
916 if packed == 0 {
917 return None;
918 }
919
920 let ptr = (packed >> 32) as u32;
921 let len = packed as u32;
922
923 let mut data = Vec::with_capacity(len as usize);
925 unsafe {
926 core::ptr::copy_nonoverlapping(ptr as *const u8, data.as_mut_ptr(), len as usize);
927 data.set_len(len as usize);
928 }
929
930 unsafe { sys::storage_free(ptr, len) };
932
933 Some(data)
934 }
935}
936
937pub mod system {
939 use super::sys;
940
941 pub fn log(message: &str) {
943 unsafe { sys::system_log(message.as_ptr() as u32, message.len() as u32) }
944 }
945
946 pub fn millis() -> u64 {
948 unsafe { sys::system_millis() }
949 }
950}
951
952pub mod prelude {
954 pub use crate::Button;
955 pub use crate::TextSize;
956 pub use crate::audio;
957 pub use crate::graphics;
958 pub use crate::input;
959 pub use crate::storage;
960 pub use crate::system;
961}
962
963#[allow(dead_code)]
965const _C_VOID: *const c_void = core::ptr::null();