summaryrefslogtreecommitdiff
path: root/src/ram.rs
blob: c7c4d432dfb82a1026dd1de5fe82b5613a8346d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::fmt;

pub struct Ram {
    pub array: [u8; u16::max_value() as usize + 1],
}

impl fmt::Debug for Ram {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut c = 0;
        let mut v: Vec<char> = vec![];
        for x in self.array.into_iter() {
            for hex_char in format!("{:02X}", *x).chars() {
                v.push(hex_char);
            }
            v.push(' ');
            if c % 8 == 7 {
                v.push('\n');
            }
            c += 1;
        }
        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, i32> {
        // The shortest possible sequence is EOF (:00000001FF)
        if s.len() < 11 {
            return Err(1)
        }
        if &s[0..1] != ":" {
            return Err(2)
        }
        let offset = (&s[3..7]).parse::<u16>().unwrap(); // TODO: handle unwrap
        let bytecount = (&s[1..3]).parse::<usize>().unwrap(); // TODO: handle unwrap

        // 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((&s[counter..counter+2]).parse::<u8>().unwrap()); // TODO handle unwrap
                counter += 2;
            }
            // TODO: check checksum
            return Ok(HexLine { rectyp: Rectyp::Data, offset, data })
        }

        Err(3)
    }
}

impl Ram {
    pub fn from_hex(hex: String) -> Self {
        let mut array = [0; u16::max_value() as usize + 1];
        for line in hex.lines() {
            let hex_line = HexLine::from(line).unwrap(); // TODO: handle unwrap
            let offset = hex_line.offset;
            match hex_line.rectyp {
                Rectyp::Data => {
                    for (ptr, byte) in hex_line.data.iter().enumerate() {
                        array[ptr + offset as usize] = *byte;
                    }
                }
                Rectyp::EndOfFile => {}
            }
        }
        Self { array }
    }
}