diff --git a/Cargo.toml b/Cargo.toml
index e23b384..058903c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,5 +6,5 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-
+rand = "0.8.4"
 sdl2 = "0.35.1"
diff --git a/src/main.rs b/src/main.rs
index f5a7238..14d146a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,16 +1,23 @@
 extern crate sdl2;
+extern crate rand;
 
 use sdl2::pixels::Color;
+#[allow(unused_imports)]
 use sdl2::event::Event;
+use sdl2::EventPump;
+#[allow(unused_imports)]
 use sdl2::keyboard::Keycode;
 use sdl2::video::Window;
+use sdl2::rect::Point;
+use sdl2::render::Canvas;
 
 use std::fs::File;
 use std::path::Path;
 use std::io;
 use std::io::Read;
 
-const font: [u8; 80] = [
+
+const FONT: [u8; 80] = [
     0xF0, 0x90, 0x90, 0x90, 0xF0,
     0x20, 0x60, 0x20, 0x20, 0x70,
     0xF0, 0x10, 0xF0, 0x80, 0xF0,
@@ -29,40 +36,40 @@ const font: [u8; 80] = [
     0xF0, 0x80, 0xF0, 0x80, 0x80 
 ];
 
+const HEIGHT: usize = 32;
+const WIDTH: usize = 64;
+
+#[allow(dead_code)]
 struct Machine {
     memory: [u8; 4096],
     key_inputs: [i32; 16],
-    display_buffer: [[i32; 64]; 32],
-    gpio: [i8; 16],
-    index: i16,
-    opcode: u16,
+    display_buffer: [[i32; WIDTH]; HEIGHT],
+    gpio: [u8; 16],
+    index: u16,
+    //opcode: u16,
     pc: usize,
-    stack: Vec<i32>
-}
-
-fn decodeOp(op1: u8, op2: u8) -> u16 {
-    let ret: u16 = u16::from(op1) << 2;
-    ret + u16::from(op2) >> 2
+    stack: Vec<u16>
 }
 
+#[allow(non_snake_case, unused_variables)]
 impl Machine {
     /// Initialise une machine en mettant tout à 0 (RAM, PC...)
     pub fn new() -> Self {
-        Machine {
+        Self {
             memory: [0; 4096],
             key_inputs: [0; 16],
-            display_buffer: [[0; 64]; 32],
+            display_buffer: [[0; WIDTH]; HEIGHT],
             gpio: [0; 16],
             index: 0,
-            opcode: 0,
+            //opcode: 0,
             pc: 0,
             stack: Vec::new(),
         }
     }
 
     pub fn init(&mut self) {
-        for i in 0..font.len() {
-            self.memory[i] = font[i];
+        for i in 0..FONT.len() {
+            self.memory[i] = FONT[i];
         }
 
         self.pc = 0x200;
@@ -81,93 +88,340 @@ impl Machine {
         Ok(())
     }
 
-    pub fn cycle(&mut self, screen: &mut sdl2::render::Canvas<Window>) {
-        self.opcode = ((self.memory[self.pc] as u16) << 8) 
+    pub fn cycle(&mut self, screen: &mut Canvas<Window>, events: &mut EventPump) {
+        let opcode = ((self.memory[self.pc] as u16) << 8) 
             + (self.memory[self.pc + 1] as u16);
 
-        self.pc += 2;
-        //let o = self.opcode & 0xf000;
+        let vx: usize = ((opcode & 0x0f00) >> 8) as usize;
+        let vy: usize = ((opcode & 0x00f0) >> 4) as usize;
+        let k: u8 = (opcode & 0x00ff) as u8;
 
-        match (self.opcode & 0xf000) >> 12 {
-            0 => match self.opcode {
-                0x00E0 => screen.clear(),
-                0x00EE => println!("RET"),
+        self.pc += 2;
+
+        match (opcode & 0xf000) >> 12 {
+            0 => match opcode {
+                0x00E0 => {
+                    self.display_buffer = [[0; 64]; 32];
+                    screen.set_draw_color(Color::RGB(0, 0, 0));
+                    screen.clear();
+                    screen.present();
+                },
+                0x00EE => self.pc = self.stack.pop().unwrap() as usize,
                 _ => println!("SYS"),
             }
-            1 => println!("JP"),
-            2 => println!("CALL"),
-            3 => println!("SE"),
-            4 => println!("SNE"),
-            5 => println!("SE 5"),
-            6 => println!("LD"),
-            7 => println!("ADD"),
+            1 => self.pc = (opcode & 0x0fff) as usize,
+            2 => { 
+                self.stack.push(self.pc as u16); 
+                self.pc = (opcode & 0x0fff) as usize
+            },
+            3 => if self.gpio[vx] == k as u8 {
+                    self.pc += 2;
+                },
+            4 => if self.gpio[vx] != k as u8 {
+                    self.pc += 2;
+                },
+            5 => if self.gpio[vx] == self.gpio[vy] {
+                    self.pc += 2;
+                }
+            6 => self.gpio[vx] = k,
+            7 => self.gpio[vx] = self.gpio[vx].saturating_add(k),
             8 => {
-                let x = (self.opcode & 0x0f00) >> 8;
-                let y = (self.opcode & 0x00f0) >> 4;
-                match self.opcode & 0x000f {
-                    0 => println!("LD 8"),
-                    1 => println!("OR"),
-                    2 => println!("AND"),
-                    3 => println!("XOR"),
-                    4 => println!("ADD"),
-                    5 => println!("SUB"),
-                    6 => println!("SHR"),
-                    7 => println!("SUBN"),
-                    0xE => println!("SHL"),
+                //let x = (opcode & 0x0f00) >> 8;
+                //let y = (opcode & 0x00f0) >> 4;
+                match opcode & 0x000f {
+                    0 => self.gpio[vx] = self.gpio[vy],
+                    1 => self.gpio[vx] |= self.gpio[vy],
+                    2 => self.gpio[vx] &= self.gpio[vy],
+                    3 => self.gpio[vx] ^= self.gpio[vy],
+                    4 => {
+                        self.gpio[vx] = self.gpio[vx].saturating_add(self.gpio[vy]);
+                        let (_, overflow) = self.gpio[vx].overflowing_add(self.gpio[vy]);
+                        if overflow {
+                            self.gpio[0xf] = 1;
+                        }
+                    },
+                    5 => {
+                        if self.gpio[vx] > self.gpio[vy] {
+                            self.gpio[0xf] = 1;
+                        } else {
+                            self.gpio[0xf] = 0;
+                        }
+
+                        self.gpio[vx] -= self.gpio[vy];
+                    },
+                    6 => {
+                        if self.gpio[vx].trailing_ones() > 0 {
+                            self.gpio[0xf] = 1;
+                        } else {
+                            self.gpio[0xf] = 0;
+                        }
+
+                        self.gpio[vx] >>= 1;
+                    },
+                    7 => {
+                        if self.gpio[vx] < self.gpio[vy] {
+                            self.gpio[0xf] = 1;
+                        } else {
+                            self.gpio[0xf] = 0;
+                        }
+
+                        self.gpio[vx] = self.gpio[vy] - self.gpio[vx];
+                    },
+                    0xE => {
+                        if self.gpio[vx].leading_ones() > 0 {
+                            self.gpio[0xf] = 1;
+                        } else {
+                            self.gpio[0xf] = 0;
+                        }
+
+                        self.gpio[vx] <<= 1;
+                    },
                     _ => println!("error 8")
                 }
             }
-            9 => println!("SNE 9"),
-            0xA => println!("LD A"),
-            0xB => println!("JP B"),
-            0xC => println!("RND "),
-            0xD => println!("DRW"),
+            9 => if self.gpio[vx] != self.gpio[vy] {
+                    self.pc += 2;
+                },
+            0xA => self.index = opcode & 0x0fff,
+            0xB => self.pc = ((self.gpio[0]) as u16 + (opcode & 0x0fff)) as usize,
+            0xC => self.gpio[vx] = rand::random::<u8>() & k,
+            0xD => {
+                let x = self.gpio[vx] as u16;
+                let y = self.gpio[vy] as u16;
+                for i in 0..(opcode & 0x000f) {
+                    //println!("{:?}", self.memory);
+                    let mut sprite = self.memory[(self.index + i as u16) as usize];
+                    for j in 0..8 {
+                        let mut case = 0;
+                        if sprite.leading_ones() > 0 { case = 1; }
+                        //println!("I :: {}", self.index + i);
+                        //println!("D :: {} - {}", sprite, case);
+                        sprite = sprite << 1;
+
+                        let ty: usize = (i + y) as usize % HEIGHT;
+                        let tx: usize = (j + x) as usize % WIDTH;
+
+                        let tmp = self.display_buffer[ty][tx];
+                        self.display_buffer[ty][tx] ^= case;
+                        if self.display_buffer[ty][tx] == 0 && tmp == 1 {
+                            self.gpio[0xf] = 1;
+                        }
+                    }   
+                }
+            },
             0xE => {
-                let x = (self.opcode & 0x0f00) >> 8;
-                match self.opcode & 0x00ff {
-                    0x9E => println!("SKP"),
-                    0xA1 => println!("SKNP"),
+                let x = (opcode & 0x0f00) >> 8;
+                match opcode & 0x00ff {
+                    0x9E => {
+                        if self.key_inputs[self.gpio[vx] as usize] == 1 {
+                            self.pc += 2;
+                        }
+                    },
+                    0xA1 => {
+                        if self.key_inputs[self.gpio[vx] as usize] == 0 {
+                            self.pc += 2;
+                        }
+                    },
                     _ => println!("error E")
                 }
             }
             0xF => {
-                let x = (self.opcode & 0x0f00) >> 8;
-                match self.opcode & 0x00ff {
+                let x = (opcode & 0x0f00) >> 8;
+                match opcode & 0x00ff {
                     0x07 => println!("LD F 7"),
-                    0x0A => println!("LD F A"),
+                    0x0A => self.check_touch(vx, events),
                     0x15 => println!("LD F 15"),
                     0x18 => println!("LD F 18"),
-                    0x1E => println!("ADD F 1E"),
-                    0x29 => println!("LD F 2"),     // self.index = self.gpio[x] * 5) & 0x0fff
+                    0x1E => self.index += self.gpio[vx] as u16,
+                    0x29 => self.index = (self.gpio[vx] as u16) * 5,     // self.index = self.gpio[x] * 5) & 0x0fff
                     0x33 => println!("LD F 3"),
-                    0x55 => println!("LD F 5"),
-                    0x65 => println!("LD F 6"),
+                    0x55 => 
+                    {
+                        //let mut j: usize = self.index as usize;
+                        for i in 0..(vx + 1) {
+                            self.memory[(self.index as usize) + i] = self.gpio[i];
+                            //j += 1;
+                        }
+                    },
+                    0x65 => {
+                        //let mut j: usize = self.index as usize;
+                        for i in 0..(vx+1) {
+                            self.gpio[i] = self.memory[(self.index as usize) + i];
+                            //j += 1;
+                        }
+                    },
                     _ => println!("error F")
                 }
             }
             _ => println!("error")
         }
     }
+
+    fn check_touch(&mut self, vx: usize, events: &mut EventPump) {
+        let touch = events.wait_event();
+        match touch {
+            Event::KeyDown { keycode: Some(Keycode::Num0), .. } => {
+                self.gpio[vx] = 0;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
+                self.gpio[vx] = 1;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num2), .. } => {
+                self.gpio[vx] = 2;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num3), .. } => {
+                self.gpio[vx] = 3;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num4), .. } => {
+                self.gpio[vx] = 4;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num5), .. } => {
+                self.gpio[vx] = 5;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num6), .. } => {
+                self.gpio[vx] = 6;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num7), .. } => {
+                self.gpio[vx] = 7;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num8), .. } => {
+                self.gpio[vx] = 8;
+            },
+            Event::KeyDown { keycode: Some(Keycode::Num9), .. } => {
+                self.gpio[vx] = 9;
+            },
+            Event::KeyDown { keycode: Some(Keycode::A), .. } => {
+                self.gpio[vx] = 0xa;
+            },
+            Event::KeyDown { keycode: Some(Keycode::B), .. } => {
+                self.gpio[vx] = 0xb;
+            },
+            Event::KeyDown { keycode: Some(Keycode::C), .. } => {
+                self.gpio[vx] = 0xc;
+            },
+            Event::KeyDown { keycode: Some(Keycode::D), .. } => {
+                self.gpio[vx] = 0xd;
+            },
+            Event::KeyDown { keycode: Some(Keycode::E), .. } => {
+                self.gpio[vx] = 0xe;
+            },
+            Event::KeyDown { keycode: Some(Keycode::F), .. } => {
+                self.gpio[vx] = 0xf;
+            },
+            _ => self.check_touch(vx, events),
+        }
+    }
 }
 
 
+fn read_file(p: &Path) -> io::Result<()> {
+    let mut buffer = Vec::new();
+    let mut f = File::open(p)?;
+    let mut mem = [0; 4096];
+    f.read_to_end(&mut buffer)?;
+
+    for i in 0..buffer.len() {
+        mem[i] = buffer[i];
+    }
+
+    println!("{:?}", mem);
+
+    let mut i = 0;
+    while i < mem.len() {
+        let opcode = ((mem[i] as u16) << 8) 
+            + (mem[i + 1] as u16);
+
+        let vx: usize = ((opcode & 0x0f00) >> 8) as usize;
+        let vy: usize = ((opcode & 0x00f0) >> 4) as usize;
+        let k: u8 = (opcode & 0x00ff) as u8;
+
+        i += 2;
+
+        match (opcode & 0xf000) >> 12 {
+            0 => match opcode {
+                0x00E0 => println!("CLS"),
+                0x00EE => println!("RET"),
+                _ => println!("SYS"),
+            }
+            1 => println!("JP {}", opcode & 0x0fff),
+            2 => println!("CALL {}", opcode & 0x0fff),
+            3 => println!("3SE {} {}", vx, k),
+            4 => println!("4SNE {} {}", vx, k),
+            5 => println!("5SE {} {}", vx, vy),
+            6 => println!("6LD {} {}", vx, k),
+            7 => println!("7ADD {} {}", vx, k),
+            8 => {
+                //let x = (opcode & 0x0f00) >> 8;
+                //let y = (opcode & 0x00f0) >> 4;
+                match opcode & 0x000f {
+                    0 => println!("8LD {} {}", vx, vy),
+                    1 => println!("8OR {} {}", vx, vy),
+                    2 => println!("8AND {} {}", vx, vy),
+                    3 => println!("8XOR {} {}", vx, vy),
+                    4 => println!("8ADD {} {}", vx, vy),
+                    5 => println!("8SUB {} {}", vx, vy),
+                    6 => println!("8SHR {} {}", vx, vy),
+                    7 => println!("8SUBN {} {}", vx, vy),
+                    0xE => println!("8SHL {} {}", vx, vy),
+                    _ => println!("error 8")
+                }
+            }
+            9 => println!("9SNE {} {}", vx, vy),
+            0xA => println!("AADD I {}", opcode & 0x0fff),
+            0xB => println!("BJP 0 {}", opcode & 0x0fff),
+            0xC => println!("RND {} {}", vx, k),
+            0xD => println!("DRW {} {} {}", vx, vy, opcode & 0x000f),
+            0xE => {
+                let x = (opcode & 0x0f00) >> 8;
+                match opcode & 0x00ff {
+                    0x9E => println!("SKP {}", vx),
+                    0xA1 => println!("SKNP {}", vx),
+                    _ => println!("error E")
+                }
+            }
+            0xF => {
+                let x = (opcode & 0x0f00) >> 8;
+                match opcode & 0x00ff {
+                    0x07 => println!("FLD {} DT", vx),
+                    0x0A => println!("FLD {} K", vx),
+                    0x15 => println!("FLD DT {}", vx),
+                    0x18 => println!("FLD ST {}", vx),
+                    0x1E => println!("FADD I {}", vx),
+                    0x29 => println!("FLD F {}", vx),
+                    0x33 => println!("FLD B {}", vx),
+                    0x55 => println!("FLD [I] {}", vx),
+                    0x65 => println!("FLD {} [I]", vx),
+                    _ => println!("error F")
+                }
+            }
+            _ => println!("error")
+        }
+    }
+
+    Ok(())
+}
+
+#[allow(unused_mut, unused_must_use, unused_labels, unused_variables)]
 fn main() {
+    //read_file(Path::new("15PUZZLE"));
+    //return;
     let mut t : Machine = Machine::new();
-    println!("{:?}", t.memory);
+    //println!("{:?}", t.memory);
     t.init();
-    t.loadRom(Path::new("15PUZZLE"));
-    println!("\n\n{:?}", t.memory);
-    //t.cycle();
+    //t.loadRom(Path::new("15PUZZLE"));
+    t.loadRom(Path::new("BLITZ"));
+
+    //println!("\n\n{:?}", t.memory);
 
     let sdl_context = sdl2::init().unwrap();
     let video_subsystem = sdl_context.video().unwrap();
-    let window = video_subsystem.window("Chip8 Emulator", 900, 700)
+    let window = video_subsystem.window("Chip8 Emulator", WIDTH as u32, HEIGHT as u32)
         .position_centered()
         .build()
         .unwrap();
 
     let mut canvas = window.into_canvas().build().unwrap();
-    canvas.set_draw_color(Color::RGB(0, 255, 255));
+    canvas.set_draw_color(Color::RGB(0, 0, 0));
     canvas.clear();
     canvas.present();
 
@@ -180,18 +434,134 @@ fn main() {
         canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
         canvas.clear();
         */
-        t.cycle(&mut canvas);
 
-        /*
+        t.cycle(&mut canvas, &mut event_pump);
+        
+        //canvas.set_draw_color(Color::RGB(0, 0, 0));
+        //canvas.clear();
+        //println!("{:?}", t.memory);
+
+        canvas.set_draw_color(Color::RGB(255, 255, 255));
+
+        //println!("{:?}", t.display_buffer);
+        //println!("\n===\n");
+
+        for i in 0..t.display_buffer.len() {
+            for j in 0..t.display_buffer[i].len() {
+                if t.display_buffer[i][j] == 1 {
+                    canvas.draw_point(Point::new(j as i32, i as i32));
+                }
+            }
+        }
+
+        //canvas.draw_line(Point::new(10, 10), Point::new(20,20));
+        //canvas.draw_point(Point::new(10, 10));
+
         for event in event_pump.poll_iter() {
             match event {
                 Event::KeyDown { keycode: Some(Keycode::Escape), ..} => {
                     break 'running
                 },
+                Event::KeyDown { keycode: Some(Keycode::Num0), .. } => {
+                    t.key_inputs[0] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
+                    t.key_inputs[1] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num2), .. } => {
+                    t.key_inputs[2] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num3), .. } => {
+                    t.key_inputs[3] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num4), .. } => {
+                    t.key_inputs[4] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num5), .. } => {
+                    t.key_inputs[5] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num6), .. } => {
+                    t.key_inputs[6] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num7), .. } => {
+                    t.key_inputs[7] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num8), .. } => {
+                    t.key_inputs[8] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::Num9), .. } => {
+                    t.key_inputs[9] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::A), .. } => {
+                    t.key_inputs[0xa] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::B), .. } => {
+                    t.key_inputs[0xb] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::C), .. } => {
+                    t.key_inputs[0xc] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::D), .. } => {
+                    t.key_inputs[0xd] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::E), .. } => {
+                    t.key_inputs[0xe] = 1;
+                },
+                Event::KeyDown { keycode: Some(Keycode::F), .. } => {
+                    t.key_inputs[0xf] = 1;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num0), .. } => {
+                    t.key_inputs[0] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num1), .. } => {
+                    t.key_inputs[1] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num2), .. } => {
+                    t.key_inputs[2] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num3), .. } => {
+                    t.key_inputs[3] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num4), .. } => {
+                    t.key_inputs[4] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num5), .. } => {
+                    t.key_inputs[5] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num6), .. } => {
+                    t.key_inputs[6] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num7), .. } => {
+                    t.key_inputs[7] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num8), .. } => {
+                    t.key_inputs[8] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::Num9), .. } => {
+                    t.key_inputs[9] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::A), .. } => {
+                    t.key_inputs[0xa] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::B), .. } => {
+                    t.key_inputs[0xb] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::C), .. } => {
+                    t.key_inputs[0xc] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::D), .. } => {
+                    t.key_inputs[0xd] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::E), .. } => {
+                    t.key_inputs[0xe] = 0;
+                },
+                Event::KeyUp { keycode: Some(Keycode::F), .. } => {
+                    t.key_inputs[0xf] = 0;
+                },
+
                 _ => {}
             }
         }
-        */
 
         canvas.present();
     }