Compare commits

...

2 commits

Author SHA1 Message Date
edaca0a9fd add peek comment 2025-01-11 17:08:01 +02:00
337b1ab05b reafactor code: split tui bin into separated crated 2025-01-11 17:06:59 +02:00
17 changed files with 95 additions and 71 deletions

View file

@ -2,7 +2,8 @@
<module type="EMPTY_MODULE" version="4"> <module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/emulator/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/chip8_core/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/chip8_tui/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

28
Cargo.lock generated
View file

@ -111,11 +111,23 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chip8_tui"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"crossterm",
"emulator",
"env_logger",
"ratatui",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.23" version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -123,9 +135,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.23" version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -135,9 +147,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.18" version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -248,13 +260,9 @@ name = "emulator"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap",
"crossterm",
"env_logger",
"log", "log",
"pretty_assertions", "pretty_assertions",
"rand", "rand",
"ratatui",
] ]
[[package]] [[package]]

View file

@ -2,5 +2,6 @@
resolver = "2" resolver = "2"
members = [ members = [
"emulator", "chip8_tui",
"chip8_core",
] ]

View file

@ -50,7 +50,7 @@ The project is written in Rust and it's organized in the following modules:
│   └── ibm-logo.ch8 # IBM Logo Test ROM │   └── ibm-logo.ch8 # IBM Logo Test ROM
├── src ├── src
│   ├── display.rs # The screen / display module. │   ├── display.rs # The screen / display module.
│   ├── emulator.rs # The emulator logic which emulates the CPU. │   ├── chip8_core.rs # The chip8_core logic which emulates the CPU.
│   ├── input.rs # The input logic. │   ├── input.rs # The input logic.
│   ├── instruction.rs # The instruction decoding logic. │   ├── instruction.rs # The instruction decoding logic.
│   ├── main.rs # The main file. This is the entrypoint. │   ├── main.rs # The main file. This is the entrypoint.

View file

@ -6,18 +6,10 @@ edition = "2021"
[lints.rust] [lints.rust]
dead_code = "allow" dead_code = "allow"
[profile.release]
lto = true
codegen-units = 1
[dependencies] [dependencies]
log = "0.4.22" log = "0.4.22"
env_logger = "0.11.5"
anyhow = "1.0.93" anyhow = "1.0.93"
ratatui = "0.29.0"
crossterm = "0.28.1"
rand = "0.8.5" rand = "0.8.5"
clap = { version = "4.5.23", features = ["derive"] }
[dev-dependencies] [dev-dependencies]
pretty_assertions = "1.4.1" pretty_assertions = "1.4.1"

13
chip8_core/src/display.rs Normal file
View file

@ -0,0 +1,13 @@
/// Represents the display's width in pixels.
pub const DISPLAY_WIDTH: usize = 64;
/// Represents the display's height pixels.
pub const DISPLAY_HEIGHT: usize = 32;
/// Display trait
pub trait Display {
/// Re-draws the display.
fn clear(&mut self);
/// Renders the display data on screen.
fn render(&mut self, display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]);
}

View file

@ -42,7 +42,7 @@ where
S: SoundModule, S: SoundModule,
I: InputModule, I: InputModule,
{ {
/// Memory represents the emulator's memory. /// Memory represents the chip8_core's memory.
memory: [u8; MEMORY_SIZE], memory: [u8; MEMORY_SIZE],
/// Registers holds the general purpose registers. /// Registers holds the general purpose registers.
registers: [u8; NUMBER_OF_REGISTERS], registers: [u8; NUMBER_OF_REGISTERS],
@ -63,7 +63,7 @@ where
sound_module: S, sound_module: S,
/// The module responsible for receiving user input. /// The module responsible for receiving user input.
input_module: I, input_module: I,
/// The stack of the emulator. /// The stack of the chip8_core.
stack: Stack<u16>, stack: Stack<u16>,
/// Holds the display data, each bit corresponds to a pixel. /// Holds the display data, each bit corresponds to a pixel.
display_data: [bool; DISPLAY_WIDTH * DISPLAY_HEIGHT], display_data: [bool; DISPLAY_WIDTH * DISPLAY_HEIGHT],
@ -467,7 +467,7 @@ where
])) ]))
} }
/// Loads the ROM found at the rom path in the emulator's RAM memory. /// Loads the ROM found at the rom path in the chip8_core's RAM memory.
fn load_rom<T>(&mut self, mut rom: T) -> Result<(), anyhow::Error> fn load_rom<T>(&mut self, mut rom: T) -> Result<(), anyhow::Error>
where where
T: Read, T: Read,

16
chip8_core/src/input.rs Normal file
View file

@ -0,0 +1,16 @@
/// InputModule retrieves the keys from the hardware or software input control module.
pub trait InputModule {
/// Returns the key value of the corresponding pressed key.
/// None if no key is pressed.
fn get_key_pressed(&mut self) -> Option<u16>;
}
/// NoInput always returns none when queried for input.
#[derive(Clone)]
pub struct NoInput;
impl InputModule for NoInput {
fn get_key_pressed(&mut self) -> Option<u16> {
None
}
}

6
chip8_core/src/lib.rs Normal file
View file

@ -0,0 +1,6 @@
pub mod display;
pub mod emulator;
pub mod input;
pub mod instruction;
pub mod sound;
pub mod stack;

5
chip8_core/src/sound.rs Normal file
View file

@ -0,0 +1,5 @@
/// SoundModule represents a module which can produce sound.
pub trait SoundModule {
/// beep makes a beep sound.
fn beep(&mut self);
}

View file

@ -23,7 +23,7 @@ impl<T: Debug> Stack<T> {
self.storage.pop() self.storage.pop()
} }
// /// Returns the top element from the stack without removing it.
pub fn peek(&self) -> Option<&T> { pub fn peek(&self) -> Option<&T> {
self.storage.last() self.storage.last()
} }

16
chip8_tui/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "chip8_tui"
version = "0.1.0"
edition = "2021"
[profile.release]
lto = true
codegen-units = 1
[dependencies]
emulator = { path = "../chip8_core" }
clap = { version = "4.5.26", features = ["derive"] }
anyhow = "1.0.95"
env_logger = "0.11.6"
ratatui = "0.29.0"
crossterm = "0.28.1"

View file

@ -3,23 +3,12 @@ use ratatui::style::{Style, Stylize};
use ratatui::widgets::{Block, Borders}; use ratatui::widgets::{Block, Borders};
use ratatui::DefaultTerminal; use ratatui::DefaultTerminal;
/// Represents the display's width in pixels. use emulator::display::{Display, DISPLAY_HEIGHT, DISPLAY_WIDTH};
pub const DISPLAY_WIDTH: usize = 64;
/// Represents the display's height pixels. /// Simple terminal display for the Chip8's chip8_core.
pub const DISPLAY_HEIGHT: usize = 32;
/// Display trait
pub trait Display {
/// Re-draws the display.
fn clear(&mut self);
/// Renders the display data on screen.
fn render(&mut self, display_data: &[bool; DISPLAY_WIDTH * DISPLAY_HEIGHT]);
}
/// Simple terminal display for the Chip8's emulator.
pub struct TerminalDisplay {} pub struct TerminalDisplay {}
#[allow(dead_code)]
impl TerminalDisplay { impl TerminalDisplay {
pub fn new() -> TerminalDisplay { pub fn new() -> TerminalDisplay {
TerminalDisplay {} TerminalDisplay {}

View file

@ -1,24 +1,8 @@
use crossterm::event::{poll, read, Event, KeyCode}; use crossterm::event::{poll, read, Event, KeyCode};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use emulator::input::InputModule;
use std::time::Duration; use std::time::Duration;
/// InputModule retrieves the keys from the hardware or software input control module.
pub trait InputModule {
/// Returns the key value of the corresponding pressed key.
/// None if no key is pressed.
fn get_key_pressed(&mut self) -> Option<u16>;
}
/// NoInput always returns none when queried for input.
#[derive(Clone)]
pub struct NoInput;
impl InputModule for NoInput {
fn get_key_pressed(&mut self) -> Option<u16> {
None
}
}
/// CrossTermInput implements input events via the crossterm crate. /// CrossTermInput implements input events via the crossterm crate.
#[derive(Clone)] #[derive(Clone)]
pub struct CrossTermInput { pub struct CrossTermInput {

View file

@ -1,21 +1,18 @@
mod display;
mod input;
mod sound;
use crate::display::RatatuiDisplay; use crate::display::RatatuiDisplay;
use crate::emulator::Emulator;
use crate::input::CrossTermInput; use crate::input::CrossTermInput;
use crate::sound::TerminalSound; use crate::sound::TerminalSound;
use clap::Parser; use clap::Parser;
use emulator::emulator::Emulator;
use std::fs::File; use std::fs::File;
mod display;
mod emulator;
mod input;
mod instruction;
mod sound;
mod stack;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command( #[command(
version = "1.0", version = "1.0",
about = "A Chip8 emulator.", about = "A Chip8 chip8_core.",
long_about = "A program which emulates the Chip8 system." long_about = "A program which emulates the Chip8 system."
)] )]
struct CliArgs { struct CliArgs {

View file

@ -1,8 +1,4 @@
/// SoundModule represents a module which can produce sound. use emulator::sound::SoundModule;
pub trait SoundModule {
/// beep makes a beep sound.
fn beep(&mut self);
}
/// TerminalSound is a simple module that makes terminal beep sound. /// TerminalSound is a simple module that makes terminal beep sound.
pub struct TerminalSound; pub struct TerminalSound;