mirror of
https://github.com/danbulant/chip8
synced 2026-07-06 03:30:54 +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 = [
|
dependencies = [
|
||||||
"debug_print",
|
"debug_print",
|
||||||
"rand",
|
"rand",
|
||||||
|
"spin_sleep",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -39,6 +40,12 @@ version = "0.2.139"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
|
@ -75,8 +82,40 @@ dependencies = [
|
||||||
"getrandom",
|
"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]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
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]
|
[dependencies]
|
||||||
rand = "0.8.5"
|
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::env::args;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use debug_print::{debug_eprint, debug_eprintln};
|
use debug_print::{debug_eprint, debug_eprintln};
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
RenderOnClsOnly = 1,
|
||||||
|
DelayWait = 2
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file_path = args().nth(1);
|
let file_path = args().nth(1);
|
||||||
match file_path {
|
match file_path {
|
||||||
|
|
@ -12,14 +18,18 @@ fn main() {
|
||||||
Some(file_path) => {
|
Some(file_path) => {
|
||||||
let mut file = File::open(file_path).unwrap();
|
let mut file = File::open(file_path).unwrap();
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
println!("read");
|
|
||||||
file.read_to_end(&mut data).unwrap();
|
file.read_to_end(&mut data).unwrap();
|
||||||
|
|
||||||
println!("init");
|
|
||||||
let mut chip8 = Chip8::new();
|
let mut chip8 = Chip8::new();
|
||||||
println!("loading");
|
|
||||||
chip8.load_rom(data);
|
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 {
|
loop {
|
||||||
chip8.run_next();
|
chip8.run_next();
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +59,11 @@ struct Chip8 {
|
||||||
/// graphics (64x32 black and white)
|
/// graphics (64x32 black and white)
|
||||||
display: [[bool; HEIGHT]; WIDTH],
|
display: [[bool; HEIGHT]; WIDTH],
|
||||||
// start_time: Instant,
|
// start_time: Instant,
|
||||||
last_processed_timers: Instant
|
last_processed_timers: Instant,
|
||||||
|
|
||||||
|
display_changed: bool,
|
||||||
|
|
||||||
|
flags: u8
|
||||||
}
|
}
|
||||||
|
|
||||||
const WIDTH: usize = 64;
|
const WIDTH: usize = 64;
|
||||||
|
|
@ -67,7 +81,9 @@ impl Chip8 {
|
||||||
sound_timer: 0,
|
sound_timer: 0,
|
||||||
display: [[false; HEIGHT]; WIDTH],
|
display: [[false; HEIGHT]; WIDTH],
|
||||||
// start_time: Instant::now(),
|
// start_time: Instant::now(),
|
||||||
last_processed_timers: Instant::now()
|
last_processed_timers: Instant::now(),
|
||||||
|
display_changed: false,
|
||||||
|
flags: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// initialize font
|
// initialize font
|
||||||
|
|
@ -128,6 +144,9 @@ impl Chip8 {
|
||||||
// syscalls
|
// syscalls
|
||||||
if current == 0x00e0 {
|
if current == 0x00e0 {
|
||||||
debug_eprintln!("CLS");
|
debug_eprintln!("CLS");
|
||||||
|
if self.display_changed {
|
||||||
|
self.render();
|
||||||
|
}
|
||||||
self.display = [[false; HEIGHT]; WIDTH];
|
self.display = [[false; HEIGHT]; WIDTH];
|
||||||
} else if current == 0x00ee {
|
} else if current == 0x00ee {
|
||||||
if self.stack.is_empty() {
|
if self.stack.is_empty() {
|
||||||
|
|
@ -248,7 +267,7 @@ impl Chip8 {
|
||||||
let x = (x as usize + b as usize) % WIDTH;
|
let x = (x as usize + b as usize) % WIDTH;
|
||||||
// println!("x{x} y{y}");
|
// println!("x{x} y{y}");
|
||||||
self.display[x][y] ^= (sprite_row & (1 << (7-b))) > 0;
|
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!("");
|
// println!("");
|
||||||
if self.v[0xF] == 0 {
|
if self.v[0xF] == 0 {
|
||||||
self.v[0xF] = if self.display[x][y] && (sprite_row & (1 << (7-b))) > 0 { 1 } else { 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");
|
self.display_changed = true;
|
||||||
|
|
||||||
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");
|
|
||||||
} else if first == 0xE {
|
} else if first == 0xE {
|
||||||
// Keyboard operations
|
// Keyboard operations
|
||||||
|
|
||||||
|
|
@ -290,6 +300,10 @@ impl Chip8 {
|
||||||
} else if last_two == 0x15 {
|
} else if last_two == 0x15 {
|
||||||
debug_eprintln!("delay(V{second}) (V{second}={:#x}={})", self.v[second as usize], self.v[second as usize]);
|
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];
|
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 {
|
} else if last_two == 0x18 {
|
||||||
debug_eprintln!("sound({second})");
|
debug_eprintln!("sound({second})");
|
||||||
self.sound_timer = self.v[second as usize];
|
self.sound_timer = self.v[second as usize];
|
||||||
|
|
@ -329,18 +343,38 @@ impl Chip8 {
|
||||||
panic!("Halted (Program counter over ROM length)");
|
panic!("Halted (Program counter over ROM length)");
|
||||||
}
|
}
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if now - self.last_processed_timers > Duration::from_millis(16) {
|
if now - self.last_processed_timers >= Duration::from_millis(15) {
|
||||||
// println!("Processing timers");
|
debug_eprintln!("Processing timers (duration: {:?})", now - self.last_processed_timers);
|
||||||
if self.sound_timer > 0 {
|
if self.sound_timer > 0 {
|
||||||
print!("\x07");
|
print!("\x07");
|
||||||
self.sound_timer -= 1;
|
self.sound_timer -= 1;
|
||||||
}
|
}
|
||||||
if self.delay_timer > 0 {
|
if self.delay_timer > 0 {
|
||||||
|
debug_eprint!("delay_timer: {} - 1 => ", self.delay_timer);
|
||||||
self.delay_timer -= 1;
|
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 {
|
} else {
|
||||||
// println!("Skipping timers, duration: {:?}", now - self.last_processed_timers);
|
// 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