use crate::*; pub fn format_inhx32(words: &[Word]) -> String { let mut records = Vec::new(); records.push(extended_linear_address(0x0000)); for (i, chunk) in words.chunks(8).enumerate() { records.push(data_record(chunk, (i * 8) as u16)); } records.push(terminating_record()); let mut output = String::new(); for record in records { output.push_str(&record.to_string()); } return output; } struct Record { bytes: Vec, } impl Record { pub fn new() -> Self { Self { bytes: Vec::new() } } pub fn byte(&mut self, byte: u8) { self.bytes.push(byte); } pub fn be_double(&mut self, double: u16) { let [high, low] = double.to_be_bytes(); self.byte(high); self.byte(low); } pub fn le_double(&mut self, double: u16) { let [high, low] = double.to_be_bytes(); self.byte(low); self.byte(high); } pub fn to_string(self) -> String { let mut sum: u8 = 0; for byte in &self.bytes { sum = sum.wrapping_add(*byte); } let checksum = sum.wrapping_neg(); let mut output = String::new(); for byte in &self.bytes { output.push_str(&format!("{byte:0>2X}")); } format!(":{output}{checksum:0>2X}\n") } } fn data_record(words: &[Word], address: u16) -> Record { let mut record = Record::new(); record.byte((words.len() * 2) as u8); record.be_double(address * 2); record.byte(0x00); for word in words { match word.bits <= 16 { true => record.le_double(word.value as u16), false => panic!("Word '{word}' has more than 16 bits."), }; } return record; } fn extended_linear_address(address: u16) -> Record { let mut record = Record::new(); record.byte(0x02); record.be_double(0x0000); record.byte(0x04); record.be_double(address); return record; } fn terminating_record() -> Record { let mut record = Record::new(); record.byte(0x00); record.be_double(0x0000); record.byte(0x01); return record; }