diff --git a/Cargo.lock b/Cargo.lock index f5ed706..5661777 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,7 @@ version = "0.1.0" dependencies = [ "debug_print", "rand", + "spin_sleep", ] [[package]] @@ -39,6 +40,12 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -75,8 +82,40 @@ dependencies = [ "getrandom", ] +[[package]] +name = "spin_sleep" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cafa7900db085f4354dbc7025e25d7a839a14360ea13b5fc4fd717f2d3b23134" +dependencies = [ + "once_cell", + "winapi", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index dd5a277..1c54b03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] rand = "0.8.5" -debug_print = "1.0.0" \ No newline at end of file +debug_print = "1.0.0" +spin_sleep = "1.1.1" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 7dd14c2..a567c49 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,16 @@ use std::env::args; use std::fs::File; use std::io::{Read, Write}; +use std::thread; use std::time::{Duration, Instant}; use rand::prelude::*; use debug_print::{debug_eprint, debug_eprintln}; +enum Flags { + RenderOnClsOnly = 1, + DelayWait = 2 +} + fn main() { let file_path = args().nth(1); match file_path { @@ -12,14 +18,18 @@ fn main() { Some(file_path) => { let mut file = File::open(file_path).unwrap(); let mut data = Vec::new(); - println!("read"); file.read_to_end(&mut data).unwrap(); - println!("init"); let mut chip8 = Chip8::new(); - println!("loading"); chip8.load_rom(data); - println!("loaded"); + + if args().any(|x| x == "--render-on-cls-only") { + chip8.flags |= Flags::RenderOnClsOnly as u8; + } + if args().any(|x| x == "--delay-wait") { + chip8.flags |= Flags::DelayWait as u8; + } + loop { chip8.run_next(); } @@ -49,7 +59,11 @@ struct Chip8 { /// graphics (64x32 black and white) display: [[bool; HEIGHT]; WIDTH], // start_time: Instant, - last_processed_timers: Instant + last_processed_timers: Instant, + + display_changed: bool, + + flags: u8 } const WIDTH: usize = 64; @@ -67,7 +81,9 @@ impl Chip8 { sound_timer: 0, display: [[false; HEIGHT]; WIDTH], // start_time: Instant::now(), - last_processed_timers: Instant::now() + last_processed_timers: Instant::now(), + display_changed: false, + flags: 0 }; // initialize font @@ -128,6 +144,9 @@ impl Chip8 { // syscalls if current == 0x00e0 { debug_eprintln!("CLS"); + if self.display_changed { + self.render(); + } self.display = [[false; HEIGHT]; WIDTH]; } else if current == 0x00ee { if self.stack.is_empty() { @@ -248,7 +267,7 @@ impl Chip8 { let x = (x as usize + b as usize) % WIDTH; // println!("x{x} y{y}"); self.display[x][y] ^= (sprite_row & (1 << (7-b))) > 0; - // print!("{}", if (sprite_row & (1 << (7-b))) > 0 { "█" } else { " " }); + // debug_eprint!("{}", if (sprite_row & (1 << (7-b))) > 0 { "█" } else { " " }); // println!(""); if self.v[0xF] == 0 { self.v[0xF] = if self.display[x][y] && (sprite_row & (1 << (7-b))) > 0 { 1 } else { 0 }; @@ -256,16 +275,7 @@ impl Chip8 { } } - debug_eprintln!("\n-----------------------------------\n"); - - for y in 0..HEIGHT { - for x in 0..WIDTH { - // println!("x{x} y{y}"); - print!("{}", if self.display[x][y] { "█" } else { " " }); - } - println!(); - } - debug_eprintln!("\n-----------------------------------\n"); + self.display_changed = true; } else if first == 0xE { // Keyboard operations @@ -290,6 +300,10 @@ impl Chip8 { } else if last_two == 0x15 { debug_eprintln!("delay(V{second}) (V{second}={:#x}={})", self.v[second as usize], self.v[second as usize]); self.delay_timer = self.v[second as usize]; + if self.flags & Flags::DelayWait as u8 != 0 { + spin_sleep::sleep(Duration::from_millis((1000 / 60) * (self.v[second as usize] as u64))); + self.delay_timer = 0; + } } else if last_two == 0x18 { debug_eprintln!("sound({second})"); self.sound_timer = self.v[second as usize]; @@ -329,18 +343,38 @@ impl Chip8 { panic!("Halted (Program counter over ROM length)"); } let now = Instant::now(); - if now - self.last_processed_timers > Duration::from_millis(16) { - // println!("Processing timers"); + if now - self.last_processed_timers >= Duration::from_millis(15) { + debug_eprintln!("Processing timers (duration: {:?})", now - self.last_processed_timers); if self.sound_timer > 0 { print!("\x07"); self.sound_timer -= 1; } if self.delay_timer > 0 { + debug_eprint!("delay_timer: {} - 1 => ", self.delay_timer); self.delay_timer -= 1; - // println!("delay_timer: {}", self.delay_timer); + debug_eprintln!("{}", self.delay_timer); } + self.last_processed_timers = now; + + if self.display_changed && self.flags & Flags::RenderOnClsOnly as u8 == 0 { self.render(); } } else { // println!("Skipping timers, duration: {:?}", now - self.last_processed_timers); } + // thread::sleep(Duration::from_micros(50)); + } + + fn render(&mut self) { + debug_eprintln!("\n-----------------------------------\n"); + + for y in 0..HEIGHT { + for x in 0..WIDTH { + // println!("x{x} y{y}"); + print!("{}", if self.display[x][y] { "█" } else { " " }); + } + println!(); + } + debug_eprintln!("\n-----------------------------------\n"); + + self.display_changed = false; } } \ No newline at end of file