bus.rs: Improve region encoding with enums

This commit is contained in:
John 2023-03-25 17:20:20 -05:00
parent e534041d00
commit 712acc5984
4 changed files with 41 additions and 24 deletions

View File

@ -11,15 +11,15 @@ use std::{
/// Creates a new bus, instantiating BusConnectable devices /// Creates a new bus, instantiating BusConnectable devices
/// # Examples /// # Examples
/// ```rust /// ```rust
/// # use chumpulator::prelude::*; /// # use chirp::prelude::*;
/// let mut bus = bus! { /// let mut bus = bus! {
/// "RAM" [0x0000..0x8000], /// Stack [0x0000..0x0800] = b"ABCDEF",
/// "ROM" [0x8000..0xFFFF], /// Program [0x0800..0x1000] = include_bytes!("bus.rs"),
/// }; /// };
/// ``` /// ```
#[macro_export] #[macro_export]
macro_rules! bus { macro_rules! bus {
($($name:literal $(:)? [$range:expr] $(= $data:expr)?) ,* $(,)?) => { ($($name:path $(:)? [$range:expr] $(= $data:expr)?) ,* $(,)?) => {
$crate::bus::Bus::new() $crate::bus::Bus::new()
$( $(
.add_region($name, $range) .add_region($name, $range)
@ -43,14 +43,30 @@ pub trait Write<T> {
fn write(&mut self, addr: impl Into<usize>, data: T); fn write(&mut self, addr: impl Into<usize>, data: T);
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Region {} pub enum Region {
Charset,
Program,
Screen,
Stack,
}
impl Display for Region {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
Region::Charset => "charset",
Region::Program => "program",
Region::Screen => "screen",
Region::Stack => "stack",
})
}
}
/// Store memory in a series of named regions with ranges /// Store memory in a series of named regions with ranges
#[derive(Debug, Default)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct Bus { pub struct Bus {
memory: Vec<u8>, memory: Vec<u8>,
region: HashMap<&'static str, Range<usize>>, region: HashMap<Region, Range<usize>>,
} }
impl Bus { impl Bus {
@ -66,25 +82,25 @@ impl Bus {
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.memory.is_empty() self.memory.is_empty()
} }
/// Grows the NewBus backing memory to at least size bytes, but does not truncate /// Grows the Bus backing memory to at least size bytes, but does not truncate
pub fn with_size(&mut self, size: usize) { pub fn with_size(&mut self, size: usize) {
if self.len() < size { if self.len() < size {
self.memory.resize(size, 0); self.memory.resize(size, 0);
} }
} }
pub fn add_region(mut self, name: &'static str, range: Range<usize>) -> Self { pub fn add_region(mut self, name: Region, range: Range<usize>) -> Self {
self.with_size(range.end); self.with_size(range.end);
self.region.insert(name, range); self.region.insert(name, range);
self self
} }
pub fn load_region(mut self, name: &str, data: &[u8]) -> Self { pub fn load_region(mut self, name: Region, data: &[u8]) -> Self {
use std::io::Write; use std::io::Write;
if let Some(mut region) = self.get_region_mut(name) { if let Some(mut region) = self.get_region_mut(name) {
dbg!(region.write(data)).ok(); // TODO: THIS SUCKS region.write(data).ok(); // TODO: THIS SUCKS
} }
self self
} }
pub fn clear_region(&mut self, name: &str) -> &mut Self { pub fn clear_region(&mut self, name: Region) -> &mut Self {
if let Some(region) = self.get_region_mut(name) { if let Some(region) = self.get_region_mut(name) {
region.fill(0) region.fill(0)
} }
@ -105,15 +121,15 @@ impl Bus {
self.memory.get_mut(index) self.memory.get_mut(index)
} }
/// Gets a slice of a named region of memory /// Gets a slice of a named region of memory
pub fn get_region(&self, name: &str) -> Option<&[u8]> { pub fn get_region(&self, name: Region) -> Option<&[u8]> {
self.get(self.region.get(name)?.clone()) self.get(self.region.get(&name)?.clone())
} }
/// Gets a mutable slice to a named region of memory /// Gets a mutable slice to a named region of memory
pub fn get_region_mut(&mut self, name: &str) -> Option<&mut [u8]> { pub fn get_region_mut(&mut self, name: Region) -> Option<&mut [u8]> {
self.get_mut(self.region.get(name)?.clone()) self.get_mut(self.region.get(&name)?.clone())
} }
pub fn print_screen(&self) -> Result<()> { pub fn print_screen(&self) -> Result<()> {
const REGION: &str = "screen"; const REGION: Region = Region::Screen;
if let Some(screen) = self.get_region(REGION) { if let Some(screen) = self.get_region(REGION) {
for (index, byte) in screen.iter().enumerate() { for (index, byte) in screen.iter().enumerate() {
if index % 8 == 0 { if index % 8 == 0 {

View File

@ -3,7 +3,7 @@
pub mod disassemble; pub mod disassemble;
use self::disassemble::Disassemble; use self::disassemble::Disassemble;
use crate::bus::{Bus, Read, Write}; use crate::bus::{Bus, Read, Region, Write};
use owo_colors::OwoColorize; use owo_colors::OwoColorize;
use rand::random; use rand::random;
use std::time::Instant; use std::time::Instant;
@ -99,6 +99,7 @@ impl CPU {
/// ```rust /// ```rust
/// # use chumpulator::prelude::*; /// # use chumpulator::prelude::*;
/// let mut cpu = CPU::new(0xf00, 0x50, 0x200, 0xefe, Disassemble::default()); /// let mut cpu = CPU::new(0xf00, 0x50, 0x200, 0xefe, Disassemble::default());
/// let mut cpu = CPU::new(0xf00, 0x50, 0x200, 0xefe, Disassemble::default(), vec![], ControlFlags::default());
/// ``` /// ```
pub fn new(screen: Adr, font: Adr, pc: Adr, sp: Adr, disassembler: Disassemble) -> Self { pub fn new(screen: Adr, font: Adr, pc: Adr, sp: Adr, disassembler: Disassemble) -> Self {
CPU { CPU {
@ -383,7 +384,7 @@ impl CPU {
/// 00e0: Clears the screen memory to 0 /// 00e0: Clears the screen memory to 0
#[inline] #[inline]
fn clear_screen(&mut self, bus: &mut Bus) { fn clear_screen(&mut self, bus: &mut Bus) {
if let Some(screen) = bus.get_region_mut("screen") { if let Some(screen) = bus.get_region_mut(Region::Screen) {
for byte in screen { for byte in screen {
*byte = 0; *byte = 0;
} }

View File

@ -1,6 +1,6 @@
//! //!
use crate::{bus::Bus, cpu::CPU, error::Result}; use crate::{bus::{Bus, Region}, cpu::CPU, error::Result};
use minifb::*; use minifb::*;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -75,7 +75,7 @@ impl FrameBuffer {
} }
} }
pub fn render(&mut self, window: &mut Window, bus: &Bus) { pub fn render(&mut self, window: &mut Window, bus: &Bus) {
if let Some(screen) = bus.get_region("screen") { if let Some(screen) = bus.get_region(Region::Screen) {
for (idx, byte) in screen.iter().enumerate() { for (idx, byte) in screen.iter().enumerate() {
for bit in 0..8 { for bit in 0..8 {
self.buffer[8 * idx + bit] = if byte & (1 << 7 - bit) as u8 != 0 { self.buffer[8 * idx + bit] = if byte & (1 << 7 - bit) as u8 != 0 {

View File

@ -9,17 +9,17 @@ Hopefully, though, you'll find some use in it.
pub mod bus; pub mod bus;
pub mod cpu; pub mod cpu;
pub mod error;
pub mod io; pub mod io;
pub mod dump; pub mod dump;
pub mod error;
/// Common imports for chumpulator /// Common imports for chumpulator
pub mod prelude { pub mod prelude {
use super::*; use super::*;
pub use crate::bus; pub use crate::bus;
pub use bus::{Bus, Read, Write};
pub use cpu::{disassemble::Disassemble, CPU}; pub use cpu::{disassemble::Disassemble, CPU};
pub use dump::{BinDumpable, Dumpable}; pub use dump::{BinDumpable, Dumpable};
pub use io::{*, WindowBuilder}; pub use io::{*, WindowBuilder};
pub use bus::{Bus, Read, Region::*, Write};
} }