risc96-rs 0.1.0

Rust SDK for risc96 fantasy console cartridges
Documentation
#![no_std]

pub const FB_WIDTH: usize = 320;
pub const FB_HEIGHT: usize = 224;
pub const FB_PIXELS: usize = FB_WIDTH * FB_HEIGHT;

pub const AUDIO_SAMPLE_RATE: usize = 48_000;
pub const AUDIO_CHANNELS: usize = 2;
pub const AUDIO_FRAMES_PER_VIDEO_FRAME: usize = 800;
pub const AUDIO_SAMPLES: usize = AUDIO_FRAMES_PER_VIDEO_FRAME * AUDIO_CHANNELS;

pub const CONTROLLER_BUTTONS: usize = 12;

const SYS_GET_FRAMEBUFFER: usize = 500;
const SYS_GET_AUDIOBUFFER: usize = 501;
const SYS_CONTROLLER_1: usize = 502;
const SYS_CONTROLLER_2: usize = 503;
const SYS_CONTROLLER_3: usize = 504;
const SYS_CONTROLLER_4: usize = 505;
const SYS_PRESENT: usize = 506;

#[repr(u8)]
#[derive(Copy, Clone)]
pub enum Button {
    Up = 0,
    Down = 1,
    Left = 2,
    Right = 3,
    A = 4,
    B = 5,
    X = 6,
    Y = 7,
    L1 = 8,
    R1 = 9,
    Start = 10,
    Select = 11,
}

#[inline]
fn syscall0(sysno: usize) -> usize {
    #[cfg(target_arch = "riscv32")]
    {
        let mut a0: usize;
        unsafe {
            core::arch::asm!(
                "ecall",
                in("a7") sysno,
                lateout("a0") a0,
                options(nostack)
            );
        }
        a0
    }

    #[cfg(not(target_arch = "riscv32"))]
    {
        let _ = sysno;
        0
    }
}

#[inline]
pub fn framebuffer() -> *mut u32 {
    syscall0(SYS_GET_FRAMEBUFFER) as *mut u32
}

#[inline]
pub fn audiobuffer() -> *mut i16 {
    syscall0(SYS_GET_AUDIOBUFFER) as *mut i16
}

#[inline]
pub fn controller_1() -> *const u8 {
    syscall0(SYS_CONTROLLER_1) as *const u8
}

#[inline]
pub fn controller_2() -> *const u8 {
    syscall0(SYS_CONTROLLER_2) as *const u8
}

#[inline]
pub fn controller_3() -> *const u8 {
    syscall0(SYS_CONTROLLER_3) as *const u8
}

#[inline]
pub fn controller_4() -> *const u8 {
    syscall0(SYS_CONTROLLER_4) as *const u8
}

#[inline]
pub fn present() {
    let _ = syscall0(SYS_PRESENT);
}

#[inline]
pub fn rgb(r: u8, g: u8, b: u8) -> u32 {
    ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
}

#[inline]
pub fn button_level(packed: *const u8, button: Button) -> u8 {
    let bit = (button as usize) * 2;
    let byte_index = bit >> 3;
    let shift = bit & 7;

    unsafe { ((*packed.add(byte_index) >> shift) & 0x3) as u8 }
}