summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-02-28 14:35:04 +1300
committerBen Bridle <ben@derelict.engineering>2025-02-28 14:35:04 +1300
commitda5c8173a56d5be7fa23d2b18eaba1542aa31dd6 (patch)
tree6ef7aa76568bfa2488b0d0d9a878016eabadcae0
parentdba769e13ca5029643c6068e53fa34ae0fea8421 (diff)
downloadtorque-asm-da5c8173a56d5be7fa23d2b18eaba1542aa31dd6.zip
Implement inhx format
inhx is the original Intel hex format.
-rw-r--r--src/formats/inhx.rs38
-rw-r--r--src/formats/inhx32.rs51
-rw-r--r--src/formats/mod.rs43
-rw-r--r--src/main.rs8
4 files changed, 94 insertions, 46 deletions
diff --git a/src/formats/inhx.rs b/src/formats/inhx.rs
new file mode 100644
index 0000000..e83e870
--- /dev/null
+++ b/src/formats/inhx.rs
@@ -0,0 +1,38 @@
+use crate::*;
+
+
+pub fn format_inhx(words: &[Word]) -> String {
+ let mut records = Vec::new();
+ for (i, chunk) in words.chunks(16).enumerate() {
+ records.push(data_record(chunk, (i * 16) as u16));
+ }
+ records.push(terminating_record());
+
+ let mut output = String::new();
+ for record in records {
+ output.push_str(&record.to_string());
+ }
+ return output;
+}
+
+fn data_record(words: &[Word], address: u16) -> InhxRecord {
+ let mut record = InhxRecord::new();
+ record.byte((words.len()) as u8);
+ record.be_double(address);
+ record.byte(0x00);
+ for word in words {
+ match word.bits <= 8 {
+ true => record.byte(word.value as u8),
+ false => panic!("Word '{word}' has more than 8 bits."),
+ };
+ }
+ return record;
+}
+
+fn terminating_record() -> InhxRecord {
+ let mut record = InhxRecord::new();
+ record.byte(0x00);
+ record.be_double(0x0000);
+ record.byte(0x01);
+ return record;
+}
diff --git a/src/formats/inhx32.rs b/src/formats/inhx32.rs
index d9c31d3..fd7fd7b 100644
--- a/src/formats/inhx32.rs
+++ b/src/formats/inhx32.rs
@@ -16,47 +16,8 @@ pub fn format_inhx32(words: &[Word]) -> String {
return output;
}
-struct Record {
- bytes: Vec<u8>,
-}
-
-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();
+fn data_record(words: &[Word], address: u16) -> InhxRecord {
+ let mut record = InhxRecord::new();
record.byte((words.len() * 2) as u8);
record.be_double(address * 2);
record.byte(0x00);
@@ -69,8 +30,8 @@ fn data_record(words: &[Word], address: u16) -> Record {
return record;
}
-fn extended_linear_address(address: u16) -> Record {
- let mut record = Record::new();
+fn extended_linear_address(address: u16) -> InhxRecord {
+ let mut record = InhxRecord::new();
record.byte(0x02);
record.be_double(0x0000);
record.byte(0x04);
@@ -78,8 +39,8 @@ fn extended_linear_address(address: u16) -> Record {
return record;
}
-fn terminating_record() -> Record {
- let mut record = Record::new();
+fn terminating_record() -> InhxRecord {
+ let mut record = InhxRecord::new();
record.byte(0x00);
record.be_double(0x0000);
record.byte(0x01);
diff --git a/src/formats/mod.rs b/src/formats/mod.rs
index 42d198c..82f19f1 100644
--- a/src/formats/mod.rs
+++ b/src/formats/mod.rs
@@ -1,2 +1,45 @@
+mod inhx;
mod inhx32;
+
+pub use inhx::*;
pub use inhx32::*;
+
+
+pub struct InhxRecord {
+ bytes: Vec<u8>,
+}
+
+impl InhxRecord {
+ 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")
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 9fb404c..f271bcd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -47,7 +47,7 @@ fn main() {
let dry_run = args.named("dry-run").short('n').as_bool();
let Ok(format) = Format::from_str(format.as_str()) else {
- fatal!("Unknown format '{format}', expected 'debug', 'inhx32', 'raw', or 'source'. ");
+ fatal!("Unknown format '{format}', expected 'debug', 'inhx', 'inhx32', 'raw', or 'source'. ");
};
// -----------------------------------------------------------------------
@@ -127,6 +127,10 @@ fn main() {
}
write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
}
+ Format::Inhx => {
+ let output = format_inhx(&bytecode.words);
+ write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
+ }
Format::Inhx32 => {
let output = format_inhx32(&bytecode.words);
write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
@@ -162,6 +166,7 @@ fn write_bytes_and_exit<P: AsRef<Path>>(bytes: &[u8], path: Option<&P>) -> ! {
#[derive(PartialEq)]
enum Format {
Debug,
+ Inhx,
Inhx32,
Raw,
Source,
@@ -172,6 +177,7 @@ impl FromStr for Format {
fn from_str(string: &str) -> Result<Self, ()> {
match string {
"debug" => Ok(Self::Debug),
+ "inhx" => Ok(Self::Inhx),
"inhx32" => Ok(Self::Inhx32),
"raw" => Ok(Self::Raw),
"source" => Ok(Self::Source),