diff --git a/examples/sdl/src/main.rs b/examples/sdl/src/main.rs
index 965230e0d64150d2b87907dd290b1cbab3501b61..a6133ff775e3da1bb1e2dbb4f8e530c4171a409f 100644
--- a/examples/sdl/src/main.rs
+++ b/examples/sdl/src/main.rs
@@ -87,7 +87,7 @@ fn main() {
     //game_boy.load_rom_file("../../res/roms.prop/alleyway.gb");
 
     //game_boy.load_rom_file("../../res/roms/firstwhite.gb");
-    //game_boy.load_rom_file("../../res/roms/opus5.gb");
+    game_boy.load_rom_file("../../res/roms/opus5.gb");
 
     //game_boy.load_rom_file("../../res/roms/paradius/cpu/01-special.gb"); // PASSED
     //game_boy.load_rom_file("../../res/roms/paradius/cpu/02-interrupts.gb"); // NO FINISH
diff --git a/examples/web/debug.css b/examples/web/debug.css
index 97a8a6a149b80b43597595730dd47f9b9bdec6f6..e4b0114329f1ddc881d99223109f87837910388c 100644
--- a/examples/web/debug.css
+++ b/examples/web/debug.css
@@ -1,4 +1,4 @@
 .debug > .canvas-tiles {
     background-color: #000000;
-    width: 480px;
+    width: 256px;
 }
diff --git a/examples/web/index.html b/examples/web/index.html
index c948d327089ff391f82280e1d73ef322b21a5a6c..521cf0df8970077317fb0151a51f42de4fc56718 100644
--- a/examples/web/index.html
+++ b/examples/web/index.html
@@ -69,7 +69,7 @@
             <div id="separator-keyboard" class="separator" style="display: none;"></div>
             <div id="section-debug" class="section" style="display: none;">
                 <div id="debug" class="debug">
-                    <canvas id="canvas-tiles" class="canvas-tiles" width="512" height="512"></canvas>
+                    <canvas id="canvas-tiles" class="canvas-tiles" width="128" height="128"></canvas>
                 </div>
             </div>
             <div id="separator-debug" class="separator" style="display: none;"></div>
diff --git a/examples/web/index.ts b/examples/web/index.ts
index eefb20faad9675f298b1e9f20c3e6a99457b13f0..c2b983a88ba011715b67405f5f8841d93932e7be 100644
--- a/examples/web/index.ts
+++ b/examples/web/index.ts
@@ -301,7 +301,7 @@ const start = async ({
 
     // resets the Game Boy engine to restore it into
     // a valid state ready to be used
-    //state.gameBoy.reset_hard(); @todo
+    state.gameBoy.reset();
     state.gameBoy.load_boot_static();
     state.gameBoy.load_rom(romData);
 
@@ -533,6 +533,43 @@ const registerButtons = () => {
             sectionNarrative.style.display = "none";
             separatorNarrative.style.display = "none";
             buttonDebug.classList.add("enabled");
+
+            const canvasTiles = document.getElementById("canvas-tiles") as HTMLCanvasElement;
+            const canvasTilesCtx = canvasTiles.getContext("2d");
+
+            const canvasImage = canvasTilesCtx.createImageData(canvasTiles.width, canvasTiles.height);
+            const videoBuff = new DataView(canvasImage.data.buffer);
+
+            const drawSprite = (index: number, format: PixelFormat = PixelFormat.RGB) => {
+                const pixels = state.gameBoy.get_tile_buffer(index);
+                const line = Math.floor(index / 16);
+                const column = index % 16;
+                console.info(`${canvasTiles.width}`);
+                let offset = ((line * canvasTiles.width * 8) + (column * 8)) * PixelFormat.RGBA;
+                console.info(`${offset}`);
+                let counter = 0;
+                for (let index = 0; index < pixels.length; index += format) {
+                    const color =
+                        (pixels[index] << 24) |
+                        (pixels[index + 1] << 16) |
+                        (pixels[index + 2] << 8) |
+                        (format == PixelFormat.RGBA ? pixels[index + 3] : 0xff);
+                    videoBuff.setUint32(offset, color);
+                    
+                    counter++;
+                    if (counter == 8) {
+                        counter = 0;
+                        offset += (canvasTiles.width - 7) * PixelFormat.RGBA;
+                    } else {
+                        offset += PixelFormat.RGBA;
+                    }
+                }
+                canvasTilesCtx.putImageData(canvasImage, 0, 0);
+            }
+
+            for (let index = 0; index < 256; index++) {
+                drawSprite(index);
+            }
         }
     });
 
@@ -698,7 +735,7 @@ const initCanvas = async () => {
     state.videoBuff = new DataView(state.image.data.buffer);
 };
 
-const updateCanvas = (pixels: Uint8Array, format: PixelFormat) => {
+const updateCanvas = (pixels: Uint8Array, format: PixelFormat = PixelFormat.RGB) => {
     let offset = 0;
     for (let index = 0; index < pixels.length; index += format) {
         const color =
@@ -726,7 +763,7 @@ const clearCanvas = async (
     );
 
     // in case an image was requested then uses that to load
-    // an image at the center of the screen
+    // an image at the center of the screen properly scaled
     if (image) {
         const img = await new Promise<HTMLImageElement>((resolve) => {
             const img = new Image();
diff --git a/src/cpu.rs b/src/cpu.rs
index e7f879abecfe0e23e1bcc8957e331248584f0528..f4f874e9845475ebd1cca115371b199b8728c3e7 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -77,6 +77,25 @@ impl Cpu {
         }
     }
 
+    pub fn reset(&mut self) {
+        self.pc = 0x0;
+        self.sp = 0x0;
+        self.a = 0x0;
+        self.b = 0x0;
+        self.c = 0x0;
+        self.d = 0x0;
+        self.e = 0x0;
+        self.h = 0x0;
+        self.l = 0x0;
+        self.ime = false;
+        self.zero = false;
+        self.sub = false;
+        self.half_carry = false;
+        self.carry = false;
+        self.halted = false;
+        self.ticks = 0;
+    }
+
     pub fn clock(&mut self) -> u8 {
         if self.halted {
             return 4;
diff --git a/src/gb.rs b/src/gb.rs
index b6eedd77fb24c9b387384c70da1ccd374bfc4899..4ef33166161da136d1fe657f1d25d227fb14c793 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -29,6 +29,12 @@ impl GameBoy {
         Self { cpu: cpu }
     }
 
+    pub fn reset(&mut self) {
+        self.ppu().reset();
+        self.mmu().reset();
+        self.cpu.reset();
+    }
+
     pub fn pc(&self) -> u16 {
         self.cpu.pc()
     }
@@ -112,6 +118,11 @@ impl GameBoy {
     pub fn get_tile(&mut self, index: usize) -> Tile {
         self.ppu().tiles()[index]
     }
+
+    pub fn get_tile_buffer(&mut self, index: usize) -> Vec<u8> {
+        let tile = self.get_tile(index);
+        tile.palette_buffer(self.ppu().palette())
+    }
 }
 
 impl GameBoy {
diff --git a/src/mmu.rs b/src/mmu.rs
index 770a651b261de52a1a2fdd5f0e0a5040c76ab934..4a67cda4da0ab7d0a60b29f11da193354a4ddfb1 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -28,6 +28,14 @@ impl Mmu {
         }
     }
 
+    pub fn reset(&mut self) {
+        self.boot_active = true;
+        self.boot = [0u8; BIOS_SIZE];
+        self.rom = [0u8; ROM_SIZE];
+        self.ram = [0u8; RAM_SIZE];
+        self.eram = [0u8; ERAM_SIZE];
+    }
+
     pub fn ppu(&mut self) -> &mut Ppu {
         &mut self.ppu
     }
@@ -159,7 +167,7 @@ impl Mmu {
                                         println!("GOING TO START DMA transfer to 0x{:x}00", value);
                                         let data = self.read_many((value as u16) << 8, 160);
                                         self.write_many(0xfe00, &data);
-                                        println!("FINISHED DMA transfer")
+                                        println!("FINISHED DMA transfer");
                                     }
                                     _ => self.ppu.write(addr, value),
                                 }
diff --git a/src/ppu.rs b/src/ppu.rs
index 17639f5d5507e4e7ddf3f2c648de5622b4b85ccb..8159ad45a56187d2e79aa0d20eab1e5c4400e146 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -26,6 +26,10 @@ pub const FRAME_BUFFER_SIZE: usize = DISPLAY_WIDTH * DISPLAY_HEIGHT * RGB_SIZE;
 // with the size of RGB (3 bytes).
 pub type Pixel = [u8; RGB_SIZE];
 
+/// Defines a type that represents a color palette
+/// within the Game Boy context.
+pub type Palette = [Pixel; PALETTE_SIZE];
+
 /// Represents a tile within the Game Boy context,
 /// should contain the pixel buffer of the tile.
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
@@ -34,6 +38,7 @@ pub struct Tile {
     buffer: [u8; 64],
 }
 
+#[cfg_attr(feature = "wasm", wasm_bindgen)]
 impl Tile {
     pub fn get(&self, x: usize, y: usize) -> u8 {
         self.buffer[y * 8 + x]
@@ -48,6 +53,15 @@ impl Tile {
     }
 }
 
+impl Tile {
+    pub fn palette_buffer(&self, palette: Palette) -> Vec<u8> {
+        self.buffer
+            .iter()
+            .flat_map(|p| palette[*p as usize])
+            .collect()
+    }
+}
+
 impl Display for Tile {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         let mut buffer = String::new();
@@ -87,11 +101,11 @@ pub struct Ppu {
     tiles: [Tile; TILE_COUNT],
     /// The palette of colors that is currently loaded in Game Boy
     /// and used for background (tiles).
-    palette: [Pixel; PALETTE_SIZE],
+    palette: Palette,
     // The palette that is going to be used for sprites/objects #0.
-    palette_obj_0: [Pixel; PALETTE_SIZE],
+    palette_obj_0: Palette,
     // The palette that is going to be used for sprites/objects #1.
-    palette_obj_1: [Pixel; PALETTE_SIZE],
+    palette_obj_1: Palette,
     /// The scroll Y register that controls the Y offset
     /// of the background.
     scy: u8,
@@ -181,6 +195,35 @@ impl Ppu {
         }
     }
 
+    pub fn reset(&mut self) {
+        self.frame_buffer = Box::new([0u8; DISPLAY_WIDTH * DISPLAY_HEIGHT * RGB_SIZE]);
+        self.vram = [0u8; VRAM_SIZE];
+        self.hram = [0u8; HRAM_SIZE];
+        self.tiles = [Tile { buffer: [0u8; 64] }; TILE_COUNT];
+        self.palette = [[0u8; RGB_SIZE]; PALETTE_SIZE];
+        self.palette_obj_0 = [[0u8; RGB_SIZE]; PALETTE_SIZE];
+        self.palette_obj_1 = [[0u8; RGB_SIZE]; PALETTE_SIZE];
+        self.scy = 0x0;
+        self.scx = 0x0;
+        self.ly = 0x0;
+        self.lyc = 0x0;
+        self.mode = PpuMode::OamRead;
+        self.mode_clock = 0;
+        self.switch_bg = false;
+        self.switch_obj = false;
+        self.obj_size = false;
+        self.bg_map = false;
+        self.bg_tile = false;
+        self.switch_window = false;
+        self.window_map = false;
+        self.switch_lcd = false;
+        self.stat_hblank = false;
+        self.stat_vblank = false;
+        self.stat_oam = false;
+        self.stat_lyc = false;
+        self.int_vblank = false;
+    }
+
     pub fn clock(&mut self, cycles: u8) {
         if !self.switch_lcd {
             return;
@@ -342,6 +385,18 @@ impl Ppu {
         self.tiles
     }
 
+    pub fn palette(&self) -> Palette {
+        self.palette
+    }
+
+    pub fn palette_obj_0(&self) -> Palette {
+        self.palette_obj_0
+    }
+
+    pub fn palette_obj_1(&self) -> Palette {
+        self.palette_obj_1
+    }
+
     pub fn int_vblank(&self) -> bool {
         self.int_vblank
     }