diff --git a/.idea/gameboy.iml b/.idea/gameboy.iml
index 72941fe..81d5aab 100644
--- a/.idea/gameboy.iml
+++ b/.idea/gameboy.iml
@@ -5,11 +5,11 @@
-
-
+
+
-
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index ed9a1a5..a8c3819 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -3,7 +3,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 1f1286c..29930b9 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -7,30 +7,83 @@
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ {
+ "associatedIndex": 0
+}
@@ -43,6 +96,7 @@
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"git-widget-placeholder": "main",
"kotlin-language-version-configured": "true",
+ "last_opened_file_path": "/mnt/datahub/projects/emulation/gameboy/gameboy-web/gameboy-wasm/Cargo.toml",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
@@ -51,27 +105,16 @@
"nodejs_package_manager_path": "npm",
"org.rust.cargo.project.model.PROJECT_DISCOVERY": "true",
"settings.editor.selected.configurable": "preferences.pluginManager",
- "ts.external.directory.path": "/mnt/datahub/projects/emulation/gameboy/gameboy-frontend/node_modules/typescript/lib",
+ "ts.external.directory.path": "/mnt/datahub/projects/emulation/gameboy/gameboy-web/node_modules/typescript/lib",
"vue.rearranger.settings.migration": "true"
}
}]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
@@ -84,7 +127,9 @@
1703977798818
-
+
+
+
@@ -94,7 +139,15 @@
1703977864757
-
+
+
+ 1703981104184
+
+
+
+ 1703981104184
+
+
@@ -102,6 +155,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/gameboy-bin/src/main.rs b/gameboy-bin/src/main.rs
index 110b233..cf05fd7 100644
--- a/gameboy-bin/src/main.rs
+++ b/gameboy-bin/src/main.rs
@@ -1,9 +1,23 @@
extern crate gameboy;
+use gameboy::GameBoy;
+use gameboy::memory::observer::Event;
+
+
fn main() {
let boot_rom = load_boot_rom();
- boot_rom.iter().for_each(|n|println!("{:x}", n));
- gameboy::start_gameboy(boot_rom);
+ let mut gameboy: GameBoy = GameBoy::new();
+ let mut memory = &mut gameboy.cpu.memory;
+
+ memory.events().subscribe(Event::Write, |subject| {
+ println!("[MEM] Writing value: 0x{:x}: 0x{:x}", subject.address, subject.value)
+ });
+
+ memory.events().subscribe(Event::Read, |subject| {
+ println!("[MEM] Reading value: 0x{:x}: 0x{:x}", subject.address, subject.value)
+ });
+
+ gameboy.start_gameboy(boot_rom);
}
fn load_boot_rom() -> Vec {
diff --git a/gameboy-frontend.iml b/gameboy-frontend.iml
deleted file mode 100644
index b3c11c2..0000000
--- a/gameboy-frontend.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/gameboy-frontend/vite.config.ts b/gameboy-frontend/vite.config.ts
deleted file mode 100644
index db4da8e..0000000
--- a/gameboy-frontend/vite.config.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import {defineConfig, searchForWorkspaceRoot} from 'vite'
-import react from '@vitejs/plugin-react'
-
-// https://vitejs.dev/config/
-export default defineConfig({
- plugins: [react()],
- server: {
- fs: {
- allow: [searchForWorkspaceRoot(process.cwd()),'../gameboy-wasm/pkg']
- }
- }
-})
diff --git a/gameboy-lib/Cargo.lock b/gameboy-lib/Cargo.lock
index 612f491..44a4097 100644
--- a/gameboy-lib/Cargo.lock
+++ b/gameboy-lib/Cargo.lock
@@ -2,6 +2,122 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "bumpalo"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
[[package]]
name = "gameboy"
version = "0.1.0"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "log"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a293318316cf6478ec1ad2a21c49390a8d5b5eae9fab736467d93fbc0edc29c5"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
diff --git a/gameboy-lib/Cargo.toml b/gameboy-lib/Cargo.toml
index e212b65..0b61605 100644
--- a/gameboy-lib/Cargo.toml
+++ b/gameboy-lib/Cargo.toml
@@ -5,4 +5,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[features]
+wasm = ["wasm-bindgen"]
+
[dependencies]
+wasm-bindgen = { version = "0.2.84", optional = true}
\ No newline at end of file
diff --git a/gameboy-lib/src/cpu/cpu.rs b/gameboy-lib/src/cpu/cpu.rs
index 34c0d21..4c43a1e 100644
--- a/gameboy-lib/src/cpu/cpu.rs
+++ b/gameboy-lib/src/cpu/cpu.rs
@@ -1,6 +1,6 @@
use crate::cpu::instructions::{JumpCondition, Target16Bit};
use crate::cpu::registers::{Register8BitName, Registers};
-use crate::memory::Memory;
+use crate::memory::memory::Memory;
use super::instructions::Target8Bit;
use super::instructions::{Instruction, Source16Bit};
@@ -12,15 +12,21 @@ pub struct CPU {
pub memory: Memory,
}
-impl CPU {
- pub fn boot(boot_rom: Vec) -> CPU {
- println!("[CPU] Starting CPU...");
+impl Default for CPU {
+ fn default() -> Self {
CPU {
register: Registers::new(),
pc: 0x0,
- memory: Memory::new(boot_rom),
+ memory: Memory::default(),
}
}
+}
+
+impl CPU {
+ pub fn boot(&mut self, boot_rom: Vec) {
+ println!("[CPU] Starting CPU...");
+ self.memory.boot(boot_rom);
+ }
pub fn execute(&mut self, instructions: Instruction) -> u16 {
match instructions {
diff --git a/gameboy-lib/src/lib.rs b/gameboy-lib/src/lib.rs
index 7f4cc66..cc98f6f 100644
--- a/gameboy-lib/src/lib.rs
+++ b/gameboy-lib/src/lib.rs
@@ -1,11 +1,28 @@
use crate::cpu::cpu::CPU;
+use crate::cpu::registers::Registers;
+use crate::memory::memory::Memory;
pub mod cpu;
-mod memory;
+pub mod memory;
-pub fn start_gameboy(boot_rom: Vec) {
- let mut cpu = CPU::boot(boot_rom);
- loop {
- cpu.step();
+pub struct GameBoy {
+ pub cpu: CPU,
+ boot_rom: Vec,
+ //game_rom: Vec
+}
+
+impl GameBoy {
+ pub fn new() -> Self {
+ GameBoy {
+ cpu: CPU::default(),
+ boot_rom: Vec::new(),
+ }
+ }
+
+ pub fn start_gameboy(&mut self, boot_rom: Vec) {
+ self.cpu.boot(boot_rom);
+ loop {
+ self.cpu.step();
+ }
}
}
\ No newline at end of file
diff --git a/gameboy-lib/src/memory.rs b/gameboy-lib/src/memory.rs
deleted file mode 100644
index d40e741..0000000
--- a/gameboy-lib/src/memory.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-pub const BOOT_ROM_BEGIN: usize = 0x00;
-pub const BOOT_ROM_END: usize = 0xFF;
-pub const BOOT_ROM_SIZE: usize = BOOT_ROM_END - BOOT_ROM_BEGIN + 1;
-
-
-#[derive(Clone)]
-pub struct Memory {
- pub memory: [u8; 0xFFFF],
-}
-
-impl Memory {
- pub fn new(boot_room: Vec) -> Memory {
- let mut memory = Memory {
- memory: [0; 0xFFFF]
- };
-
- println!("[MEM] Loading bootstrap rom...");
- for (idx, value) in boot_room.iter().enumerate() {
- memory.write_byte(idx as u16, value.clone());
- }
-
- return memory;
- }
- pub fn write_byte(&mut self, address: u16, value: u8) {
- println!("[MEM] Writing memory: address: 0x{:x} value: 0x{:x}", address, value);
- self.memory[address as usize] = value;
- }
-
- pub fn read_byte(&self, address: u16) -> u8 {
- let mem_value = self.memory[address as usize];
- println!("[MEM] Reading memory: address: 0x{:x} value: 0x{:x}", address, mem_value);
- return mem_value;
- }
-
- pub fn read_next_word(&self, pc: u16) -> u16 {
- ((self.read_byte(pc + 2) as u16) << 8) | (self.read_byte(pc + 1) as u16)
- }
-}
diff --git a/gameboy-lib/src/memory/memory.rs b/gameboy-lib/src/memory/memory.rs
new file mode 100644
index 0000000..9a17c9f
--- /dev/null
+++ b/gameboy-lib/src/memory/memory.rs
@@ -0,0 +1,59 @@
+use crate::memory::observer::{Event, Publisher, Subject};
+
+pub const BOOT_ROM_BEGIN: usize = 0x00;
+pub const BOOT_ROM_END: usize = 0xFF;
+pub const BOOT_ROM_SIZE: usize = BOOT_ROM_END - BOOT_ROM_BEGIN + 1;
+
+
+#[derive(Clone)]
+pub struct Memory {
+ publisher: Publisher,
+ pub memory: [u8; 0xFFFF],
+}
+
+
+impl Default for Memory {
+ fn default() -> Self {
+ Memory {
+ publisher: Publisher::default(),
+ memory: [0; 0xFFFF],
+ }
+ }
+}
+
+impl Memory {
+ pub fn boot(&mut self, boot_room: Vec) {
+ for (idx, value) in boot_room.iter().enumerate() {
+ self.write_byte(idx as u16, value.clone());
+ }
+ }
+
+ pub fn events(&mut self) -> &mut Publisher {
+ return &mut self.publisher;
+ }
+
+ pub fn write_byte(&mut self, address: u16, value: u8) {
+ // println!("[MEM] Writing memory: address: 0x{:x} value: 0x{:x}", address, value);
+ self.memory[address as usize] = value;
+ self.publisher.notify(Event::Write, self.create_subject(value, address));
+ }
+
+ pub fn read_byte(&self, address: u16) -> u8 {
+ let mem_value = self.memory[address as usize];
+ // println!("[MEM] Reading memory: address: 0x{:x} value: 0x{:x}", address, mem_value);
+ self.publisher.notify(Event::Read, self.create_subject(mem_value, address));
+ return mem_value;
+ }
+
+ pub fn read_next_word(&self, pc: u16) -> u16 {
+ ((self.read_byte(pc + 2) as u16) << 8) | (self.read_byte(pc + 1) as u16)
+ }
+
+ fn create_subject(&self, value: u8, address: u16) -> Subject {
+ return Subject {
+ value,
+ address,
+ memory: self.memory.clone(),
+ };
+ }
+}
diff --git a/gameboy-lib/src/memory/mod.rs b/gameboy-lib/src/memory/mod.rs
new file mode 100644
index 0000000..58cdea1
--- /dev/null
+++ b/gameboy-lib/src/memory/mod.rs
@@ -0,0 +1,2 @@
+pub mod observer;
+pub mod memory;
\ No newline at end of file
diff --git a/gameboy-lib/src/memory/observer.rs b/gameboy-lib/src/memory/observer.rs
new file mode 100644
index 0000000..bbe1e3b
--- /dev/null
+++ b/gameboy-lib/src/memory/observer.rs
@@ -0,0 +1,41 @@
+use std::collections::HashMap;
+
+#[derive(PartialEq, Eq, Hash, Clone)]
+pub enum Event {
+ Write,
+ Read,
+}
+
+#[derive(Clone)]
+pub struct Subject {
+ pub value: u8,
+ pub address: u16,
+ pub memory: [u8; 0xFFFF],
+}
+
+pub type Subscriber = fn(subject: Subject);
+
+#[derive(Default, Clone)]
+pub struct Publisher {
+ events: HashMap>,
+}
+
+impl Publisher {
+ pub fn subscribe(&mut self, event: Event, listener: Subscriber) {
+ self.events.entry(event.clone()).or_default();
+ self.events.get_mut(&event).unwrap().push(listener);
+ }
+
+ pub fn unsubscribe(&mut self, event: Event, listener: Subscriber) {
+ self.events.get_mut(&event).unwrap().retain(|&x| x != listener);
+ }
+
+ pub fn notify(&self, event: Event, subject: Subject) {
+ let listeners = self.events.get(&event);
+ if let Some(listeners) = listeners {
+ for listener in listeners {
+ listener(subject.clone());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/gameboy-wasm/src/lib.rs b/gameboy-wasm/src/lib.rs
deleted file mode 100644
index 90a13d8..0000000
--- a/gameboy-wasm/src/lib.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-mod utils;
-
-use wasm_bindgen::prelude::*;
-
-#[wasm_bindgen]
-extern "C" {
- fn alert(s: &str);
-}
-
-#[wasm_bindgen]
-pub fn greet() {
- alert("Hello, gameboy-wasm!");
-}
diff --git a/gameboy-web.iml b/gameboy-web.iml
new file mode 100644
index 0000000..961c6e2
--- /dev/null
+++ b/gameboy-web.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gameboy-frontend/.eslintrc.cjs b/gameboy-web/.eslintrc.cjs
similarity index 100%
rename from gameboy-frontend/.eslintrc.cjs
rename to gameboy-web/.eslintrc.cjs
diff --git a/gameboy-frontend/.gitignore b/gameboy-web/.gitignore
similarity index 100%
rename from gameboy-frontend/.gitignore
rename to gameboy-web/.gitignore
diff --git a/gameboy-web/.rsw/rsw.crates b/gameboy-web/.rsw/rsw.crates
new file mode 100644
index 0000000..786a484
--- /dev/null
+++ b/gameboy-web/.rsw/rsw.crates
@@ -0,0 +1 @@
+gameboy-wasm :~> gameboy-wasm/pkg
\ No newline at end of file
diff --git a/gameboy-web/.rsw/rsw.err b/gameboy-web/.rsw/rsw.err
new file mode 100644
index 0000000..e69de29
diff --git a/gameboy-web/.rsw/rsw.info b/gameboy-web/.rsw/rsw.info
new file mode 100644
index 0000000..b334884
--- /dev/null
+++ b/gameboy-web/.rsw/rsw.info
@@ -0,0 +1,3 @@
+[RSW::OK]
+[RSW::NAME] :~> gameboy-wasm
+[RSW::PATH] :~> /mnt/datahub/projects/emulation/gameboy/gameboy-web/./gameboy-wasm/src/lib.rs
\ No newline at end of file
diff --git a/gameboy-frontend/README.md b/gameboy-web/README.md
similarity index 100%
rename from gameboy-frontend/README.md
rename to gameboy-web/README.md
diff --git a/gameboy-wasm/.appveyor.yml b/gameboy-web/gameboy-wasm/.appveyor.yml
similarity index 100%
rename from gameboy-wasm/.appveyor.yml
rename to gameboy-web/gameboy-wasm/.appveyor.yml
diff --git a/gameboy-wasm/.github/dependabot.yml b/gameboy-web/gameboy-wasm/.github/dependabot.yml
similarity index 100%
rename from gameboy-wasm/.github/dependabot.yml
rename to gameboy-web/gameboy-wasm/.github/dependabot.yml
diff --git a/gameboy-wasm/.gitignore b/gameboy-web/gameboy-wasm/.gitignore
similarity index 100%
rename from gameboy-wasm/.gitignore
rename to gameboy-web/gameboy-wasm/.gitignore
diff --git a/gameboy-wasm/.travis.yml b/gameboy-web/gameboy-wasm/.travis.yml
similarity index 100%
rename from gameboy-wasm/.travis.yml
rename to gameboy-web/gameboy-wasm/.travis.yml
diff --git a/gameboy-wasm/Cargo.toml b/gameboy-web/gameboy-wasm/Cargo.toml
similarity index 90%
rename from gameboy-wasm/Cargo.toml
rename to gameboy-web/gameboy-wasm/Cargo.toml
index 6a9ed3c..3b6161b 100644
--- a/gameboy-wasm/Cargo.toml
+++ b/gameboy-web/gameboy-wasm/Cargo.toml
@@ -11,6 +11,7 @@ crate-type = ["cdylib", "rlib"]
default = ["console_error_panic_hook"]
[dependencies]
+gameboy = { path = "../../gameboy-lib", features = ["wasm"] }
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
@@ -18,6 +19,7 @@ wasm-bindgen = "0.2.84"
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
+log = "0.4.20"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"
diff --git a/gameboy-wasm/LICENSE_APACHE b/gameboy-web/gameboy-wasm/LICENSE_APACHE
similarity index 100%
rename from gameboy-wasm/LICENSE_APACHE
rename to gameboy-web/gameboy-wasm/LICENSE_APACHE
diff --git a/gameboy-wasm/LICENSE_MIT b/gameboy-web/gameboy-wasm/LICENSE_MIT
similarity index 100%
rename from gameboy-wasm/LICENSE_MIT
rename to gameboy-web/gameboy-wasm/LICENSE_MIT
diff --git a/gameboy-wasm/README.md b/gameboy-web/gameboy-wasm/README.md
similarity index 100%
rename from gameboy-wasm/README.md
rename to gameboy-web/gameboy-wasm/README.md
diff --git a/gameboy-web/gameboy-wasm/src/lib.rs b/gameboy-web/gameboy-wasm/src/lib.rs
new file mode 100644
index 0000000..659e164
--- /dev/null
+++ b/gameboy-web/gameboy-wasm/src/lib.rs
@@ -0,0 +1,43 @@
+mod utils;
+
+use std::ops::Deref;
+use wasm_bindgen::prelude::*;
+use gameboy::GameBoy;
+use gameboy::memory::observer::Event;
+
+#[wasm_bindgen]
+extern "C" {
+ fn alert(s: &str);
+ #[wasm_bindgen(js_namespace = console)]
+ fn log(s: &str);
+}
+
+#[wasm_bindgen]
+pub fn start_gameboy() {
+ log("Starting...");
+ let boot_rom = load_boot_rom();
+ let mut gameboy: GameBoy = GameBoy::new();
+ let mut memory = &mut gameboy.cpu.memory;
+
+ memory.events().subscribe(Event::Write, |subject| {
+ log(format!("[MEM WASM] Writing value: 0x{:x}: 0x{:x}", subject.address, subject.value).as_str())
+ });
+
+ memory.events().subscribe(Event::Read, |subject| {
+ log(format!("[MEM WASM] Reading value: 0x{:x}: 0x{:x}", subject.address, subject.value).as_str())
+ });
+
+ gameboy.start_gameboy(boot_rom);
+
+ log("End");
+}
+
+fn load_boot_rom() -> Vec {
+ let boot_rom = "31FEFFAF21FF9F32CB7C20FB2126FF0E113E8032E20C3EF3E2323E77773EFCE0471104012110801ACD9500CD9600137BFE3420F311D80006081A1322230520F93E19EA1099212F990E0C3D2808320D20F92E0F18F3673E6457E0423E91E040041E020E0CF044FE9020FA0D20F71D20F20E13247C1E83FE6228061EC1FE6420067BE20C3E87E2F04290E0421520D205204F162018CB4F0604C5CB1117C1CB11170520F522232223C9CEED6666CC0D000B03730083000C000D0008111F8889000EDCCC6EE6DDDDD999BBBB67636E0EECCCDDDC999FBBB9333E3C42B9A5B9A5423C21040111A8001A13BE20FE237DFE3420F506197886230520FB8620FE3E01E050";
+ boot_rom.chars()
+ .collect::>()
+ .chunks(2)
+ .map(|c| c.iter().collect::())
+ .map(|s| u8::from_str_radix(s.as_str(), 16).unwrap())
+ .collect()
+}
diff --git a/gameboy-wasm/src/utils.rs b/gameboy-web/gameboy-wasm/src/utils.rs
similarity index 100%
rename from gameboy-wasm/src/utils.rs
rename to gameboy-web/gameboy-wasm/src/utils.rs
diff --git a/gameboy-wasm/tests/web.rs b/gameboy-web/gameboy-wasm/tests/web.rs
similarity index 100%
rename from gameboy-wasm/tests/web.rs
rename to gameboy-web/gameboy-wasm/tests/web.rs
diff --git a/gameboy-frontend/index.html b/gameboy-web/index.html
similarity index 82%
rename from gameboy-frontend/index.html
rename to gameboy-web/index.html
index e4b78ea..0931ec5 100644
--- a/gameboy-frontend/index.html
+++ b/gameboy-web/index.html
@@ -8,6 +8,6 @@
-
+