1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use crate::memory_mapped::{MemoryMapped, MemoryMapped1DArray}; use core::fmt::Write; #[derive(Eq, PartialEq, Clone, Copy)] #[allow(dead_code)] pub enum DebugLevel { Fatal = 0, Error = 1, Warning = 2, Info = 3, Debug = 4, } const OUTPUT_STRING: MemoryMapped1DArray<u8, 256> = unsafe { MemoryMapped1DArray::new(0x04FF_F600) }; const DEBUG_ENABLE: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x04FF_F780) }; const ENABLE_HANDSHAKE_IN: u16 = 0xC0DE; const ENABLE_HANDSHAKE_OUT: u16 = 0x1DEA; const DEBUG_LEVEL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x04FF_F700) }; const DEBUG_FLAG_CODE: u16 = 0x0100; fn is_running_in_mgba() -> bool { DEBUG_ENABLE.set(ENABLE_HANDSHAKE_IN); DEBUG_ENABLE.get() == ENABLE_HANDSHAKE_OUT } pub struct Mgba { bytes_written: usize, } impl Mgba { pub fn new() -> Option<Self> { if is_running_in_mgba() { Some(Mgba { bytes_written: 0 }) } else { None } } pub fn print( &mut self, output: core::fmt::Arguments, level: DebugLevel, ) -> Result<(), core::fmt::Error> { write!(self, "{}", output)?; self.set_level(level); Ok(()) } } impl Mgba { pub fn set_level(&mut self, level: DebugLevel) { DEBUG_LEVEL.set(DEBUG_FLAG_CODE | level as u16); self.bytes_written = 0; } } impl core::fmt::Write for Mgba { fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { let mut str_iter = s.bytes(); while self.bytes_written < 255 { match str_iter.next() { Some(byte) => { OUTPUT_STRING.set(self.bytes_written, byte); self.bytes_written += 1; } None => return Ok(()), } } Ok(()) } }