use crate::{memory::Result, PsxConfig};
use super::BusLine;
pub struct ExpansionRegion1 {
data: Box<[u8; 0x80000]>,
}
impl Default for ExpansionRegion1 {
fn default() -> Self {
Self {
data: Box::new([0; 0x80000]),
}
}
}
impl BusLine for ExpansionRegion1 {
fn read_u8(&mut self, addr: u32) -> Result<u8> {
Ok(self.data[addr as usize])
}
fn write_u8(&mut self, addr: u32, data: u8) -> Result<()> {
self.data[addr as usize] = data;
log::info!(
"expansion region r1 write at {:05X}, value {:02X}",
addr,
data
);
Ok(())
}
}
struct DuartTTY {
tty_buffer: String,
line_temp_buffer: String,
config: PsxConfig,
}
impl DuartTTY {
fn new(config: PsxConfig) -> Self {
Self {
tty_buffer: String::new(),
line_temp_buffer: String::new(),
config,
}
}
fn read(&self, addr: u32) -> u8 {
match addr & 0xF {
0x0 => todo!(),
0x1 => 0b100,
0x2 => todo!(),
0x3 => todo!(),
0x4 => todo!(),
0x5 => todo!(),
0x6 => todo!(),
0x7 => todo!(),
0x8 => todo!(),
0x9 => todo!(),
0xA => todo!(),
0xB => todo!(),
0xC => todo!(),
0xD => todo!(),
0xE => todo!(),
0xF => todo!(),
_ => unreachable!(),
}
}
fn write(&mut self, addr: u32, data: u8) {
match addr & 0xF {
0x0 => {}
0x1 => {}
0x2 => {}
0x3 => {
let ch = data as char;
self.tty_buffer.push(ch);
if ch == '\n' {
if self.config.stdout_debug {
println!("DEBUG: {}", self.line_temp_buffer);
}
self.line_temp_buffer.clear();
} else {
self.line_temp_buffer.push(ch);
}
}
0x4 => {}
0x5 => {}
0x6 => todo!(),
0x7 => todo!(),
0x8 => todo!(),
0x9 => todo!(),
0xA => {}
0xB => todo!(),
0xC => todo!(),
0xD => {}
0xE => {}
0xF => todo!(),
_ => unreachable!(),
}
}
}
pub struct ExpansionRegion2 {
data: [u8; 0x90],
tty_duart: DuartTTY,
}
impl ExpansionRegion2 {
pub fn new(config: PsxConfig) -> Self {
Self {
data: [0; 0x90],
tty_duart: DuartTTY::new(config),
}
}
}
impl BusLine for ExpansionRegion2 {
fn read_u8(&mut self, addr: u32) -> Result<u8> {
let out = match addr {
0x20..=0x2F => self.tty_duart.read(addr & 0xF),
_ => self.data[addr as usize],
};
log::info!("expansion region 2 read at {:02X}, value {:02X}", addr, out);
Ok(out)
}
fn write_u8(&mut self, addr: u32, data: u8) -> Result<()> {
log::info!(
"expansion region 2 write at {:02X}, value {:02X}",
addr,
data
);
match addr {
0x20..=0x2F => self.tty_duart.write(addr & 0xF, data),
0x41 => println!("TraceStep {:02X}", data),
_ => self.data[addr as usize] = data,
}
self.data[addr as usize] = data;
Ok(())
}
fn read_u16(&mut self, addr: u32) -> Result<u16> {
let low = self.read_u8(addr)? as u16;
let high = self.read_u8(addr + 1)? as u16;
Ok(low | (high << 8))
}
fn write_u16(&mut self, addr: u32, data: u16) -> Result<()> {
self.write_u8(addr, data as u8)?;
self.write_u8(addr + 1, (data >> 8) as u8)
}
fn read_u32(&mut self, addr: u32) -> Result<u32> {
let low = self.read_u16(addr)? as u32;
let high = self.read_u16(addr + 2)? as u32;
Ok(low | (high << 16))
}
fn write_u32(&mut self, addr: u32, data: u32) -> Result<()> {
self.write_u16(addr, data as u16)?;
self.write_u16(addr + 2, (data >> 16) as u16)
}
}