mirror of
https://github.com/danbulant/chip8
synced 2026-05-19 03:48:32 +00:00
more efficient rendering, improved delay timers
This commit is contained in:
parent
0ee20edd71
commit
41ed39f797
3 changed files with 95 additions and 21 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
debug_print = "1.0.0"
|
||||
debug_print = "1.0.0"
|
||||
spin_sleep = "1.1.1"
|
||||
74
src/main.rs
74
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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue