Compare commits

...

2 commits

Author SHA1 Message Date
86680d85a3 implement sdl2 display module 2025-01-21 22:15:56 +02:00
86acbf6fc8 fix emulator tests 2025-01-20 21:49:31 +02:00
8 changed files with 272 additions and 50 deletions

View file

@ -4,6 +4,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/chip8_core/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/chip8_core/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/chip8_tui/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/chip8_tui/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/chip8_sdl/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

61
Cargo.lock generated
View file

@ -78,6 +78,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.6.0"
@ -111,6 +117,18 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chip8_sdl"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"emulator",
"env_logger",
"log",
"sdl2",
]
[[package]] [[package]]
name = "chip8_tui" name = "chip8_tui"
version = "0.1.0" version = "0.1.0"
@ -189,7 +207,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.6.0",
"crossterm_winapi", "crossterm_winapi",
"mio", "mio",
"parking_lot", "parking_lot",
@ -396,6 +414,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.169" version = "0.2.169"
@ -553,7 +577,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.6.0",
"cassowary", "cassowary",
"compact_str", "compact_str",
"crossterm", "crossterm",
@ -574,7 +598,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.6.0",
] ]
[[package]] [[package]]
@ -612,7 +636,7 @@ version = "0.38.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.6.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@ -637,6 +661,29 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 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]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.3.17" version = "0.3.17"
@ -759,6 +806,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version-compare"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"

View file

@ -7,4 +7,5 @@ resolver = "2"
members = [ members = [
"chip8_tui", "chip8_tui",
"chip8_core", "chip8_core",
"chip8_sdl",
] ]

View file

@ -11,3 +11,12 @@ pub trait Display {
/// Renders the display data on screen. /// Renders the display data on screen.
fn render(&mut self, display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]); fn render(&mut self, display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]);
} }
/// Simple display module for testing. Does nothing.
pub(crate) struct TestingDisplay;
impl Display for TestingDisplay {
fn clear(&mut self) {}
fn render(&mut self, _display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]) {}
}

View file

@ -485,16 +485,16 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::display::TerminalDisplay; use crate::display::TestingDisplay;
use crate::input::NoInput; use crate::input::NoInput;
use crate::sound::TerminalSound; use crate::sound::TestingSound;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use std::fs::File; use std::fs::File;
use std::io::{Seek, SeekFrom}; use std::io::{Seek, SeekFrom};
#[test] #[test]
fn test_load_font_data() { fn test_load_font_data() {
let emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
assert_eq!(emulator.memory[0xf0..0xf0 + 80], FONT_SPRITES) assert_eq!(emulator.memory[0xf0..0xf0 + 80], FONT_SPRITES)
} }
@ -509,7 +509,7 @@ mod tests {
let _ = file.seek(SeekFrom::Start(0)); let _ = file.seek(SeekFrom::Start(0));
// Test // Test
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.load_rom(file).expect("failed to load ROM"); emulator.load_rom(file).expect("failed to load ROM");
// Assert // Assert
@ -519,7 +519,7 @@ mod tests {
#[test] #[test]
fn test_execute_clear_screen_instruction() { fn test_execute_clear_screen_instruction() {
// Setup // Setup
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
for i in 10..30 { for i in 10..30 {
emulator.display_data[i] = true; emulator.display_data[i] = true;
} }
@ -538,7 +538,7 @@ mod tests {
#[test] #[test]
fn test_execute_jump() { fn test_execute_jump() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator emulator
.execute_instruction(Instruction::new([0x1A, 0xBC])) .execute_instruction(Instruction::new([0x1A, 0xBC]))
@ -549,7 +549,7 @@ mod tests {
#[test] #[test]
fn test_execute_set_register() { fn test_execute_set_register() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
for i in 0x0..=0xF { for i in 0x0..=0xF {
let random_data: u8 = rand::thread_rng().gen_range(0x00..0xFF); let random_data: u8 = rand::thread_rng().gen_range(0x00..0xFF);
@ -562,7 +562,7 @@ mod tests {
#[test] #[test]
fn test_execute_add_value_to_register() { fn test_execute_add_value_to_register() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator emulator
.execute_instruction(Instruction::new([0x71, 0xCC])) .execute_instruction(Instruction::new([0x71, 0xCC]))
@ -582,7 +582,7 @@ mod tests {
#[test] #[test]
fn test_execute_set_index_register() { fn test_execute_set_index_register() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator emulator
.execute_instruction(Instruction::new([0xAA, 0xBC])) .execute_instruction(Instruction::new([0xAA, 0xBC]))
@ -593,7 +593,7 @@ mod tests {
#[test] #[test]
fn test_execute_draw() { fn test_execute_draw() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.index_register = 0xF0; emulator.index_register = 0xF0;
emulator emulator
@ -608,7 +608,7 @@ mod tests {
#[test] #[test]
fn test_execute_call() { fn test_execute_call() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.program_counter = 0x200; emulator.program_counter = 0x200;
emulator emulator
@ -621,7 +621,7 @@ mod tests {
#[test] #[test]
fn test_execute_return() { fn test_execute_return() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.stack.push(0x269); emulator.stack.push(0x269);
emulator emulator
@ -633,7 +633,7 @@ mod tests {
#[test] #[test]
fn test_execute_set() { fn test_execute_set() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator emulator
.execute_instruction(Instruction::new([0x61, 0x40])) .execute_instruction(Instruction::new([0x61, 0x40]))
@ -644,7 +644,7 @@ mod tests {
#[test] #[test]
fn test_execute_binary_or() { fn test_execute_binary_or() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x6; emulator.registers[0x1] = 0x6;
emulator.registers[0xF] = 0x9; emulator.registers[0xF] = 0x9;
@ -657,7 +657,7 @@ mod tests {
#[test] #[test]
fn test_execute_binary_and() { fn test_execute_binary_and() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x6; emulator.registers[0x1] = 0x6;
emulator.registers[0xF] = 0x9; emulator.registers[0xF] = 0x9;
@ -670,7 +670,7 @@ mod tests {
#[test] #[test]
fn test_execute_logical_xor() { fn test_execute_logical_xor() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x7; emulator.registers[0x1] = 0x7;
emulator.registers[0xF] = 0x9; emulator.registers[0xF] = 0x9;
@ -683,7 +683,7 @@ mod tests {
#[test] #[test]
fn test_execute_logical_add() { fn test_execute_logical_add() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x7; emulator.registers[0x1] = 0x7;
emulator.registers[0xF] = 0x9; emulator.registers[0xF] = 0x9;
@ -696,7 +696,7 @@ mod tests {
#[test] #[test]
fn test_execute_logical_subtract_vx() { fn test_execute_logical_subtract_vx() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x7; emulator.registers[0x1] = 0x7;
emulator.registers[0xE] = 0x9; emulator.registers[0xE] = 0x9;
@ -709,7 +709,7 @@ mod tests {
#[test] #[test]
fn test_execute_logical_subtract_vy() { fn test_execute_logical_subtract_vy() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x7; emulator.registers[0x1] = 0x7;
emulator.registers[0xF] = 0x9; emulator.registers[0xF] = 0x9;
@ -722,7 +722,7 @@ mod tests {
#[test] #[test]
fn test_execute_logical_shift_left() { fn test_execute_logical_shift_left() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x7; emulator.registers[0x1] = 0x7;
emulator.registers[0x2] = 0x9; emulator.registers[0x2] = 0x9;
@ -735,7 +735,7 @@ mod tests {
#[test] #[test]
fn test_execute_logical_shift_right() { fn test_execute_logical_shift_right() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x1] = 0x7; emulator.registers[0x1] = 0x7;
emulator.registers[0x2] = 0x9; emulator.registers[0x2] = 0x9;
@ -748,7 +748,7 @@ mod tests {
#[test] #[test]
fn test_execute_jump_with_offset() { fn test_execute_jump_with_offset() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0x0] = 0x2; emulator.registers[0x0] = 0x2;
emulator emulator
@ -760,7 +760,7 @@ mod tests {
#[test] #[test]
fn test_execute_random_number() { fn test_execute_random_number() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator emulator
.execute_instruction(Instruction::new([0xCA, 0xBC])) .execute_instruction(Instruction::new([0xCA, 0xBC]))
@ -771,7 +771,7 @@ mod tests {
#[test] #[test]
fn test_execute_skip_equal_vx_data() { fn test_execute_skip_equal_vx_data() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xBC; emulator.registers[0xA] = 0xBC;
emulator emulator
@ -783,7 +783,7 @@ mod tests {
#[test] #[test]
fn test_execute_skip_not_equal_vx_data() { fn test_execute_skip_not_equal_vx_data() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xB1; emulator.registers[0xA] = 0xB1;
emulator emulator
@ -795,7 +795,7 @@ mod tests {
#[test] #[test]
fn test_execute_skip_equal_vx_vy() { fn test_execute_skip_equal_vx_vy() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xBC; emulator.registers[0xA] = 0xBC;
emulator.registers[0xB] = 0xBC; emulator.registers[0xB] = 0xBC;
@ -808,7 +808,7 @@ mod tests {
#[test] #[test]
fn test_execute_skip_not_equal_vx_vy() { fn test_execute_skip_not_equal_vx_vy() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xBD; emulator.registers[0xA] = 0xBD;
emulator.registers[0xB] = 0xBC; emulator.registers[0xB] = 0xBC;
@ -821,7 +821,7 @@ mod tests {
#[test] #[test]
fn test_execute_set_vx_to_delay_timer() { fn test_execute_set_vx_to_delay_timer() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.delay_timer = 0xEE; emulator.delay_timer = 0xEE;
emulator emulator
@ -833,7 +833,7 @@ mod tests {
#[test] #[test]
fn test_execute_set_delay_timer() { fn test_execute_set_delay_timer() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xEE; emulator.registers[0xA] = 0xEE;
emulator emulator
@ -845,7 +845,7 @@ mod tests {
#[test] #[test]
fn test_execute_set_sound_timer() { fn test_execute_set_sound_timer() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xEE; emulator.registers[0xA] = 0xEE;
emulator emulator
@ -857,7 +857,7 @@ mod tests {
#[test] #[test]
fn test_execute_add_to_index() { fn test_execute_add_to_index() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xEE; emulator.registers[0xA] = 0xEE;
emulator emulator
@ -869,7 +869,7 @@ mod tests {
#[test] #[test]
fn test_execute_get_font_character() { fn test_execute_get_font_character() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xEE; emulator.registers[0xA] = 0xEE;
emulator emulator
@ -881,7 +881,7 @@ mod tests {
#[test] #[test]
fn test_execute_bcd_convert() { fn test_execute_bcd_convert() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0xFE; emulator.registers[0xA] = 0xFE;
emulator emulator
@ -895,7 +895,7 @@ mod tests {
#[test] #[test]
fn test_execute_store_memory() { fn test_execute_store_memory() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.index_register = 0x20; emulator.index_register = 0x20;
for i in 0..0xF { for i in 0..0xF {
emulator.registers[i] = (0xF + i) as u8; emulator.registers[i] = (0xF + i) as u8;
@ -915,7 +915,7 @@ mod tests {
#[test] #[test]
fn test_execute_load_memory() { fn test_execute_load_memory() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.index_register = 0x20; emulator.index_register = 0x20;
for i in 0..0xF { for i in 0..0xF {
emulator.memory[(emulator.index_register + i) as usize] = (0xF + i) as u8; emulator.memory[(emulator.index_register + i) as usize] = (0xF + i) as u8;
@ -932,7 +932,7 @@ mod tests {
#[test] #[test]
fn test_execute_get_key_blocking() { fn test_execute_get_key_blocking() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.program_counter = 0x10; emulator.program_counter = 0x10;
emulator emulator
@ -950,7 +950,7 @@ mod tests {
#[test] #[test]
fn test_execute_skip_key_pressed() { fn test_execute_skip_key_pressed() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.program_counter = 0; emulator.program_counter = 0;
emulator.registers[0xA] = 0x1; emulator.registers[0xA] = 0x1;
@ -968,7 +968,7 @@ mod tests {
#[test] #[test]
fn test_execute_skip_key_not_pressed() { fn test_execute_skip_key_not_pressed() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.program_counter = 0; emulator.program_counter = 0;
emulator.registers[0xA] = 0x1; emulator.registers[0xA] = 0x1;
@ -986,7 +986,7 @@ mod tests {
#[test] #[test]
fn test_execute_set_vx_to_vy() { fn test_execute_set_vx_to_vy() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.registers[0xA] = 0; emulator.registers[0xA] = 0;
emulator.registers[0xB] = 0xEF; emulator.registers[0xB] = 0xEF;
@ -999,7 +999,7 @@ mod tests {
#[test] #[test]
fn test_fetch_instruction() { fn test_fetch_instruction() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.program_counter = 0x200; emulator.program_counter = 0x200;
emulator.memory[0x200] = 0x00; emulator.memory[0x200] = 0x00;
emulator.memory[0x201] = 0xEE; emulator.memory[0x201] = 0xEE;
@ -1017,7 +1017,7 @@ mod tests {
#[test] #[test]
fn test_handle_timers() { fn test_handle_timers() {
let mut emulator = Emulator::new(TerminalDisplay::new(), TerminalSound, NoInput); let mut emulator = Emulator::new(TestingDisplay, TestingSound, NoInput);
emulator.sound_timer = 10; emulator.sound_timer = 10;
emulator.delay_timer = 12; emulator.delay_timer = 12;
@ -1039,11 +1039,7 @@ mod tests {
} }
} }
let mut emulator = Emulator::new( let mut emulator = Emulator::new(TestingDisplay, TestSound { did_beep: false }, NoInput);
TerminalDisplay::new(),
TestSound { did_beep: false },
NoInput,
);
emulator.sound_timer = 0; emulator.sound_timer = 0;
emulator.handle_timers(); emulator.handle_timers();

View file

@ -3,3 +3,10 @@ pub trait SoundModule {
/// beep makes a beep sound. /// beep makes a beep sound.
fn beep(&mut self); fn beep(&mut self);
} }
/// A simple module for testing the sound.
pub(crate) struct TestingSound;
impl SoundModule for TestingSound {
fn beep(&mut self) {}
}

12
chip8_sdl/Cargo.toml Normal file
View file

@ -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"

143
chip8_sdl/src/main.rs Normal file
View file

@ -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<Self, anyhow::Error> {
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<u16> {
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(())
}