diff --git a/src/emu/iomem.rs b/src/emu/iomem.rs index 060efd9..7d83ef6 100644 --- a/src/emu/iomem.rs +++ b/src/emu/iomem.rs @@ -1,11 +1,12 @@ - use crate::emu::mmu::Memory; +use crate::misc::emulator_error::EmulatorError; use crate::misc::endian::MemoryOperations; +use crate::misc::result::EmulatorResult; #[derive(Debug, Copy, Clone)] pub struct MemoryMappedIO { //FIXME use a keyboard - keyboard_bytes: [u8;2], + keyboard_bytes: [u8; 2], program_counter: [u8; 3], //FIXME use a device pixel_reg: u8, @@ -16,7 +17,7 @@ pub struct MemoryMappedIO { impl MemoryMappedIO { pub fn new() -> MemoryMappedIO { MemoryMappedIO { - keyboard_bytes: [0,0], + keyboard_bytes: [0, 0], program_counter: [0, 0, 0], pixel_reg: 0, audio_sample_address_base: [0, 0], @@ -42,31 +43,32 @@ const AUDIO_SAMPLE_BASE_LEN: u32 = 2; const AUDIO_SAMPLE_BASE_END: u32 = AUDIO_SAMPLE_BASE_START + AUDIO_SAMPLE_BASE_LEN - 1; impl Memory for MemoryMappedIO { - fn get_byte(&self, address: u32) -> u8 { - match address { + fn try_get_byte(&self, address: u32) -> EmulatorResult { + let byte = match address { KEYBOARD_BIT_START..=KEYBOARD_BIT_END => { let addr_usize = address as usize; let keyboard_byte = self.keyboard_bytes[addr_usize]; log::trace!("Fetching keyboard({}) byte segment {} -> {}",MemoryOperations::read_big_endian_u16(&self.keyboard_bytes),address,keyboard_byte); keyboard_byte - }, + } PC_START_ADDR..=PC_END_ADDR => { let pc_index = (address - PC_START_ADDR) as usize; let pc_byte = self.program_counter[pc_index]; log::trace!("Fetching PC({}) byte segment {} -> {}",MemoryOperations::read_big_endian_u24(&self.program_counter),pc_index,pc_byte); pc_byte - }, + } PIXEL_BASE => { log::trace!("Fetching pixel base reg {}",self.pixel_reg); self.pixel_reg - }, + } AUDIO_SAMPLE_BASE_START => self.audio_sample_address_base[0], AUDIO_SAMPLE_BASE_END => self.audio_sample_address_base[1], _ => { panic!("Unreachable code") } - } + }; + Ok(byte) } - fn set_byte(&mut self, address: u32, val: u8) { + fn try_set_byte(&mut self, address: u32, val: u8) -> EmulatorResult<()> { todo!() } } diff --git a/src/emu/mem.rs b/src/emu/mem.rs index de153ee..ebb14b5 100644 --- a/src/emu/mem.rs +++ b/src/emu/mem.rs @@ -1,4 +1,8 @@ +use std::ops::Index; use crate::emu::mmu::Memory; +use crate::misc::emulator_error::DeviceType::RAM; +use crate::misc::emulator_error::EmulatorError; +use crate::misc::result::EmulatorResult; const MEM_LENGTH: usize = 2 << 24; @@ -8,21 +12,30 @@ pub struct RamMemory { } impl RamMemory { - pub fn new() -> RamMemory { - RamMemory { - data: vec![0; MEM_LENGTH].into_boxed_slice().try_into().expect("Incorrect ram allocation") - } + pub fn try_new() -> EmulatorResult { + let alloc_result = vec![0; MEM_LENGTH].into_boxed_slice(); + let data = alloc_result.try_into().map_err(|err|{ + EmulatorError::AllocationError(RAM,"Allocation failed") + })?; + Ok(RamMemory { + data + }) } } + impl Memory for RamMemory { - fn get_byte(&self, address: u32) -> u8 { + fn try_get_byte(&self, address: u32) -> EmulatorResult { log::trace!("Fetch RAM memory at address {}",address); - let x = *self.data.get(address as usize).expect("Unchecked address fetch"); - x + let x = *self.data.get(address as usize).ok_or(EmulatorError::UnreachableMemoryError(RAM,address))?; + Ok(x) } - fn set_byte(&mut self, address: u32, val: u8) { - self.data[address as usize] = val; + fn try_set_byte(&mut self, address: u32, value: u8) -> EmulatorResult<()> { + if address>= MEM_LENGTH as u32 { + return Err(EmulatorError::UnreachableMemoryError(RAM,address)) + } + self.data[address as usize] = value; + Ok(()) } } \ No newline at end of file diff --git a/src/emu/mmu.rs b/src/emu/mmu.rs index 1c47db6..56ee6f5 100644 --- a/src/emu/mmu.rs +++ b/src/emu/mmu.rs @@ -1,47 +1,55 @@ use crate::emu::iomem::MemoryMappedIO; use crate::emu::mem::RamMemory; +use crate::misc::emulator_error::DeviceType::MMU; + +use crate::misc::emulator_error::EmulatorError::UnreachableMemoryError; +use crate::misc::result::EmulatorResult; // 8 bytes that are memory mapped i/o -pub const MMAPPEDIO_END: u32 = RAM_MEM_START-1; -pub const RAM_MEM_START:u32 = 8; +pub const MMAPPEDIO_END: u32 = RAM_MEM_START - 1; +pub const RAM_MEM_START: u32 = 8; /// Last index of ram -pub const RAM_MEM_END: u32 = 2<<24 - 1; +pub const RAM_MEM_END: u32 = 2 << 24 - 1; /// /// mapped I/O + RAM. pub trait Memory { /// Get the value (24bit) at the address(24bit) - fn get_byte(&self, address: u32) -> u8; + fn try_get_byte(&self, address: u32) -> EmulatorResult; /// Set the value at the 24bit address - fn set_byte(&mut self, address: u32, value: u8); + fn try_set_byte(&mut self, address: u32, value: u8) -> EmulatorResult<()>; } -#[derive(Debug,Clone)] + +#[derive(Debug, Clone)] pub struct MappedMemory { memory_mapped_io: MemoryMappedIO, ram_memory: RamMemory, } + impl MappedMemory { - pub fn new(memory_mapped_io: MemoryMappedIO, ram_memory: RamMemory)-> MappedMemory { + pub fn new(memory_mapped_io: MemoryMappedIO, ram_memory: RamMemory) -> MappedMemory { MappedMemory { memory_mapped_io, - ram_memory + ram_memory, } } } impl Memory for MappedMemory { - fn get_byte(&self, address: u32) -> u8 { - match address { + fn try_get_byte(&self, address: u32) -> EmulatorResult { + let byte_at_addr = match address { 0..=MMAPPEDIO_END => { - self.memory_mapped_io.get_byte(address) - }, - RAM_MEM_START..=RAM_MEM_END =>{ - self.ram_memory.get_byte(address) + self.memory_mapped_io.try_get_byte(address) } - _ => { panic!("Invalid address") } - } + RAM_MEM_START..=RAM_MEM_END => { + self.ram_memory.try_get_byte(address) + } + _ => { Err(UnreachableMemoryError(MMU, address)) } + }?; + + Ok(byte_at_addr) } - fn set_byte(&mut self, address: u32, value: u8) { + fn try_set_byte(&mut self, address: u32, value: u8) -> EmulatorResult<()> { todo!() } } diff --git a/src/main.rs b/src/main.rs index a929eae..d77dd0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,19 +2,20 @@ use simple_logger::SimpleLogger; use crate::emu::iomem::MemoryMappedIO; use crate::emu::mem::RamMemory; use crate::emu::mmu::{Memory, MappedMemory}; +use crate::misc::emulator_error::EmulatorError; mod emu; mod args; mod misc; -fn main() { +fn main() ->Result<(),EmulatorError> { SimpleLogger::new().env().init().unwrap(); let mmio = MemoryMappedIO::new(); - let ram = RamMemory::new(); + let ram = RamMemory::try_new()?; let mmu = MappedMemory::new(mmio, ram); for i in 0..10 { - log::info!("Memory at {} is {}",i,mmu.get_byte(i)); + log::info!("Memory at {} is {}",i,mmu.try_get_byte(i)?); } - + Ok(()) } diff --git a/src/misc/emulator_error.rs b/src/misc/emulator_error.rs new file mode 100644 index 0000000..c2e1efc --- /dev/null +++ b/src/misc/emulator_error.rs @@ -0,0 +1,21 @@ +use std::fmt::Debug; + +#[derive(Debug)] +pub enum DeviceType { + RAM, + MMU, + KEYBOARD, + AUDIO, + GRAPHICS, +} + +#[derive(Debug)] +pub enum EmulatorError { + AllocationError(DeviceType, &'static str), + UnreachableMemoryError(DeviceType, u32), +} + + + + + diff --git a/src/misc/mod.rs b/src/misc/mod.rs index 52b9862..7113f1e 100644 --- a/src/misc/mod.rs +++ b/src/misc/mod.rs @@ -1 +1,3 @@ -pub mod endian; \ No newline at end of file +pub mod endian; +pub mod emulator_error; +pub mod result; \ No newline at end of file diff --git a/src/misc/result.rs b/src/misc/result.rs new file mode 100644 index 0000000..78f8832 --- /dev/null +++ b/src/misc/result.rs @@ -0,0 +1,3 @@ +use crate::misc::emulator_error::EmulatorError; + +pub type EmulatorResult = Result; \ No newline at end of file