Skip to main content

micro144_sdk/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use alloc::vec::Vec;
6use core::fmt::{self, Write};
7
8mod sys {
9    #[link(wasm_import_module = "env")]
10    unsafe extern "C" {
11        pub fn GetWinSizeX() -> i32;
12        pub fn GetWinSizeY() -> i32;
13        pub fn SetWinSize(w: i32, h: i32);
14        pub fn GetScreenWidth() -> i32;
15        pub fn GetScreenHeight() -> i32;
16        pub fn DrawRect(x: i32, y: i32, w: i32, h: i32, color: u32);
17        pub fn DrawText(x: i32, y: i32, ptr: *const u8, len: i32, color: u32);
18        pub fn Print(ptr: *const u8, len: i32);
19
20        pub fn GetFileSize(path_ptr: *const u8, path_len: i32) -> i32;
21        pub fn ReadFile(path_ptr: *const u8, path_len: i32, out_ptr: *mut u8, max_len: i32) -> i32;
22        pub fn WriteFile(path_ptr: *const u8, path_len: i32, data_ptr: *const u8, data_len: i32) -> i32;
23        pub fn RmFile(path_ptr: *const u8, len: i32) -> i32;
24
25        pub fn PollEvent(out_ptr: *mut u8) -> i32;
26        pub fn Die(code: i32) -> i32;
27
28        pub fn PerfON() -> i32;
29        pub fn PerfOFF() -> i32;
30    }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum Event {
35    KeyDown(u16),
36    KeyUp(u16),
37    MouseLeftDown { x: i32, y: i32 },
38    MouseLeftUp { x: i32, y: i32 },
39    MouseRightDown { x: i32, y: i32 },
40    MouseRightUp { x: i32, y: i32 },
41    MouseMove { x: i32, y: i32 },
42    ScrollUp,
43    ScrollDown,
44}
45
46pub struct Stdout;
47
48impl Write for Stdout {
49    fn write_str(&mut self, s: &str) -> fmt::Result {
50        print(s);
51        Ok(())
52    }
53}
54
55#[macro_export]
56macro_rules! print {
57    ($($arg:tt)*) => {{
58        use core::fmt::Write;
59        let _ = write!($crate::Stdout, $($arg)*);
60    }};
61}
62
63#[macro_export]
64macro_rules! println {
65    () => ($crate::print!("\n"));
66    ($($arg:tt)*) => {{
67        $crate::print!($($arg)*);
68        $crate::print!("\n");
69    }};
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub struct Color(pub u32);
74
75impl Color {
76    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
77        Self(((r as u32) << 16) | ((g as u32) << 8) | (b as u32))
78    }
79    pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
80        Self(((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32))
81    }
82}
83
84pub struct Window;
85
86impl Window {
87    pub fn size() -> (i32, i32) {
88        unsafe { (sys::GetWinSizeX(), sys::GetWinSizeY()) }
89    }
90
91    pub fn set_size(width: i32, height: i32) {
92        unsafe { sys::SetWinSize(width, height) }
93    }
94
95    pub fn screen_size() -> (i32, i32) {
96        unsafe { (sys::GetScreenWidth(), sys::GetScreenHeight()) }
97    }
98}
99
100pub struct Graphics;
101
102impl Graphics {
103    pub fn draw_rect(x: i32, y: i32, w: i32, h: i32, color: u32) {
104        unsafe { sys::DrawRect(x, y, w, h, color) }
105    }
106
107    pub fn draw_text(x: i32, y: i32, text: &str, color: u32) {
108        unsafe {
109            sys::DrawText(x, y, text.as_ptr(), text.len() as i32, color);
110        }
111    }
112}
113
114pub fn print(text: &str) {
115    unsafe {
116        sys::Print(text.as_ptr(), text.len() as i32);
117    }
118}
119
120pub fn die(code: i32) {
121    unsafe {
122        sys::Die(code);
123    }
124}
125
126pub struct System;
127
128impl System {
129    ///Unsafe because it makes CPU burn
130    pub unsafe fn performance_mode(state: bool) {
131        unsafe {
132            if state { sys::PerfON(); }
133            else { sys::PerfOFF(); }
134        }
135    }
136}
137
138pub struct Fs;
139pub const MAX_FILE_SIZE: i32 = 512 * 1024 * 1024;
140
141impl Fs {
142    pub fn get_file_size(path: &str) -> Result<i32, FsError> {
143        let res = unsafe { sys::GetFileSize(path.as_ptr(), path.len() as i32) };
144        if res >= 0 {
145            Ok(res)
146        } else {
147            Err(FsError::from_code(res))
148        }
149    }
150
151    pub fn read_file(path: &str) -> Result<Vec<u8>, i32> {
152        let size = unsafe { sys::GetFileSize(path.as_ptr(), path.len() as i32) };
153
154        if size < 0 {
155            return Err(size);
156        }
157
158        if size > MAX_FILE_SIZE {
159            return Err(-6);
160        }
161
162        let mut buffer = alloc::vec![0u8; size as usize];
163        let res = unsafe {
164            sys::ReadFile(
165                path.as_ptr(),
166                          path.len() as i32,
167                          buffer.as_mut_ptr(),
168                          buffer.len() as i32,
169            )
170        };
171
172        if res >= 0 {
173            buffer.truncate(res as usize);
174            Ok(buffer)
175        } else {
176            Err(res)
177        }
178    }
179
180    pub fn write_file(path: &str, data: &[u8]) -> Result<(), FsError> {
181        let res = unsafe {
182            sys::WriteFile(
183                path.as_ptr(),
184                           path.len() as i32,
185                           data.as_ptr(),
186                           data.len() as i32,
187            )
188        };
189
190        if res == 0 {
191            Ok(())
192        } else {
193            Err(FsError::from_code(res))
194        }
195    }
196
197    pub fn remove_file(path: &str) -> Result<(), FsError> {
198        let res = unsafe { sys::RmFile(path.as_ptr(), path.len() as i32) };
199
200        if res == 0 {
201            Ok(())
202        } else {
203            Err(FsError::from_code(res))
204        }
205    }
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209pub enum FsError {
210    NotFound,
211    PermissionDenied,
212    AlreadyExists,
213    DiskFull,
214    InvalidPath,
215    FileTooLarge,
216    Unknown(i32),
217}
218
219#[allow(non_upper_case_globals)]
220impl FsError {
221    pub const Dolbayob: Self = crate::FsError::NotFound;
222    pub const IdiNahui: Self = crate::FsError::PermissionDenied;
223    pub const AlreadyFucked: Self = crate::FsError::AlreadyExists;
224    pub const AssFull: Self = crate::FsError::DiskFull;
225    pub const YouInvalid: Self = crate::FsError::InvalidPath;
226    pub const DickTooLarge: Self = crate::FsError::FileTooLarge;
227
228    pub fn from_code(code: i32) -> Self {
229        match code {
230            -1 => Self::NotFound,
231            -2 => Self::PermissionDenied,
232            -3 => Self::AlreadyExists,
233            -4 => Self::DiskFull,
234            -5 => Self::InvalidPath,
235            -6 => Self::FileTooLarge,
236            c => Self::Unknown(c),
237        }
238    }
239
240    pub fn from_code_but_for_me(code: i32) -> Self {
241        match code {
242            -1 => Self::Dolbayob,
243            -2 => Self::IdiNahui,
244            -3 => Self::AlreadyFucked,
245            -4 => Self::AssFull,
246            -5 => Self::YouInvalid,
247            -6 => Self::DickTooLarge,
248            c => Self::Unknown(c),
249        }
250    }
251}
252
253pub fn poll_event() -> Option<Event> {
254    let mut buf = [0u8; 16];
255    let res = unsafe { sys::PollEvent(buf.as_mut_ptr()) };
256
257    if res == 0 {
258        return None;
259    }
260
261    match buf[0] {
262        1 => {
263            let code = u16::from_le_bytes([buf[1], buf[2]]);
264            Some(Event::KeyDown(code))
265        }
266        2 => {
267            let code = u16::from_le_bytes([buf[1], buf[2]]);
268            Some(Event::KeyUp(code))
269        }
270        3 => {
271            let x = i32::from_le_bytes([buf[1], buf[2], buf[3], buf[4]]);
272            let y = i32::from_le_bytes([buf[5], buf[6], buf[7], buf[8]]);
273            Some(Event::MouseLeftDown { x, y })
274        }
275        4 => {
276            let x = i32::from_le_bytes([buf[1], buf[2], buf[3], buf[4]]);
277            let y = i32::from_le_bytes([buf[5], buf[6], buf[7], buf[8]]);
278            Some(Event::MouseLeftUp { x, y })
279        }
280        5 => {
281            let x = i32::from_le_bytes([buf[1], buf[2], buf[3], buf[4]]);
282            let y = i32::from_le_bytes([buf[5], buf[6], buf[7], buf[8]]);
283            Some(Event::MouseRightDown { x, y })
284        }
285        6 => {
286            let x = i32::from_le_bytes([buf[1], buf[2], buf[3], buf[4]]);
287            let y = i32::from_le_bytes([buf[5], buf[6], buf[7], buf[8]]);
288            Some(Event::MouseRightUp { x, y })
289        }
290        7 => {
291            let x = i32::from_le_bytes([buf[1], buf[2], buf[3], buf[4]]);
292            let y = i32::from_le_bytes([buf[5], buf[6], buf[7], buf[8]]);
293            Some(Event::MouseMove { x, y })
294        }
295        8 => Some(Event::ScrollUp),
296        9 => Some(Event::ScrollDown),
297        _ => None,
298    }
299}