diff --git a/src/emu/cpu.rs b/src/emu/cpu.rs index b6d88ec..121293d 100644 --- a/src/emu/cpu.rs +++ b/src/emu/cpu.rs @@ -1,6 +1,7 @@ -use crate::emu::mmu::{MappedMemory, Memory}; -use crate::emu::program_counter::ProgramCounter; -use crate::misc::endian::read_big_endian_u24; +use crate::emu::graphics::GraphicsProcessor; +use crate::emu::mmu::{ Memory}; +use crate::emu::ram::RamMemory; +use crate::misc::endian::{read_big_endian_u24, write_big_endian_u24}; use crate::misc::result::EmulatorResult; #[derive(Debug)] @@ -11,56 +12,75 @@ pub enum CpuState{ #[derive(Debug)] pub struct Cpu<'a>{ - mapped_memory:&'a MappedMemory<'a>, - program_counter: &'a ProgramCounter + pub memory: &'a RamMemory, + pub graphics_processor: &'a GraphicsProcessor<'a> } impl <'a> Cpu<'a>{ - pub fn new(mapped_memory: &'a MappedMemory<'a>,program_counter: &'a ProgramCounter)->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{ - mapped_memory, - program_counter + graphics_processor, + 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(); + read_big_endian_u24(data.try_into().unwrap()) + } + pub fn set_pc(&self,address:u32){ + let mut memory_slice = self.memory.data.borrow_mut(); + + let mut pc_big_endian_slice = Self::PC_ZERO; + 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{ - let address_to_execute = self.program_counter.get_pc_value(); + let address_to_execute = self.get_pc(); //fetch - let num1 = self.fetch_triplet(address_to_execute)?; - self.set_triplet(address_to_execute+3,&num1)?; - - let new_pc = read_big_endian_u24(&self.fetch_triplet(address_to_execute+6)?); - self.program_counter.set_address(new_pc)?; + self.copy_u24(address_to_execute)?; + let new_pc_location = address_to_execute+2*(Self::PC_LEN as u32) ; + let new_pc = self.memory.try_get_u24(new_pc_location)?; + self.set_pc(new_pc); } - // TODO send graphics + log::debug!("Finished internal loop"); + self.graphics_processor.draw()?; // TODO send audio Ok(()) } + 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)?; + + self.memory.try_set_byte(bloc,self.memory.try_get_byte(aloc)?) + } + + fn fetch_triplet(&self, address: u32) -> EmulatorResult<[u8;3]> { - let first_byte = self.mapped_memory.try_get_byte(address)?; - let second_byte = self.mapped_memory.try_get_byte(address+1)?; - let third_byte = self.mapped_memory.try_get_byte(address+2)?; + 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]; Ok(num) } fn set_triplet(&self, address: u32, val:&[u8;3]) -> EmulatorResult<()> { - self.mapped_memory.try_set_byte(address, val[0])?; - self.mapped_memory.try_set_byte(address + 1, val[1])?; - self.mapped_memory.try_set_byte(address + 2, val[2])?; + 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])?; Ok(()) } - fn set_pc(&self,value: &[u8;3])->EmulatorResult<()>{ - let x = read_big_endian_u24(value); - self.program_counter.set_address(x) - } } - - #[cfg(test)] mod test{ diff --git a/src/emu/graphics.rs b/src/emu/graphics.rs index 99ccfb1..7090532 100644 --- a/src/emu/graphics.rs +++ b/src/emu/graphics.rs @@ -1,5 +1,6 @@ -use std::cell::RefCell; -use crate::graphics::graphics_adapter::GraphicsAdapter; +use std::cell::{Ref, RefCell}; +use crate::emu::mmu::Memory; +use crate::emu::ram::RamMemory; use crate::misc::emulator_error::DeviceType::GRAPHICS; use crate::misc::emulator_error::EmulatorError; use crate::misc::result::EmulatorResult; @@ -7,34 +8,45 @@ use crate::misc::result::EmulatorResult; pub const DEVICE_FRAMEBUFFER_SIZE: usize = 256 * 256; #[derive(Debug)] -pub struct GraphicsProcessor { +pub struct GraphicsProcessor<'a> { + ram: &'a RamMemory, frame_buffer: RefCell>, - graphics_adapter: Box } -/// Abstracted graphics processor. Calls `[GraphicsAdapter]` -impl GraphicsProcessor { - pub fn try_new(graphics_adapter: Box) -> EmulatorResult { +/// Abstracted graphics processor. Calls `[GraphicsAdapter]` with the associated framebuffer +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() .map_err(|_| { EmulatorError::AllocationFailure(GRAPHICS, "Failed to allocate graphics") })?; Ok(GraphicsProcessor { + ram: ram_memory, frame_buffer: RefCell::new(framebuffer), - graphics_adapter }) } /// take a copy of FB and - pub fn draw(&self, memory_slice: &[u8;DEVICE_FRAMEBUFFER_SIZE])->EmulatorResult<()>{ - self.set_framebuffer(memory_slice); + pub fn draw(&self)->EmulatorResult<()>{ + self.copy_indicated_pixel_data_block()?; let fb_immut = self.frame_buffer.borrow(); - self.graphics_adapter.draw(fb_immut) + Ok(()) + } + + fn copy_indicated_pixel_data_block(&self) -> Result<(), EmulatorError> { + let fb_base_register = (self.ram.try_get_byte(5)? as u32) << 16; + let mut fb = self.frame_buffer.borrow_mut(); + + self.ram.get_block(fb_base_register, fb.as_mut())?; + Ok(()) } 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>{ + self.frame_buffer.borrow() + } } #[cfg(test)] diff --git a/src/emu/iomem.rs b/src/emu/iomem.rs deleted file mode 100644 index d05937d..0000000 --- a/src/emu/iomem.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::cell::Cell; -use crate::emu::mmu::Memory; -use crate::emu::program_counter::ProgramCounter; -use crate::misc::emulator_error::{EmulatorError}; -use crate::misc::emulator_error::DeviceType::MMU; -use crate::misc::endian::{read_big_endian_u16}; -use crate::misc::result::EmulatorResult; - -#[derive(Debug)] -pub struct MemoryMappedIO<'a> { - //FIXME use a keyboard - keyboard_bytes: Cell<[u8; 2]>, - program_counter: &'a ProgramCounter, - //FIXME use a device - pixel_reg: Cell, - //FIXME use a device - audio_sample_address_base: Cell<[u8; 2]>, -} - -/// Represents the memory mapped segment of IO. Aggregates the mapping logic. -impl<'a> MemoryMappedIO<'a> { - // 2 byte keyboard bits - pub const KEYBOARD_BIT_START: u32 = 0; - const KEYBOARD_BIT_END: u32 = 1; - - // 3 bytes PC - const PC_START_ADDR: u32 = 2; - const PC_LEN: u32 = 3; - const PC_END_ADDR: u32 = Self::PC_START_ADDR + Self::PC_LEN - 1; - - // 1 byte pixel base reg - pub const PIXEL_BASE: u32 = 5; - - // 2 byte audio sample base reg - pub const AUDIO_SAMPLE_BASE_START: u32 = 6; - pub const AUDIO_SAMPLE_BASE_LEN: u32 = 2; - const AUDIO_SAMPLE_BASE_END: u32 = Self::AUDIO_SAMPLE_BASE_START + Self::AUDIO_SAMPLE_BASE_LEN - 1; - - pub fn new(program_counter: &'a ProgramCounter) -> MemoryMappedIO<'a> { - MemoryMappedIO { - keyboard_bytes: Cell::new([0, 0]), - program_counter, - pixel_reg: Cell::new(0), - audio_sample_address_base: Cell::new([0, 0]), - } - } -} - - -impl<'a> Memory for MemoryMappedIO<'a> { - fn try_get_byte(&self, address: u32) -> EmulatorResult { - let byte = match address { - Self::KEYBOARD_BIT_START..=Self::KEYBOARD_BIT_END => { - let addr_usize = address as usize; - let keyboard_bytes = self.keyboard_bytes.get(); - let keyboard_byte = keyboard_bytes[addr_usize]; - log::trace!("Fetching keyboard({}) byte segment {} -> {}",read_big_endian_u16(&keyboard_bytes),address,keyboard_byte); - Ok(keyboard_byte) - } - Self::PC_START_ADDR..=Self::PC_END_ADDR => { - let pc_index = address - Self::PC_START_ADDR; - self.program_counter.try_get_byte(pc_index) - } - Self::PIXEL_BASE => { - log::trace!("Fetching pixel base reg {}",self.pixel_reg.get()); - Ok(self.pixel_reg.get()) - } - Self::AUDIO_SAMPLE_BASE_START => Ok(self.audio_sample_address_base.get()[0]), - Self::AUDIO_SAMPLE_BASE_END => Ok(self.audio_sample_address_base.get()[1]), - address => { - Err(EmulatorError::UnreachableMemory(MMU, address)) - } - }; - byte - } - - fn try_set_byte(&self, address: u32, byte_value: u8) -> EmulatorResult<()> { - match address { - Self::KEYBOARD_BIT_START..=Self::KEYBOARD_BIT_END => { - let mut keyboard_bytes = self.keyboard_bytes.get(); - log::trace!("Setting keyboard({}) byte segment {} -> {}",read_big_endian_u16(&keyboard_bytes),address,byte_value); - keyboard_bytes[address as usize] = byte_value; - self.keyboard_bytes.set(keyboard_bytes); - } - Self::PC_START_ADDR..=Self::PC_END_ADDR => { - let pc_index = address - Self::PC_START_ADDR; - self.program_counter.try_set_byte(pc_index, byte_value)? - } - Self::PIXEL_BASE => { - log::trace!("Setting pixel base reg to {}",byte_value); - self.pixel_reg.set(byte_value); - } - Self::AUDIO_SAMPLE_BASE_START..=Self::AUDIO_SAMPLE_BASE_END => { - let audio_reg_index = (address - Self::AUDIO_SAMPLE_BASE_START) as usize; - let mut audio_sample_address_base = self.audio_sample_address_base.get(); - audio_sample_address_base[audio_reg_index] = byte_value; - self.audio_sample_address_base.set(audio_sample_address_base); - } - _ => { return Err(EmulatorError::UnreachableMemory(MMU, address)); } - }; - Ok(()) - } -} diff --git a/src/emu/mmu.rs b/src/emu/mmu.rs index 4d6ae08..8a71bd5 100644 --- a/src/emu/mmu.rs +++ b/src/emu/mmu.rs @@ -1,17 +1,5 @@ -use crate::emu::iomem::MemoryMappedIO; -use crate::emu::ram::RamMemory; -use crate::misc::emulator_error::DeviceType::MMU; - -use crate::misc::emulator_error::EmulatorError::UnreachableMemory; 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; -/// Last index of ram -pub const RAM_MEM_END: u32 = 2 << 24 - 1; - -/// /// mapped I/O + RAM. pub trait Memory { /// Get the value (24bit) at the address(24bit) @@ -20,47 +8,4 @@ pub trait Memory { fn try_set_byte(&self, address: u32, value: u8) -> EmulatorResult<()>; } -#[derive(Debug)] -pub struct MappedMemory<'a> { - memory_mapped_io: &'a MemoryMappedIO<'a>, - ram_memory: &'a RamMemory, -} - -impl <'a> MappedMemory<'a> { - pub fn new(memory_mapped_io: &'a MemoryMappedIO<'a>, ram_memory:&'a RamMemory) -> MappedMemory<'a> { - MappedMemory { - memory_mapped_io, - ram_memory, - } - } -} - -impl <'a> Memory for MappedMemory<'a> { - fn try_get_byte(&self, address: u32) -> EmulatorResult { - let byte_at_addr = match address { - 0..=MMAPPEDIO_END => { - self.memory_mapped_io.try_get_byte(address) - } - RAM_MEM_START..=RAM_MEM_END => { - let memory_index = address - RAM_MEM_START; - self.ram_memory.try_get_byte(memory_index) - } - _ => { Err(UnreachableMemory(MMU, address)) } - }?; - - Ok(byte_at_addr) - } - fn try_set_byte(&self, address: u32, value: u8) -> EmulatorResult<()> { - match address { - 0..=MMAPPEDIO_END => { - self.memory_mapped_io.try_set_byte(address,value) - } - RAM_MEM_START..=RAM_MEM_END => { - let memory_index = address - RAM_MEM_START; - self.ram_memory.try_set_byte(memory_index,value) - } - _ => { Err(UnreachableMemory(MMU, address)) } - } - } -} diff --git a/src/emu/mod.rs b/src/emu/mod.rs index 2fec204..be48bdd 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -1,6 +1,4 @@ pub mod cpu; pub mod mmu; pub mod ram; -pub mod iomem; -pub mod program_counter; pub mod graphics; \ No newline at end of file diff --git a/src/emu/program_counter.rs b/src/emu/program_counter.rs deleted file mode 100644 index 054f469..0000000 --- a/src/emu/program_counter.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::cell::Cell; -use crate::emu::mmu::{Memory}; -use crate::misc::emulator_error::DeviceType::PC; -use crate::misc::emulator_error::EmulatorError; -use crate::misc::endian::{read_big_endian_u24, write_big_endian_u24}; -use crate::misc::result::EmulatorResult; - - -#[derive(Debug, Default, Clone)] -pub struct ProgramCounter { - /// 24bit location register - program_counter_register: Cell<[u8; 3]>, -} - -impl ProgramCounter { - const PROGRAM_COUNTER_ZERO:[u8;3] = [0;3]; - pub fn new() -> ProgramCounter { - ProgramCounter { - program_counter_register: Cell::new(Self::PROGRAM_COUNTER_ZERO) - } - } - // get the current program counter as an address - pub fn get_pc_value(&self) -> u32 { - read_big_endian_u24(&self.program_counter_register.get()) - } - // assign a value of PC to start execution - pub fn set_address(&self, address: u32) -> EmulatorResult<()> { - log::debug!("Setting PC as {}",address); - if address >= (2 << 24) { - return Err(EmulatorError::UnreachableMemory(PC, address)); - } - let mut data = self.program_counter_register.get(); - write_big_endian_u24(address, &mut data); - self.program_counter_register.set(data); - Ok(()) - } -} - -/// Allow Using Program counter as mapped memory -impl Memory for ProgramCounter { - fn try_get_byte(&self, address: u32) -> EmulatorResult { - log::trace!("Fetching PC({}) byte segment index {}",read_big_endian_u24(&self.program_counter_register.get()),address); - self.program_counter_register.get().get(address as usize) - .map(|e| *e) - .ok_or(EmulatorError::UnreachableMemory(PC, address)) - } - /// TODO: Set a byte of PC from the memory. - fn try_set_byte(&self, address: u32, value: u8) -> EmulatorResult<()> { - match address { - 0..=2 => { - let mut data = self.program_counter_register.get(); - data[address as usize] = value; - self.program_counter_register.set(data); - } - _ => { return Err(EmulatorError::UnreachableMemory(PC, address)); } - } - Ok(()) - } -} - - -#[cfg(test)] -mod test { - use crate::emu::program_counter::ProgramCounter; - - #[test] - pub fn setting_address_works() { - const ADDRESS: u32 = 4; - let mut pc = ProgramCounter::new(); - let res = pc.set_address(ADDRESS); - assert!(res.is_ok()); - assert_eq!(ADDRESS, pc.get_pc_value()); - } - - #[test] - pub fn set_invalid_addr_returns_error() { - const ADDRESS: u32 = 2 << 24; - let mut pc = ProgramCounter::new(); - let res = pc.set_address(ADDRESS); - assert!(res.is_err()); - } -} \ No newline at end of file diff --git a/src/emu/ram.rs b/src/emu/ram.rs index 4163a3c..9d8edee 100644 --- a/src/emu/ram.rs +++ b/src/emu/ram.rs @@ -3,14 +3,15 @@ use std::cell::RefCell; use crate::emu::mmu::Memory; use crate::misc::emulator_error::DeviceType::RAM; use crate::misc::emulator_error::EmulatorError; +use crate::misc::endian::read_big_endian_u24; use crate::misc::result::EmulatorResult; const MAPPED_MEMORY_NOT_REQUIRED: u8 = 8; -const MEM_LENGTH: usize = (2 << 24) - (MAPPED_MEMORY_NOT_REQUIRED as usize); +pub const MEM_LENGTH: usize = 2 << 23; #[derive(Clone, Debug)] pub struct RamMemory { - data: RefCell>, + pub data: RefCell>, } impl RamMemory { @@ -24,6 +25,34 @@ impl RamMemory { data: data_refcell }) } + 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(); + fixed_size_alloc_box.copy_from_slice(&existing_data); + + Ok(RamMemory{ + data: RefCell::new(fixed_size_alloc_box) + }) + } + + 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))?; + Ok(read_big_endian_u24(a.try_into()?)) + } + + 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))?; + output.copy_from_slice(data_requested_slice); + Ok(()) + } + + } diff --git a/src/graphics/color.rs b/src/graphics/color.rs index 7f6e61c..5a02a88 100644 --- a/src/graphics/color.rs +++ b/src/graphics/color.rs @@ -1,6 +1,8 @@ use crate::misc::emulator_error::EmulatorError; use crate::misc::result::EmulatorResult; +/// A Color as represented in BytePusher. +/// It is a byte that contains a packed 6 digit red, green and blue #[derive(Debug, Copy, Clone)] pub struct Color(u8); @@ -26,16 +28,24 @@ impl Color { } Ok(Color(in_mem_color)) } + /// wrap to black if needed + pub fn new(in_mem_color: u8)->Color{ + if in_mem_color > Self::COLOR_MAX { + Color(0) + }else{ + Color(in_mem_color) + } + } pub fn get_mem_byte(&self) -> u8 { self.0 } /// This fetches the rgb triplet - pub fn get_rgb(self) -> [u8; 3] { + pub fn get_rgb(self) -> (u8,u8,u8) { let r = self.0 / Self::RED_MULT; let gb_byte_remainder = self.0 % Self::RED_MULT; let g = gb_byte_remainder / Self::GREEN_MULT; let b = gb_byte_remainder % Self::GREEN_MULT; - [r * Self::COLOR_FACTOR_8_BIT, g * Self::COLOR_FACTOR_8_BIT, b * Self::COLOR_FACTOR_8_BIT] + (r * Self::COLOR_FACTOR_8_BIT, g * Self::COLOR_FACTOR_8_BIT, b * Self::COLOR_FACTOR_8_BIT) } } @@ -47,7 +57,7 @@ mod tests { #[test] pub fn test_from_mem_zero() { let color = Color::try_new(0).unwrap(); - assert_eq!([0u8; 3], color.get_rgb()) + assert_eq!((0,0,0), color.get_rgb()) } #[test] @@ -59,7 +69,7 @@ mod tests { #[test] pub fn test_from_mem_max() { let color = Color::try_new(Color::COLOR_MAX).unwrap(); - assert_eq!([255u8; 3], color.get_rgb()) + assert_eq!((255,255,255), color.get_rgb()) } #[test] diff --git a/src/graphics/graphics_adapter.rs b/src/graphics/graphics_adapter.rs index 3b209fb..6ac3cc3 100644 --- a/src/graphics/graphics_adapter.rs +++ b/src/graphics/graphics_adapter.rs @@ -1,18 +1,53 @@ use std::cell::Ref; -use std::fmt::Debug; +use std::fmt::{Debug, Formatter}; +use sdl2::render::{Canvas, WindowCanvas}; +use crate::emu::graphics::{DEVICE_FRAMEBUFFER_SIZE, GraphicsProcessor}; +use crate::graphics::color::Color; +use crate::misc::emulator_error::EmulatorError; use crate::misc::result::EmulatorResult; -pub trait GraphicsAdapter: Debug { - fn draw(&self, frame_buf: Ref>) -> EmulatorResult<()>; + +#[derive(Clone)] +pub struct SDLGraphicsAdapter<'a> { + pub graphics_processor: &'a GraphicsProcessor<'a> } -#[derive(Debug, Clone)] -pub struct SDLGraphicsAdapter { -} - -impl GraphicsAdapter for SDLGraphicsAdapter { - fn draw(&self, frame_buffer: Ref>) -> EmulatorResult<()> { - todo!() +impl <'a> Debug for SDLGraphicsAdapter<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str("SDL2 adapter") + } +} + +impl <'a> SDLGraphicsAdapter<'a> { + pub fn new(graphics_processor: &'a GraphicsProcessor)->SDLGraphicsAdapter<'a>{ + SDLGraphicsAdapter{ + graphics_processor + } + } + pub fn draw(&self, canvas:&mut WindowCanvas) -> EmulatorResult<()> { + let mut canvas_ref = &canvas; + let fb = self.graphics_processor.get_framebuffer(); + for i in 0..fb.len() { + let i = i as u32; + let y_coord = i&0xff00; + let x_coord = i&0x00ff; + + } + let xyc = fb.iter().enumerate().map(|(i,e)| { + let i = i as u32; + let y_coord = i&0xff00; + let x_coord = i&0x00ff; + let color = Color::new(*e); + (x_coord,y_coord,color) + }); + for (x,y,c) in xyc{ + canvas.set_draw_color(c.get_rgb()); + let coordinates = (x as i32,y as i32); + let draw_result = canvas.draw_point(coordinates).map_err(|str|EmulatorError::OtherError(str)); + + draw_result?; + } + Ok(()) } } diff --git a/src/main.rs b/src/main.rs index 9a6e8d8..90b2508 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,17 @@ +use std::fs::File; +use std::io::Read; use std::time::Duration; use sdl2::event::Event; +use sdl2::EventPump; use sdl2::keyboard::Keycode; use sdl2::pixels::Color; +use sdl2::render::WindowCanvas; use simple_logger::SimpleLogger; use crate::emu::cpu::Cpu; -use crate::emu::iomem::MemoryMappedIO; -use crate::emu::ram::RamMemory; -use crate::emu::mmu::{Memory, MappedMemory}; -use crate::emu::program_counter::ProgramCounter; +use crate::emu::graphics::GraphicsProcessor; +use crate::emu::ram::{MEM_LENGTH, RamMemory}; +use crate::emu::mmu::{Memory}; +use crate::graphics::graphics_adapter::SDLGraphicsAdapter; use crate::misc::result::EmulatorResult; @@ -17,51 +21,60 @@ mod misc; mod graphics; fn main() -> EmulatorResult<()> { + let mut fileLoc = File::open("rom.BytePusher").unwrap(); + let mut filebytes = vec![0u8; MEM_LENGTH]; + let x = fileLoc.read(&mut filebytes).unwrap(); + assert!(x < MEM_LENGTH); SimpleLogger::new().env().init().unwrap(); - let program_counter = ProgramCounter::new(); - let mmio = MemoryMappedIO::new(&program_counter); - let ram = RamMemory::try_new()?; - let mmu = MappedMemory::new(&mmio,&ram); + let ram = RamMemory::try_from(filebytes.as_slice())?; + + let (mut canvas,mut event_pump) = initiate_sdl(); + + let graphics_processor = GraphicsProcessor::try_new(&ram)?; + let sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor); + let cpu = Cpu::new(&ram,&graphics_processor); + + let mut i = 0; + 'running: loop { + i = (i + 1) % 255; + canvas.set_draw_color(Color::RGB(0,0,0)); + canvas.clear(); + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | + Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { + break 'running + }, + event => { + log::info!("Received window event {:?}",event); + } + } + + } - let mut cpu = Cpu::new(&mmu,&program_counter); - for i in 0..1{ cpu.cycle()?; + // The rest of the game loop goes here... + sdl2_graphics_adapter.draw(&mut canvas)?; + canvas.present(); + ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); } - // let sdl_context = sdl2::init().unwrap(); - // let video_subsystem = sdl_context.video().unwrap(); - // - // let window = video_subsystem.window("rust-sdl2 demo", 512, 512) - // .position_centered() - // .build() - // .unwrap(); - // let mut canvas = window.into_canvas().build().unwrap(); - // - // canvas.set_draw_color(Color::RGB(0, 255, 255)); - // canvas.clear(); - // canvas.present(); - // let mut event_pump = sdl_context.event_pump().unwrap(); - // let mut i = 0; - // 'running: loop { - // i = (i + 1) % 255; - // canvas.set_draw_color(Color::RGB(i, 64, 255 - i)); - // canvas.clear(); - // for event in event_pump.poll_iter() { - // match event { - // Event::Quit {..} | - // Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { - // break 'running - // }, - // event => { - // log::info!("Received window event {:?}",event); - // } - // } - // } - // // The rest of the game loop goes here... - // - // canvas.present(); - // ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); - // } - Ok(()) } + +fn initiate_sdl() -> (WindowCanvas, EventPump) { + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let window = video_subsystem.window("rust-sdl2 demo", 512, 512) + .position_centered() + .build() + .unwrap(); + let mut canvas = window.into_canvas().build().unwrap(); + + canvas.set_draw_color(Color::RGB(0, 255, 255)); + canvas.clear(); + canvas.present(); + let mut event_pump = sdl_context.event_pump().unwrap(); + (canvas, event_pump) +} diff --git a/src/misc/emulator_error.rs b/src/misc/emulator_error.rs index 21e2336..fc444a8 100644 --- a/src/misc/emulator_error.rs +++ b/src/misc/emulator_error.rs @@ -1,3 +1,4 @@ +use std::array::TryFromSliceError; use std::fmt::Debug; #[derive(Debug, Copy, Clone)] @@ -16,10 +17,16 @@ pub enum DeviceType { pub enum EmulatorError { AllocationFailure(DeviceType, &'static str), UnreachableMemory(DeviceType, u32), - InvalidColor(u8) + InvalidColor(u8), + OtherError(String) +} + +impl From for EmulatorError{ + fn from(value: TryFromSliceError) -> Self { + EmulatorError::UnreachableMemory(DeviceType::RAM,0x5a5a) + } } -