macro_rules! then_inc { ($v:expr) => {{ $v = $v.wrapping_add(1); $v as usize }}; } type Page = [u8; 65536]; fn new_blank_page() -> [u8; 65536] { [0; 65536] } pub struct MemoryDevice { pages: Vec, pub page_limit: u16, pub page_1: u16, pub address_1: u16, pub page_2: u16, pub address_2: u16, pub copy_length: u16, } impl MemoryDevice { pub fn new() -> Self { Self { pages: Vec::new(), page_limit: 0, page_1: 0, address_1: 0, page_2: 0, address_2: 0, copy_length: 0, } } pub fn page_count(&self) -> u16 { self.pages.len() as u16 } pub fn copy(&mut self) { // Return if at least one page is out-of-bounds if self.page_1 as usize >= self.pages.len() || self.page_2 as usize >= self.pages.len() { return } let p1 = self.page_1 as usize; let p2 = self.page_2 as usize; let a1 = self.address_1; let a2 = self.address_2; for i in 0..=self.copy_length { let byte = self.pages[p2][a2.wrapping_add(i) as usize]; self.pages[p1][a1.wrapping_add(i) as usize] = byte; } } pub fn expand_memory(&mut self) { let size = std::cmp::max(self.page_1, self.page_2) as usize + 1; if size < self.page_limit as usize { self.pages.resize_with(size, new_blank_page); } } pub fn read_from_head_1(&mut self) -> u8 { let address = then_inc!(self.address_1); if let Some(page) = self.pages.get(self.page_1 as usize) { page[address] } else { 0x00 } } pub fn read_from_head_2(&mut self) -> u8 { let address = then_inc!(self.address_2); if let Some(page) = self.pages.get(self.page_2 as usize) { page[address] } else { 0x00 } } pub fn write_to_head_1(&mut self, byte: u8) { let address = then_inc!(self.address_1); if let Some(page) = self.pages.get_mut(self.page_1 as usize) { page[address] = byte; } } pub fn write_to_head_2(&mut self, byte: u8) { let address = then_inc!(self.address_2); if let Some(page) = self.pages.get_mut(self.page_2 as usize) { page[address] = byte; } } }