diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-02-27 14:53:21 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-02-27 14:53:31 +1300 |
commit | 67470aea034fd46f4bbcfe815c51ad3451043188 (patch) | |
tree | 83d78d3d28e094d6a3af347d2ff2ff16472e5421 /src/formats | |
parent | 4e8fae09f0f7d6f3a4ddbe285aeb01ef0622b761 (diff) | |
download | torque-asm-67470aea034fd46f4bbcfe815c51ad3451043188.zip |
Finish first working version of Torque
This is a huge and messy commit, worked on piecemeal while traveling
and while the language was still being designed.
Diffstat (limited to 'src/formats')
-rw-r--r-- | src/formats/inhx32.rs | 87 | ||||
-rw-r--r-- | src/formats/mod.rs | 2 |
2 files changed, 89 insertions, 0 deletions
diff --git a/src/formats/inhx32.rs b/src/formats/inhx32.rs new file mode 100644 index 0000000..d9c31d3 --- /dev/null +++ b/src/formats/inhx32.rs @@ -0,0 +1,87 @@ +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<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(); + 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; +} diff --git a/src/formats/mod.rs b/src/formats/mod.rs new file mode 100644 index 0000000..42d198c --- /dev/null +++ b/src/formats/mod.rs @@ -0,0 +1,2 @@ +mod inhx32; +pub use inhx32::*; |