diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 29930b9..b3d9a6c 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -10,49 +10,24 @@
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -78,6 +53,18 @@
+
+
+
+
@@ -111,6 +98,7 @@
}]]>
+
@@ -129,7 +117,7 @@
1703977798818
-
+
@@ -147,7 +135,15 @@
1703981104184
-
+
+
+ 1704223021658
+
+
+
+ 1704223021658
+
+
@@ -157,6 +153,7 @@
-
+
+
\ No newline at end of file
diff --git a/gameboy-lib/Cargo.lock b/gameboy-lib/Cargo.lock
index 44a4097..09715de 100644
--- a/gameboy-lib/Cargo.lock
+++ b/gameboy-lib/Cargo.lock
@@ -18,6 +18,8 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
name = "gameboy"
version = "0.1.0"
dependencies = [
+ "serde",
+ "serde_derive",
"wasm-bindgen",
]
@@ -35,27 +37,47 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "proc-macro2"
-version = "1.0.72"
+version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a293318316cf6478ec1ad2a21c49390a8d5b5eae9fab736467d93fbc0edc29c5"
+checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.33"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
+[[package]]
+name = "serde"
+version = "1.0.194"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.194"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "syn"
-version = "2.0.43"
+version = "2.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
+checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e"
dependencies = [
"proc-macro2",
"quote",
diff --git a/gameboy-lib/Cargo.toml b/gameboy-lib/Cargo.toml
index 0b61605..6ecc392 100644
--- a/gameboy-lib/Cargo.toml
+++ b/gameboy-lib/Cargo.toml
@@ -6,7 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
+serialize = ["serde", "serde_derive"]
wasm = ["wasm-bindgen"]
[dependencies]
-wasm-bindgen = { version = "0.2.84", optional = true}
\ No newline at end of file
+wasm-bindgen = { version = "0.2.84", optional = true}
+serde = { version = "1.0.194", optional = true }
+serde_derive = { version = "1.0.194", 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 4c43a1e..cc512a9 100644
--- a/gameboy-lib/src/cpu/cpu.rs
+++ b/gameboy-lib/src/cpu/cpu.rs
@@ -1,11 +1,13 @@
+use serde_derive::Serialize;
use crate::cpu::instructions::{JumpCondition, Target16Bit};
use crate::cpu::registers::{Register8BitName, Registers};
-use crate::memory::memory::Memory;
+use crate::memory::Memory;
use super::instructions::Target8Bit;
use super::instructions::{Instruction, Source16Bit};
use super::registers::Register16BitName;
+#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct CPU {
pub register: Registers,
pub pc: u16,
diff --git a/gameboy-lib/src/cpu/registers/flag_register.rs b/gameboy-lib/src/cpu/registers/flag_register.rs
index 4a56b8a..8df3fab 100644
--- a/gameboy-lib/src/cpu/registers/flag_register.rs
+++ b/gameboy-lib/src/cpu/registers/flag_register.rs
@@ -1,4 +1,7 @@
+use serde_derive::Serialize;
+
#[derive(Copy, Clone, Debug, PartialEq)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct FlagRegister {
pub zero: bool,
pub subtract: bool,
diff --git a/gameboy-lib/src/cpu/registers/mod.rs b/gameboy-lib/src/cpu/registers/mod.rs
index b21a91d..8d1d804 100644
--- a/gameboy-lib/src/cpu/registers/mod.rs
+++ b/gameboy-lib/src/cpu/registers/mod.rs
@@ -1,3 +1,4 @@
+use serde_derive::Serialize;
use super::registers::flag_register::FlagRegister;
use super::registers::register::Register;
use super::registers::register_8bit::Register8Bit;
@@ -9,6 +10,7 @@ mod register_8bit;
mod stack_pointer;
#[derive(Clone)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct Registers {
a: Register8Bit,
b: Register8Bit,
diff --git a/gameboy-lib/src/cpu/registers/register_8bit.rs b/gameboy-lib/src/cpu/registers/register_8bit.rs
index 4e3375b..cae9a93 100644
--- a/gameboy-lib/src/cpu/registers/register_8bit.rs
+++ b/gameboy-lib/src/cpu/registers/register_8bit.rs
@@ -1,6 +1,8 @@
+use serde_derive::Serialize;
use super::register::Register;
#[derive(Clone)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct Register8Bit {
name: String,
value: u8,
diff --git a/gameboy-lib/src/cpu/registers/stack_pointer.rs b/gameboy-lib/src/cpu/registers/stack_pointer.rs
index a81415b..d5e1011 100644
--- a/gameboy-lib/src/cpu/registers/stack_pointer.rs
+++ b/gameboy-lib/src/cpu/registers/stack_pointer.rs
@@ -1,6 +1,8 @@
+use serde_derive::Serialize;
use super::Register;
#[derive(Clone)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct StackPointer {
name: String,
value: u16
diff --git a/gameboy-lib/src/lib.rs b/gameboy-lib/src/lib.rs
index cc98f6f..443c1d4 100644
--- a/gameboy-lib/src/lib.rs
+++ b/gameboy-lib/src/lib.rs
@@ -1,6 +1,4 @@
use crate::cpu::cpu::CPU;
-use crate::cpu::registers::Registers;
-use crate::memory::memory::Memory;
pub mod cpu;
pub mod memory;
@@ -25,4 +23,4 @@ impl GameBoy {
self.cpu.step();
}
}
-}
\ No newline at end of file
+}
diff --git a/gameboy-lib/src/memory/memory.rs b/gameboy-lib/src/memory.rs
similarity index 62%
rename from gameboy-lib/src/memory/memory.rs
rename to gameboy-lib/src/memory.rs
index 9a17c9f..2a403fe 100644
--- a/gameboy-lib/src/memory/memory.rs
+++ b/gameboy-lib/src/memory.rs
@@ -1,4 +1,4 @@
-use crate::memory::observer::{Event, Publisher, Subject};
+use serde_derive::Serialize;
pub const BOOT_ROM_BEGIN: usize = 0x00;
pub const BOOT_ROM_END: usize = 0xFF;
@@ -6,17 +6,16 @@ pub const BOOT_ROM_SIZE: usize = BOOT_ROM_END - BOOT_ROM_BEGIN + 1;
#[derive(Clone)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct Memory {
- publisher: Publisher,
- pub memory: [u8; 0xFFFF],
+ pub memory: Vec,
}
impl Default for Memory {
fn default() -> Self {
Memory {
- publisher: Publisher::default(),
- memory: [0; 0xFFFF],
+ memory: vec![0; 0xFFFF],
}
}
}
@@ -28,32 +27,18 @@ impl Memory {
}
}
- 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
deleted file mode 100644
index 58cdea1..0000000
--- a/gameboy-lib/src/memory/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-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
deleted file mode 100644
index bbe1e3b..0000000
--- a/gameboy-lib/src/memory/observer.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-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-web/gameboy-wasm/Cargo.toml b/gameboy-web/gameboy-wasm/Cargo.toml
index 3b6161b..f2818ab 100644
--- a/gameboy-web/gameboy-wasm/Cargo.toml
+++ b/gameboy-web/gameboy-wasm/Cargo.toml
@@ -11,15 +11,13 @@ 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
-# logging them with `console.error`. This is great for development, but requires
-# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
-# code size when deploying.
+gameboy = { path = "../../gameboy-lib", features = ["wasm", "serialize"] }
+wasm-bindgen = { version = "0.2.84", features = ["serde-serialize"] }
console_error_panic_hook = { version = "0.1.7", optional = true }
log = "0.4.20"
+serde = "1.0.194"
+serde_derive = "1.0.194"
+serde-wasm-bindgen = "0.6.3"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"
diff --git a/gameboy-web/gameboy-wasm/src/lib.rs b/gameboy-web/gameboy-wasm/src/lib.rs
index 659e164..eb2fcec 100644
--- a/gameboy-web/gameboy-wasm/src/lib.rs
+++ b/gameboy-web/gameboy-wasm/src/lib.rs
@@ -1,9 +1,8 @@
mod utils;
use std::ops::Deref;
+use serde_derive::Serialize;
use wasm_bindgen::prelude::*;
-use gameboy::GameBoy;
-use gameboy::memory::observer::Event;
#[wasm_bindgen]
extern "C" {
@@ -13,26 +12,25 @@ extern "C" {
}
#[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;
+#[derive(Serialize)]
+pub struct CPU(gameboy::cpu::cpu::CPU);
- 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");
+#[wasm_bindgen]
+impl CPU {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> CPU {
+ utils::set_panic_hook();
+ let cpu = gameboy::cpu::cpu::CPU::default();
+ return CPU(cpu);
+ }
+
+ pub fn to_json(&self) -> Result {
+ Ok(serde_wasm_bindgen::to_value(&self)?)
+ }
}
-fn load_boot_rom() -> Vec {
+#[wasm_bindgen]
+pub fn load_boot_rom() -> Vec {
let boot_rom = "31FEFFAF21FF9F32CB7C20FB2126FF0E113E8032E20C3EF3E2323E77773EFCE0471104012110801ACD9500CD9600137BFE3420F311D80006081A1322230520F93E19EA1099212F990E0C3D2808320D20F92E0F18F3673E6457E0423E91E040041E020E0CF044FE9020FA0D20F71D20F20E13247C1E83FE6228061EC1FE6420067BE20C3E87E2F04290E0421520D205204F162018CB4F0604C5CB1117C1CB11170520F522232223C9CEED6666CC0D000B03730083000C000D0008111F8889000EDCCC6EE6DDDDD999BBBB67636E0EECCCDDDC999FBBB9333E3C42B9A5B9A5423C21040111A8001A13BE20FE237DFE3420F506197886230520FB8620FE3E01E050";
boot_rom.chars()
.collect::>()
diff --git a/gameboy-web/src/App.tsx b/gameboy-web/src/App.tsx
index 207f181..90a88be 100644
--- a/gameboy-web/src/App.tsx
+++ b/gameboy-web/src/App.tsx
@@ -1,5 +1,5 @@
import {useEffect, useState} from "react";
-import init, {start_gameboy} from "gameboy-wasm";
+import init, {load_boot_rom, CPU} from "gameboy-wasm";
function App() {
@@ -10,13 +10,16 @@ function App() {
}, [])
const handleButton = () => {
- start_gameboy()
+ const cpu = new CPU();
+ const cpuAsJson = cpu.to_json();
+ const memory = cpuAsJson.memory;
+ console.log("Memory", memory)
}
return (
-
+
)
}