From 86680d85a3c562455c8708c7c97f3cb175c42626 Mon Sep 17 00:00:00 2001 From: Denis Nutiu Date: Tue, 21 Jan 2025 22:15:56 +0200 Subject: [PATCH] implement sdl2 display module --- .idea/Chip8Emulator.iml | 1 + Cargo.lock | 61 ++++++++++++++-- Cargo.toml | 1 + chip8_core/src/display.rs | 2 +- chip8_sdl/Cargo.toml | 12 ++++ chip8_sdl/src/main.rs | 143 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 chip8_sdl/Cargo.toml create mode 100644 chip8_sdl/src/main.rs 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(()) +}