use std::fs; use crate::error::Error; use crate::devices::{Address, Addressable, Transmutable, TransmutableBox, MAX_READ}; pub struct MemoryBlock { pub contents: Vec, } impl MemoryBlock { pub fn new(contents: Vec) -> MemoryBlock { MemoryBlock { contents } } pub fn load(filename: &str) -> Result { match fs::read(filename) { Ok(contents) => Ok(MemoryBlock::new(contents)), Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))), } } pub fn load_at(&mut self, mut addr: Address, filename: &str) -> Result<(), Error> { match fs::read(filename) { Ok(contents) => { for byte in contents { self.contents[addr as usize] = byte; addr += 1; } Ok(()) }, Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))), } } } impl Addressable for MemoryBlock { fn len(&self) -> usize { self.contents.len() } fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { for i in 0..data.len() { data[i] = self.contents[(addr as usize) + i]; } Ok(()) } fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> { for byte in data { self.contents[addr as usize] = *byte; addr += 1; } Ok(()) } } impl Transmutable for MemoryBlock { fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { Some(self) } } pub struct Block { pub base: Address, pub length: usize, pub dev: TransmutableBox, } pub struct Bus { pub blocks: Vec, pub address_mask: Address, } impl Bus { pub fn new() -> Bus { Bus { blocks: vec!(), address_mask: !0, } } pub fn set_address_bits(&mut self, bits: u8) { self.address_mask = 0; for _ in 0..bits { self.address_mask = (self.address_mask << 1) | 0x01; } } pub fn insert(&mut self, base: Address, length: usize, dev: TransmutableBox) { let block = Block { base, length, dev }; for i in 0..self.blocks.len() { if self.blocks[i].base > block.base { self.blocks.insert(i, block); return; } } self.blocks.insert(0, block); } pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(TransmutableBox, Address), Error> { let addr = addr & self.address_mask; for block in &self.blocks { if addr >= block.base && addr <= (block.base + block.length as Address) { let relative_addr = addr - block.base; if relative_addr as usize + count <= block.length { return Ok((block.dev.clone(), relative_addr)); } else { return Err(Error::new(&format!("Error reading address {:#010x}", addr))); } } } return Err(Error::new(&format!("No segment found at {:#08x}", addr))); } pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) { while count > 0 { let mut line = format!("{:#010x}: ", addr); let to = if count < 16 { count / 2 } else { 8 }; for _ in 0..to { let word = self.read_beu16(addr); if word.is_err() { println!("{}", line); return; } line += &format!("{:#06x} ", word.unwrap()); addr += 2; count -= 2; } println!("{}", line); } } } impl Addressable for Bus { fn len(&self) -> usize { let block = &self.blocks[self.blocks.len() - 1]; (block.base as usize) + block.length } fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { let (dev, relative_addr) = self.get_device_at(addr, data.len())?; let result = dev.borrow_mut().as_addressable().unwrap().read(relative_addr, data); result } fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { let (dev, relative_addr) = self.get_device_at(addr, data.len())?; let result = dev.borrow_mut().as_addressable().unwrap().write(relative_addr, data); result } }