Implement a stack for emulation

This commit is contained in:
Denis-Cosmin Nutiu 2024-11-29 22:43:32 +02:00
parent 3c6aad798c
commit e31c05ac9b
4 changed files with 85 additions and 11 deletions

View file

@ -1,4 +1,3 @@
/// Represents the display's width in pixels. /// Represents the display's width in pixels.
const DISPLAY_WIDTH: usize = 64; const DISPLAY_WIDTH: usize = 64;
@ -22,7 +21,7 @@ pub struct TerminalDisplay {
impl TerminalDisplay { impl TerminalDisplay {
pub fn new() -> TerminalDisplay { pub fn new() -> TerminalDisplay {
TerminalDisplay { TerminalDisplay {
display_data: [false; DISPLAY_WIDTH * DISPLAY_HEIGHT] display_data: [false; DISPLAY_WIDTH * DISPLAY_HEIGHT],
} }
} }
} }
@ -47,4 +46,4 @@ impl Display for TerminalDisplay {
print!("\n") print!("\n")
} }
} }
} }

View file

@ -1,9 +1,10 @@
use crate::display::Display;
use crate::stack::Stack;
use anyhow::anyhow; 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};
const MEMORY_SIZE: usize = 4096; const MEMORY_SIZE: usize = 4096;
const NUMBER_OF_REGISTERS: usize = 16; const NUMBER_OF_REGISTERS: usize = 16;
@ -27,7 +28,10 @@ const FONT_SPRITES: [u8; 80] = [
]; ];
/// Emulator emulates the Chip8 CPU. /// Emulator emulates the Chip8 CPU.
pub struct Emulator<D> where D: Display { pub struct Emulator<D>
where
D: Display,
{
/// Memory represents the emulator's memory. /// Memory represents the emulator's memory.
memory: [u8; MEMORY_SIZE], memory: [u8; MEMORY_SIZE],
/// Registers holds the general purpose registers. /// Registers holds the general purpose registers.
@ -44,10 +48,14 @@ pub struct Emulator<D> where D: Display {
/// 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 /// The display_data holds all the data associated with the display
display: D display: D,
stack: Stack<u16>,
} }
impl <D> Emulator<D> where D: Display { impl<D> Emulator<D>
where
D: Display,
{
/// Creates a new `Emulator` instance. /// Creates a new `Emulator` instance.
/// ///
pub fn new(display: D) -> Emulator<D> { pub fn new(display: D) -> Emulator<D> {
@ -60,6 +68,7 @@ impl <D> Emulator<D> where D: Display {
delay_timer: 0, delay_timer: 0,
sound_timer: 0, sound_timer: 0,
stack_pointer: 0, stack_pointer: 0,
stack: Stack::new(),
}; };
emulator.load_font_data(); emulator.load_font_data();
@ -113,7 +122,7 @@ impl <D> Emulator<D> where D: Display {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::display::{TerminalDisplay}; use crate::display::TerminalDisplay;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
#[test] #[test]

View file

@ -1,9 +1,10 @@
use crate::display::TerminalDisplay;
use crate::emulator::Emulator; use crate::emulator::Emulator;
use env_logger; use env_logger;
use crate::display::TerminalDisplay;
mod emulator;
mod display; mod display;
mod emulator;
mod stack;
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
env_logger::init(); env_logger::init();

65
src/stack.rs Normal file
View file

@ -0,0 +1,65 @@
use std::fmt::Debug;
/// Implements a simple stack based on a vector.
#[derive(Debug)]
pub struct Stack<T> {
storage: Vec<T>,
}
impl<T: Debug> Stack<T> {
pub fn new() -> Self {
Stack {
storage: Vec::new(),
}
}
/// Pushes an element on the top of the stack
pub fn push(&mut self, element: T) {
self.storage.push(element)
}
/// Returns the top element from the stack.
pub fn pop(&mut self) -> Option<T> {
self.storage.pop()
}
//
pub fn peek(&self) -> Option<&T> {
self.storage.last()
}
/// Size returns the size of the stack.
pub fn size(&self) -> usize {
self.storage.len()
}
/// Is Empty returns true if the stack is empty.
pub fn is_empty(&self) -> bool {
self.storage.len() == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic_operations() {
// Given
let mut stack = Stack::<u16>::new();
// Then
stack.push(15);
assert_eq!(1, stack.size());
assert_eq!(15u16, *stack.peek().unwrap());
let element = stack.pop();
assert_eq!(15u16, element.unwrap());
assert_eq!(0, stack.size());
assert_eq!(true, stack.is_empty());
let element = stack.pop();
assert_eq!(true, element.is_none())
}
}