use core::{ffi::c_char, fmt::{Error, Write}};
use crate::mmio::JOYP;
#[allow(unused_imports)]
use super::{drawing::{DmgColor, TILE_HEIGHT, TILE_WIDTH}, gbdk_c::{console::{cls, gotoxy}, font::{font_color, font_ibm, font_init, font_load, font_set, font_t}, stdio::putchar}};
#[allow(unused_imports)]
use crate::gbdk_c;
#[macro_export]
macro_rules! println {
() => {
$crate::print!("\n")
};
($($arg:tt)*) => {{
use core::fmt::Write;
let mut s = gb::io::GbStream::stream();
s.write_fmt(core::format_args_nl!($($arg)*)).unwrap();
}};
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => {{
use core::fmt::Write;
let mut s = gb::io::GbStream::stream();
s.write_fmt(core::format_args!($($arg)*)).unwrap();
}};
}
pub struct GbStream {
private: ()
}
impl GbStream {
pub fn stream() -> Self {
GbStream { private: () }
}
pub fn clear() {
unsafe { cls();}
}
pub fn cursor(x: u8, y: u8) {
if x >= TILE_WIDTH {
panic!("Cursor x outbounded");
}
if y >= TILE_HEIGHT {
panic!("Cursor y outbounded");
}
unsafe {gotoxy(x, y)};
}
#[cfg(feature="prototype")]
pub fn set_color(foreground: DmgColor, background: DmgColor) {
unsafe {
cls();
font_init();
font_color(foreground as u8, background as u8);
}
let font = unsafe { font_load(font_ibm) };
unsafe { font_set(font) };
}
#[cfg(feature="prototype")]
pub unsafe fn set_font_and_color(font: font_t, foreground: DmgColor, background: DmgColor) {
unsafe {
cls();
font_init();
font_color(foreground as u8, background as u8)
}
let font = unsafe { font_load(font) };
unsafe { font_set(font) };
}
pub fn write_byte(&mut self, b: u8) -> Result<(), Error> {
unsafe { putchar(b as c_char) }
Ok(())
}
}
impl Write for GbStream {
#[inline(never)]
fn write_str(&mut self, s: &str) -> core::fmt::Result {
for c in s.bytes() {
unsafe { putchar(c as c_char) }
}
Ok(())
}
}
#[repr(u8)]
enum JoypadMode {
None = 0x30,
DPad = 0x20,
Button = 0x10,
All = 0x00
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq)]
pub enum JoypadKey {
Right = 0x01,
Left = 0x02,
Up = 0x04,
Down = 0x08,
A = 0x10,
B = 0x20,
Select = 0x40,
Start = 0x80
}
#[derive(Clone, Copy)]
pub struct Joypad(u8);
impl Joypad {
fn change_mode(mode: JoypadMode) {
unsafe {JOYP.write(mode as u8)};
JOYP.read();
}
pub fn read() -> Self {
Joypad::change_mode(JoypadMode::Button);
let buttons = (JOYP.read() << 4) | 0xF;
Joypad::change_mode(JoypadMode::DPad);
let d_pad = JOYP.read() | 0xF0;
Joypad(!(buttons & d_pad))
}
pub fn a(&self) -> bool {
self.0 & (JoypadKey::A as u8) != 0
}
pub fn b(&self) -> bool {
self.0 & (JoypadKey::B as u8) != 0
}
pub fn select(&self) -> bool {
self.0 & (JoypadKey::Select as u8) != 0
}
pub fn start(&self) -> bool {
self.0 & (JoypadKey::Start as u8) != 0
}
pub fn right(&self) -> bool {
self.0 & (JoypadKey::Right as u8) != 0
}
pub fn left(&self) -> bool {
self.0 & (JoypadKey::Left as u8) != 0
}
pub fn up(&self) -> bool {
self.0 & (JoypadKey::Up as u8) != 0
}
pub fn down(&self) -> bool {
self.0 & (JoypadKey::Down as u8) != 0
}
pub fn wait_until_press() -> Self {
let mut current = Joypad::read();
while u8::from(current) == 0 {
current = Joypad::read();
}
return current;
}
pub fn wait_until_release() {
let mut current = Joypad::read();
while u8::from(current) != 0 {
current = Joypad::read();
}
}
}
impl From<Joypad> for u8 {
fn from(value: Joypad) -> Self {
value.0
}
}