2020-10-24 13:54:31 +01:00
|
|
|
/// mGBA 0.8.1 Debug peripheral support
|
|
|
|
use std::str;
|
|
|
|
|
|
|
|
use log::log;
|
|
|
|
use log::Level;
|
|
|
|
|
2022-09-14 23:21:11 +01:00
|
|
|
use super::arm7tdmi::memory::BusIO;
|
|
|
|
use crate::iodev::consts::{REG_DEBUG_ENABLE, REG_DEBUG_FLAGS, REG_DEBUG_STRING};
|
2020-10-24 17:32:43 +01:00
|
|
|
|
2020-10-24 13:54:31 +01:00
|
|
|
pub const DEBUG_STRING_SIZE: usize = 0x100;
|
|
|
|
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
pub struct DebugPort {
|
|
|
|
enable: bool,
|
|
|
|
flags: DebugFlags,
|
|
|
|
debug_string: Box<[u8]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DebugPort {
|
|
|
|
pub fn new() -> DebugPort {
|
|
|
|
DebugPort {
|
|
|
|
enable: false,
|
|
|
|
flags: DebugFlags(0),
|
|
|
|
debug_string: vec![0; DEBUG_STRING_SIZE].into_boxed_slice(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn is_debug_access(x: u32) -> bool {
|
|
|
|
x == REG_DEBUG_ENABLE
|
|
|
|
|| x == REG_DEBUG_FLAGS
|
|
|
|
|| (x >= REG_DEBUG_STRING && x <= REG_DEBUG_STRING + (DEBUG_STRING_SIZE as u32))
|
|
|
|
}
|
|
|
|
|
2020-10-24 17:32:43 +01:00
|
|
|
pub fn read(&mut self, addr: u32) -> u16 {
|
|
|
|
if !self.enable {
|
|
|
|
return 0;
|
|
|
|
}
|
2020-10-24 13:54:31 +01:00
|
|
|
match addr {
|
2020-10-24 17:32:43 +01:00
|
|
|
REG_DEBUG_ENABLE => 0x1DEA,
|
|
|
|
REG_DEBUG_FLAGS => self.flags.0,
|
|
|
|
x if x >= REG_DEBUG_STRING && x <= REG_DEBUG_STRING + (DEBUG_STRING_SIZE as u32) => {
|
|
|
|
self.debug_string.read_16(addr - REG_DEBUG_STRING)
|
2020-10-24 13:54:31 +01:00
|
|
|
}
|
|
|
|
_ => 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write(&mut self, addr: u32, value: u16) {
|
|
|
|
match addr {
|
2020-10-24 17:32:43 +01:00
|
|
|
REG_DEBUG_ENABLE => {
|
|
|
|
self.enable = value == 0xC0DE;
|
|
|
|
info!("mGBA log enabled: {}", self.enable);
|
|
|
|
}
|
2020-10-24 13:54:31 +01:00
|
|
|
REG_DEBUG_FLAGS => {
|
|
|
|
if self.enable {
|
|
|
|
self.flags.0 = value;
|
|
|
|
self.debug();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
x if x >= REG_DEBUG_STRING && x <= REG_DEBUG_STRING + (DEBUG_STRING_SIZE as u32) => {
|
2020-10-24 17:32:43 +01:00
|
|
|
if self.enable {
|
|
|
|
self.debug_string.write_16(addr - REG_DEBUG_STRING, value);
|
|
|
|
}
|
2020-10-24 13:54:31 +01:00
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn debug(&mut self) {
|
|
|
|
if self.flags.send() {
|
|
|
|
let message = str::from_utf8(&self.debug_string)
|
|
|
|
.expect("Failed to parse log message to valid utf8");
|
|
|
|
|
|
|
|
let level: Level = match self.flags.level() {
|
|
|
|
0 | 1 => Level::Error,
|
|
|
|
2 => Level::Warn,
|
|
|
|
3 => Level::Info,
|
|
|
|
4 => Level::Debug,
|
|
|
|
_ => panic!("invalid log level"),
|
|
|
|
};
|
|
|
|
|
|
|
|
log!(level, "[mGBA mLOG]: {}", message);
|
|
|
|
|
|
|
|
for i in self.debug_string.iter_mut() {
|
|
|
|
*i = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.flags.set_send(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bitfield! {
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
pub struct DebugFlags(u16);
|
|
|
|
impl Debug;
|
|
|
|
u16;
|
|
|
|
pub into usize, level, _: 3, 0;
|
|
|
|
pub send, set_send: 8;
|
|
|
|
}
|