diff --git a/chip8/src/lib.rs b/chip8/src/lib.rs index 322a326..4a5553a 100644 --- a/chip8/src/lib.rs +++ b/chip8/src/lib.rs @@ -11,7 +11,7 @@ pub struct Chip8 { v: [u8; 16], index: u16, pc: u16, - gfx: [u8; w * h], + pub gfx: [u8; w * h], delay_timer: u8, sound_timer: u8, stack: [u16; 16], @@ -146,7 +146,84 @@ impl Chip8 { self.pc += 2; } 0x8000 => { - // TODO + match self.opcode & 0x000F { + 0x0000 => { + // 0x8XY0 Sets VX to the value of VY + self.v[x] = self.v[y]; + self.pc += 2; + } + 0x0001 => { + // 0x8XY1 Sets VX to VX or VY. (Bitwise OR operation) + self.v[x] = (self.v[x] | self.v[y]); + self.pc += 2; + } + 0x0002 => { + // 0x8XY2 Sets VX to VX and VY. (Bitwise AND operation) + self.v[x] = (self.v[x] & self.v[y]); + self.pc += 2; + } + 0x0003 => { + // 0x8XY3 Sets VX to VX xor VY + self.v[x] = (self.v[x] ^ self.v[y]); + self.pc += 2; + } + 0x0004 => { + // 0x8XY4 Adds VY to VX. VF is set to 1 when there's a + // carry, and to 0 when there isn't + if self.v[y] > (0xFF - self.v[x]) { + self.v[0xF] = 1; + } else { + self.v[0xF] = 0; + } + self.v[x] += self.v[y]; + self.pc += 2; + } + 0x0005 => { + // 0x8XY5 VY is subtracted from VX. VF is set to 0 when + // there's a borrow, and 1 when there isn't + if self.v[x] > self.v[y] { + self.v[0xF] = 1; + } else { + self.v[0xF] = 0; + } + self.v[x] -= self.v[y]; + self.pc += 2; + } + 0x0006 => { + // 0x8XY6 Stores the least significant bit of VX in VF + // and then shifts VX to the right by 1 + if self.opcode & 0x1 >= 1 { + self.v[0xF] = 1; + } else { + self.v[0xF] = 0; + } + self.v[x] = self.v[x] >> 1; + self.pc += 2; + } + 0x0007 => { + // 0x8XY7 Sets VX to VY minus VX. VF is set to 0 when + // there's a borrow, and 1 when there isn't + if self.v[y] > self.v[x] { + self.v[0xF] = 1; + } else { + self.v[0xF] = 0; + } + self.v[x] = self.v[y] - self.v[x]; + self.pc += 2; + } + 0x000E => { + // 0x8XYE Stores the most significant bit of VX in VF + // and then shifts VX to the left by 1 + if self.opcode & 0x80 == 0x80 { + self.v[0xF] = 1; + } else { + self.v[0xF] = 0; + } + self.v[x] = self.v[x] << 1; + self.pc += 2; + } + _ => println!("unk {:x}", self.opcode), + } } 0x9000 => { // 9XY0 Skips the next instruction if VX doesn't equal VY. @@ -176,7 +253,33 @@ impl Chip8 { self.pc += 2; } 0xD000 => { - // TODO + // DXYN Draws a sprite at coordinate (VX, VY) that has a width + // of 8 pixels and a height of N+1 pixels. Each row of 8 pixels + // is read as bit-coded starting from memory location I; I + // value doesn’t change after the execution of this + // instruction. As described above, VF is set to 1 if any + // screen pixels are flipped from set to unset when the sprite + // is drawn, and to 0 if that doesn’t happen + let heigh = self.opcode & 0x000F; + let mut pixel: u8; + self.v[0xF] = 0; + for yline in 0..heigh { + pixel = self.memory[(self.index + yline) as usize]; + for xline in 0..8 { + if (pixel & (0x80 >> xline)) != 0 { + let pos = (self.v[x] as u16 + xline) as usize + + (self.v[y] as u16 + yline) as usize * w; + if pos >= 2048 { + break; + } + if self.gfx[pos] == 1 { + self.v[0xF] = 1; + } else { + self.v[0xF] ^= 1; + } + } + } + } self.draw_flag = true; self.pc += 2;