diff --git a/src/emu.rs b/src/emu.rs index f91f929..b04b96b 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -1,4 +1,5 @@ use crate::apu::gen::SampleProducer; +use crate::bus::BOOT_SIZE; use crate::cpu::Cpu; use crate::joypad::{self, Joypad}; use crate::{Cycle, GB_HEIGHT, GB_WIDTH}; @@ -6,7 +7,7 @@ use clap::crate_name; use gilrs::Gilrs; use std::fs::File; use std::io::{Read, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::Duration; use winit_input_helper::WinitInputHelper; @@ -39,21 +40,47 @@ pub struct Emulator { timestamp: Cycle, } +impl Default for Emulator { + fn default() -> Self { + Self::new() + } +} + impl Emulator { - fn new(cpu: Cpu) -> Self { + pub fn new() -> Self { Self { - cpu, + cpu: Cpu::with_boot(*include_bytes!("../bin/bootix_dmg.bin")), timestamp: Default::default(), } } + pub fn from_boot_rom>(path: P) -> std::io::Result { + Ok(Self { + cpu: Cpu::with_boot(Self::read_boot(path)?), + timestamp: Default::default(), + }) + } + + fn read_boot>(path: P) -> std::io::Result<[u8; BOOT_SIZE]> { + let mut buf = [0; BOOT_SIZE]; + let mut file = File::open(path.as_ref())?; + + file.read_exact(&mut buf)?; + Ok(buf) + } + fn step(&mut self) -> Cycle { let cycles = self.cpu.step(); self.timestamp += cycles; cycles } - fn load_cart(&mut self, rom: Vec) { + pub fn read_game_rom>(&mut self, path: P) -> std::io::Result<()> { + self.load_rom(std::fs::read(path.as_ref())?); + Ok(()) + } + + fn load_rom(&mut self, rom: Vec) { self.cpu.bus_mut().load_cart(rom); } @@ -92,10 +119,11 @@ impl Emulator { save_path.push(title); save_path.set_extension("sav"); - if let Ok(mut file) = File::open(save_path) { + if let Ok(mut file) = File::open(&save_path) { + tracing::info!("Loading {:?}", save_path); + let mut memory = Vec::new(); file.read_to_end(&mut memory)?; - cart.write_ext_ram(memory); } } @@ -115,67 +143,3 @@ impl Emulator { } } } - -pub mod build { - use std::fs::File; - use std::io::{Read, Result}; - use std::path::Path; - - use tracing::info; - - use crate::bus::BOOT_SIZE; - use crate::cpu::Cpu; - - use super::Emulator; - - #[derive(Debug, Default)] - pub struct EmulatorBuilder { - boot: Option<[u8; BOOT_SIZE]>, - cart: Option>, - } - - impl EmulatorBuilder { - pub fn new() -> Self { - Default::default() - } - - pub fn with_boot>(mut self, path: P) -> Result { - let mut file = File::open(path.as_ref())?; - - let mut buf = [0x00; BOOT_SIZE]; - file.read_exact(&mut buf)?; - - self.boot = Some(buf); - Ok(self) - } - - pub fn with_cart>(mut self, path: P) -> Result { - let mut file = File::open(path.as_ref())?; - - let mut buf = Vec::new(); - file.read_to_end(&mut buf)?; - - self.cart = Some(buf); - Ok(self) - } - - pub fn finish(mut self) -> Emulator { - let mut emu = Emulator::new(match self.boot { - Some(rom) => { - info!("User-provided Boot ROM"); - Cpu::with_boot(rom) - } - None => { - info!("Built-in Boot ROM"); - Cpu::with_boot(*include_bytes!("../bin/bootix_dmg.bin")) - } - }); - - if let Some(rom) = self.cart.take() { - emu.load_cart(rom) - } - - emu - } - } -} diff --git a/src/main.rs b/src/main.rs index 60a4ffc..b218cf4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,7 @@ use std::convert::TryInto; use anyhow::Result; use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg}; -use gb::emu::build::EmulatorBuilder; -use gb::emu::CYCLES_IN_FRAME; +use gb::emu::{Emulator, CYCLES_IN_FRAME}; use gb::{Cycle, GB_HEIGHT, GB_WIDTH}; use gilrs::Gilrs; use pixels::{PixelsBuilder, SurfaceTexture}; @@ -30,7 +29,6 @@ fn main() -> Result<()> { Arg::with_name("rom") .value_name("ROM_FILE") .takes_value(true) - .required(true) .index(1) .help("Path to the Game ROM"), ) @@ -53,17 +51,23 @@ fn main() -> Result<()> { .with_env_filter(EnvFilter::from_default_env()) .init(); - let mut emu_build = - EmulatorBuilder::new().with_cart(m.value_of("rom").expect("ROM path provided"))?; + let mut emu = match m.value_of("boot") { + Some(path) => { + tracing::info!("User-provided boot ROM"); + Emulator::from_boot_rom(path)? + } + None => { + tracing::info!("Built-in boot ROM"); + Emulator::new() + } + }; - if let Some(path) = m.value_of("boot") { - emu_build = emu_build.with_boot(path)?; + if let Some(path) = m.value_of("rom") { + tracing::info!("User-provided cartridge ROM"); + emu.read_game_rom(path)?; } - let mut emu = emu_build.finish(); - // Load Save file if it exists - info!("Attempt to load .sav"); emu.try_load_sav().expect("Load save if exists"); let rom_title = emu.title();