mod instr; mod memory; use std::fs::File; use std::io::{Read, Write}; use std::collections::HashMap; use anyhow::Result; use crate::memory::*; use crate::instr::*; lazy_static::lazy_static! { static ref CH: (HashMap, HashMap) = { let mut chmap = HashMap::new(); let mut chmap2 = HashMap::new(); let m = [ b"0123456789ABCDEF", b"GHIJKLMNOPQRSTUV", b"WXYZ +-*/<=>()[]", b"{}#$_?|^&!~,.:\n\x00", ]; for (nrow, row) in m.iter().enumerate() { for (ncol, cell) in row.iter().enumerate() { let n = nrow * 0o20 + ncol; chmap.insert(*cell, n); chmap2.insert(n, *cell); } } (chmap, chmap2) }; } struct Clock { } #[derive(Default)] pub struct Control { instrs: Vec, memory: Memory, condition: bool, overflow: bool, zero: bool, carry: bool, sign: bool, ip: usize, } impl Control { fn step(&mut self) { let instr = &self.instrs[self.ip]; self.ip += 1; let (cond, op, a, b, c) = match instr { Instr::Invalid => panic!("halt"), Instr::Normal { cond, op, a, b, c } => (cond, op, *a, *b, *c), }; println!("instr: {:?}", instr); // skip conditionals that aren't taken match (self.condition, cond) { (false, Cond::IfTrue) | (true, Cond::IfFalse) => return, _ => {}, } match op { Op::AddI => { self.memory.write(a, b + c) }, Op::Label => { /* don't do anything here */ }, Op::CmpRR(cm) | Op::CmpRI(cm) | Op::CmpII(cm) => { let (op1, op2) = match op { Op::CmpRR(_) => (self.memory.read(b), self.memory.read(c)), Op::CmpRI(_) => (self.memory.read(b), c), Op::CmpII(_) => (b, c), _ => unreachable!(), }; let result = match cm { Cm::Tr => true, Cm::Fa => false, Cm::Eq => }; } Op::JmpUp | Op::JmpDn => { let lab = (a, b); let rc = self.memory.read(c); loop { if let Op::JmpUp = op { self.ip -= 1; } else { self.ip += 1; } let (cond, op, a, b, c) = match &self.instrs[self.ip] { Instr::Invalid => panic!("halt"), Instr::Normal { cond, op, a, b, c } => (cond, op, *a, *b, *c), }; if lab == (a, b) && c == rc { println!("JUMPED TO {:?}", self.ip); break; } } }, _ => unreachable!("unhandled {:?}", op), }; println!("memory: {:?}", self.memory); println!("{:?}", std::str::from_utf8(self.memory.array.iter().map(|i| *CH.1.get(&(*i as usize)).unwrap()).collect::>().as_slice())); } } fn main() -> Result<()> { let mut file = File::open("mandelflag.rom")?; let mut contents = String::new(); file.read_to_string(&mut contents)?; let contents = base64::decode(&contents)?; let instrs = contents.chunks(3) .map(|c| ((c[0] as u32) << 16) | ((c[1] as u32) << 8) | c[2] as u32) .map(Instr::decode) .collect::>(); let mut cpu = Control::default(); cpu.instrs = instrs; for _ in 0..1000 { cpu.step(); } Ok(()) }