bus.rs: Improve region encoding with enums
This commit is contained in:
		
							
								
								
									
										52
									
								
								src/bus.rs
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								src/bus.rs
									
									
									
									
									
								
							| @@ -11,15 +11,15 @@ use std::{ | ||||
| /// Creates a new bus, instantiating BusConnectable devices | ||||
| /// # Examples | ||||
| /// ```rust | ||||
| /// # use chumpulator::prelude::*; | ||||
| /// # use chirp::prelude::*; | ||||
| /// let mut bus = bus! { | ||||
| ///     "RAM" [0x0000..0x8000], | ||||
| ///     "ROM" [0x8000..0xFFFF], | ||||
| ///     Stack   [0x0000..0x0800] = b"ABCDEF", | ||||
| ///     Program [0x0800..0x1000] = include_bytes!("bus.rs"), | ||||
| /// }; | ||||
| /// ``` | ||||
| #[macro_export] | ||||
| macro_rules! bus { | ||||
|     ($($name:literal $(:)? [$range:expr] $(= $data:expr)?) ,* $(,)?) => { | ||||
|     ($($name:path $(:)? [$range:expr] $(= $data:expr)?) ,* $(,)?) => { | ||||
|         $crate::bus::Bus::new() | ||||
|         $( | ||||
|             .add_region($name, $range) | ||||
| @@ -43,14 +43,30 @@ pub trait Write<T> { | ||||
|     fn write(&mut self, addr: impl Into<usize>, data: T); | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Copy, Debug)] | ||||
| pub enum Region {} | ||||
| #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||
| 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 | ||||
| #[derive(Debug, Default)] | ||||
| #[derive(Clone, Debug, Default, PartialEq)] | ||||
| pub struct Bus { | ||||
|     memory: Vec<u8>, | ||||
|     region: HashMap<&'static str, Range<usize>>, | ||||
|     region: HashMap<Region, Range<usize>>, | ||||
| } | ||||
|  | ||||
| impl Bus { | ||||
| @@ -66,25 +82,25 @@ impl Bus { | ||||
|     pub fn is_empty(&self) -> bool { | ||||
|         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) { | ||||
|         if self.len() < size { | ||||
|             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.region.insert(name, range); | ||||
|         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; | ||||
|         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 | ||||
|     } | ||||
|     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) { | ||||
|             region.fill(0) | ||||
|         } | ||||
| @@ -105,15 +121,15 @@ impl Bus { | ||||
|         self.memory.get_mut(index) | ||||
|     } | ||||
|     /// Gets a slice of a named region of memory | ||||
|     pub fn get_region(&self, name: &str) -> Option<&[u8]> { | ||||
|         self.get(self.region.get(name)?.clone()) | ||||
|     pub fn get_region(&self, name: Region) -> Option<&[u8]> { | ||||
|         self.get(self.region.get(&name)?.clone()) | ||||
|     } | ||||
|     /// Gets a mutable slice to a named region of memory | ||||
|     pub fn get_region_mut(&mut self, name: &str) -> Option<&mut [u8]> { | ||||
|         self.get_mut(self.region.get(name)?.clone()) | ||||
|     pub fn get_region_mut(&mut self, name: Region) -> Option<&mut [u8]> { | ||||
|         self.get_mut(self.region.get(&name)?.clone()) | ||||
|     } | ||||
|     pub fn print_screen(&self) -> Result<()> { | ||||
|         const REGION: &str = "screen"; | ||||
|         const REGION: Region = Region::Screen; | ||||
|         if let Some(screen) = self.get_region(REGION) { | ||||
|             for (index, byte) in screen.iter().enumerate() { | ||||
|                 if index % 8 == 0 { | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| pub mod disassemble; | ||||
|  | ||||
| use self::disassemble::Disassemble; | ||||
| use crate::bus::{Bus, Read, Write}; | ||||
| use crate::bus::{Bus, Read, Region, Write}; | ||||
| use owo_colors::OwoColorize; | ||||
| use rand::random; | ||||
| use std::time::Instant; | ||||
| @@ -99,6 +99,7 @@ impl CPU { | ||||
|     /// ```rust | ||||
|     /// # 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(), vec![], ControlFlags::default()); | ||||
|     /// ``` | ||||
|     pub fn new(screen: Adr, font: Adr, pc: Adr, sp: Adr, disassembler: Disassemble) -> Self { | ||||
|         CPU { | ||||
| @@ -383,7 +384,7 @@ impl CPU { | ||||
|     /// 00e0: Clears the screen memory to 0 | ||||
|     #[inline] | ||||
|     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 { | ||||
|                 *byte = 0; | ||||
|             } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| //! | ||||
|  | ||||
| use crate::{bus::Bus, cpu::CPU, error::Result}; | ||||
| use crate::{bus::{Bus, Region}, cpu::CPU, error::Result}; | ||||
| use minifb::*; | ||||
|  | ||||
| #[derive(Clone, Copy, Debug)] | ||||
| @@ -75,7 +75,7 @@ impl FrameBuffer { | ||||
|         } | ||||
|     } | ||||
|     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 bit in 0..8 { | ||||
|                     self.buffer[8 * idx + bit] = if byte & (1 << 7 - bit) as u8 != 0 { | ||||
|   | ||||
| @@ -9,17 +9,17 @@ Hopefully, though, you'll find some use in it. | ||||
|  | ||||
| pub mod bus; | ||||
| pub mod cpu; | ||||
| pub mod error; | ||||
| pub mod io; | ||||
|  | ||||
| pub mod dump; | ||||
| pub mod error; | ||||
|  | ||||
| /// Common imports for chumpulator | ||||
| pub mod prelude { | ||||
|     use super::*; | ||||
|     pub use crate::bus; | ||||
|     pub use bus::{Bus, Read, Write}; | ||||
|     pub use cpu::{disassemble::Disassemble, CPU}; | ||||
|     pub use dump::{BinDumpable, Dumpable}; | ||||
|     pub use io::{*, WindowBuilder}; | ||||
|     pub use bus::{Bus, Read, Region::*, Write}; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user