diff --git a/examples/benchmark/src/main.rs b/examples/benchmark/src/main.rs index d69c8981287de9d66d48200cf19bc34f541055cc..b5ca3e94ee584c0f32e89b344fbb24f63e75889b 100644 --- a/examples/benchmark/src/main.rs +++ b/examples/benchmark/src/main.rs @@ -18,7 +18,7 @@ fn benchmark_chip8() { println!("[Chip8] Running {} cycles for {}", cycles, rom_path); for _ in 0..CYCLE_COUNT { - chip8.tick(); + chip8.clock(); } let duration_s = instant.elapsed().as_seconds_f32(); @@ -33,8 +33,11 @@ fn benchmark_chip8() { fn benchmark_chip8_neo() { let rom_path = "./resources/pong.ch8"; + let rom = read_file(rom_path); let mut chip8 = Chip8Neo::new(); + chip8.reset_hard(); + chip8.load_rom(&rom); let instant = Instant::now(); @@ -43,7 +46,7 @@ fn benchmark_chip8_neo() { println!("[Chip8Neo] Running {} cycles for {}", cycles, rom_path); for _ in 0..CYCLE_COUNT { - chip8.tick(); + chip8.clock(); } let duration_s = instant.elapsed().as_seconds_f32(); diff --git a/examples/sdl/src/main.rs b/examples/sdl/src/main.rs index 7940d90bebc43ec18cdf441e6497a82d795a4ab8..363ddb1d6ee7c564637b9545140fe6a7521a687e 100644 --- a/examples/sdl/src/main.rs +++ b/examples/sdl/src/main.rs @@ -1,5 +1,6 @@ use chip_ahoyto::{ - chip8::Chip8, chip8::SCREEN_PIXEL_HEIGHT, chip8::SCREEN_PIXEL_WIDTH, util::read_file, + chip8::Chip8, chip8::SCREEN_PIXEL_HEIGHT, chip8::SCREEN_PIXEL_WIDTH, chip8_neo::Chip8Neo, + util::read_file, }; use sdl2::{ audio::AudioCallback, audio::AudioSpecDesired, event::Event, image::LoadSurface, @@ -83,7 +84,7 @@ impl BeepCallback { } pub struct State { - system: Chip8, + system: Chip8Neo, logic_frequency: u32, visual_frequency: u32, idle_frequency: u32, @@ -110,7 +111,7 @@ fn main() { // builds the CHIP-8 machine, this is the instance that // is going to logically represent the CHIP-8 let mut state = State { - system: Chip8::new(), + system: Chip8Neo::new(), logic_frequency: LOGIC_HZ, visual_frequency: VISUAL_HZ, idle_frequency: IDLE_HZ, diff --git a/src/chip8_neo.rs b/src/chip8_neo.rs index 3683ef20b720fc17671cef476046debf62697903..a5b463b77679c61fe76024d246f88b50633580c3 100644 --- a/src/chip8_neo.rs +++ b/src/chip8_neo.rs @@ -58,7 +58,28 @@ impl Chip8Neo { chip8 } - pub fn tick(&mut self) { + pub fn reset(&mut self) { + self.vram = [0u8; DISPLAY_WIDTH * DISPLAY_HEIGHT]; + self.stack = [0u16; STACK_SIZE]; + self.registers = [0u8; REGISTERS_SIZE]; + self.pc = ROM_START as u16; + self.i = 0x0; + self.sp = 0x0; + self.dt = 0x0; + self.st = 0x0; + self.load_default_font(); + } + + pub fn reset_hard(&mut self) { + self.ram = [0u8; RAM_SIZE]; + self.reset(); + } + + pub fn pixels(&self) -> Vec<u8> { + self.vram.to_vec() + } + + pub fn clock(&mut self) { // fetches the current instruction and increments // the PC (program counter) accordingly let instruction = @@ -67,7 +88,9 @@ impl Chip8Neo { let opcode = instruction & 0xf000; let address = instruction & 0x0fff; - let nibble = ((instruction & 0x0f00) >> 8) as u8; + let first_nibble = ((instruction & 0x0f00) >> 8) as u8; + let second_nibble = ((instruction & 0x00f0) >> 4) as u8; + let third_nibble = (instruction & 0x000f) as u8; let byte = (instruction & 0x00ff) as u8; match opcode { @@ -76,17 +99,54 @@ impl Chip8Neo { _ => println!("unimplemented instruction"), }, 0x1000 => self.pc = address, - 0x6000 => { - self.registers[nibble as usize] = byte; + 0x6000 => self.registers[first_nibble as usize] = byte, + 0x7000 => self.registers[first_nibble as usize] += byte, + 0xa000 => self.i = address, + 0xd000 => { + let mut x = self.registers[first_nibble as usize]; + let mut y = self.registers[second_nibble as usize]; + let mut offset = 0; + for i in 0..third_nibble { + y = (y + i) % DISPLAY_HEIGHT as u8; + for j in 0..8 { + x = (x + j) % DISPLAY_WIDTH as u8; + let pixel = self.ram[(self.i + offset) as usize]; + self.vram[(y * DISPLAY_WIDTH as u8 + x) as usize] = pixel; + offset += 1; + } + } } - _ => println!("unimplemented instruction"), + _ => println!( + "unimplemented opcode {}, instruction {}", + opcode, instruction + ), } } + pub fn clock_dt(&mut self) {} + + pub fn clock_st(&mut self) {} + + pub fn key_press(&mut self, key: u8) {} + + pub fn key_lift(&mut self, key: u8) {} + pub fn load_rom(&mut self, rom: &[u8]) { self.ram[ROM_START..ROM_START + rom.len()].clone_from_slice(&rom); } + pub fn beep(&self) -> bool { + false + } + + pub fn pc(&self) -> u16 { + self.pc + } + + pub fn sp(&self) -> u8 { + self.sp + } + fn load_font(&mut self, position: usize, font_set: &[u8]) { self.ram[position..position + font_set.len()].clone_from_slice(&font_set); }