v0.1.1 Partial Super Chip Support #11

Merged
j merged 12 commits from schip into main 2023-04-15 04:00:41 +00:00
12 changed files with 77 additions and 40 deletions
Showing only changes of commit 43fa623da3 - Show all commits

View File

@ -1,18 +1,40 @@
[package] [package]
name = "chirp" name = "chirp"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
ignore = ["justfile", ".gitmodules", "chip8-test-suite", "chip8Archive"]
default-run = "chirp"
authors = ["John Breaux"] authors = ["John Breaux"]
license = "MIT" license = "MIT"
publish = false
[features] [features]
default = ["unstable", "drawille"] default = ["unstable", "drawille", "minifb"]
unstable = [] unstable = []
drawille = ["dep:drawille"] drawille = ["dep:drawille"]
iced = ["dep:iced"] iced = ["dep:iced"]
minifb = ["dep:minifb"]
rhexdump = ["dep:rhexdump"] rhexdump = ["dep:rhexdump"]
serde = ["dep:serde"] serde = ["dep:serde"]
[[bin]]
name = "chirp"
path = "src/bin/chirp-minifb/main.rs"
required-features = ["minifb"]
[[bin]]
name = "chirp-disasm"
required-features = ["default"]
[[bin]]
name = "chirp-iced"
required-features = ["iced"]
[[bin]]
name = "chirp-shot-viewer"
required-features = ["default", "drawille"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release] [profile.release]
opt-level = 3 opt-level = 3
@ -31,10 +53,10 @@ drawille = {version = "0.3.0", optional = true}
iced = {version = "0.8.0", optional = true} iced = {version = "0.8.0", optional = true}
rhexdump = {version = "^0.1.1", optional = true } rhexdump = {version = "^0.1.1", optional = true }
serde = { version = "^1.0", features = ["derive"], optional = true } serde = { version = "^1.0", features = ["derive"], optional = true }
minifb = { version = "^0.24.0", optional = true }
gumdrop = "^0.8.1" gumdrop = "^0.8.1"
imperative-rs = "0.3.1" imperative-rs = "0.3.1"
minifb = { version = "^0.24.0" }
owo-colors = "^3" owo-colors = "^3"
rand = "^0.8.5" rand = "^0.8.5"
thiserror = "^1.0.39" thiserror = "^1.0.39"

View File

@ -8,19 +8,19 @@ test:
cargo nextest run cargo nextest run
run rom: run rom:
cargo run --bin chirp-minifb -- '{{rom}}' cargo run -- '{{rom}}'
debug rom: debug rom:
cargo run --bin chirp-minifb -- -d '{{rom}}' cargo run -- -d '{{rom}}'
# Run at 2100000 instructions per frame, and output per-frame runtime statistics # Run at 2100000 instructions per frame, and output per-frame runtime statistics
bench: bench:
cargo run --bin chirp-minifb --release -- chip8Archive/roms/1dcell.ch8 -Ps10 -S2100000 -m xochip cargo run --release -- chip8Archive/roms/1dcell.ch8 -Ps10 -S2100000 -m xochip
flame rom: flame rom:
CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -F 15300 --open --bin chirp-minifb -- '{{rom}}' -s10 CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -F 15300 --open --bin chirp-minifb -- '{{rom}}' -s10
flamebench: flamebench:
CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -F 15300 --open --bin chirp-minifb -- chip8Archive/roms/1dcell.ch8 -xPs10 -S2100000 CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -F 15300 --open --bin chirp-minifb -- chip8Archive/roms/1dcell.ch8 -Ps10 -S2100000 -m xochip
cover: cover:
cargo llvm-cov --open --doctests cargo llvm-cov --open --doctests

View File

@ -66,6 +66,7 @@ Optional arguments:
## TODO: ## TODO:
- [ ] Move the screen, stack, charset, and program memory into the CPU
- [ ] Implement sound - [ ] Implement sound
- [ ] Finish unit tests for "quirks" - [ ] Finish unit tests for "quirks"
- [ ] Make pausing/unpausing the emulator less messy - [ ] Make pausing/unpausing the emulator less messy

View File

@ -1,24 +1,8 @@
use chirp::{cpu::Disassembler, error::Result, *}; use chirp::{error::Result, *};
use gumdrop::*; use gumdrop::*;
use owo_colors::OwoColorize; use owo_colors::OwoColorize;
use std::{fs::read, path::PathBuf}; use std::{fs::read, path::PathBuf};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Options, Hash)]
struct Arguments {
#[options(help = "Show help text")]
help: bool,
#[options(help = "Load a ROM to run on Chirp", free, required)]
pub file: PathBuf,
#[options(help = "Load address (usually 200)", parse(try_from_str = "parse_hex"))]
pub loadaddr: u16,
#[options(help = "Start disassembling at offset...")]
pub offset: usize,
}
fn parse_hex(value: &str) -> std::result::Result<u16, std::num::ParseIntError> {
u16::from_str_radix(value, 16)
}
fn main() -> Result<()> { fn main() -> Result<()> {
let options = Arguments::parse_args_default_or_exit(); let options = Arguments::parse_args_default_or_exit();
let contents = &read(&options.file)?; let contents = &read(&options.file)?;
@ -40,3 +24,19 @@ fn main() -> Result<()> {
} }
Ok(()) Ok(())
} }
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Options, Hash)]
struct Arguments {
#[options(help = "Show help text")]
help: bool,
#[options(help = "Load a ROM to run on Chirp", free, required)]
pub file: PathBuf,
#[options(help = "Load address (usually 200)", parse(try_from_str = "parse_hex"))]
pub loadaddr: u16,
#[options(help = "Start disassembling at offset...")]
pub offset: usize,
}
fn parse_hex(value: &str) -> std::result::Result<u16, std::num::ParseIntError> {
u16::from_str_radix(value, 16)
}

View File

@ -6,12 +6,6 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
/// Disassembles Chip-8 instructions
pub trait Disassembler {
/// Disassemble a single instruction
fn once(&self, insn: u16) -> String;
}
pub mod disassembler; pub mod disassembler;
pub mod flags; pub mod flags;
pub mod instruction; pub mod instruction;
@ -19,7 +13,7 @@ pub mod mode;
pub mod quirks; pub mod quirks;
use self::{ use self::{
disassembler::{Dis, Insn}, disassembler::{Dis, Disassembler, Insn},
flags::Flags, flags::Flags,
mode::Mode, mode::Mode,
quirks::Quirks, quirks::Quirks,
@ -57,7 +51,7 @@ impl Default for Timers {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct CPU { pub struct CPU {
/// Flags that control how the CPU behaves, but which aren't inherent to the /// Flags that control how the CPU behaves, but which aren't inherent to the
/// implementation. Includes [Quirks], target IPF, etc. /// chip-8. Includes [Quirks], target IPF, etc.
pub flags: Flags, pub flags: Flags,
// memory map info // memory map info
screen: Adr, screen: Adr,
@ -478,7 +472,7 @@ impl CPU {
/// ``` /// ```
pub fn tick(&mut self, bus: &mut Bus) -> Result<&mut Self> { pub fn tick(&mut self, bus: &mut Bus) -> Result<&mut Self> {
// Do nothing if paused // Do nothing if paused
if self.flags.pause || self.flags.draw_wait || self.flags.keypause { if self.flags.is_paused() {
// always tick in test mode // always tick in test mode
if self.flags.monotonic.is_some() { if self.flags.monotonic.is_some() {
self.cycle += 1; self.cycle += 1;

View File

@ -1,10 +1,15 @@
//! A disassembler for Chip-8 opcodes //! A disassembler for Chip-8 opcodes
#![allow(clippy::bad_bit_mask)] #![allow(clippy::bad_bit_mask)]
use super::Disassembler;
use imperative_rs::InstructionSet; use imperative_rs::InstructionSet;
use owo_colors::{OwoColorize, Style}; use owo_colors::{OwoColorize, Style};
use std::fmt::Display; use std::fmt::Display;
/// Disassembles Chip-8 instructions
pub trait Disassembler {
/// Disassemble a single instruction
fn once(&self, insn: u16) -> String;
}
#[allow(non_camel_case_types, non_snake_case, missing_docs)] #[allow(non_camel_case_types, non_snake_case, missing_docs)]
#[derive(Clone, Copy, Debug, InstructionSet, PartialEq, Eq)] #[derive(Clone, Copy, Debug, InstructionSet, PartialEq, Eq)]
/// Implements a Disassembler using imperative_rs /// Implements a Disassembler using imperative_rs

View File

@ -1,8 +1,8 @@
//! Represents flags that aid in implementation but aren't a part of the Chip-8 spec //! Represents [Flags] that aid in implementation but aren't a part of the Chip-8 spec
use super::{Mode, Quirks}; use super::{Mode, Quirks};
/// Represents flags that aid in operation, but aren't inherent to the CPU /// Represents flags that aid in implementation but aren't a part of the Chip-8 spec
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Flags { pub struct Flags {
/// Set when debug (live disassembly) mode enabled /// Set when debug (live disassembly) mode enabled
@ -55,4 +55,9 @@ impl Flags {
pub fn pause(&mut self) { pub fn pause(&mut self) {
self.pause = !self.pause self.pause = !self.pause
} }
/// Gets whether the CPU is paused for any reason
pub fn is_paused(&self) -> bool {
self.pause || self.draw_wait || self.keypause
}
} }

View File

@ -1,7 +1,7 @@
// (c) 2023 John A. Breaux // (c) 2023 John A. Breaux
// This code is licensed under MIT license (see LICENSE.txt for details) // This code is licensed under MIT license (see LICENSE.txt for details)
//! Contains implementations for each instruction defined in [super::disassembler] //! Contains implementations for each [Insn] as private member functions of [CPU]
use super::*; use super::*;

View File

@ -1,4 +1,7 @@
//! Selects the memory behavior of the [super::CPU] //! Selects the memory behavior of the [super::CPU]
//!
//! Since [super::Quirks] implements [From<Mode>],
//! this can be used to select the appropriate quirk-set
use crate::error::Error; use crate::error::Error;
use std::str::FromStr; use std::str::FromStr;

View File

@ -1,4 +1,4 @@
//! Controls the authenticity behavior of the CPU on a granular level. //! Controls the [Quirks] behavior of the CPU on a granular level.
use super::Mode; use super::Mode;
/// Controls the authenticity behavior of the CPU on a granular level. /// Controls the authenticity behavior of the CPU on a granular level.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]

View File

@ -64,6 +64,7 @@ pub enum Error {
/// Error originated in [std::array::TryFromSliceError] /// Error originated in [std::array::TryFromSliceError]
#[error(transparent)] #[error(transparent)]
TryFromSliceError(#[from] std::array::TryFromSliceError), TryFromSliceError(#[from] std::array::TryFromSliceError),
#[cfg(feature = "minifb")]
/// Error originated in [minifb] /// Error originated in [minifb]
#[error(transparent)] #[error(transparent)]
MinifbError(#[from] minifb::Error), MinifbError(#[from] minifb::Error),

View File

@ -14,8 +14,14 @@ pub mod error;
// Common imports for Chirp // Common imports for Chirp
pub use bus::{Bus, Read, Region::*, Write}; pub use bus::{Bus, Read, Region::*, Write};
pub use cpu::{disassembler::Dis, flags::Flags, mode::Mode, quirks::Quirks, CPU}; pub use cpu::{
pub use error::Result; disassembler::{Dis, Disassembler},
flags::Flags,
mode::Mode,
quirks::Quirks,
CPU,
};
pub use error::{Error, Result};
/// Holds the state of a Chip-8 /// Holds the state of a Chip-8
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]