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);
     }