use crate::memory::Memory; use std::fmt; pub struct Rom { array: [u8; u16::max_value() as usize + 1], } impl fmt::Debug for Rom { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut v: Vec = vec![]; for (c, x) in self.array.iter().enumerate() { for hex_char in format!("{:02X}", *x).chars() { v.push(hex_char); } v.push(' '); if c % 8 == 7 { v.push('\n'); } } write!(f, "{}", v.iter().collect::()) } } enum Rectyp { Data, EndOfFile, //ExtendedSegAddr, //StartSegAddr, //ExtendedLinearAddr, //StartLinearAddr, } struct HexLine { rectyp: Rectyp, offset: u16, data: Vec, } impl HexLine { fn from(s: &str) -> Result { // The shortest possible sequence is EOF (:00000001FF) if s.len() < 11 { return Err(usize::max_value()); } if &s[0..1] != ":" { return Err(0); } let offset = match u16::from_str_radix(&s[3..7], 16) { Ok(value) => value, Err(_) => return Err(3), }; let bytecount = match usize::from_str_radix(&s[1..3], 16) { Ok(value) => value, Err(_) => return Err(1), }; // If EOF reached if &s[7..9] == "01" { return Ok(HexLine { rectyp: Rectyp::EndOfFile, offset, data: vec![0], }); } else if &s[7..9] == "00" { let mut counter = 9; let mut data = vec![]; while counter < s.len() - 2 && counter < (9 + bytecount * 2) { data.push(match u8::from_str_radix(&s[counter..counter + 2], 16) { Ok(value) => value, Err(_) => return Err(counter), }); counter += 2; } // TODO: check checksum return Ok(HexLine { rectyp: Rectyp::Data, offset, data, }); } Err(3) } } impl Rom { /// Empty constructor pub fn new() -> Self { Self { array: [0; u16::max_value() as usize + 1], } } /// Constructor from hex pub fn from_hex(hex: String) -> Result { Self::new().hex(hex) } /// Method for sequential consuming building pub fn hex(mut self, hex: String) -> Result { match self.load_hex(hex) { Ok(_) => Ok(self), Err(string) => Err(string), } } /// Method for occasional incremental hex loading pub fn load_hex(&mut self, hex: String) -> Result<(), String> { for (linenum, line) in hex.lines().enumerate() { let hex_line = match HexLine::from(line) { Ok(value) => value, Err(charnum) => return Err(format!("ihex parsing error {}:{}", linenum, charnum)), }; let offset = hex_line.offset; match hex_line.rectyp { Rectyp::Data => { for (ptr, byte) in hex_line.data.iter().enumerate() { self.array[ptr + offset as usize] = *byte; } } Rectyp::EndOfFile => {} } } Ok(()) } } impl Memory for Rom { fn get(&self, a: u16) -> u8 { self.array[a as usize] } fn set(&mut self, a: u16, v: u8) { self.array[a as usize] = v; } }