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