[???] Fix program execution
This commit is contained in:
0
src/emu/audio.rs
Normal file
0
src/emu/audio.rs
Normal file
@@ -40,19 +40,20 @@ impl<'a> Cpu<'a> {
|
||||
}
|
||||
|
||||
pub fn cycle(&self) -> EmulatorResult<()> {
|
||||
|
||||
let mut program_counter = self.get_pc();
|
||||
for _i in 0..65536 {
|
||||
let address_to_execute = self.get_pc();
|
||||
|
||||
//execute p1
|
||||
self.copy_u24(address_to_execute)?;
|
||||
self.copy_u24(program_counter)?;
|
||||
//execute p2
|
||||
let new_pc_location = address_to_execute + 2 * (Self::PC_LEN as u32);
|
||||
let new_pc_location = program_counter + 2 * (Self::PC_LEN as u32);
|
||||
|
||||
let new_pc = self.memory.try_get_u24(new_pc_location)?;
|
||||
|
||||
self.set_pc(new_pc);
|
||||
program_counter = self.memory.try_get_u24(new_pc_location)?;
|
||||
}
|
||||
log::debug!("Finished internal loop");
|
||||
|
||||
// self.set_pc(program_counter);
|
||||
log::trace!("Finished internal loop");
|
||||
self.graphics_processor.draw()?;
|
||||
// TODO send audio
|
||||
Ok(())
|
||||
@@ -65,20 +66,6 @@ impl<'a> Cpu<'a> {
|
||||
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.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.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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -37,7 +37,7 @@ impl<'a> GraphicsProcessor<'a> {
|
||||
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())?;
|
||||
self.ram.try_copy_block(fb_base_register, fb.as_mut())?;
|
||||
Ok(())
|
||||
}
|
||||
fn set_framebuffer(&self, memory_slice: &[u8; DEVICE_FRAMEBUFFER_SIZE]) {
|
||||
|
@@ -13,6 +13,7 @@ pub trait Memory {
|
||||
fn try_get_byte(&self, address: u32) -> EmulatorResult<u8>;
|
||||
/// Set the value at the 24bit address
|
||||
fn try_set_byte(&self, address: u32, value: u8) -> EmulatorResult<()>;
|
||||
fn try_set_u16(&self, address: u32, value: u16) -> EmulatorResult<()>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -50,7 +51,8 @@ impl RamMemory {
|
||||
Ok(read_big_endian_u24(a.try_into()?))
|
||||
}
|
||||
|
||||
pub fn get_block(&self, address: u32, output: &mut [u8]) -> EmulatorResult<()> {
|
||||
/// write a block of memory into an output slice
|
||||
pub fn try_copy_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))?;
|
||||
@@ -65,17 +67,17 @@ impl RamMemory {
|
||||
self.data.borrow_mut()
|
||||
}
|
||||
/// set keyboard bits
|
||||
pub fn set_keyboard(&self,keyboard_bits: u16) {
|
||||
pub fn set_u16(&self, address: u32, 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());
|
||||
write_big_endian_u16(keyboard_bits, keyboard_slice.try_into().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
impl Memory for RamMemory {
|
||||
fn try_get_byte(&self, address: u32) -> EmulatorResult<u8> {
|
||||
log::trace!("Fetch RAM memory at address {}",address);
|
||||
let mut data = self.data.borrow_mut();
|
||||
let data = self.data.borrow();
|
||||
let x = *data.get(address as usize).ok_or(EmulatorError::UnreachableMemory(RAM, address))?;
|
||||
Ok(x)
|
||||
}
|
||||
@@ -88,6 +90,15 @@ impl Memory for RamMemory {
|
||||
data[address as usize] = value;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_set_u16(&self, address: u32, value: u16) -> EmulatorResult<()> {
|
||||
let address = address as usize;
|
||||
let mut data_ref = self.data.borrow_mut();
|
||||
let data = data_ref.get_mut(address..(address + 2)).ok_or(EmulatorError::UnreachableMemory(RAM, address as u32))?;
|
||||
|
||||
write_big_endian_u16(value, data.try_into()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
pub mod cpu;
|
||||
pub mod memory;
|
||||
pub mod graphics;
|
||||
pub mod audio;
|
||||
pub mod keyboard;
|
@@ -48,6 +48,16 @@ impl Color {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn to_rgb_555(&self)->u16{
|
||||
let r = (self.0 / Self::RED_MULT) as u16;
|
||||
let gb_byte_remainder = self.0 % Self::RED_MULT;
|
||||
let g = (gb_byte_remainder / Self::GREEN_MULT) as u16;
|
||||
let b = gb_byte_remainder % Self::GREEN_MULT;
|
||||
|
||||
(r*25)<<10 + (g*25)<<5 + b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,10 @@
|
||||
use std::cell::Ref;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem::size_of;
|
||||
use sdl2::pixels::PixelFormatEnum;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::render::WindowCanvas;
|
||||
use crate::emu::graphics::GraphicsProcessor;
|
||||
use sdl2::render::{TextureAccess, WindowCanvas};
|
||||
use crate::emu::graphics::{DEVICE_FRAMEBUFFER_SIZE, GraphicsProcessor};
|
||||
use crate::graphics::color::Color;
|
||||
use crate::misc::error::EmulatorError;
|
||||
use crate::misc::result::EmulatorResult;
|
||||
@@ -9,6 +12,7 @@ use crate::misc::result::EmulatorResult;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SDLGraphicsAdapter<'a> {
|
||||
color_fb: Box<[u8; DEVICE_FRAMEBUFFER_SIZE * 3]>,
|
||||
graphics_processor: &'a GraphicsProcessor<'a>,
|
||||
}
|
||||
|
||||
@@ -20,33 +24,36 @@ impl<'a> Debug for SDLGraphicsAdapter<'a> {
|
||||
|
||||
impl<'a> SDLGraphicsAdapter<'a> {
|
||||
pub fn new(graphics_processor: &'a GraphicsProcessor) -> SDLGraphicsAdapter<'a> {
|
||||
let color_fb_vec = vec![0u8; DEVICE_FRAMEBUFFER_SIZE * 3].into_boxed_slice().try_into().expect("???");
|
||||
SDLGraphicsAdapter {
|
||||
graphics_processor
|
||||
color_fb: color_fb_vec,
|
||||
graphics_processor,
|
||||
}
|
||||
}
|
||||
pub fn draw(&self, canvas: &mut WindowCanvas, draw_factor: u32) -> EmulatorResult<()> {
|
||||
pub fn draw(&mut self, canvas: &mut WindowCanvas) -> EmulatorResult<()> {
|
||||
let fb = self.graphics_processor.get_framebuffer();
|
||||
self.fill_my_texture(fb);
|
||||
|
||||
|
||||
let texture_creator = canvas.texture_creator();
|
||||
|
||||
let mut texture = texture_creator.create_texture(PixelFormatEnum::RGB24, TextureAccess::Streaming, 256, 256).expect("Failed to make texture");
|
||||
texture.with_lock(None, |f, _i| {
|
||||
f.copy_from_slice(self.color_fb.as_ref())
|
||||
}).expect("TODO: panic message");
|
||||
canvas.copy(&texture, None, None).expect("Failed to write texture");
|
||||
|
||||
let xyc = fb.iter().enumerate().map(|(i, e)| {
|
||||
let i = i as u32;
|
||||
let y_coord = (i & 0xff00) >> 8;
|
||||
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 = Self::draw_scaled_point(canvas, coordinates, draw_factor);
|
||||
draw_result?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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))
|
||||
.map_err(|str| EmulatorError::OtherError(str))
|
||||
fn fill_my_texture(&mut self, dev_fb_ref: Ref<Box<[u8; DEVICE_FRAMEBUFFER_SIZE]>>) {
|
||||
for (i, e) in dev_fb_ref.iter().enumerate() {
|
||||
let color = Color::new(*e).get_rgb();
|
||||
self.color_fb[3 * i] = color.0;
|
||||
self.color_fb[3 * i + 1] = color.1;
|
||||
self.color_fb[3 * i + 2] = color.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
61
src/main.rs
61
src/main.rs
@@ -5,11 +5,12 @@ use sdl2::event::Event;
|
||||
use sdl2::EventPump;
|
||||
use sdl2::keyboard::Keycode;
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::render::WindowCanvas;
|
||||
use sdl2::render::{BlendMode, WindowCanvas};
|
||||
use simple_logger::SimpleLogger;
|
||||
use crate::emu::cpu::Cpu;
|
||||
use crate::emu::graphics::GraphicsProcessor;
|
||||
use crate::emu::memory::{MEM_LENGTH, RamMemory};
|
||||
use crate::emu::keyboard::Keyboard;
|
||||
use crate::emu::memory::{MEM_LENGTH, Memory, RamMemory};
|
||||
use crate::graphics::graphics_adapter::SDLGraphicsAdapter;
|
||||
|
||||
use crate::misc::result::EmulatorResult;
|
||||
@@ -23,15 +24,20 @@ fn main() -> EmulatorResult<()> {
|
||||
let (file_bytes, x) = try_load_rom()?;
|
||||
assert!(x < MEM_LENGTH);
|
||||
SimpleLogger::new().env().init().unwrap();
|
||||
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
||||
|
||||
let (mut canvas, mut event_pump, draw_factor) = initiate_sdl();
|
||||
|
||||
|
||||
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
||||
let graphics_processor = GraphicsProcessor::try_new(&ram)?;
|
||||
let sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor);
|
||||
let mut keyboard = Keyboard::new(&ram);
|
||||
let cpu = Cpu::new(&ram, &graphics_processor);
|
||||
|
||||
let mut sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor);
|
||||
|
||||
let mut i = 0;
|
||||
'running: loop {
|
||||
i = (i+1)%255;
|
||||
canvas.set_draw_color(Color::BLACK);
|
||||
canvas.clear();
|
||||
for event in event_pump.poll_iter() {
|
||||
@@ -39,7 +45,17 @@ fn main() -> EmulatorResult<()> {
|
||||
Event::Quit { .. } |
|
||||
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
|
||||
break 'running;
|
||||
}
|
||||
Event::KeyDown { keycode: Some(x),repeat:false,.. } => {
|
||||
if let Some(key_val) = get_key_index(x) {
|
||||
keyboard.key_down(key_val)
|
||||
}
|
||||
},
|
||||
Event::KeyUp { keycode: Some(x), repeat:false, .. } => {
|
||||
if let Some(key_val) = get_key_index(x) {
|
||||
keyboard.key_up(key_val)
|
||||
}
|
||||
}
|
||||
|
||||
event => {
|
||||
log::trace!("Received window event {:?}",event);
|
||||
@@ -47,10 +63,12 @@ fn main() -> EmulatorResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
keyboard.flush_keyboard()?;
|
||||
|
||||
// The rest of the game loop goes here...
|
||||
cpu.cycle()?;
|
||||
// draw graphics
|
||||
sdl2_graphics_adapter.draw(&mut canvas, draw_factor)?;
|
||||
sdl2_graphics_adapter.draw(&mut canvas)?;
|
||||
// TODO render audio
|
||||
|
||||
canvas.present();
|
||||
@@ -61,10 +79,33 @@ fn main() -> EmulatorResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// get index of key pressed. 0..9+A..F provides a u8
|
||||
fn get_key_index(p0: Keycode) -> Option<u8> {
|
||||
match p0 {
|
||||
Keycode::Kp0 => Some(0x0),
|
||||
Keycode::Kp1 => Some(0x1),
|
||||
Keycode::Kp2 => Some(0x2),
|
||||
Keycode::Kp3 => Some(0x3),
|
||||
Keycode::Kp4 => Some(0x4),
|
||||
Keycode::Kp5 => Some(0x5),
|
||||
Keycode::Kp6 => Some(0x6),
|
||||
Keycode::Kp7 => Some(0x7),
|
||||
Keycode::Kp8 => Some(0x8),
|
||||
Keycode::Kp9 => Some(0x9),
|
||||
Keycode::A => Some(0xA),
|
||||
Keycode::B => Some(0xB),
|
||||
Keycode::C => Some(0xC),
|
||||
Keycode::D => Some(0xD),
|
||||
Keycode::E => Some(0xE),
|
||||
Keycode::F => Some(0xF),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn try_load_rom() -> EmulatorResult<(Vec<u8>, usize)> {
|
||||
let mut file_bytes = vec![0u8; MEM_LENGTH];
|
||||
|
||||
let mut file_handle = File::open("rom.BytePusher")?;
|
||||
let mut file_handle = File::open("roms/Keyboard Test(1).BytePusher")?;
|
||||
let x = file_handle.read(&mut file_bytes)?;
|
||||
|
||||
Ok((file_bytes, x))
|
||||
@@ -83,9 +124,13 @@ fn initiate_sdl() -> (WindowCanvas, EventPump, u32) {
|
||||
.unwrap();
|
||||
let mut canvas = window.into_canvas().build().unwrap();
|
||||
|
||||
canvas.set_draw_color(Color::RGB(0, 255, 255));
|
||||
canvas.set_draw_color(Color::RGB(0x10, 0x10, 0x10));
|
||||
canvas.set_integer_scale(true).expect("Setting int scale");
|
||||
|
||||
canvas.set_scale(DRAW_FACTOR as f32,DRAW_FACTOR as f32).expect("Setting scale");
|
||||
canvas.clear();
|
||||
canvas.set_blend_mode(BlendMode::None);
|
||||
canvas.present();
|
||||
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||
let event_pump = sdl_context.event_pump().unwrap();
|
||||
(canvas, event_pump, DRAW_FACTOR)
|
||||
}
|
||||
|
Reference in New Issue
Block a user