[ref] Cleanup
This commit is contained in:
12
src/args.rs
12
src/args.rs
@@ -1,8 +1,10 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
#[derive(Debug,Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(version, about, long_about = "Byte Pusher Emulator")]
|
#[command(version, about, author)]
|
||||||
pub struct BytePusherArgs{
|
pub struct BytePusherArgs {
|
||||||
#[arg(short,long)]
|
#[arg(short, long, help = "ROM file to load")]
|
||||||
pub file_name:Option<String>
|
pub file_name: Option<String>,
|
||||||
|
#[arg(short, long, help = "Scale at which to draw", default_value_t = 2.0)]
|
||||||
|
pub draw_scale: f32,
|
||||||
}
|
}
|
@@ -8,7 +8,10 @@ use crate::misc::error::EmulatorError;
|
|||||||
use crate::misc::result::EmulatorResult;
|
use crate::misc::result::EmulatorResult;
|
||||||
|
|
||||||
pub const AUDIO_BUFFER_SIZE: usize = 256;
|
pub const AUDIO_BUFFER_SIZE: usize = 256;
|
||||||
|
const I8_SIGN_BYTE: u8 = 0x80;
|
||||||
|
const AUDIO_REG_START: usize = 6;
|
||||||
|
const AUDIO_REG_LEN: usize = 2;
|
||||||
|
const AUDIO_REG_END: usize = AUDIO_REG_START + AUDIO_REG_LEN -1;
|
||||||
|
|
||||||
pub struct AudioProcessor<'a> {
|
pub struct AudioProcessor<'a> {
|
||||||
ram: &'a RamMemory,
|
ram: &'a RamMemory,
|
||||||
@@ -31,6 +34,7 @@ impl<'a> AudioProcessor<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> AudioProcessor<'a> {
|
impl<'a> AudioProcessor<'a> {
|
||||||
pub fn queue(&mut self) -> EmulatorResult<()> {
|
pub fn queue(&mut self) -> EmulatorResult<()> {
|
||||||
let audio_base_reg = (self.get_audio_base_reg() as u32) << 8;
|
let audio_base_reg = (self.get_audio_base_reg() as u32) << 8;
|
||||||
@@ -39,22 +43,22 @@ impl<'a> AudioProcessor<'a> {
|
|||||||
// The CPU frame timing is just a little less than 60 fps to prevent audio stutter.
|
// The CPU frame timing is just a little less than 60 fps to prevent audio stutter.
|
||||||
// We will then wait for audio to drain to adjust frame timing
|
// We will then wait for audio to drain to adjust frame timing
|
||||||
if self.audio_queue.size() == 0 {
|
if self.audio_queue.size() == 0 {
|
||||||
log::trace!("Detected Queue empty!");
|
log::info!("Detected Queue empty! Audio stutter may occur");
|
||||||
}
|
}
|
||||||
while self.audio_queue.size() > 32 {
|
while self.audio_queue.size() > (AUDIO_BUFFER_SIZE / 2) as u32 {
|
||||||
::std::thread::sleep(Duration::from_micros(1))
|
::std::thread::sleep(Duration::from_micros(1))
|
||||||
}
|
}
|
||||||
self.ram.try_copy_block(audio_base_reg, fb)?;
|
self.ram.try_copy_block(audio_base_reg, fb)?;
|
||||||
|
|
||||||
//convert to u8 audio format (Bytepusher stores it as "i8")
|
//convert to u8 audio format (Bytepusher stores it as "i8")
|
||||||
fb.iter_mut().for_each(|item|{
|
fb.iter_mut().for_each(|item|{
|
||||||
*item^= 0x80;
|
*item ^= I8_SIGN_BYTE;
|
||||||
});
|
});
|
||||||
self.audio_queue.queue_audio(fb).map_err(|s| { EmulatorError::OtherError(Some(AUDIO), s) })
|
self.audio_queue.queue_audio(fb).map_err(|s| { EmulatorError::OtherError(Some(AUDIO), s) })
|
||||||
}
|
}
|
||||||
fn get_audio_base_reg(&self) -> u16 {
|
fn get_audio_base_reg(&self) -> u16 {
|
||||||
let data = self.ram.get_data_ref();
|
let data = self.ram.get_data_ref();
|
||||||
let audio_base_reg = data.get(6..8).unwrap();
|
let audio_base_reg = data.get(AUDIO_REG_START..=AUDIO_REG_END).unwrap();
|
||||||
read_big_endian_u16(audio_base_reg.try_into().unwrap())
|
read_big_endian_u16(audio_base_reg.try_into().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -5,7 +5,8 @@ use crate::misc::error::DeviceType::GRAPHICS;
|
|||||||
use crate::misc::error::EmulatorError;
|
use crate::misc::error::EmulatorError;
|
||||||
use crate::misc::result::EmulatorResult;
|
use crate::misc::result::EmulatorResult;
|
||||||
|
|
||||||
pub const DEVICE_FRAMEBUFFER_SIZE: usize = 256 * 256;
|
pub const DEVICE_RESOLUTION: usize = 256;
|
||||||
|
pub const DEVICE_FRAMEBUFFER_SIZE: usize = DEVICE_RESOLUTION * DEVICE_RESOLUTION;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GraphicsProcessor<'a> {
|
pub struct GraphicsProcessor<'a> {
|
||||||
|
34
src/main.rs
34
src/main.rs
@@ -13,7 +13,7 @@ use simple_logger::SimpleLogger;
|
|||||||
use crate::args::BytePusherArgs;
|
use crate::args::BytePusherArgs;
|
||||||
use crate::emu::audio::AudioProcessor;
|
use crate::emu::audio::AudioProcessor;
|
||||||
use crate::emu::cpu::Cpu;
|
use crate::emu::cpu::Cpu;
|
||||||
use crate::emu::graphics::GraphicsProcessor;
|
use crate::emu::graphics::{DEVICE_RESOLUTION, GraphicsProcessor};
|
||||||
use crate::emu::keyboard::Keyboard;
|
use crate::emu::keyboard::Keyboard;
|
||||||
use crate::emu::memory::{MEM_LENGTH, RamMemory};
|
use crate::emu::memory::{MEM_LENGTH, RamMemory};
|
||||||
use crate::graphics::graphics_adapter::SDLGraphicsAdapter;
|
use crate::graphics::graphics_adapter::SDLGraphicsAdapter;
|
||||||
@@ -26,14 +26,13 @@ mod misc;
|
|||||||
mod graphics;
|
mod graphics;
|
||||||
|
|
||||||
fn main() -> EmulatorResult<()> {
|
fn main() -> EmulatorResult<()> {
|
||||||
let BytePusherArgs { file_name } = BytePusherArgs::parse();
|
let BytePusherArgs { file_name ,draw_scale} = BytePusherArgs::parse();
|
||||||
SimpleLogger::new().with_level(LevelFilter::Info).env().init().unwrap();
|
SimpleLogger::new().with_level(LevelFilter::Info).env().init()?;
|
||||||
|
|
||||||
|
|
||||||
let (file_bytes, x) = try_load_rom(&file_name)?;
|
let (file_bytes, ..) = try_load_rom(&file_name)?;
|
||||||
assert!(x < MEM_LENGTH);
|
|
||||||
|
|
||||||
let (mut canvas, mut event_pump, audio_queue) = initiate_sdl();
|
let (mut canvas, mut event_pump, audio_queue) = initiate_sdl(draw_scale);
|
||||||
|
|
||||||
|
|
||||||
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
let ram = RamMemory::try_from(file_bytes.as_slice())?;
|
||||||
@@ -44,9 +43,9 @@ fn main() -> EmulatorResult<()> {
|
|||||||
|
|
||||||
let mut sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor);
|
let mut sdl2_graphics_adapter = SDLGraphicsAdapter::new(&graphics_processor);
|
||||||
|
|
||||||
'running: loop {
|
|
||||||
canvas.set_draw_color(Color::BLACK);
|
canvas.set_draw_color(Color::BLACK);
|
||||||
canvas.clear();
|
canvas.clear();
|
||||||
|
'running: loop {
|
||||||
for event in event_pump.poll_iter() {
|
for event in event_pump.poll_iter() {
|
||||||
match event {
|
match event {
|
||||||
Event::Quit { .. } |
|
Event::Quit { .. } |
|
||||||
@@ -71,13 +70,12 @@ fn main() -> EmulatorResult<()> {
|
|||||||
|
|
||||||
// The rest of the game loop goes here...
|
// The rest of the game loop goes here...
|
||||||
cpu.cycle()?;
|
cpu.cycle()?;
|
||||||
// draw graphics
|
|
||||||
sdl2_graphics_adapter.draw(&mut canvas)?;
|
|
||||||
// TODO render audio
|
|
||||||
audio_processor.queue()?;
|
|
||||||
|
|
||||||
|
sdl2_graphics_adapter.draw(&mut canvas)?;
|
||||||
|
audio_processor.queue()?;
|
||||||
canvas.present();
|
canvas.present();
|
||||||
|
|
||||||
|
|
||||||
// 60fps - small offset to consider for cpu cycle time
|
// 60fps - small offset to consider for cpu cycle time
|
||||||
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60 - 2000_000));
|
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60 - 2000_000));
|
||||||
}
|
}
|
||||||
@@ -121,10 +119,8 @@ fn try_load_rom(file_name_option: &Option<String>) -> EmulatorResult<(Vec<u8>, u
|
|||||||
Ok((file_bytes, bytes_read))
|
Ok((file_bytes, bytes_read))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initiate_sdl() -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
fn initiate_sdl(draw_scale:f32) -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
||||||
const BASE_RESOLUTION: u32 = 256;
|
let window_resolution: u32 = (DEVICE_RESOLUTION as f32 * draw_scale) as u32;
|
||||||
const DRAW_FACTOR: u32 = 4;
|
|
||||||
const WINDOW_RESOLUTION: u32 = BASE_RESOLUTION * DRAW_FACTOR;
|
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
let audio_subsystem = sdl_context.audio().unwrap();
|
let audio_subsystem = sdl_context.audio().unwrap();
|
||||||
@@ -137,18 +133,16 @@ fn initiate_sdl() -> (WindowCanvas, EventPump, AudioQueue<u8>) {
|
|||||||
audio_queue.resume();
|
audio_queue.resume();
|
||||||
|
|
||||||
|
|
||||||
let window = video_subsystem.window("byte-pusher-emu", WINDOW_RESOLUTION, WINDOW_RESOLUTION)
|
let window = video_subsystem.window("byte-pusher-emu", window_resolution, window_resolution)
|
||||||
.position_centered()
|
.position_centered()
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut canvas = window.into_canvas().build().unwrap();
|
let mut canvas = window.into_canvas().build().unwrap();
|
||||||
|
|
||||||
canvas.set_draw_color(Color::RGB(0x10, 0x10, 0x10));
|
canvas.set_scale(draw_scale, draw_scale).expect("Setting scale");
|
||||||
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.set_blend_mode(BlendMode::None);
|
||||||
|
canvas.clear();
|
||||||
canvas.present();
|
canvas.present();
|
||||||
let event_pump = sdl_context.event_pump().unwrap();
|
let event_pump = sdl_context.event_pump().unwrap();
|
||||||
(canvas, event_pump, audio_queue)
|
(canvas, event_pump, audio_queue)
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
use std::array::TryFromSliceError;
|
use std::array::TryFromSliceError;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
|
use log::SetLoggerError;
|
||||||
use crate::misc::error::EmulatorError::EmulatorIOError;
|
use crate::misc::error::EmulatorError::EmulatorIOError;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -24,12 +25,18 @@ impl From<TryFromSliceError> for EmulatorError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for EmulatorError {
|
impl From<Error> for EmulatorError {
|
||||||
fn from(value: Error) -> Self {
|
fn from(value: Error) -> Self {
|
||||||
EmulatorIOError(value)
|
EmulatorIOError(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<SetLoggerError> for EmulatorError{
|
||||||
|
fn from(value: SetLoggerError) -> Self {
|
||||||
|
EmulatorError::OtherError(None,format!("Logger allocation failed! Error: {}",value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user