/src/stdlib.rs
use core::arch::global_asm;

use crate::timer::Ticks;

extern "C" {
    fn _svc_call(a: u32, b: u32, c: u32, d: u32) -> u32;
}

global_asm!(r#"
    .global _svc_call
    .type _svc_call,function
_svc_call:
    svc #64
    bx lr
"#);

pub fn sleep(t: Ticks) {
    unsafe { _svc_call(1, t, 0, 0); }
}

pub fn print(s: &str) {
    let bytes = s.as_bytes();
    write(bytes);
}

pub fn write(buf: &[u8]) {
    let ptr = buf.as_ptr() as u32;
    let len = buf.len();
    let mut written = 0;
    while written < len {
        let w = ptr + (written as u32);
        let l = (len - written) as u32;
        written += unsafe { _svc_call(2, w, l, 0) } as usize;
    }
}

pub fn read(buf: &mut [u8]) -> usize {
    let ptr = buf.as_ptr() as u32;
    let len = buf.len();
    unsafe { _svc_call(3, ptr, len as u32, 0) as usize }
}

pub fn led(on: bool) {
    unsafe { _svc_call(4, on as u32, 0, 0); }
}

pub fn exit() -> ! {
    unsafe { _svc_call(100, 0, 0, 0); }
    unreachable!();
}

pub fn spawn(entry: fn(u32, u32) -> !) -> u32 {
    let entry = entry as u32;
    unsafe { _svc_call(101, entry, 0, 0) }
}

pub fn ps() {
    unsafe { _svc_call(102, 0, 0, 0); }
}

pub fn kernel_panic() {
    unsafe { _svc_call(200, 0, 0, 0); }
}

pub fn kb_read_matrix(buf: &mut [u32; 3]) {
    let ptr = buf.as_ptr() as u32;
    unsafe { _svc_call(1000, ptr, 0, 0); }
}

pub fn kb_write_hid(buf: &[u8]) -> bool {
    let ptr = buf.as_ptr() as u32;
    let len = buf.len() as u32;
    unsafe { _svc_call(1001, ptr, len, 0) == 1 }
}