#![no_std]
#![deny(missing_docs)]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Gamepad {
X = 1 << 0,
Z = 1 << 1,
Left = 1 << 4,
Right = 1 << 5,
Up = 1 << 6,
Down = 1 << 7,
}
impl Gamepad {
const GAMEPADS: *const [u8; 4] = 0x16 as *const [u8; 4];
#[inline]
pub fn pressed(self, player: Player) -> bool {
unsafe { (*Self::GAMEPADS)[player as usize] & self as u8 == self as u8 }
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Player {
P1 = 0,
P2,
P3,
P4,
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Mouse {
Left = 1 << 0,
Right = 1 << 1,
Middle = 1 << 2,
}
impl Mouse {
const MOUSE_POSITION: *const [i16; 2] = 0x1a as *const [i16; 2];
const MOUSE_BUTTONS: *const u8 = 0x1e as *const u8;
#[inline]
pub fn pressed(self) -> bool {
unsafe { *Self::MOUSE_BUTTONS & self as u8 == self as u8 }
}
#[inline]
pub fn x() -> i16 {
unsafe { (*Self::MOUSE_POSITION)[0] }
}
#[inline]
pub fn y() -> i16 {
unsafe { (*Self::MOUSE_POSITION)[1] }
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Palette {
C1 = 0,
C2,
C3,
C4,
}
impl Palette {
const PALETTE: *mut [u32; 4] = 0x04 as *mut [u32; 4];
#[inline]
pub fn load(self) -> Color {
unsafe { Color::from_u32((*Self::PALETTE)[self as usize]) }
}
#[inline]
pub fn store(self, color: Color) {
unsafe { (*Self::PALETTE)[self as usize] = color.as_u32() }
}
}
#[derive(Clone, Copy)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl Color {
#[inline]
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
pub const fn as_u32(self) -> u32 {
((self.r as u32) << 16) | ((self.g as u32) << 8) as u32 | self.b as u32
}
pub const fn from_u32(v: u32) -> Self {
Self {
r: (v >> 16) as u8,
g: (v >> 8) as u8,
b: v as u8,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum DrawColor {
C1 = 0,
C2,
C3,
C4,
}
impl DrawColor {
const DRAW_COLORS: *mut u16 = 0x14 as *mut u16;
pub fn load(self) -> Option<Palette> {
let offset = 4 * self as u8;
let mask: u16 = 0b1111 << offset;
match unsafe { *Self::DRAW_COLORS & mask } >> offset {
0b0000 => None,
0b0001 => Some(Palette::C1),
0b0010 => Some(Palette::C2),
0b0011 => Some(Palette::C3),
0b0100 => Some(Palette::C4),
_ => unreachable!(),
}
}
pub fn store(self, palette: Option<Palette>) {
let offset = 4 * self as u8;
let mask: u16 = 0b1111 << offset;
let index: u16 = match palette {
Some(color) => ((color as u8) + 1) as u16,
None => 0,
};
unsafe {
*Self::DRAW_COLORS ^= *Self::DRAW_COLORS & mask;
*Self::DRAW_COLORS |= index << offset;
}
}
}
pub mod w4 {
extern "C" {
pub fn blit(
sprite: *const u8,
x: i32,
y: i32,
width: i32,
height: i32,
flags: i32,
);
#[link_name = "blitSub"]
pub fn blit_sub(
sprite: *const u8,
x: i32,
y: i32,
width: i32,
height: i32,
src_x: i32,
src_y: i32,
stride: i32,
flags: i32,
);
pub fn line(x1: i32, y1: i32, x2: i32, y2: i32);
pub fn hline(x: i32, y: i32, len: i32);
pub fn vline(x: i32, y: i32, len: i32);
pub fn oval(x: i32, y: i32, width: i32, height: i32);
pub fn rect(x: i32, y: i32, width: i32, height: i32);
#[link_name = "textUtf8"]
pub fn text(string: *const u8, len: i32, x: i32, y: i32);
pub fn tone(frequency: i32, duration: i32, volume: i32, flags: i32);
pub fn diskr(dest: *const u8, size: i32) -> i32;
pub fn diskw(src: *const u8, size: i32) -> i32;
#[link_name = "traceUtf8"]
pub fn trace(text: *const u8, len: usize);
}
}
#[inline]
pub fn trace<T: AsRef<str>>(text: T) {
let text = text.as_ref();
unsafe { w4::trace(text.as_ptr(), text.len()) }
}