summaryrefslogtreecommitdiff
path: root/src/formats
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-02-27 14:53:21 +1300
committerBen Bridle <ben@derelict.engineering>2025-02-27 14:53:31 +1300
commit67470aea034fd46f4bbcfe815c51ad3451043188 (patch)
tree83d78d3d28e094d6a3af347d2ff2ff16472e5421 /src/formats
parent4e8fae09f0f7d6f3a4ddbe285aeb01ef0622b761 (diff)
downloadtorque-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.rs87
-rw-r--r--src/formats/mod.rs2
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::*;