diff --git a/.idea/Chip8Emulator.iml b/.idea/Chip8Emulator.iml
index e5ed26c..f150b5d 100644
--- a/.idea/Chip8Emulator.iml
+++ b/.idea/Chip8Emulator.iml
@@ -4,6 +4,7 @@
+
diff --git a/Cargo.lock b/Cargo.lock
index 202d2a1..aaf67d9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -78,6 +78,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
[[package]]
name = "bitflags"
version = "2.6.0"
@@ -111,6 +117,18 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "chip8_sdl"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "emulator",
+ "env_logger",
+ "log",
+ "sdl2",
+]
+
[[package]]
name = "chip8_tui"
version = "0.1.0"
@@ -189,7 +207,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
- "bitflags",
+ "bitflags 2.6.0",
"crossterm_winapi",
"mio",
"parking_lot",
@@ -396,6 +414,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
[[package]]
name = "libc"
version = "0.2.169"
@@ -553,7 +577,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
- "bitflags",
+ "bitflags 2.6.0",
"cassowary",
"compact_str",
"crossterm",
@@ -574,7 +598,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
- "bitflags",
+ "bitflags 2.6.0",
]
[[package]]
@@ -612,7 +636,7 @@ version = "0.38.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
dependencies = [
- "bitflags",
+ "bitflags 2.6.0",
"errno",
"libc",
"linux-raw-sys",
@@ -637,6 +661,29 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "sdl2"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380"
+dependencies = [
+ "bitflags 1.3.2",
+ "lazy_static",
+ "libc",
+ "sdl2-sys",
+]
+
+[[package]]
+name = "sdl2-sys"
+version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "version-compare",
+]
+
[[package]]
name = "signal-hook"
version = "0.3.17"
@@ -759,6 +806,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+[[package]]
+name = "version-compare"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
+
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
diff --git a/Cargo.toml b/Cargo.toml
index e67c4ec..95c504f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,4 +7,5 @@ resolver = "2"
members = [
"chip8_tui",
"chip8_core",
+ "chip8_sdl",
]
diff --git a/chip8_core/src/display.rs b/chip8_core/src/display.rs
index 6798430..4528a0a 100644
--- a/chip8_core/src/display.rs
+++ b/chip8_core/src/display.rs
@@ -18,5 +18,5 @@ pub(crate) struct TestingDisplay;
impl Display for TestingDisplay {
fn clear(&mut self) {}
- fn render(&mut self, display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]) {}
+ fn render(&mut self, _display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]) {}
}
diff --git a/chip8_sdl/Cargo.toml b/chip8_sdl/Cargo.toml
new file mode 100644
index 0000000..16b3cea
--- /dev/null
+++ b/chip8_sdl/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "chip8_sdl"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+emulator = { path = "../chip8_core" }
+env_logger = "0.11.6"
+clap = { version = "4.5.26", features = ["derive"] }
+anyhow = "1.0.95"
+sdl2 = { version = "0.37.0", features = ["unsafe_textures"] }
+log = "0.4.22"
diff --git a/chip8_sdl/src/main.rs b/chip8_sdl/src/main.rs
new file mode 100644
index 0000000..56322de
--- /dev/null
+++ b/chip8_sdl/src/main.rs
@@ -0,0 +1,143 @@
+use anyhow::anyhow;
+use clap::Parser;
+use emulator::display::{Display, DISPLAY_HEIGHT, DISPLAY_WIDTH};
+use emulator::emulator::Emulator;
+use emulator::input::InputModule;
+use emulator::sound::SoundModule;
+use log::error;
+use sdl2::pixels::Color;
+use sdl2::rect::Rect;
+use sdl2::render::WindowCanvas;
+use sdl2::Sdl;
+use std::fs::File;
+
+const BACKGROUND_COLOR: Color = Color::RGB(0, 0, 0);
+const PIXEL_COLOR: Color = Color::RGB(0, 255, 0);
+
+#[derive(Parser, Debug)]
+#[command(
+ version = "1.0",
+ about = "A Chip8 chip8_core.",
+ long_about = "A program which emulates the Chip8 system."
+)]
+struct CliArgs {
+ /// The path to the ROM file to emulate.
+ rom_path: String,
+}
+
+/// SDL2 display module for the Chip8 emulator.
+struct SDLDisplayBackend {
+ canvas: WindowCanvas,
+}
+
+impl SDLDisplayBackend {
+ fn new(sdl_context: &Sdl) -> Result {
+ let video_subsystem = sdl_context.video().map_err(|s| anyhow!(s))?;
+
+ let window = video_subsystem
+ .window("Chip8 Emulator by nuculabs.dev", 816, 648)
+ .vulkan()
+ .build()
+ .map_err(|e| e.to_string())
+ .map_err(|s| anyhow!(s))?;
+
+ let canvas = window
+ .into_canvas()
+ .build()
+ .map_err(|e| e.to_string())
+ .map_err(|s| anyhow!(s))?;
+
+ Ok(SDLDisplayBackend { canvas })
+ }
+}
+
+impl Display for SDLDisplayBackend {
+ fn clear(&mut self) {
+ self.canvas.set_draw_color(BACKGROUND_COLOR);
+ self.canvas.clear();
+ }
+
+ fn render(&mut self, display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]) {
+ for row in 0..32 {
+ for column in 0..64 {
+ if display_data[row * DISPLAY_WIDTH + column] {
+ self.canvas.set_draw_color(PIXEL_COLOR);
+ let result = self.canvas.fill_rect(Rect::new(
+ column as i32 * 12 + 24,
+ row as i32 * 18 + 18,
+ 12,
+ 18,
+ ));
+ if let Err(error_message) = result {
+ error!("{}", error_message)
+ }
+ } else {
+ self.canvas.set_draw_color(BACKGROUND_COLOR);
+ let result = self.canvas.fill_rect(Rect::new(
+ column as i32 * 12 + 24,
+ row as i32 * 18 + 18,
+ 12,
+ 18,
+ ));
+ if let Err(error_message) = result {
+ error!("{}", error_message)
+ }
+ }
+ }
+ }
+ self.canvas.present()
+ }
+}
+
+struct DummySound;
+
+impl SoundModule for DummySound {
+ fn beep(&mut self) {}
+}
+
+#[derive(Clone)]
+struct DummyInputHandler;
+
+impl InputModule for DummyInputHandler {
+ fn get_key_pressed(&mut self) -> Option {
+ return None;
+ }
+}
+
+fn main() -> Result<(), anyhow::Error> {
+ env_logger::init();
+ let args = CliArgs::parse();
+
+ let file = File::open(&args.rom_path)?;
+
+ let sdl_context = sdl2::init().map_err(|s| anyhow!(s))?;
+
+ let sdl_display_backend: SDLDisplayBackend = SDLDisplayBackend::new(&sdl_context)?;
+
+ let mut emulator = Emulator::new(sdl_display_backend, DummySound, DummyInputHandler);
+ emulator.emulate(file)?;
+
+ // let event_pump = sdl_context.event_pump().map_err(|s| anyhow!(s))?;
+
+ // Show it on the screen
+ // canvas.present();
+ // let mut index = 0;
+ // 'main: loop {
+ // index += 10;
+ // canvas.fill_rect(Rect::new(index, 100, 10, 10))?;
+ // canvas.present();
+ // thread::sleep(Duration::new(1, 0));
+ // for event in event_pump.poll_iter() {
+ // match event {
+ // Event::Quit { .. }
+ // | Event::KeyDown {
+ // keycode: Some(Keycode::Escape),
+ // ..
+ // } => break 'main,
+ // _ => {}
+ // }
+ // }
+ // }
+
+ Ok(())
+}