1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
mod config;
mod draw_thread;
mod input;
use chiprust_emu::Chip8;
use config::Config;
#[cfg(feature = "sound")]
use rodio::Sink;
use std::{sync::Arc, thread};
use parking_lot::Mutex;
use spin_sleep::LoopHelper;
static FOREGROUND_COLOR: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF];
static mut BACKGROUND_COLOR: [u8; 4] = [0x10, 0x10, 0x10, 0xFF];
#[inline(always)]
pub fn cpu_thread(chip: Arc<Mutex<Chip8>>, cpu_freq: u32) {
let loop_helper = LoopHelper::builder()
.report_interval_s(0.5);
let mut loop_helper = if cpu_freq != 0 {
loop_helper.build_with_target_rate(cpu_freq)
} else {
loop_helper.build_without_target_rate()
};
loop {
loop_helper.loop_start();
{
let mut chip = chip.lock();
chip.cpu_tick().unwrap();
};
loop_helper.loop_sleep()
}
}
#[inline(always)]
pub fn timers_thread(chip: Arc<Mutex<Chip8>>, timers_freq: u32, #[cfg(feature = "sound")] sink: Option<Sink>) {
let loop_helper = LoopHelper::builder()
.report_interval_s(0.5);
let mut loop_helper = if timers_freq != 0 {
loop_helper.build_with_target_rate(timers_freq)
} else {
loop_helper.build_without_target_rate()
};
#[cfg(feature = "sound")]
let sink = sink.unwrap();
loop {
loop_helper.loop_start();
{
let mut chip = chip.lock();
chip.timers_tick();
#[cfg(feature = "sound")]
if chip.is_sound_playing() {
sink.play()
} else {
sink.pause()
}
}
loop_helper.loop_sleep()
}
}
pub fn run() {
let config = match Config::load_args() {
Ok(v) => v,
Err(e) => {
eprintln!("{}", e);
return;
}
};
let mut chip = Chip8::new
::<&'static (dyn Fn() -> u8 + Send + Sync + 'static),
&'static (dyn Fn(u8) -> bool + Send + Sync + 'static)>
(&input::key_wait_handler, &input::key_state_handler);
chip.load(0x200, &config.program, None);
let chip = Arc::new(Mutex::new(chip));
let chip_clone = chip.clone();
let cpu_freq = config.cpu_freq;
thread::spawn(move || cpu_thread(chip_clone, cpu_freq));
let chip_clone = chip.clone();
let timers_freq = config.timers_freq;
#[cfg(feature = "sound")]
let sink = config.sink;
thread::spawn(move || timers_thread(chip_clone, timers_freq, #[cfg(feature = "sound")] sink));
draw_thread::draw_thread(chip, config.draw_freq)
}