From 09dc9bd473ee766b055f9594bba342ad7ad2d48c Mon Sep 17 00:00:00 2001 From: Atreya Bain Date: Mon, 19 Feb 2024 14:25:57 +0530 Subject: [PATCH] [ref] format and use methods to get references Plus, add setting keyboard support --- src/emu/cpu.rs | 65 +++++++++++++++----------------- src/emu/graphics.rs | 20 +++++----- src/emu/memory.rs | 60 +++++++++++++++++------------ src/graphics/graphics_adapter.rs | 4 +- src/misc/emulator_error.rs | 10 ++--- src/misc/endian.rs | 4 ++ 6 files changed, 86 insertions(+), 77 deletions(-) diff --git a/src/emu/cpu.rs b/src/emu/cpu.rs index b4e2490..69d7274 100644 --- a/src/emu/cpu.rs +++ b/src/emu/cpu.rs @@ -4,49 +4,49 @@ use crate::misc::endian::{read_big_endian_u24, write_big_endian_u24}; use crate::misc::result::EmulatorResult; #[derive(Debug)] -pub enum CpuState{ +pub enum CpuState { Running, - Paused + Paused, } #[derive(Debug)] -pub struct Cpu<'a>{ - pub memory: &'a RamMemory, - pub graphics_processor: &'a GraphicsProcessor<'a> +pub struct Cpu<'a> { + memory: &'a RamMemory, + graphics_processor: &'a GraphicsProcessor<'a>, } -impl <'a> Cpu<'a>{ - const PC_START:usize = 2; - const PC_LEN:usize = 3; - const PC_ZERO:[u8;3] = [0;3]; - pub fn new(memory: &'a RamMemory, graphics_processor: &'a GraphicsProcessor<'a>) ->Cpu<'a>{ - Cpu{ +impl<'a> Cpu<'a> { + const PC_START: usize = 2; + const PC_LEN: usize = 3; + const PC_ZERO: [u8; 3] = [0; 3]; + pub fn new(memory: &'a RamMemory, graphics_processor: &'a GraphicsProcessor<'a>) -> Cpu<'a> { + Cpu { graphics_processor, - memory + memory, } } - pub fn get_pc(&self)->u32{ - let memory_slice = self.memory.data.borrow(); - let data = memory_slice.get(Self::PC_START..(Self::PC_START+Self::PC_LEN)).unwrap(); + pub fn get_pc(&self) -> u32 { + let memory_slice = self.memory.get_data_ref(); + let data = memory_slice.get(Self::PC_START..(Self::PC_START + Self::PC_LEN)).unwrap(); read_big_endian_u24(data.try_into().unwrap()) } - pub fn set_pc(&self,address:u32){ - let mut memory_slice = self.memory.data.borrow_mut(); + pub fn set_pc(&self, address: u32) { + let mut memory_slice = self.memory.get_data_ref_mut(); let mut pc_big_endian_slice = Self::PC_ZERO; - write_big_endian_u24(address,&mut pc_big_endian_slice); + write_big_endian_u24(address, &mut pc_big_endian_slice); memory_slice[Self::PC_START..(Self::PC_START + Self::PC_LEN)].copy_from_slice(&pc_big_endian_slice); } - pub fn cycle(&self)->EmulatorResult<()>{ - for _i in 0..65536{ + pub fn cycle(&self) -> EmulatorResult<()> { + for _i in 0..65536 { let address_to_execute = self.get_pc(); //execute p1 self.copy_u24(address_to_execute)?; //execute p2 - let new_pc_location = address_to_execute+2*(Self::PC_LEN as u32) ; + let new_pc_location = address_to_execute + 2 * (Self::PC_LEN as u32); let new_pc = self.memory.try_get_u24(new_pc_location)?; @@ -60,20 +60,20 @@ impl <'a> Cpu<'a>{ fn copy_u24(&self, address_to_execute: u32) -> EmulatorResult<()> { let aloc = self.memory.try_get_u24(address_to_execute)?; - let bloc = self.memory.try_get_u24(address_to_execute+Self::PC_LEN as u32)?; + let bloc = self.memory.try_get_u24(address_to_execute + Self::PC_LEN as u32)?; - self.memory.try_set_byte(bloc,self.memory.try_get_byte(aloc)?) + self.memory.try_set_byte(bloc, self.memory.try_get_byte(aloc)?) } - fn fetch_triplet(&self, address: u32) -> EmulatorResult<[u8;3]> { + fn fetch_triplet(&self, address: u32) -> EmulatorResult<[u8; 3]> { let first_byte = self.memory.try_get_byte(address)?; - let second_byte = self.memory.try_get_byte(address+1)?; - let third_byte = self.memory.try_get_byte(address+2)?; - let num = [first_byte,second_byte,third_byte]; + let second_byte = self.memory.try_get_byte(address + 1)?; + let third_byte = self.memory.try_get_byte(address + 2)?; + let num = [first_byte, second_byte, third_byte]; Ok(num) } - fn set_triplet(&self, address: u32, val:&[u8;3]) -> EmulatorResult<()> { + fn set_triplet(&self, address: u32, val: &[u8; 3]) -> EmulatorResult<()> { self.memory.try_set_byte(address, val[0])?; self.memory.try_set_byte(address + 1, val[1])?; self.memory.try_set_byte(address + 2, val[2])?; @@ -82,13 +82,8 @@ impl <'a> Cpu<'a>{ } - #[cfg(test)] -mod test{ - +mod test { #[test] - pub fn construct(){ - - } - + pub fn construct() {} } \ No newline at end of file diff --git a/src/emu/graphics.rs b/src/emu/graphics.rs index a63cf2b..887b358 100644 --- a/src/emu/graphics.rs +++ b/src/emu/graphics.rs @@ -14,7 +14,7 @@ pub struct GraphicsProcessor<'a> { } /// Abstracted graphics processor. Calls `[GraphicsAdapter]` with the associated framebuffer -impl <'a> GraphicsProcessor<'a> { +impl<'a> GraphicsProcessor<'a> { pub fn try_new(ram_memory: &'a RamMemory) -> EmulatorResult { let framebuffer = vec![0; DEVICE_FRAMEBUFFER_SIZE].into_boxed_slice() .try_into() @@ -26,11 +26,11 @@ impl <'a> GraphicsProcessor<'a> { frame_buffer: RefCell::new(framebuffer), }) } - /// take a copy of FB and - pub fn draw(&self)->EmulatorResult<()>{ - self.copy_indicated_pixel_data_block()?; - let fb_immut = self.frame_buffer.borrow(); - Ok(()) + /// Draw the pixels. + /// Since this is a VM, we just copy and store it in a buffer. + /// take a copy of FB and store it + pub fn draw(&self) -> EmulatorResult<()> { + self.copy_indicated_pixel_data_block() } fn copy_indicated_pixel_data_block(&self) -> Result<(), EmulatorError> { @@ -40,16 +40,14 @@ impl <'a> GraphicsProcessor<'a> { self.ram.get_block(fb_base_register, fb.as_mut())?; Ok(()) } - fn set_framebuffer(&self, memory_slice: &[u8;DEVICE_FRAMEBUFFER_SIZE]) { + fn set_framebuffer(&self, memory_slice: &[u8; DEVICE_FRAMEBUFFER_SIZE]) { let mut fb = self.frame_buffer.borrow_mut(); fb.copy_from_slice(memory_slice); } - pub fn get_framebuffer(&self)->Ref>{ + pub fn get_framebuffer(&self) -> Ref> { self.frame_buffer.borrow() } } #[cfg(test)] -mod test{ - -} \ No newline at end of file +mod test {} \ No newline at end of file diff --git a/src/emu/memory.rs b/src/emu/memory.rs index a289828..f0d0d8a 100644 --- a/src/emu/memory.rs +++ b/src/emu/memory.rs @@ -1,8 +1,8 @@ -use std::cell::RefCell; +use std::cell::{Ref, RefCell, RefMut}; use crate::misc::emulator_error::DeviceType::RAM; use crate::misc::emulator_error::EmulatorError; -use crate::misc::endian::read_big_endian_u24; +use crate::misc::endian::{read_big_endian_u24, write_big_endian_u16}; use crate::misc::result::EmulatorResult; pub const MEM_LENGTH: usize = 2 << 23; @@ -17,13 +17,13 @@ pub trait Memory { #[derive(Clone, Debug)] pub struct RamMemory { - pub data: RefCell>, + data: RefCell>, } impl RamMemory { pub fn try_new() -> EmulatorResult { let alloc_result = vec![0; MEM_LENGTH].into_boxed_slice(); - let data = alloc_result.try_into().map_err(|err|{ + let data = alloc_result.try_into().map_err(|err| { EmulatorError::AllocationFailure(RAM, "Allocation failed") })?; let data_refcell = RefCell::new(data); @@ -31,35 +31,47 @@ impl RamMemory { data: data_refcell }) } - pub fn try_from(existing_data:&[u8]) -> EmulatorResult{ + pub fn try_from(existing_data: &[u8]) -> EmulatorResult { let alloc_result = vec![0u8; MEM_LENGTH].into_boxed_slice(); // get box of fixed size - let mut fixed_size_alloc_box:Box<[u8;MEM_LENGTH]> = alloc_result.try_into().unwrap(); + let mut fixed_size_alloc_box: Box<[u8; MEM_LENGTH]> = alloc_result.try_into().unwrap(); fixed_size_alloc_box.copy_from_slice(&existing_data); - Ok(RamMemory{ + Ok(RamMemory { data: RefCell::new(fixed_size_alloc_box) }) } - pub fn try_get_u24(&self,index:u32)->EmulatorResult{ - const U24_LEN:usize = 3; + pub fn try_get_u24(&self, index: u32) -> EmulatorResult { + const U24_LEN: usize = 3; let index_usize = index as usize; let data = self.data.borrow(); - let a = data.get(index_usize..(index_usize +U24_LEN)).ok_or(EmulatorError::UnreachableMemory(RAM, index))?; + let a = data.get(index_usize..(index_usize + U24_LEN)).ok_or(EmulatorError::UnreachableMemory(RAM, index))?; Ok(read_big_endian_u24(a.try_into()?)) } - pub fn get_block(&self,address:u32,output:&mut [u8])->EmulatorResult<()>{ + pub fn get_block(&self, address: u32, output: &mut [u8]) -> EmulatorResult<()> { let address = address as usize; let data = self.data.borrow(); - let data_requested_slice = data.get(address..address+output.len()).ok_or(EmulatorError::UnreachableMemory(RAM,address as u32))?; + let data_requested_slice = data.get(address..address + output.len()).ok_or(EmulatorError::UnreachableMemory(RAM, address as u32))?; output.copy_from_slice(data_requested_slice); Ok(()) } - + pub fn get_data_ref(&self) -> Ref> { + self.data.borrow() + } + pub fn get_data_ref_mut(&self) -> RefMut> { + self.data.borrow_mut() + } + /// set keyboard bits + pub fn set_keyboard(&self,keyboard_bits: u16) { + let mut keyboard_slice_ref = self.data.borrow_mut(); + let keyboard_slice = keyboard_slice_ref.get_mut(0..2).unwrap(); + write_big_endian_u16(keyboard_bits,keyboard_slice.try_into().unwrap()); + } } + impl Memory for RamMemory { fn try_get_byte(&self, address: u32) -> EmulatorResult { log::trace!("Fetch RAM memory at address {}",address); @@ -69,8 +81,8 @@ impl Memory for RamMemory { } fn try_set_byte(&self, address: u32, value: u8) -> EmulatorResult<()> { - if address>= MEM_LENGTH as u32 { - return Err(EmulatorError::UnreachableMemory(RAM, address)) + if address >= MEM_LENGTH as u32 { + return Err(EmulatorError::UnreachableMemory(RAM, address)); } let mut data = self.data.borrow_mut(); data[address as usize] = value; @@ -79,28 +91,28 @@ impl Memory for RamMemory { } - - #[cfg(test)] -mod tests{ +mod tests { use crate::emu::memory::RamMemory; use crate::emu::memory::Memory; - const EXAMPLE_ADDRESS:u32=0x24; + + const EXAMPLE_ADDRESS: u32 = 0x24; #[test] - pub fn get_mem(){ + pub fn get_mem() { let ram_result = RamMemory::try_new(); assert!(ram_result.is_ok()) } + #[test] - pub fn get_set_memory(){ - const EXAMPLE_DATA:u8 = 0xa5; + pub fn get_set_memory() { + const EXAMPLE_DATA: u8 = 0xa5; let mut ram = RamMemory::try_new().unwrap(); let byte_before = ram.try_get_byte(EXAMPLE_ADDRESS).unwrap(); ram.try_set_byte(EXAMPLE_ADDRESS, EXAMPLE_DATA).unwrap(); let byte_after = ram.try_get_byte(EXAMPLE_ADDRESS).unwrap(); - assert_eq!(0,byte_before); - assert_eq!(EXAMPLE_DATA,byte_after); + assert_eq!(0, byte_before); + assert_eq!(EXAMPLE_DATA, byte_after); } } diff --git a/src/graphics/graphics_adapter.rs b/src/graphics/graphics_adapter.rs index 8e7df24..3d324e7 100644 --- a/src/graphics/graphics_adapter.rs +++ b/src/graphics/graphics_adapter.rs @@ -9,7 +9,7 @@ use crate::misc::result::EmulatorResult; #[derive(Clone)] pub struct SDLGraphicsAdapter<'a> { - pub graphics_processor: &'a GraphicsProcessor<'a>, + graphics_processor: &'a GraphicsProcessor<'a>, } impl<'a> Debug for SDLGraphicsAdapter<'a> { @@ -45,7 +45,7 @@ impl<'a> SDLGraphicsAdapter<'a> { fn draw_scaled_point(canvas: &mut WindowCanvas, coordinates: (i32, i32), draw_factor: u32) -> Result<(), EmulatorError> { canvas - .fill_rect(Rect::new(coordinates.0*draw_factor as i32, coordinates.1*draw_factor as i32, draw_factor, draw_factor)) + .fill_rect(Rect::new(coordinates.0 * draw_factor as i32, coordinates.1 * draw_factor as i32, draw_factor, draw_factor)) .map_err(|str| EmulatorError::OtherError(str)) } } diff --git a/src/misc/emulator_error.rs b/src/misc/emulator_error.rs index 8317fc9..3f88f0f 100644 --- a/src/misc/emulator_error.rs +++ b/src/misc/emulator_error.rs @@ -18,16 +18,16 @@ pub enum EmulatorError { UnreachableMemory(DeviceType, u32), InvalidColor(u8), EmulatorIOError(Error), - OtherError(String) + OtherError(String), } -impl From for EmulatorError{ - fn from(value: TryFromSliceError) -> Self { - EmulatorError::UnreachableMemory(DeviceType::RAM,0x5a5a) +impl From for EmulatorError { + fn from(_: TryFromSliceError) -> Self { + EmulatorError::UnreachableMemory(DeviceType::RAM, 0x5a5a) } } -impl From for EmulatorError{ +impl From for EmulatorError { fn from(value: Error) -> Self { EmulatorIOError(value) } diff --git a/src/misc/endian.rs b/src/misc/endian.rs index 8db0b57..1d037f6 100644 --- a/src/misc/endian.rs +++ b/src/misc/endian.rs @@ -10,4 +10,8 @@ pub fn read_big_endian_u16(input: &[u8; 2]) -> u16 { /// Write 24-bit endian number into slice pub fn write_big_endian_u24(input: u32, output_slice: &mut [u8; 3]) { BigEndian::write_u24(output_slice, input); +} + +pub fn write_big_endian_u16(input: u16, output_slice: &mut [u8; 2]) { + BigEndian::write_u16(output_slice, input); } \ No newline at end of file