From: Greg Burri Date: Sat, 10 Sep 2022 17:42:18 +0000 (+0200) Subject: Add memory and registers implementations X-Git-Url: http://git.euphorik.ch/?a=commitdiff_plain;h=cffc1269846766ed8f767dbf038dfa137ecf8222;p=rust_in_action.git Add memory and registers implementations --- diff --git a/ch5-data-in-depth/src/chip8.rs b/ch5-data-in-depth/src/chip8.rs index 2b6d1a4..77c7363 100644 --- a/ch5-data-in-depth/src/chip8.rs +++ b/ch5-data-in-depth/src/chip8.rs @@ -6,52 +6,84 @@ /// 4) Opcode subgroup (d) / Number of bytes (n). / Integer (kk) / Memory address (nnn). struct CPU { - registers: [u8; 16], - position_in_memory: usize, + registers: [u8; 16], // 4 bits can address a 16 positions register. The last position (0xF) is used to indicate an overflow. + position_in_memory: usize, // Programm counter. memory: [u8; 0x1000], // 4 KB of memory. } impl CPU { + fn new() -> CPU { + CPU { + registers: [0; 16], + position_in_memory: 0, + memory: [0; 0x1000], + } + } + fn read_opcode(&self) -> u16 { - self.current_operation + let p = self.position_in_memory; + let op_byte1 = self.memory[p] as u16; + let op_byte2 = self.memory[p + 1] as u16; + op_byte1 << 8 | op_byte2 } fn run(&mut self) { - // loop { + loop { let opcode = self.read_opcode(); + self.position_in_memory += 2; + let c = ((opcode & 0xF000) >> 12) as u8; let x = ((opcode & 0x0F00) >> 8) as u8; let y = ((opcode & 0x00F0) >> 4) as u8; let d = ((opcode & 0x000F) >> 0) as u8; match (c, x, y, d) { + (0, 0, 0, 0) => { return; } (0x8, _, _, 0x4) => self.add_xy(x, y), _ => todo!("opcode: {:04x}", opcode), } - //} + } } fn add_xy(&mut self, x: u8, y: u8) { - self.registers[x as usize] += self.registers[y as usize]; + let arg1 = self.registers[x as usize]; + let arg2 = self.registers[y as usize]; + + let (val, overflow) = arg1.overflowing_add(arg2); + self.registers[x as usize] = val; + + if overflow { + self.registers[0xF] = 1; + } else { + self.registers[0xF] = 0; + } } } mod tests { use super::*; + /// 5 + 10 + 10 + 10 = 35. (three operations). #[test] fn addition() { - let mut cpu = CPU { - current_operation: 0, - registers: [0; 2] - }; + let mut cpu = CPU::new(); + + cpu.memory[0] = 0x80; + cpu.memory[1] = 0x14; + + cpu.memory[2] = 0x80; + cpu.memory[3] = 0x24; + + cpu.memory[4] = 0x80; + cpu.memory[5] = 0x34; - cpu.current_operation = 0x8014; cpu.registers[0] = 5; cpu.registers[1] = 10; + cpu.registers[2] = 10; + cpu.registers[3] = 10; cpu.run(); - assert_eq!(cpu.registers[0], 15); + assert_eq!(cpu.registers[0], 35); } } \ No newline at end of file