summaryrefslogtreecommitdiff
path: root/src/progmem.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/progmem.rs')
-rw-r--r--src/progmem.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/progmem.rs b/src/progmem.rs
new file mode 100644
index 0000000..325eab1
--- /dev/null
+++ b/src/progmem.rs
@@ -0,0 +1,136 @@
+use crate::memory::Memory;
+use std::fmt;
+
+pub struct ProgramMemory {
+ array: [u8; u16::max_value() as usize + 1],
+}
+
+impl fmt::Debug for ProgramMemory {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut v: Vec<char> = 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::<String>())
+ }
+}
+
+enum Rectyp {
+ Data,
+ EndOfFile,
+ //ExtendedSegAddr,
+ //StartSegAddr,
+ //ExtendedLinearAddr,
+ //StartLinearAddr,
+}
+
+struct HexLine {
+ rectyp: Rectyp,
+ offset: u16,
+ data: Vec<u8>,
+}
+
+impl HexLine {
+ fn from(s: &str) -> Result<Self, usize> {
+ // 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 ProgramMemory {
+ /// 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, String> {
+ Self::new().hex(hex)
+ }
+
+ /// Method for sequential consuming building
+ pub fn hex(mut self, hex: String) -> Result<Self, String> {
+ 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<u16> for ProgramMemory {
+ 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;
+ }
+}