Compare commits
2 commits
9a360be045
...
86680d85a3
Author | SHA1 | Date | |
---|---|---|---|
86680d85a3 | |||
86acbf6fc8 |
8 changed files with 272 additions and 50 deletions
|
@ -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
61
Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -7,4 +7,5 @@ resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"chip8_tui",
|
"chip8_tui",
|
||||||
"chip8_core",
|
"chip8_core",
|
||||||
|
"chip8_sdl",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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]) {}
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
12
chip8_sdl/Cargo.toml
Normal 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
143
chip8_sdl/src/main.rs
Normal 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(())
|
||||||
|
}
|
Loading…
Reference in a new issue