diff --git a/src/bin/chirp-disasm/main.rs b/src/bin/chirp-disasm/main.rs index 0c8a893..fa0ac8f 100644 --- a/src/bin/chirp-disasm/main.rs +++ b/src/bin/chirp-disasm/main.rs @@ -1,4 +1,4 @@ -use chirp::{cpu::Disassembler, error::Result, prelude::*}; +use chirp::{cpu::Disassembler, error::Result, *}; use gumdrop::*; use owo_colors::OwoColorize; use std::{fs::read, path::PathBuf}; diff --git a/src/bin/chirp-iced/main.rs b/src/bin/chirp-iced/main.rs index 5cd4a4e..e5dd2c5 100644 --- a/src/bin/chirp-iced/main.rs +++ b/src/bin/chirp-iced/main.rs @@ -1,5 +1,5 @@ #![allow(unused_imports)] -use chirp::prelude::*; +use chirp::*; #[cfg(features = "iced")] use iced::{ executor, time, window, Alignment, Application, Command, Element, Length, Settings, diff --git a/src/bin/chirp-minifb/main.rs b/src/bin/chirp-minifb/main.rs index fbc6850..dca6b2f 100644 --- a/src/bin/chirp-minifb/main.rs +++ b/src/bin/chirp-minifb/main.rs @@ -4,19 +4,20 @@ //! Chirp: A chip-8 interpreter in Rust //! Hello, world! -mod io; #[cfg(test)] mod tests; +mod ui; -use chirp::{error::Result, prelude::*}; +use chirp::error::Error::BreakpointHit; +use chirp::{error::Result, *}; use gumdrop::*; -use io::*; use owo_colors::OwoColorize; use std::fs::read; use std::{ path::PathBuf, time::{Duration, Instant}, }; +use ui::*; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Options, Hash)] struct Arguments { @@ -136,10 +137,10 @@ impl State { state.ch8.bus.write(0x1feu16, options.data); Ok(state) } - fn keys(&mut self) -> Result> { + fn keys(&mut self) -> Result { self.ui.keys(&mut self.ch8) } - fn frame(&mut self) -> Option<()> { + fn frame(&mut self) -> Result { self.ui.frame(&mut self.ch8) } fn tick_cpu(&mut self) -> Result<()> { @@ -180,14 +181,23 @@ impl Iterator for State { fn next(&mut self) -> Option { self.wait_for_next_frame(); match self.keys() { - Ok(opt) => opt?, - Err(e) => return Some(Err(e)), // summary + Ok(opt) if !opt => return None, + Err(e) => return Some(Err(e)), // summary lol + _ => (), } - self.keys().unwrap_or(None)?; - if let Err(e) = self.tick_cpu() { - return Some(Err(e)); + // Allow breakpoint hit messages + match self.tick_cpu() { + Err(BreakpointHit { addr, next }) => { + eprintln!("Breakpoint hit: {:3x} ({:4x})", addr, next); + } + Err(e) => return Some(Err(e)), + _ => (), + } + match self.frame() { + Ok(opt) if !opt => return None, + Err(e) => return Some(Err(e)), + _ => (), } - self.frame()?; Some(Ok(())) } } diff --git a/src/bin/chirp-minifb/tests.rs b/src/bin/chirp-minifb/tests.rs index 27d70df..23104f7 100644 --- a/src/bin/chirp-minifb/tests.rs +++ b/src/bin/chirp-minifb/tests.rs @@ -1,7 +1,7 @@ //! Tests for chirp-minifb -use super::io::*; -use chirp::prelude::*; +use super::ui::*; +use chirp::*; use std::{collections::hash_map::DefaultHasher, hash::Hash}; mod ui_builder { diff --git a/src/bin/chirp-minifb/io.rs b/src/bin/chirp-minifb/ui.rs similarity index 85% rename from src/bin/chirp-minifb/io.rs rename to src/bin/chirp-minifb/ui.rs index 08f6b60..5a72c36 100644 --- a/src/bin/chirp-minifb/io.rs +++ b/src/bin/chirp-minifb/ui.rs @@ -104,7 +104,7 @@ impl FrameBuffer { format: Default::default(), } } - pub fn render(&mut self, window: &mut Window, bus: &Bus) { + pub fn render(&mut self, window: &mut Window, bus: &Bus) -> Result<()> { if let Some(screen) = bus.get_region(Region::Screen) { for (idx, byte) in screen.iter().enumerate() { for bit in 0..8 { @@ -116,10 +116,8 @@ impl FrameBuffer { } } } - //TODO: NOT THIS - window - .update_with_buffer(&self.buffer, self.width, self.height) - .expect("The window manager should update the buffer."); + window.update_with_buffer(&self.buffer, self.width, self.height)?; + Ok(()) } } @@ -139,27 +137,25 @@ pub struct UI { } impl UI { - pub fn frame(&mut self, ch8: &mut Chip8) -> Option<()> { - { - if ch8.cpu.flags.pause { - self.window.set_title("Chirp ⏸") - } else { - self.window.set_title(&format!( - "Chirp ▶ {:02.02}", - (1.0 / self.time.elapsed().as_secs_f64()) - )); - } - if !self.window.is_open() { - std::process::exit(0); - } - self.time = Instant::now(); - // update framebuffer - self.fb.render(&mut self.window, &ch8.bus); + pub fn frame(&mut self, ch8: &mut Chip8) -> Result { + if ch8.cpu.flags.pause { + self.window.set_title("Chirp ⏸") + } else { + self.window.set_title(&format!( + "Chirp ▶ {:02.02}", + (1.0 / self.time.elapsed().as_secs_f64()) + )); } - Some(()) + if !self.window.is_open() { + return Ok(false); + } + self.time = Instant::now(); + // update framebuffer + self.fb.render(&mut self.window, &ch8.bus)?; + Ok(true) } - pub fn keys(&mut self, ch8: &mut Chip8) -> Result> { + pub fn keys(&mut self, ch8: &mut Chip8) -> Result { // TODO: Remove this hacky workaround for minifb's broken get_keys_* functions. let get_keys_pressed = || { self.window @@ -173,7 +169,7 @@ impl UI { .into_iter() .filter(|key| !self.window.get_keys().contains(key)) }; - use crate::io::Region::*; + use crate::ui::Region::*; for key in get_keys_released() { if let Some(key) = identify_key(key) { ch8.cpu.release(key)?; @@ -184,10 +180,7 @@ impl UI { use Key::*; match key { F1 | Comma => ch8.cpu.dump(), - F2 | Period => ch8 - .bus - .print_screen() - .expect("The 'screen' memory region should exist"), + F2 | Period => ch8.bus.print_screen()?, F3 => { debug_dump_screen(ch8, &self.rom).expect("Unable to write debug screen dump"); } @@ -226,7 +219,7 @@ impl UI { ch8.cpu.soft_reset(); ch8.bus.clear_region(Screen); } - Escape => return Ok(None), + Escape => return Ok(false), key => { if let Some(key) = identify_key(key) { ch8.cpu.press(key)?; @@ -235,7 +228,7 @@ impl UI { } } self.keyboard = self.window.get_keys(); - Ok(Some(())) + Ok(true) } } diff --git a/src/bin/chirp-shot-viewer/main.rs b/src/bin/chirp-shot-viewer/main.rs index e03c6a5..91b14a6 100644 --- a/src/bin/chirp-shot-viewer/main.rs +++ b/src/bin/chirp-shot-viewer/main.rs @@ -1,4 +1,4 @@ -use chirp::{error::Result, prelude::*}; +use chirp::{error::Result, *}; use std::{env::args, fs::read}; fn main() -> Result<()> { diff --git a/src/bus.rs b/src/bus.rs index b9eb5ff..f330009 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -15,7 +15,7 @@ use std::{ /// Creates a new bus, growing the backing memory as needed /// # Examples /// ```rust -/// # use chirp::prelude::*; +/// # use chirp::*; /// let mut bus = bus! { /// Stack [0x0000..0x0800] = b"ABCDEF", /// Program [0x0800..0x1000] = include_bytes!("bus.rs"), @@ -92,7 +92,7 @@ impl Bus { /// Constructs a new bus /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new(); /// assert!(bus.is_empty()); @@ -106,7 +106,7 @@ impl Bus { /// Gets the length of the bus' backing memory /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Program, 0..1234); @@ -121,7 +121,7 @@ impl Bus { /// Returns true if the backing memory contains no elements /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new(); /// assert!(bus.is_empty()); @@ -134,7 +134,7 @@ impl Bus { /// Grows the Bus backing memory to at least size bytes, but does not truncate /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let mut bus = Bus::new(); /// bus.with_size(1234); @@ -152,7 +152,7 @@ impl Bus { /// Adds a new named range (Region) to the bus /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new().add_region(Program, 0..1234); /// assert_eq!(1234, bus.len()); @@ -169,7 +169,7 @@ impl Bus { /// Loads data into a named region /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Program, 0..1234) @@ -188,7 +188,7 @@ impl Bus { /// Fills a named region with zeroes /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Program, 0..1234) @@ -199,7 +199,7 @@ impl Bus { /// ``` /// If the region doesn't exist, that's okay. /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Program, 0..1234) @@ -218,7 +218,7 @@ impl Bus { /// Gets a slice of bus memory /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Program, 0..10); @@ -236,7 +236,7 @@ impl Bus { /// Gets a mutable slice of bus memory /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let mut bus = Bus::new() /// .add_region(Program, 0..10); @@ -254,7 +254,7 @@ impl Bus { /// Gets a slice of a named region of memory /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Program, 0..10); @@ -269,7 +269,7 @@ impl Bus { /// Gets a mutable slice of a named region of memory /// # Examples /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let mut bus = Bus::new() /// .add_region(Program, 0..10); @@ -286,7 +286,7 @@ impl Bus { /// /// [Bus::print_screen] will print the screen /// ```rust - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let bus = Bus::new() /// .add_region(Screen, 0x000..0x100); @@ -296,7 +296,7 @@ impl Bus { /// ``` /// If there is no Screen region, it will return Err([MissingRegion]) /// ```rust,should_panic - ///# use chirp::prelude::*; + ///# use chirp::*; ///# fn main() -> Result<()> { /// let mut bus = Bus::new() /// .add_region(Program, 0..10); diff --git a/src/cpu.rs b/src/cpu.rs index 1c4f680..e282b7e 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -95,7 +95,7 @@ impl ControlFlags { /// /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(true, cpu.flags.debug); /// // Toggle debug mode @@ -110,7 +110,7 @@ impl ControlFlags { /// /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(false, cpu.flags.pause); /// // Pause the cpu @@ -169,7 +169,7 @@ impl CPU { /// Constructs a new CPU, taking all configurable parameters /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let cpu = CPU::new( /// 0xf00, // screen location /// 0x50, // font location @@ -207,7 +207,7 @@ impl CPU { /// /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// /// // press key `7` @@ -238,7 +238,7 @@ impl CPU { /// and the [ControlFlags::lastkey] is recorded. /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// // press key `7` /// cpu.press(0x7).unwrap(); @@ -269,7 +269,7 @@ impl CPU { /// If the register doesn't exist, returns [Error::InvalidRegister] /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// // Create a new CPU, and set v4 to 0x41 /// let mut cpu = CPU::default(); /// cpu.set_v(0x4, 0x41).unwrap(); @@ -288,7 +288,7 @@ impl CPU { /// Gets a slice of the entire general purpose registers /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// // Create a new CPU, and set v4 to 0x41 /// let mut cpu = CPU::default(); /// cpu.set_v(0x0, 0x41); @@ -304,7 +304,7 @@ impl CPU { /// Gets the program counter /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(0x200, cpu.pc()); /// ``` @@ -315,7 +315,7 @@ impl CPU { /// Gets the I register /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(0, cpu.i()); /// ``` @@ -326,7 +326,7 @@ impl CPU { /// Gets the value in the Sound Timer register /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(0, cpu.sound()); /// ``` @@ -337,7 +337,7 @@ impl CPU { /// Gets the value in the Delay Timer register /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(0, cpu.delay()); /// ``` @@ -351,7 +351,7 @@ impl CPU { /// updated even when the CPU is in drawpause or keypause /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(0x0, cpu.cycle()); /// ``` @@ -363,7 +363,7 @@ impl CPU { /// reinitializing the program counter to 0x200 /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::new( /// 0xf00, /// 0x50, @@ -416,7 +416,7 @@ impl CPU { /// Gets a slice of breakpoints /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// assert_eq!(cpu.breakpoints(), &[]); /// ``` @@ -433,7 +433,7 @@ impl CPU { /// NOTE: does not synchronize with delay timers /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// let mut bus = bus!{ /// Program [0x0200..0x0f00] = &[ @@ -459,7 +459,7 @@ impl CPU { /// Ticks the timers every `rate` ticks /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// let mut bus = bus!{ /// Program [0x0200..0x0f00] = &[ @@ -524,7 +524,7 @@ impl CPU { /// Executes a single instruction /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// let mut bus = bus!{ /// Program [0x0200..0x0f00] = &[ @@ -540,7 +540,7 @@ impl CPU { /// ``` /// Returns [Error::UnimplementedInstruction] if the instruction is not implemented. /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// # use chirp::error::Error; /// let mut cpu = CPU::default(); /// # cpu.flags.debug = true; // enable live disassembly @@ -610,7 +610,7 @@ impl CPU { /// Dumps the current state of all CPU registers, and the cycle count /// # Examples /// ```rust - /// # use chirp::prelude::*; + /// # use chirp::*; /// let mut cpu = CPU::default(); /// cpu.dump(); /// ``` @@ -663,7 +663,7 @@ impl Default for CPU { /// /// # Examples /// ```rust - /// use chirp::prelude::*; + /// use chirp::*; /// let mut cpu = CPU::default(); /// ``` fn default() -> Self { @@ -689,9 +689,6 @@ impl Default for CPU { } } -// Below this point, comments may be duplicated per impl' block, -// since some opcodes handle multiple instructions. - impl CPU { /// Executes a single [Insn] #[inline(always)] @@ -736,6 +733,9 @@ impl CPU { } } +// Below this point, comments may be duplicated per impl' block, +// since some opcodes handle multiple instructions. + // |`0aaa`| Issues a "System call" (ML routine) // // |opcode| effect | diff --git a/src/lib.rs b/src/lib.rs index f4c6a79..b2db64b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,15 +12,10 @@ pub mod bus; pub mod cpu; pub mod error; -/// Common imports for Chirp -pub mod prelude { - pub use super::Chip8; - use super::*; - pub use crate::bus; - pub use bus::{Bus, Read, Region::*, Write}; - pub use cpu::{disassembler::Dis, ControlFlags, CPU}; - pub use error::Result; -} +// Common imports for Chirp +pub use bus::{Bus, Read, Region::*, Write}; +pub use cpu::{disassembler::Dis, ControlFlags, CPU}; +pub use error::Result; /// Holds the state of a Chip-8 #[derive(Clone, Debug, Default, PartialEq)] diff --git a/tests/chip8_test_suite.rs b/tests/chip8_test_suite.rs index ae3b2e0..5310c7d 100644 --- a/tests/chip8_test_suite.rs +++ b/tests/chip8_test_suite.rs @@ -1,6 +1,6 @@ //! These are a series of interpreter tests using Timendus's incredible test suite -pub use chirp::prelude::*; +pub use chirp::*; fn setup_environment() -> (CPU, Bus) { let mut cpu = CPU::default(); diff --git a/tests/integration.rs b/tests/integration.rs index 7ec5630..14003aa 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,5 +1,5 @@ //! Testing methods on Chirp's public API -use chirp::prelude::*; +use chirp::*; use std::{collections::hash_map::DefaultHasher, hash::Hash}; #[test]