diff --git a/CHANGELOG.md b/CHANGELOG.md
index a70ff91541a4ca0081ab6c59bf37ab2c2328a209..0fd37ba9369e9a1610dd69695beab75c565ccb6d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 *
 
+## [0.4.4] - 2022-11-12
+
+### Added
+
+* Support for responsive physical keyboard
+
+## [0.4.3] - 2022-11-11
+
+### Added
+
+* Better debug panel support
+* Support for some `GET` parameters
+* Support for fullscreen on screen keyboard mode
+
 ## [0.4.2] - 2022-11-09
 
 ### Fixed
diff --git a/Cargo.toml b/Cargo.toml
index 39618c7d8cd69da2070da6ea6eb24d2b1a6363f5..bf0a16b2eb24642d7b55b347389ee3ab8e09d9ae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "boytacean"
 description = "A Game Boy emulator that is written in Rust."
-version = "0.4.2"
+version = "0.4.4"
 authors = ["João Magalhães <joamag@gmail.com>"]
 license = "Apache-2.0"
 repository = "https://gitlab.stage.hive.pt/joamag/boytacean"
diff --git a/README.md b/README.md
index dd8077ba3b31b08c74609b59f3f9e7363703a131..aea440dc79767513863da6ba588d27be36f6f45a 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,18 @@ npm install && npm run build
 cd dist && python3 -m http.server
 ```
 
+## Web version
+
+You can use some GET parameters to control the initial behaviour of the emulator.
+
+| Parameter    | Type    | Description                                                                    |
+| ------------ | ------- | ------------------------------------------------------------------------------ |
+| `rom_url`    | String  | The URL from which the initial ROM is going to be loaded, should support CORS. |
+| `url`        | String  | The same as `url`.                                                             |
+| `fullscreen` | Boolean | If the emulator should start in fullscreen mode.                               |
+| `debug`      | Boolean | If the "debugger" should start visible.                                        |
+| `keyboard`   | Boolean | If the on screen keyboard should start visible.                                |
+
 ## Inspiration
 
 ### Documentation
diff --git a/examples/sdl/Cargo.toml b/examples/sdl/Cargo.toml
index 134f97f0c9105722571ba9e128fce4d4c4db1e3e..c558f5bf6dd2cbd251e9e9a9904182a9587b3487 100644
--- a/examples/sdl/Cargo.toml
+++ b/examples/sdl/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "boytacean-sdl"
-version = "0.4.2"
+version = "0.4.4"
 authors = ["João Magalhães <joamag@gmail.com>"]
 description = "Game Boy Emulator SDL (Desktop) Application"
 license = "Apache-2.0"
diff --git a/examples/web/index.ts b/examples/web/index.ts
index 036d5c0d635101d3707f1a7c4fef99de1b9393ee..2d5409d696ddcca5328a783878415026f17debac 100644
--- a/examples/web/index.ts
+++ b/examples/web/index.ts
@@ -21,8 +21,6 @@ const LOGIC_HZ = 4194304;
 const VISUAL_HZ = 59.7275;
 const IDLE_HZ = 10;
 
-const FREQUENCY_DELTA = 400000;
-
 const SAMPLE_RATE = 2;
 
 const BACKGROUNDS = [
@@ -35,17 +33,6 @@ const BACKGROUNDS = [
     "3a5a40"
 ];
 
-const KEYS: Record<string, number> = {
-    ArrowUp: PadKey.Up,
-    ArrowDown: PadKey.Down,
-    ArrowLeft: PadKey.Left,
-    ArrowRight: PadKey.Right,
-    Enter: PadKey.Start,
-    " ": PadKey.Select,
-    a: PadKey.A,
-    s: PadKey.B
-};
-
 const KEYS_NAME: Record<string, number> = {
     ArrowUp: PadKey.Up,
     ArrowDown: PadKey.Down,
@@ -57,13 +44,6 @@ const KEYS_NAME: Record<string, number> = {
     B: PadKey.B
 };
 
-const ARROW_KEYS: Record<string, boolean> = {
-    ArrowUp: true,
-    ArrowDown: true,
-    ArrowLeft: true,
-    ArrowRight: true
-};
-
 const ROM_PATH = require("../../res/roms/20y.gb");
 
 /**
@@ -99,20 +79,11 @@ class GameboyEmulator extends EmulatorBase implements Emulator {
     private romSize: number = 0;
     private cartridge: Cartridge | null = null;
 
-    async main() {
-        // parses the current location URL as retrieves
-        // some of the "relevant" GET parameters for logic
-        const params = new URLSearchParams(window.location.search);
-        const romUrl = params.get("url");
-
+    async main({ romUrl }: { romUrl?: string }) {
         // initializes the WASM module, this is required
         // so that the global symbols become available
         await wasm();
 
-        // initializes the complete set of sub-systems
-        // and registers the event handlers
-        await this.register();
-
         // boots the emulator subsystem with the initial
         // ROM retrieved from a remote data source
         await this.boot({ loadRom: true, romPath: romUrl ?? undefined });
@@ -343,43 +314,6 @@ class GameboyEmulator extends EmulatorBase implements Emulator {
         this.trigger("booted");
     }
 
-    // @todo remove this method, or at least most of it
-    async register() {
-        await Promise.all([this.registerKeys()]);
-    }
-
-    registerKeys() {
-        document.addEventListener("keydown", (event) => {
-            const keyCode = KEYS[event.key];
-            const isArrow = ARROW_KEYS[event.key] ?? false;
-            if (isArrow) event.preventDefault();
-            if (keyCode !== undefined) {
-                this.gameBoy?.key_press(keyCode);
-                return;
-            }
-
-            switch (event.key) {
-                case "+":
-                    this.frequency += FREQUENCY_DELTA;
-                    break;
-
-                case "-":
-                    this.frequency -= FREQUENCY_DELTA;
-                    break;
-            }
-        });
-
-        document.addEventListener("keyup", (event) => {
-            const keyCode = KEYS[event.key];
-            const isArrow = ARROW_KEYS[event.key] ?? false;
-            if (isArrow) event.preventDefault();
-            if (keyCode !== undefined) {
-                this.gameBoy?.key_lift(keyCode);
-                return;
-            }
-        });
-    }
-
     setRom(name: string, data: Uint8Array, cartridge: Cartridge) {
         this.romName = name;
         this.romData = data;
@@ -415,6 +349,10 @@ class GameboyEmulator extends EmulatorBase implements Emulator {
         return "https://gitlab.stage.hive.pt/joamag/boytacean/-/blob/master/CHANGELOG.md";
     }
 
+    get romExts(): string[] {
+        return ["gb"];
+    }
+
     get pixelFormat(): PixelFormat {
         return PixelFormat.RGB;
     }
@@ -426,7 +364,7 @@ class GameboyEmulator extends EmulatorBase implements Emulator {
      * @returns The current pixel data for the emulator display.
      */
     get imageBuffer(): Uint8Array {
-        return this.gameBoy!.frame_buffer_eager();
+        return this.gameBoy?.frame_buffer_eager() ?? new Uint8Array();
     }
 
     get romInfo(): RomInfo {
@@ -452,12 +390,38 @@ class GameboyEmulator extends EmulatorBase implements Emulator {
         this.trigger("frequency", value);
     }
 
+    get frequencyDelta(): number | null {
+        return 400000;
+    }
+
     get framerate(): number {
         return this.fps;
     }
 
+    get registers(): Record<string, string | number> {
+        const registers = this.gameBoy?.registers();
+        if (!registers) return {};
+        return {
+            pc: registers.pc,
+            sp: registers.sp,
+            a: registers.a,
+            b: registers.b,
+            c: registers.c,
+            d: registers.d,
+            e: registers.e,
+            h: registers.h,
+            l: registers.l,
+            scy: registers.scy,
+            scx: registers.scx,
+            wy: registers.wy,
+            wx: registers.wx,
+            ly: registers.ly,
+            lyc: registers.lyc
+        };
+    }
+
     getTile(index: number): Uint8Array {
-        return this.gameBoy!.get_tile_buffer(index);
+        return this.gameBoy?.get_tile_buffer(index) ?? new Uint8Array();
     }
 
     toggleRunning() {
@@ -556,7 +520,25 @@ const wasm = async () => {
 };
 
 (async () => {
+    // parses the current location URL as retrieves
+    // some of the "relevant" GET parameters for logic
+    const params = new URLSearchParams(window.location.search);
+    const romUrl = params.get("rom_url") ?? params.get("url") ?? undefined;
+    const fullscreen = ["1", "true", "True"].includes(
+        params.get("fullscreen") ?? ""
+    );
+    const debug = ["1", "true", "True"].includes(params.get("debug") ?? "");
+    const keyboard = ["1", "true", "True"].includes(
+        params.get("keyboard") ?? ""
+    );
+
     const emulator = new GameboyEmulator();
-    startApp("app", emulator, BACKGROUNDS);
-    await emulator.main();
+    startApp("app", {
+        emulator: emulator,
+        fullscreen: fullscreen,
+        debug: debug,
+        keyboard: keyboard,
+        backgrounds: BACKGROUNDS
+    });
+    await emulator.main({ romUrl: romUrl });
 })();
diff --git a/examples/web/package.json b/examples/web/package.json
index a16a5149e41fd43e7033350794d4e0e2d65a7a48..31599354544a21fa32958115fe53f5438a42ca6d 100644
--- a/examples/web/package.json
+++ b/examples/web/package.json
@@ -1,6 +1,6 @@
 {
     "name": "boytacean-web",
-    "version": "0.4.2",
+    "version": "0.4.4",
     "description": "The web version of Boytacean",
     "repository": {
         "type": "git",
diff --git a/examples/web/react/app.css b/examples/web/react/app.css
index d44f28a65d33844a5029ac0909c352465c2cb860..f21e17fbb362d937ec40c4108a3e96e2fd4fe010 100644
--- a/examples/web/react/app.css
+++ b/examples/web/react/app.css
@@ -1,11 +1,12 @@
 .app {
     color: #ffffff;
     font-family: VT323, Roboto, Open Sans, Arial, Helvetica, sans-serif;
-    margin: 0px 0px 0px 0px;
+    margin: 0px auto 0px auto;
+    max-width: 1400px;
 }
 
 .app h3 {
-    margin: 10px 0px 10px 0px;
+    margin: 0px 0px 16px 0px;
 }
 
 .app .display-container {
diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx
index ad01897b2abce06c63cb7597a93fab38b216e681..8ab6fd4b59128b01e3a5a33e62be28ad00bcf4dc 100644
--- a/examples/web/react/app.tsx
+++ b/examples/web/react/app.tsx
@@ -1,6 +1,8 @@
 import React, { FC, useEffect, useRef, useState } from "react";
 import ReactDOM from "react-dom/client";
 
+const FREQUENCY_DELTA = 100000;
+
 declare const require: any;
 
 import {
@@ -20,6 +22,7 @@ import {
     Pair,
     PanelSplit,
     Paragraph,
+    RegistersGB,
     Section,
     Tiles,
     Title,
@@ -97,6 +100,10 @@ export interface Emulator extends ObservableI {
      */
     get device(): string;
 
+    /**
+     * A URL to a website that describes the device that is
+     * being emulated by the emulator (eg: Wikipedia link).
+     */
     get deviceUrl(): string | undefined;
 
     /**
@@ -125,6 +132,12 @@ export interface Emulator extends ObservableI {
      */
     get engine(): string | null;
 
+    /**
+     * The complete set of file extensions that this emulator
+     * supports.
+     */
+    get romExts(): string[];
+
     /**
      * The pixel format of the emulator's display
      * image buffer (eg: RGB).
@@ -154,11 +167,30 @@ export interface Emulator extends ObservableI {
     get frequency(): number;
     set frequency(value: number);
 
+    /**
+     * The recommended frequency delta in hertz for scale up
+     * and scale down operations in the CPU frequency.
+     */
+    get frequencyDelta(): number | null;
+
     /**
      * The current logic framerate of the running emulator.
      */
     get framerate(): number;
 
+    /**
+     * A dictionary that contains the register names associated
+     * with their value either as strings or numbers.
+     */
+    get registers(): Record<string, string | number>;
+
+    /**
+     * Obtains the pixel buffer for the VRAM tile at the given
+     * index.
+     *
+     * @param index The index of the tile to obtain pixel buffer.
+     * @returns The pixel buffer of the tile at the given index.
+     */
     getTile(index: number): Uint8Array;
 
     /**
@@ -210,6 +242,10 @@ export class EmulatorBase extends Observable {
     get versionUrl(): string | undefined {
         return undefined;
     }
+
+    get frequencyDelta(): number | null {
+        return FREQUENCY_DELTA;
+    }
 }
 
 /**
@@ -223,6 +259,9 @@ export enum PixelFormat {
 
 type AppProps = {
     emulator: Emulator;
+    fullscreen?: boolean;
+    debug?: boolean;
+    keyboard?: boolean;
     backgrounds?: string[];
 };
 
@@ -230,9 +269,15 @@ const isTouchDevice = () => {
     return "ontouchstart" in window || navigator.maxTouchPoints > 0;
 };
 
-export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
+export const App: FC<AppProps> = ({
+    emulator,
+    fullscreen = false,
+    debug = false,
+    keyboard = false,
+    backgrounds = ["264653"]
+}) => {
     const [paused, setPaused] = useState(false);
-    const [fullscreen, setFullscreen] = useState(false);
+    const [fullscreenState, setFullscreenState] = useState(fullscreen);
     const [backgroundIndex, setBackgroundIndex] = useState(0);
     const [romInfo, setRomInfo] = useState<RomInfo>({});
     const [framerate, setFramerate] = useState(0);
@@ -243,9 +288,11 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
     const [toastText, setToastText] = useState<string>();
     const [toastError, setToastError] = useState(false);
     const [toastVisible, setToastVisible] = useState(false);
-    const [keyboardVisible, setKeyboardVisible] = useState(isTouchDevice());
+    const [keyboardVisible, setKeyboardVisible] = useState(
+        isTouchDevice() || keyboard
+    );
     const [infoVisible, setInfoVisible] = useState(true);
-    const [debugVisible, setDebugVisible] = useState(false);
+    const [debugVisible, setDebugVisible] = useState(debug);
 
     const toastCounterRef = useRef(0);
     const frameRef = useRef<boolean>(false);
@@ -258,22 +305,46 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
     }, [backgroundIndex]);
     useEffect(() => {
         switch (keyaction) {
+            case "Plus":
+                emulator.frequency +=
+                    emulator.frequencyDelta ?? FREQUENCY_DELTA;
+                setKeyaction(undefined);
+                break;
+            case "Minus":
+                emulator.frequency -=
+                    emulator.frequencyDelta ?? FREQUENCY_DELTA;
+                setKeyaction(undefined);
+                break;
             case "Escape":
-                setFullscreen(false);
+                setFullscreenState(false);
                 setKeyaction(undefined);
                 break;
             case "Fullscreen":
-                setFullscreen(!fullscreen);
+                setFullscreenState(!fullscreenState);
                 setKeyaction(undefined);
                 break;
         }
     }, [keyaction]);
     useEffect(() => {
         const onKeyDown = (event: KeyboardEvent) => {
-            if (event.key === "Escape") {
-                setKeyaction("Escape");
-                event.stopPropagation();
-                event.preventDefault();
+            switch (event.key) {
+                case "+":
+                    setKeyaction("Plus");
+                    event.stopPropagation();
+                    event.preventDefault();
+                    break;
+
+                case "-":
+                    setKeyaction("Minus");
+                    event.stopPropagation();
+                    event.preventDefault();
+                    break;
+
+                case "Escape":
+                    setKeyaction("Escape");
+                    event.stopPropagation();
+                    event.preventDefault();
+                    break;
             }
             if (event.key === "f" && event.ctrlKey === true) {
                 setKeyaction("Fullscreen");
@@ -334,9 +405,8 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
     };
 
     const onFile = async (file: File) => {
-        // @todo must make this more flexible and not just
-        // Game Boy only (using the emulator interface)
-        if (!file.name.endsWith(".gb")) {
+        const fileExtension = file.name.split(".").pop() ?? "";
+        if (!emulator.romExts.includes(fileExtension)) {
             showToast(
                 `This is probably not a ${emulator.device} ROM file!`,
                 true
@@ -393,7 +463,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
         );
     };
     const onFullscreenClick = () => {
-        setFullscreen(!fullscreen);
+        setFullscreenState(!fullscreenState);
     };
     const onKeyboardClick = () => {
         setKeyboardVisible(!keyboardVisible);
@@ -428,7 +498,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
         });
     };
     const onMinimize = () => {
-        setFullscreen(!fullscreen);
+        setFullscreenState(!fullscreenState);
     };
     const onKeyDown = (key: string) => {
         emulator.keyPress(key);
@@ -478,7 +548,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
                 left={
                     <div className="display-container">
                         <Display
-                            fullscreen={fullscreen}
+                            fullscreen={fullscreenState}
                             onDrawHandler={onDrawHandler}
                             onClearHandler={onClearHandler}
                             onMinimize={onMinimize}
@@ -488,7 +558,11 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
             >
                 {keyboardVisible && (
                     <Section separatorBottom={true}>
-                        <KeyboardGB onKeyDown={onKeyDown} onKeyUp={onKeyUp} />
+                        <KeyboardGB
+                            fullscreen={fullscreenState}
+                            onKeyDown={onKeyDown}
+                            onKeyUp={onKeyUp}
+                        />
                     </Section>
                 )}
                 <Title
@@ -536,11 +610,33 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
                 </Section>
                 {debugVisible && (
                     <Section>
-                        <h3>VRAM Tiles</h3>
-                        <Tiles
-                            getTile={(index) => emulator.getTile(index)}
-                            tileCount={384}
-                        />
+                        <div
+                            style={{
+                                display: "inline-block",
+                                verticalAlign: "top",
+                                marginRight: 32,
+                                width: 256
+                            }}
+                        >
+                            <h3>VRAM Tiles</h3>
+                            <Tiles
+                                getTile={(index) => emulator.getTile(index)}
+                                tileCount={384}
+                                width={"100%"}
+                                contentBox={false}
+                            />
+                        </div>
+                        <div
+                            style={{
+                                display: "inline-block",
+                                verticalAlign: "top"
+                            }}
+                        >
+                            <h3>Registers</h3>
+                            <RegistersGB
+                                getRegisters={() => emulator.registers}
+                            />
+                        </div>
                     </Section>
                 )}
                 {infoVisible && (
@@ -582,7 +678,12 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
                                 valueNode={
                                     <ButtonIncrement
                                         value={emulator.frequency / 1000 / 1000}
-                                        delta={0.4}
+                                        delta={
+                                            (emulator.frequencyDelta ??
+                                                FREQUENCY_DELTA) /
+                                            1000 /
+                                            1000
+                                        }
                                         min={0}
                                         suffix={"MHz"}
                                         decimalPlaces={2}
@@ -688,16 +789,33 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
 
 export const startApp = (
     element: string,
-    emulator: Emulator,
-    backgrounds: string[]
+    {
+        emulator,
+        fullscreen = false,
+        debug = false,
+        keyboard = false,
+        backgrounds = []
+    }: {
+        emulator: Emulator;
+        fullscreen?: boolean;
+        debug?: boolean;
+        keyboard?: boolean;
+        backgrounds: string[];
+    }
 ) => {
     const elementRef = document.getElementById(element);
-    if (!elementRef) {
-        return;
-    }
+    if (!elementRef) return;
 
     const root = ReactDOM.createRoot(elementRef);
-    root.render(<App emulator={emulator} backgrounds={backgrounds} />);
+    root.render(
+        <App
+            emulator={emulator}
+            fullscreen={fullscreen}
+            debug={debug}
+            keyboard={keyboard}
+            backgrounds={backgrounds}
+        />
+    );
 };
 
 export default App;
diff --git a/examples/web/react/components/canvas/canvas.tsx b/examples/web/react/components/canvas/canvas.tsx
index 24f7544a1c8e7f5de294f02b474cda82f3dda36e..5cad1d5c5d8f82c2073ebb210bce035523ad5d6b 100644
--- a/examples/web/react/components/canvas/canvas.tsx
+++ b/examples/web/react/components/canvas/canvas.tsx
@@ -12,6 +12,7 @@ export type CanvasStructure = {
 type CanvasProps = {
     width: number;
     height: number;
+    scaledWidth?: number | string;
     scale?: number;
     style?: string[];
     onCanvas?: (structure: CanvasStructure) => void;
@@ -20,6 +21,7 @@ type CanvasProps = {
 export const Canvas: FC<CanvasProps> = ({
     width,
     height,
+    scaledWidth,
     scale = 1,
     style = [],
     onCanvas
@@ -41,7 +43,7 @@ export const Canvas: FC<CanvasProps> = ({
         <canvas
             ref={canvasRef}
             className={classes()}
-            style={{ width: width * scale }}
+            style={{ width: scaledWidth ?? width * scale }}
             width={width}
             height={height}
         />
diff --git a/examples/web/react/components/display/display.css b/examples/web/react/components/display/display.css
index f0e987b779519ae3a66b0069e7596f97b81adfca..4c8bef99b089b0bdba70faa5dee74fd458739882 100644
--- a/examples/web/react/components/display/display.css
+++ b/examples/web/react/components/display/display.css
@@ -57,6 +57,13 @@
     -webkit-user-select: none;
 }
 
+@media only screen and (max-width: 1120px) {
+    .display > .display-minimize {
+        bottom: initial;
+        top: 22px;
+    }
+}
+
 .display > .display-minimize > img {
     height: 32px;
     width: 32px;
diff --git a/examples/web/react/components/index.ts b/examples/web/react/components/index.ts
index 838636b94e5c09949d1234242e97bcdccf67ca09..a2980dabb48825fb1403af2a17b42b20a0243bbf 100644
--- a/examples/web/react/components/index.ts
+++ b/examples/web/react/components/index.ts
@@ -14,6 +14,7 @@ export * from "./overlay/overlay";
 export * from "./pair/pair";
 export * from "./panel-split/panel-split";
 export * from "./paragraph/paragraph";
+export * from "./registers-gb/registers-gb";
 export * from "./section/section";
 export * from "./tiles/tiles";
 export * from "./title/title";
diff --git a/examples/web/react/components/keyboard-chip8/keyboard-chip8.css b/examples/web/react/components/keyboard-chip8/keyboard-chip8.css
index 97507e3b920202c9458befbe75fdac9c13108c00..a9552b23a6e438d1965fd7d90e61af622f01ac30 100644
--- a/examples/web/react/components/keyboard-chip8/keyboard-chip8.css
+++ b/examples/web/react/components/keyboard-chip8/keyboard-chip8.css
@@ -1,4 +1,3 @@
-
 .keyboard-chip8 {
     font-size: 0px;
     text-align: center;
diff --git a/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx b/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx
index 99ddd4f8272700828680589bd53f23278e7593d9..2208c1c11b3d4c2a9800a7029a1c080693d1ce53 100644
--- a/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx
+++ b/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx
@@ -18,11 +18,10 @@ export const KeyboardChip8: FC<KeyboardChip8Props> = ({
     const classes = () => ["keyboard", "keyboard-chip8", ...style].join(" ");
     const renderKey = (key: string, styles: string[] = []) => {
         const [pressed, setPressed] = useState(false);
+        const classes = ["key", pressed ? "pressed" : "", ...styles].join(" ");
         return (
             <span
-                className={["key", pressed ? "pressed" : "", ...styles].join(
-                    " "
-                )}
+                className={classes}
                 key={key}
                 tabIndex={focusable ? 0 : undefined}
                 onKeyDown={(event) => {
diff --git a/examples/web/react/components/keyboard-gb/keyboard-gb.css b/examples/web/react/components/keyboard-gb/keyboard-gb.css
index fce8fc547108e455ee868cc71b224c423b69a75c..d26aaf967584bf6a9246396ffbd0e77d8e8f86a8 100644
--- a/examples/web/react/components/keyboard-gb/keyboard-gb.css
+++ b/examples/web/react/components/keyboard-gb/keyboard-gb.css
@@ -1,3 +1,17 @@
+.keyboard-container.fullscreen {
+    bottom: 30px;
+    left: 0px;
+    pointer-events: none;
+    position: fixed;
+    width: 100%;
+    z-index: 10;
+}
+
+@media only screen and (max-width: 1120px) {
+    .keyboard-container.fullscreen {
+        bottom: 0px;
+    }
+}
 
 .keyboard-gb {
     font-size: 0px;
@@ -16,7 +30,39 @@
     -webkit-user-select: none;
 }
 
+.keyboard-gb.fullscreen {
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 24px 24px 24px 24px;
+    -o-border-radius: 24px 24px 24px 24px;
+    -ms-border-radius: 24px 24px 24px 24px;
+    -moz-border-radius: 24px 24px 24px 24px;
+    -khtml-border-radius: 24px 24px 24px 24px;
+    -webkit-border-radius: 24px 24px 24px 24px;
+    margin: 0px auto 0px auto;
+    max-width: 600px;
+    padding: 18px 0px 18px 0px;
+    pointer-events: initial;
+}
+
+@media only screen and (max-width: 600px) {
+    .keyboard-gb.fullscreen {
+        border-radius: 0px 0px 0px 0px;
+        -o-border-radius: 0px 0px 0px 0px;
+        -ms-border-radius: 0px 0px 0px 0px;
+        -moz-border-radius: 0px 0px 0px 0px;
+        -khtml-border-radius: 0px 0px 0px 0px;
+        -webkit-border-radius: 0px 0px 0px 0px;
+        padding: 12px 0px 12px 0px;
+    }
+}
+
 .keyboard-gb > .keyboard-line {
+    border-radius: 24px 24px 24px 24px;
+    -o-border-radius: 24px 24px 24px 24px;
+    -ms-border-radius: 24px 24px 24px 24px;
+    -moz-border-radius: 24px 24px 24px 24px;
+    -khtml-border-radius: 24px 24px 24px 24px;
+    -webkit-border-radius: 24px 24px 24px 24px;
     margin-bottom: 12px;
 }
 
@@ -54,7 +100,13 @@
 .keyboard-gb > .dpad {
     float: left;
     text-align: center;
-    width: 180px;
+    width: 172px;
+}
+
+@media only screen and (max-width: 600px) {
+    .keyboard-gb > .dpad {
+        width: 162px;
+    }
 }
 
 .keyboard-gb > .dpad > .dpad-top {
@@ -146,6 +198,12 @@
     margin-right: 18px;
 }
 
+@media only screen and (max-width: 600px) {
+    .keyboard-gb > .action {
+        margin-right: 8px;
+    }
+}
+
 .keyboard-gb > .action > .key {
     border-radius: 32px 32px 32px 32px;
     -o-border-radius: 32px 32px 32px 32px;
@@ -177,6 +235,12 @@
     margin-top: 32px;
 }
 
+@media only screen and (max-width: 600px) {
+    .keyboard-gb > .options {
+        margin-top: 22px;
+    }
+}
+
 .keyboard-gb > .options > .key {
     font-size: 14px;
     font-weight: 900;
diff --git a/examples/web/react/components/keyboard-gb/keyboard-gb.tsx b/examples/web/react/components/keyboard-gb/keyboard-gb.tsx
index 18672a13bc9713059756d6e97d3e5ed43c42d30d..96ed59c40db5a05919f1a5b103f4fc5a6b39adcb 100644
--- a/examples/web/react/components/keyboard-gb/keyboard-gb.tsx
+++ b/examples/web/react/components/keyboard-gb/keyboard-gb.tsx
@@ -1,11 +1,32 @@
-import React, { FC, useState } from "react";
+import React, { FC, useEffect, useRef, useState } from "react";
 
 import "./keyboard-gb.css";
 
+const KEYS: Record<string, string> = {
+    ArrowUp: "ArrowUp",
+    ArrowDown: "ArrowDown",
+    ArrowLeft: "ArrowLeft",
+    ArrowRight: "ArrowRight",
+    Enter: "Start",
+    " ": "Select",
+    a: "A",
+    s: "B"
+};
+
+const PREVENT_KEYS: Record<string, boolean> = {
+    ArrowUp: true,
+    ArrowDown: true,
+    ArrowLeft: true,
+    ArrowRight: true,
+    " ": true
+};
+
 declare const require: any;
 
 type KeyboardGBProps = {
     focusable?: boolean;
+    fullscreen?: boolean;
+    selectedKeys?: string[];
     style?: string[];
     onKeyDown?: (key: string) => void;
     onKeyUp?: (key: string) => void;
@@ -13,22 +34,69 @@ type KeyboardGBProps = {
 
 export const KeyboardGB: FC<KeyboardGBProps> = ({
     focusable = true,
+    fullscreen = false,
+    selectedKeys = [],
     style = [],
     onKeyDown,
     onKeyUp
 }) => {
-    const classes = () => ["keyboard", "keyboard-gb", ...style].join(" ");
+    const containerClasses = () =>
+        ["keyboard-container", fullscreen ? "fullscreen" : ""].join(" ");
+    const recordRef =
+        useRef<Record<string, React.Dispatch<React.SetStateAction<boolean>>>>();
+    const classes = () =>
+        [
+            "keyboard",
+            "keyboard-gb",
+            fullscreen ? "fullscreen" : "",
+            ...style
+        ].join(" ");
+    useEffect(() => {
+        const _onKeyDown = (event: KeyboardEvent) => {
+            const keyCode = KEYS[event.key];
+            const isPrevent = PREVENT_KEYS[event.key] ?? false;
+            if (isPrevent) event.preventDefault();
+            if (keyCode !== undefined) {
+                const records = recordRef.current ?? {};
+                const setter = records[keyCode];
+                setter(true);
+                onKeyDown && onKeyDown(keyCode);
+                return;
+            }
+        };
+        const _onKeyUp = (event: KeyboardEvent) => {
+            const keyCode = KEYS[event.key];
+            const isPrevent = PREVENT_KEYS[event.key] ?? false;
+            if (isPrevent) event.preventDefault();
+            if (keyCode !== undefined) {
+                const records = recordRef.current ?? {};
+                const setter = records[keyCode];
+                setter(false);
+                onKeyUp && onKeyUp(keyCode);
+                return;
+            }
+        };
+        document.addEventListener("keydown", _onKeyDown);
+        document.addEventListener("keyup", _onKeyUp);
+        return () => {
+            document.removeEventListener("keydown", _onKeyDown);
+            document.removeEventListener("keyup", _onKeyUp);
+        };
+    }, []);
     const renderKey = (
         key: string,
         keyName?: string,
+        selected = false,
         styles: string[] = []
     ) => {
-        const [pressed, setPressed] = useState(false);
+        const [pressed, setPressed] = useState(selected);
+        const classes = ["key", pressed ? "pressed" : "", ...styles].join(" ");
+        const records = recordRef.current ?? {};
+        records[keyName ?? key ?? "undefined"] = setPressed;
+        recordRef.current = records;
         return (
             <span
-                className={["key", pressed ? "pressed" : "", ...styles].join(
-                    " "
-                )}
+                className={classes}
                 key={keyName ?? key}
                 tabIndex={focusable ? 0 : undefined}
                 onKeyDown={(event) => {
@@ -86,32 +154,64 @@ export const KeyboardGB: FC<KeyboardGBProps> = ({
         );
     };
     return (
-        <div
-            className={classes()}
-            onTouchStart={(e) => e.preventDefault()}
-            onTouchEnd={(e) => e.preventDefault()}
-        >
-            <div className="dpad">
-                <div className="dpad-top">
-                    {renderKey("â–²", "ArrowUp", ["up"])}
+        <div className={containerClasses()}>
+            <div
+                className={classes()}
+                onTouchStart={(e) => e.preventDefault()}
+                onTouchEnd={(e) => e.preventDefault()}
+            >
+                <div className="dpad">
+                    <div className="dpad-top">
+                        {renderKey(
+                            "â–²",
+                            "ArrowUp",
+                            selectedKeys.includes("ArrowUp"),
+                            ["up"]
+                        )}
+                    </div>
+                    <div>
+                        {renderKey(
+                            "â—„",
+                            "ArrowLeft",
+                            selectedKeys.includes("ArrowLeft"),
+                            ["left"]
+                        )}
+                        {renderKey(
+                            "â–º",
+                            "ArrowRight",
+                            selectedKeys.includes("ArrowRight"),
+                            ["right"]
+                        )}
+                    </div>
+                    <div className="dpad-bottom">
+                        {renderKey(
+                            "â–¼",
+                            "ArrowDown",
+                            selectedKeys.includes("ArrowDown"),
+                            ["down"]
+                        )}
+                    </div>
                 </div>
-                <div>
-                    {renderKey("â—„", "ArrowLeft", ["left"])}
-                    {renderKey("â–º", "ArrowRight", ["right"])}
+                <div className="action">
+                    {renderKey("B", "B", selectedKeys.includes("B"), ["b"])}
+                    {renderKey("A", "A", selectedKeys.includes("A"), ["a"])}
                 </div>
-                <div className="dpad-bottom">
-                    {renderKey("â–¼", "ArrowDown", ["down"])}
+                <div className="break"></div>
+                <div className="options">
+                    {renderKey(
+                        "START",
+                        "Start",
+                        selectedKeys.includes("Start"),
+                        ["start"]
+                    )}
+                    {renderKey(
+                        "SELECT",
+                        "Select",
+                        selectedKeys.includes("Select"),
+                        ["select"]
+                    )}
                 </div>
             </div>
-            <div className="action">
-                {renderKey("B", "B", ["b"])}
-                {renderKey("A", "A", ["a"])}
-            </div>
-            <div className="break"></div>
-            <div className="options">
-                {renderKey("START", "Start", ["start"])}
-                {renderKey("SELECT", "Select", ["select"])}
-            </div>
         </div>
     );
 };
diff --git a/examples/web/react/components/registers-gb/registers-gb.css b/examples/web/react/components/registers-gb/registers-gb.css
new file mode 100644
index 0000000000000000000000000000000000000000..0801939b049a3955f55675c88db3af75cb271045
--- /dev/null
+++ b/examples/web/react/components/registers-gb/registers-gb.css
@@ -0,0 +1,32 @@
+.registers-gb > .section {
+    display: inline-block;
+    margin-right: 32px;
+    vertical-align: top;
+}
+
+.registers-gb > .section:last-child {
+    margin-right: 0px;
+}
+
+.registers-gb > .section > h4 {
+    font-size: 22px;
+    margin: 0px 0px 8px 0px;
+}
+
+.registers-gb > .section > .register {
+    font-size: 0px;
+    line-height: 22px;
+}
+
+.registers-gb > .section > .register > .register-key {
+    display: inline-block;
+    font-size: 20px;
+    width: 40px;
+}
+
+.registers-gb > .section > .register > .register-value {
+    display: inline-block;
+    font-size: 20px;
+    text-align: right;
+    width: 66px;
+}
diff --git a/examples/web/react/components/registers-gb/registers-gb.tsx b/examples/web/react/components/registers-gb/registers-gb.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..988ba20ea37839ee3fa392000f66b1f6a532774f
--- /dev/null
+++ b/examples/web/react/components/registers-gb/registers-gb.tsx
@@ -0,0 +1,79 @@
+import React, { FC, useEffect, useRef, useState } from "react";
+
+import "./registers-gb.css";
+
+type RegistersGBProps = {
+    getRegisters: () => Record<string, string | number>;
+    interval?: number;
+    style?: string[];
+};
+
+export const RegistersGB: FC<RegistersGBProps> = ({
+    getRegisters,
+    interval = 50,
+    style = []
+}) => {
+    const classes = () => ["registers-gb", ...style].join(" ");
+    const [registers, setRegisters] = useState<Record<string, string | number>>(
+        {}
+    );
+    const intervalsRef = useRef<number>();
+    useEffect(() => {
+        const updateRegisters = () => {
+            const registers = getRegisters();
+            setRegisters(registers);
+        };
+        setInterval(() => updateRegisters(), interval);
+        updateRegisters();
+        return () => {
+            if (intervalsRef.current) {
+                clearInterval(intervalsRef.current);
+            }
+        };
+    }, []);
+    const renderRegister = (
+        key: string,
+        value?: number,
+        size = 2,
+        styles: string[] = []
+    ) => {
+        const classes = ["register", ...styles].join(" ");
+        const valueS =
+            value?.toString(16).toUpperCase().padStart(size, "0") ?? value;
+        return (
+            <div className={classes}>
+                <span className="register-key">{key}</span>
+                <span className="register-value">
+                    {valueS ? `0x${valueS}` : "-"}
+                </span>
+            </div>
+        );
+    };
+    return (
+        <div className={classes()}>
+            <div className="section">
+                <h4>CPU</h4>
+                {renderRegister("PC", registers.pc as number, 4)}
+                {renderRegister("SP", registers.sp as number, 4)}
+                {renderRegister("A", registers.a as number)}
+                {renderRegister("B", registers.b as number)}
+                {renderRegister("C", registers.c as number)}
+                {renderRegister("D", registers.d as number)}
+                {renderRegister("E", registers.e as number)}
+                {renderRegister("H", registers.h as number)}
+                {renderRegister("L", registers.l as number)}
+            </div>
+            <div className="section">
+                <h4>PPU</h4>
+                {renderRegister("SCY", registers.scy as number)}
+                {renderRegister("SCX", registers.scx as number)}
+                {renderRegister("WY", registers.wy as number)}
+                {renderRegister("WX", registers.wx as number)}
+                {renderRegister("LY", registers.ly as number)}
+                {renderRegister("LYC", registers.lyc as number)}
+            </div>
+        </div>
+    );
+};
+
+export default RegistersGB;
diff --git a/examples/web/react/components/tiles/tiles.css b/examples/web/react/components/tiles/tiles.css
index 59b7d18240ad1bc4ea361b700e70c75c911782de..030a9575febd3db6e663c0740256eb48c5a89e88 100644
--- a/examples/web/react/components/tiles/tiles.css
+++ b/examples/web/react/components/tiles/tiles.css
@@ -1,11 +1,14 @@
 .tiles > .canvas {
     background-color: #1b1a17;
     border: 2px solid #50cb93;
+    padding: 8px 8px 8px 8px;
+}
+
+.tiles > .canvas.content-box {
     box-sizing: content-box;
     -o-box-sizing: content-box;
     -ms-box-sizing: content-box;
     -moz-box-sizing: content-box;
     -khtml-box-sizing: content-box;
     -webkit-box-sizing: content-box;
-    padding: 8px 8px 8px 8px;
 }
diff --git a/examples/web/react/components/tiles/tiles.tsx b/examples/web/react/components/tiles/tiles.tsx
index e879f383585faaab2a29889295ec78793182cb5c..78b340e123425d43ee1d05b7cf13e799f7ea6c83 100644
--- a/examples/web/react/components/tiles/tiles.tsx
+++ b/examples/web/react/components/tiles/tiles.tsx
@@ -5,19 +5,24 @@ import Canvas, { CanvasStructure } from "../canvas/canvas";
 import "./tiles.css";
 
 type TilesProps = {
-    tileCount: number;
     getTile: (index: number) => Uint8Array;
+    tileCount: number;
+    width?: number | string;
+    contentBox?: boolean;
     interval?: number;
     style?: string[];
 };
 
 export const Tiles: FC<TilesProps> = ({
-    tileCount,
     getTile,
-    interval = 500,
+    tileCount,
+    width,
+    contentBox = true,
+    interval = 1000,
     style = []
 }) => {
-    const classes = () => ["tiles", ...style].join(" ");
+    const classes = () =>
+        ["tiles", contentBox ? "content-box" : "", ...style].join(" ");
     const intervalsRef = useRef<number>();
     useEffect(() => {
         return () => {
@@ -38,7 +43,13 @@ export const Tiles: FC<TilesProps> = ({
     };
     return (
         <div className={classes()}>
-            <Canvas width={128} height={192} scale={2} onCanvas={onCanvas} />
+            <Canvas
+                width={128}
+                height={192}
+                scale={2}
+                scaledWidth={width}
+                onCanvas={onCanvas}
+            />
         </div>
     );
 };
diff --git a/src/cpu.rs b/src/cpu.rs
index e253dba68cb622d24f5743b7e8646bdd63589b4e..a6632d0616a0d2bd8ca48d9e0914a2c8900fc3e7 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -21,12 +21,16 @@ pub struct Cpu {
     pub e: u8,
     pub h: u8,
     pub l: u8,
+
     ime: bool,
     zero: bool,
     sub: bool,
     half_carry: bool,
     carry: bool,
     halted: bool,
+
+    /// Reference to the MMU (Memory Management Unit) to be used
+    /// for memory bus access operations.
     pub mmu: Mmu,
 
     /// Temporary counter used to control the number of cycles
@@ -52,7 +56,7 @@ impl Cpu {
             half_carry: false,
             carry: false,
             halted: false,
-            mmu: mmu,
+            mmu,
             cycles: 0,
         }
     }
@@ -113,14 +117,13 @@ impl Cpu {
 
         // @todo this is so bad, need to improve this by an order
         // of magnitude, to be able to have better performance
-        if self.halted {
-            if ((self.mmu.ie & 0x01 == 0x01) && self.mmu.ppu().int_vblank())
+        if self.halted
+            && (((self.mmu.ie & 0x01 == 0x01) && self.mmu.ppu().int_vblank())
                 || ((self.mmu.ie & 0x02 == 0x02) && self.mmu.ppu().int_stat())
                 || ((self.mmu.ie & 0x04 == 0x04) && self.mmu.timer().int_tima())
-                || ((self.mmu.ie & 0x10 == 0x10) && self.mmu.pad().int_pad())
-            {
-                self.halted = false;
-            }
+                || ((self.mmu.ie & 0x10 == 0x10) && self.mmu.pad().int_pad()))
+        {
+            self.halted = false;
         }
 
         if self.ime {
diff --git a/src/gb.rs b/src/gb.rs
index 3a72d3ff9efea0b3c76c963e58912eb729fffde7..77691658d0104aba62197896f07a597d25bb05ac 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -23,6 +23,25 @@ pub struct GameBoy {
     cpu: Cpu,
 }
 
+#[cfg_attr(feature = "wasm", wasm_bindgen)]
+pub struct Registers {
+    pub pc: u16,
+    pub sp: u16,
+    pub a: u8,
+    pub b: u8,
+    pub c: u8,
+    pub d: u8,
+    pub e: u8,
+    pub h: u8,
+    pub l: u8,
+    pub scy: u8,
+    pub scx: u8,
+    pub wy: u8,
+    pub wx: u8,
+    pub ly: u8,
+    pub lyc: u8,
+}
+
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
 impl GameBoy {
     #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
@@ -32,7 +51,7 @@ impl GameBoy {
         let timer = Timer::new();
         let mmu = Mmu::new(ppu, pad, timer);
         let cpu = Cpu::new(mmu);
-        Self { cpu: cpu }
+        Self { cpu }
     }
 
     pub fn reset(&mut self) {
@@ -113,6 +132,27 @@ impl GameBoy {
         self.frame_buffer().to_vec()
     }
 
+    pub fn registers(&mut self) -> Registers {
+        let ppu_registers = self.ppu().registers();
+        Registers {
+            pc: self.cpu.pc,
+            sp: self.cpu.sp,
+            a: self.cpu.a,
+            b: self.cpu.b,
+            c: self.cpu.c,
+            d: self.cpu.d,
+            e: self.cpu.e,
+            h: self.cpu.h,
+            l: self.cpu.l,
+            scy: ppu_registers.scy,
+            scx: ppu_registers.scx,
+            wy: ppu_registers.wy,
+            wx: ppu_registers.wx,
+            ly: ppu_registers.ly,
+            lyc: ppu_registers.lyc,
+        }
+    }
+
     /// Obtains the tile structure for the tile at the
     /// given index, no conversion in the pixel buffer
     /// is done so that the color reference is the GB one.
@@ -129,6 +169,8 @@ impl GameBoy {
     }
 }
 
+/// Gameboy implementations that are meant with performance
+/// in mind and that do not support WASM interface of copy.
 impl GameBoy {
     /// The logical frequency of the Game Boy
     /// CPU in hz.
diff --git a/src/inst.rs b/src/inst.rs
index 497523a1efe4a4222dbad1af862a21d3cf02025a..0b7ad53941a62f764162f7e500b0d3733508afb6 100644
--- a/src/inst.rs
+++ b/src/inst.rs
@@ -1,6 +1,6 @@
 use crate::cpu::Cpu;
 
-pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 256] = [
+pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &str); 256] = [
     // 0x0 opcodes
     (nop, 4, "NOP"),
     (ld_bc_u16, 12, "LD BC, u16"),
@@ -275,7 +275,7 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 256] = [
     (rst_38h, 16, "RST 38h"),
 ];
 
-pub const EXTENDED: [(fn(&mut Cpu), u8, &'static str); 256] = [
+pub const EXTENDED: [(fn(&mut Cpu), u8, &str); 256] = [
     // 0x0 opcodes
     (rlc_b, 8, "RLC B"),
     (rlc_c, 8, "RLC C"),
diff --git a/src/mmu.rs b/src/mmu.rs
index a8ce0a41af042ade35751fab8f416dcc09ce9a3d..78f9e36b53b8d755b7b44b821904735c95ca4321 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -37,9 +37,9 @@ pub struct Mmu {
 impl Mmu {
     pub fn new(ppu: Ppu, pad: Pad, timer: Timer) -> Self {
         Self {
-            ppu: ppu,
-            pad: pad,
-            timer: timer,
+            ppu,
+            pad,
+            timer,
             rom: Cartridge::new(),
             boot_active: true,
             boot: [0u8; BOOT_SIZE],
@@ -119,11 +119,10 @@ impl Mmu {
                 0xe00 => self.ppu.oam[(addr & 0x009f) as usize],
                 0xf00 => match addr & 0x00ff {
                     0x0f => {
-                        let value = if self.ppu.int_vblank() { 0x01 } else { 0x00 }
+                        (if self.ppu.int_vblank() { 0x01 } else { 0x00 }
                             | if self.ppu.int_stat() { 0x02 } else { 0x00 }
                             | if self.timer.int_tima() { 0x04 } else { 0x00 }
-                            | if self.pad.int_pad() { 0x10 } else { 0x00 };
-                        value
+                            | if self.pad.int_pad() { 0x10 } else { 0x00 })
                     }
                     0x80..=0xfe => self.ppu.hram[(addr & 0x007f) as usize],
                     0xff => self.ie,
@@ -245,7 +244,7 @@ impl Mmu {
             data.push(byte);
         }
 
-        return data;
+        data
     }
 
     pub fn write_boot(&mut self, addr: u16, buffer: &[u8]) {
diff --git a/src/pad.rs b/src/pad.rs
index ed15c9d8e34adf8655dee247166e5fff86a2efac..84c833a158465586a4b741bbd99b4e467afe186f 100644
--- a/src/pad.rs
+++ b/src/pad.rs
@@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*;
 
 use crate::warnln;
 
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Eq)]
 pub enum PadSelection {
     Action,
     Direction,
diff --git a/src/ppu.rs b/src/ppu.rs
index df6b83acedf529b7428bfa5b86db1005bfd39d60..e2ef8060cff890837188f6f595b219849fb422c4 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -51,7 +51,7 @@ 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)]
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Eq)]
 pub struct Tile {
     buffer: [u8; 64],
 }
@@ -93,14 +93,14 @@ impl Display for Tile {
             for x in 0..8 {
                 buffer.push_str(format!("{}", self.get(x, y)).as_str());
             }
-            buffer.push_str("\n");
+            buffer.push('\n');
         }
         write!(f, "{}", buffer)
     }
 }
 
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Eq)]
 pub struct ObjectData {
     x: i16,
     y: i16,
@@ -122,6 +122,15 @@ impl Display for ObjectData {
     }
 }
 
+pub struct PpuRegisters {
+    pub scy: u8,
+    pub scx: u8,
+    pub wy: u8,
+    pub wx: u8,
+    pub ly: u8,
+    pub lyc: u8,
+}
+
 /// Represents the Game Boy PPU (Pixel Processing Unit) and controls
 /// all of the logic behind the graphics processing and presentation.
 /// Should store both the VRAM and HRAM together with the internal
@@ -262,7 +271,7 @@ pub struct Ppu {
 }
 
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Eq)]
 pub enum PpuMode {
     HBlank = 0,
     VBlank = 1,
@@ -425,24 +434,22 @@ impl Ppu {
     pub fn read(&mut self, addr: u16) -> u8 {
         match addr & 0x00ff {
             0x0040 => {
-                let value = if self.switch_bg { 0x01 } else { 0x00 }
+                (if self.switch_bg { 0x01 } else { 0x00 }
                     | if self.switch_obj { 0x02 } else { 0x00 }
                     | if self.obj_size { 0x04 } else { 0x00 }
                     | if self.bg_map { 0x08 } else { 0x00 }
                     | if self.bg_tile { 0x10 } else { 0x00 }
                     | if self.switch_window { 0x20 } else { 0x00 }
                     | if self.window_map { 0x40 } else { 0x00 }
-                    | if self.switch_lcd { 0x80 } else { 0x00 };
-                value
+                    | if self.switch_lcd { 0x80 } else { 0x00 })
             }
             0x0041 => {
-                let value = if self.stat_hblank { 0x08 } else { 0x00 }
+                (if self.stat_hblank { 0x08 } else { 0x00 }
                     | if self.stat_vblank { 0x10 } else { 0x00 }
                     | if self.stat_oam { 0x20 } else { 0x00 }
                     | if self.stat_lyc { 0x40 } else { 0x00 }
                     | if self.lyc == self.ly { 0x04 } else { 0x00 }
-                    | (self.mode as u8 & 0x03);
-                value
+                    | (self.mode as u8 & 0x03))
             }
             0x0042 => self.scy,
             0x0043 => self.scx,
@@ -664,15 +671,26 @@ impl Ppu {
             0x02 => obj.tile = value,
             0x03 => {
                 obj.palette = if value & 0x10 == 0x10 { 1 } else { 0 };
-                obj.xflip = if value & 0x20 == 0x20 { true } else { false };
-                obj.yflip = if value & 0x40 == 0x40 { true } else { false };
-                obj.priority = if value & 0x80 == 0x80 { false } else { true };
+                obj.xflip = value & 0x20 == 0x20;
+                obj.yflip = value & 0x40 == 0x40;
+                obj.priority = value & 0x80 != 0x80;
                 obj.index = obj_index as u8;
             }
             _ => (),
         }
     }
 
+    pub fn registers(&self) -> PpuRegisters {
+        PpuRegisters {
+            scy: self.scy,
+            scx: self.scx,
+            wy: self.wy,
+            wx: self.wx,
+            ly: self.ly,
+            lyc: self.lyc,
+        }
+    }
+
     fn render_line(&mut self) {
         if self.first_frame {
             return;
@@ -846,7 +864,7 @@ impl Ppu {
                     tile = &self.tiles[obj.tile as usize & 0xfe];
                 } else {
                     tile = &self.tiles[obj.tile as usize | 0x01];
-                    tile_offset = tile_offset - 8;
+                    tile_offset -= 8;
                 }
             }
             // otherwise we're facing a 8x8 sprite and we should grab
diff --git a/src/rom.rs b/src/rom.rs
index 8cffef5b02cceae4530469ebae7b7d0f66caa2be..b01458eb489a74f8ef4a408fa2b3d6a1f114c9a9 100644
--- a/src/rom.rs
+++ b/src/rom.rs
@@ -475,7 +475,7 @@ pub static MBC1: Mbc = Mbc {
             // ROM bank selection 5 lower bits
             0x2000 | 0x3000 => {
                 let mut rom_bank = value & 0x1f;
-                rom_bank = rom_bank & (rom.rom_bank_count * 2 - 1) as u8;
+                rom_bank &= (rom.rom_bank_count * 2 - 1) as u8;
                 if rom_bank == 0 {
                     rom_bank = 1;
                 }
@@ -537,7 +537,7 @@ pub static MBC3: Mbc = Mbc {
             // ROM bank selection
             0x2000 | 0x3000 => {
                 let mut rom_bank = value & 0x7f;
-                rom_bank = rom_bank & (rom.rom_bank_count * 2 - 1) as u8;
+                rom_bank &= (rom.rom_bank_count * 2 - 1) as u8;
                 if rom_bank == 0 {
                     rom_bank = 1;
                 }
@@ -592,7 +592,7 @@ pub static MBC5: Mbc = Mbc {
             }
             // ROM bank selection
             0x2000 => {
-                let rom_bank = value & 0xff;
+                let rom_bank = value;
                 rom.set_rom_bank(rom_bank);
             }
             // RAM bank selection