use crate::operands::{Byte, ImmediateOperand, Word}; use super::interpreter::InterpreterError; /// 2*20 = 1MiB const MEMORY_SIZE: usize = 1048576; #[derive(Debug, Clone, Copy)] pub struct Memory { pub raw: [Byte; MEMORY_SIZE as usize], } impl Memory { pub fn new() -> Self { Self { raw: [0; MEMORY_SIZE as usize], } } /// Safely writes a [`ImmediateOperand`] into an index of memory. /// Warning: Does access at `addr`, not `DS:addr`! pub fn write_raw(&mut self, addr: Word, val: ImmediateOperand) -> Result<(), InterpreterError> { match val { ImmediateOperand::Byte(b) => { if addr as usize > MEMORY_SIZE { return Err(InterpreterError::MemoryOutOfBound(addr)); } else { self.raw[addr as usize] = b; log::debug!("Wrote raw byte {b:#04x} at addr {addr:#04x}"); } } ImmediateOperand::Word(w) => { if (addr + 1) as usize > MEMORY_SIZE { return Err(InterpreterError::MemoryOutOfBound(addr)); } else { let [low, high] = w.to_le_bytes(); self.raw[addr as usize] = low; self.raw[(addr + 1) as usize] = high; log::debug!( "Wrote raw byte {low:#04x} and {high:#04x}, starting at addr {addr:#04x}" ); } } } Ok(()) } /// Safely reads a [`Word`] from an index of memory. /// Warning: Does access at `addr`, not `DS:addr`! pub fn read_raw(&self, addr: Word) -> Result { let b1 = self .raw .get(addr as usize) .ok_or(InterpreterError::MemoryOutOfBound(addr))? .to_owned(); let b2 = self .raw .get((addr + 1) as usize) .ok_or(InterpreterError::MemoryOutOfBound(addr))? .to_owned(); log::debug!("Read raw byte {b1:#04x} and {b2:#04x}, starting at addr {addr:#04x}"); Ok(Word::from_be_bytes([b2, b1])) } }