1mod commands;
2mod instructions;
3mod print;
4use std::error::Error;
5use std::fs::File;
6use std::io::prelude::*;
7use std::io::stdin;
8
9use instructions::Instruction;
10use print::*;
11
12pub struct State {
20 registers: Vec<u64>,
21 program_map: Vec<u8>,
22 condition_code: u8,
23 program_size: u64,
24 program_counter: u64,
25}
26
27impl State {
28 pub fn new(file_name: String) -> Result<Self, Box<dyn Error>> {
32 let mut file = File::open(file_name)?;
33 let program_size = file.metadata()?.len();
34 let program_counter = 0;
35 let mut program_map = Vec::new();
36 file.read_to_end(&mut program_map)?;
37 Ok(State {
38 registers: vec![0; 16],
39 program_map,
40 program_size,
41 condition_code: 0,
42 program_counter,
43 })
44 }
45
46 pub fn get_register(&self, register_id: u8) -> u64 {
49 self.registers[register_id as usize]
50 }
51
52 pub fn set_register(&mut self, register_id: u8, value: u64) {
56 self.registers[register_id as usize] = value;
57 }
58
59 pub fn get_condition_code(&self) -> u8 {
61 self.condition_code
62 }
63
64 pub fn set_condition_code(&mut self, value: u8) {
67 self.condition_code = value;
68 }
69
70 pub fn get_program_size(&self) -> u64 {
72 self.program_size
73 }
74
75 pub fn read_le(&self, address: u64) -> Result<u64, Box<dyn Error>> {
79 let mut res: u64 = 0;
80 for i in 0..8 {
81 res = (res << 8) | self.program_map[(address + 7 - i) as usize] as u64;
82 }
83 Ok(res)
84 }
85
86 pub fn write_le(&mut self, address: u64, value: u64) -> Result<(), Box<dyn Error>> {
91 for i in 0..8 {
92 let val = ((value >> 8 * i) & 0xFF) as u8;
93 self.program_map[(address + i) as usize] = val;
94 }
95 Ok(())
96 }
97
98 pub fn set_pc(&mut self, new_pc: u64) {
101 self.program_counter = new_pc;
102 }
103
104 pub fn get_pc(&self) -> u64 {
106 self.program_counter
107 }
108
109
110 pub fn read_byte(&self, address: u64) -> u8 {
113 self.program_map[address as usize]
114 }
115}
116
117
118pub fn debug(file_name: String) -> Result<(), Box<dyn Error>> {
121 let mut state = State::new(file_name.clone())?;
122 while state.read_byte(state.get_pc()) == 0 {
123 state.set_pc(state.get_pc() + 1);
124 }
125 println!(
126 "## Opened {:}, starting PC 0x{:x}",
127 file_name,
128 state.get_pc()
129 );
130
131 loop {
132 let mut instruction = Instruction::new(&state)?;
133 print_instruction(&instruction);
134 print!("> ");
135 std::io::stdout().flush()?;
136 let mut buffer = String::new();
137 match stdin().read_line(&mut buffer) {
138 Ok(_) => (),
139 Err(_) => {
140 eprintln!("Could not parse input, please try again");
141 continue;
142 }
143 }
144 buffer = buffer.trim().to_string();
145 if buffer.starts_with("quit") {
146 break;
147 }
148 match commands::run(buffer, &mut instruction, &mut state) {
149 Ok(_) => (),
150 Err(e) => {
151 eprintln!("{:}", e);
152 }
153 }
154 }
155 Ok(())
156}