chirp-minifb: Propagate errors up to main

This commit is contained in:
John 2023-03-30 10:46:35 -05:00
parent c1f457814d
commit 627511282a
4 changed files with 39 additions and 22 deletions

View File

@ -6,6 +6,7 @@
use chirp::{error::Result, prelude::*};
use gumdrop::*;
use owo_colors::OwoColorize;
use std::fs::read;
use std::{
path::PathBuf,
@ -23,11 +24,12 @@ struct Arguments {
#[options(help = "Enable pause mode at startup.")]
pub pause: bool,
#[options(help = "Set the instructions-per-frame rate.")]
#[options(help = "Set the instructions-per-delay rate, or use realtime.")]
pub speed: Option<usize>,
#[options(help = "Run the emulator as fast as possible for `step` instructions.")]
#[options(help = "Set the instructions-per-frame rate.")]
pub step: Option<usize>,
#[options(help = "Enable performance benchmarking on stderr (requires -S)")]
pub perf: bool,
#[options(
short = "z",
help = "Disable setting vF to 0 after a bitwise operation."
@ -77,6 +79,7 @@ struct State {
pub speed: usize,
pub step: Option<usize>,
pub rate: u64,
pub perf: bool,
pub ch8: Chip8,
pub ui: UI,
pub ft: Instant,
@ -88,6 +91,7 @@ impl State {
speed: options.speed.unwrap_or(8),
step: options.step,
rate: options.frame_rate,
perf: options.perf,
ch8: Chip8 {
bus: bus! {
// Load the charset into ROM
@ -140,6 +144,7 @@ impl State {
Some(ticks) => {
let time = Instant::now();
self.ch8.cpu.multistep(&mut self.ch8.bus, ticks)?;
if self.perf {
let time = time.elapsed();
let nspt = time.as_secs_f64() / ticks as f64;
eprintln!(
@ -147,9 +152,7 @@ impl State {
nspt * 1_000_000_000.0,
((1.0 / 60.0f64) / nspt).trunc(),
);
// Pause the CPU and clear step
//self.ch8.cpu.flags.pause = true;
//self.step = None;
}
}
None => {
self.ch8.cpu.multistep(&mut self.ch8.bus, rate)?;
@ -166,21 +169,33 @@ impl State {
}
impl Iterator for State {
type Item = ();
type Item = Result<()>;
/// Pretty heavily abusing iterators here, in an annoying way
fn next(&mut self) -> Option<Self::Item> {
self.wait_for_next_frame();
self.keys().unwrap_or_else(|_| None)?;
self.tick_cpu().ok()?;
self.frame();
Some(())
match self.keys() {
Ok(opt) => opt?,
Err(e) => return Some(Err(e)), // summary
}
self.keys().unwrap_or(None)?;
if let Err(e) = self.tick_cpu() {
return Some(Err(e));
}
self.frame()?;
Some(Ok(()))
}
}
fn main() -> Result<()> {
let options = Arguments::parse_args_default_or_exit();
let state = State::new(options)?;
Ok(for _ in state {})
Ok(for result in state {
if let Err(e) = result {
eprintln!("{}", e.bold().red());
break;
}
})
}
/// Parses a hexadecimal string into a u16

View File

@ -580,7 +580,6 @@ impl CPU {
};
// Print opcode disassembly:
if self.flags.debug {
println!("{:?}", self.timers.insn.elapsed().bright_black());
self.timers.insn = Instant::now();

View File

@ -15,7 +15,7 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
/// Represents an unimplemented operation
#[error("Unrecognized opcode {word}")]
#[error("Unrecognized opcode: {word:04x}")]
UnimplementedInstruction {
/// The offending word
word: u16,
@ -27,7 +27,7 @@ pub enum Error {
region: Region,
},
/// Tried to fetch [Range] from bus, received nothing
#[error("Invalid range {range:?} for bus")]
#[error("Invalid range {range:04x?} for bus")]
InvalidBusRange {
/// The offending [Range]
range: Range<usize>,

View File

@ -151,6 +151,9 @@ impl UI {
(1.0 / self.time.elapsed().as_secs_f64()).trunc()
));
}
if !self.window.is_open() {
std::process::exit(0);
}
self.time = Instant::now();
// update framebuffer
self.fb.render(&mut self.window, &mut ch8.bus);