diff options
Diffstat (limited to 'src/formats/inhx32.rs')
-rw-r--r-- | src/formats/inhx32.rs | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/src/formats/inhx32.rs b/src/formats/inhx32.rs index fd7fd7b..8febeae 100644 --- a/src/formats/inhx32.rs +++ b/src/formats/inhx32.rs @@ -1,11 +1,19 @@ use crate::*; -pub fn format_inhx32(words: &[Word]) -> String { +pub fn format_inhx32(segments: &[Segment]) -> Result<Vec<u8>, FormatError> { 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)); + let mut address = 0; + records.push(extended_linear_address(0)); + for segment in segments { + if (segment.address >> 16) != (address >> 16) { + records.push(extended_linear_address(segment.address)); + } + address = segment.address; + for chunk in segment.words.chunks(8) { + records.push(data_record(chunk, address)?); + address += 8; + } } records.push(terminating_record()); @@ -13,24 +21,29 @@ pub fn format_inhx32(words: &[Word]) -> String { for record in records { output.push_str(&record.to_string()); } - return output; + return Ok(output.as_bytes().to_vec()); } -fn data_record(words: &[Word], address: u16) -> InhxRecord { +fn data_record(words: &[Tracked<Word>], address: usize) -> Result<InhxRecord, FormatError> { + let Ok(address) = u32::try_from(address * 2) else { + return Err(FormatError::AddressTooLarge(u32::MAX as usize / 2, address)); + }; + let address = address as u16; let mut record = InhxRecord::new(); record.byte((words.len() * 2) as u8); - record.be_double(address * 2); + record.be_double(address); 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."), - }; + if word.value.width > 16 { + return Err(FormatError::WordTooWide(16, word.width, word.source.clone())); + } + record.le_double(word.value.value as u16); } - return record; + return Ok(record); } -fn extended_linear_address(address: u16) -> InhxRecord { +fn extended_linear_address(address: usize) -> InhxRecord { + let address = (address >> 16) as u16; let mut record = InhxRecord::new(); record.byte(0x02); record.be_double(0x0000); |