Add terminal display.rs
This commit is contained in:
parent
6e76f96467
commit
668d2a18d5
4 changed files with 66 additions and 7 deletions
|
@ -3,6 +3,9 @@ name = "Chip8Emulator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
dead_code = "allow"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
env_logger = "0.11.5"
|
env_logger = "0.11.5"
|
||||||
|
|
50
src/display.rs
Normal file
50
src/display.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
/// Represents the display's width in pixels.
|
||||||
|
const DISPLAY_WIDTH: usize = 64;
|
||||||
|
|
||||||
|
/// Represents the display's height pixels.
|
||||||
|
const DISPLAY_HEIGHT: usize = 32;
|
||||||
|
|
||||||
|
/// Display trait
|
||||||
|
pub trait Display {
|
||||||
|
/// Re-draws the display.
|
||||||
|
fn redraw(&self);
|
||||||
|
/// Draws the display.
|
||||||
|
fn draw(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Display models the Chip8's display.
|
||||||
|
pub struct TerminalDisplay {
|
||||||
|
/// Holds the display data, each bit corresponds to a pixel.
|
||||||
|
display_data: [bool; DISPLAY_WIDTH * DISPLAY_HEIGHT],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerminalDisplay {
|
||||||
|
pub fn new() -> TerminalDisplay {
|
||||||
|
TerminalDisplay {
|
||||||
|
display_data: [false; DISPLAY_WIDTH * DISPLAY_HEIGHT]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for TerminalDisplay {
|
||||||
|
/// Re-draws the display.
|
||||||
|
fn redraw(&self) {
|
||||||
|
// ANSI Escape code to move cursor to row 1 column 1
|
||||||
|
// See https://stackoverflow.com/a/4062051
|
||||||
|
print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
|
||||||
|
}
|
||||||
|
/// Draws the display.
|
||||||
|
fn draw(&mut self) {
|
||||||
|
for row in 0..32 {
|
||||||
|
for column in 0..64 {
|
||||||
|
if self.display_data[row * DISPLAY_WIDTH + column] {
|
||||||
|
print!("█")
|
||||||
|
} else {
|
||||||
|
print!(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print!("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,8 @@ use anyhow::anyhow;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::{Path};
|
||||||
|
use crate::display::{Display, TerminalDisplay};
|
||||||
|
|
||||||
const MEMORY_SIZE: usize = 4096;
|
const MEMORY_SIZE: usize = 4096;
|
||||||
const NUMBER_OF_REGISTERS: usize = 16;
|
const NUMBER_OF_REGISTERS: usize = 16;
|
||||||
|
@ -42,15 +43,18 @@ pub struct Emulator {
|
||||||
sound_timer: u8,
|
sound_timer: u8,
|
||||||
/// The stack pointer register.
|
/// The stack pointer register.
|
||||||
stack_pointer: u8,
|
stack_pointer: u8,
|
||||||
|
/// The display_data holds all the data associated with the display
|
||||||
|
display: Box<dyn Display>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emulator {
|
impl Emulator {
|
||||||
/// Creates a new `Emulator` instance.
|
/// Creates a new `Emulator` instance.
|
||||||
///
|
///
|
||||||
pub fn new() -> Emulator {
|
pub fn new(display: Box<dyn Display>) -> Emulator {
|
||||||
let mut emulator = Emulator {
|
let mut emulator = Emulator {
|
||||||
memory: [0; 4096],
|
memory: [0; MEMORY_SIZE],
|
||||||
registers: [0; 16],
|
registers: [0; NUMBER_OF_REGISTERS],
|
||||||
|
display,
|
||||||
index_register: 0,
|
index_register: 0,
|
||||||
program_counter: 0,
|
program_counter: 0,
|
||||||
delay_timer: 0,
|
delay_timer: 0,
|
||||||
|
@ -113,7 +117,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_font_data() {
|
fn test_load_font_data() {
|
||||||
let emulator = Emulator::new();
|
let emulator = Emulator::new(Box::from(TerminalDisplay::new()));
|
||||||
assert_eq!(emulator.memory[0xf0..0xf0 + 80], FONT_SPRITES)
|
assert_eq!(emulator.memory[0xf0..0xf0 + 80], FONT_SPRITES)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +130,7 @@ mod tests {
|
||||||
.expect("Failed to read test ROM");
|
.expect("Failed to read test ROM");
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
let mut emulator = Emulator::new();
|
let mut emulator = Emulator::new(Box::from(TerminalDisplay::new()));
|
||||||
emulator
|
emulator
|
||||||
.load_rom("roms/ibm-logo.ch8")
|
.load_rom("roms/ibm-logo.ch8")
|
||||||
.expect("failed to load ROM");
|
.expect("failed to load ROM");
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use crate::emulator::Emulator;
|
use crate::emulator::Emulator;
|
||||||
use env_logger;
|
use env_logger;
|
||||||
|
use crate::display::TerminalDisplay;
|
||||||
|
|
||||||
mod emulator;
|
mod emulator;
|
||||||
|
mod display;
|
||||||
|
|
||||||
fn main() -> Result<(), anyhow::Error> {
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
let mut emulator = Emulator::new();
|
let mut emulator = Emulator::new(Box::from(TerminalDisplay::new()));
|
||||||
|
|
||||||
emulator.emulate(String::from("./roms/ibm-logo.ch8"))?;
|
emulator.emulate(String::from("./roms/ibm-logo.ch8"))?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue