chore: remove Emulator struct
This commit is contained in:
146
src/emu.rs
146
src/emu.rs
@@ -15,125 +15,91 @@ pub const CYCLES_IN_FRAME: Cycle = 456 * 154; // 456 Cycles times 154 scanlines
|
||||
pub(crate) const SM83_CLOCK_SPEED: u64 = 0x40_0000; // Hz which is 4.194304Mhz
|
||||
const DEFAULT_TITLE: &str = "DMG-01 Emulator";
|
||||
|
||||
pub fn run_frame(emu: &mut Emulator, gamepad: &mut Gilrs, key: KeyboardInput) -> Cycle {
|
||||
pub fn run_frame(cpu: &mut Cpu, gamepad: &mut Gilrs, key: KeyboardInput) -> Cycle {
|
||||
let mut elapsed = 0;
|
||||
|
||||
if let Some(event) = gamepad.next_event() {
|
||||
crate::joypad::handle_gamepad_input(&mut emu.cpu.bus.joyp, event);
|
||||
crate::joypad::handle_gamepad_input(&mut cpu.bus.joyp, event);
|
||||
}
|
||||
crate::joypad::handle_keyboard_input(&mut emu.cpu.bus.joyp, key);
|
||||
crate::joypad::handle_keyboard_input(&mut cpu.bus.joyp, key);
|
||||
|
||||
while elapsed < CYCLES_IN_FRAME {
|
||||
elapsed += emu.step();
|
||||
elapsed += cpu.step();
|
||||
}
|
||||
|
||||
elapsed
|
||||
}
|
||||
|
||||
pub fn pixel_buf(emu: &Emulator) -> &[u8; GB_HEIGHT * GB_WIDTH * 4] {
|
||||
emu.cpu.bus.ppu.frame_buf.as_ref()
|
||||
pub fn pixel_buf(cpu: &Cpu) -> &[u8; GB_HEIGHT * GB_WIDTH * 4] {
|
||||
cpu.bus.ppu.frame_buf.as_ref()
|
||||
}
|
||||
|
||||
pub struct Emulator {
|
||||
cpu: Cpu,
|
||||
timestamp: Cycle,
|
||||
pub fn from_boot_rom<P: AsRef<Path>>(path: P) -> std::io::Result<Cpu> {
|
||||
Ok(Cpu::new(read_boot(path)?))
|
||||
}
|
||||
|
||||
impl Default for Emulator {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
pub fn read_game_rom<P: AsRef<Path>>(cpu: &mut Cpu, path: P) -> std::io::Result<()> {
|
||||
Ok(cpu.bus.load_cart(std::fs::read(path.as_ref())?))
|
||||
}
|
||||
|
||||
impl Emulator {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cpu: Cpu::with_boot(*include_bytes!("../bin/bootix_dmg.bin")),
|
||||
timestamp: Default::default(),
|
||||
pub fn set_audio_producer(cpu: &mut Cpu, producer: SampleProducer<f32>) {
|
||||
cpu.bus.apu.attach_producer(producer);
|
||||
}
|
||||
|
||||
pub fn rom_title(cpu: &Cpu) -> &str {
|
||||
cpu.bus.cart_title().unwrap_or(DEFAULT_TITLE)
|
||||
}
|
||||
|
||||
pub fn write_save(cpu: &Cpu) -> std::io::Result<()> {
|
||||
if let Some(ext_ram) = cpu.bus.cart.as_ref().map(|c| c.ext_ram()).flatten() {
|
||||
if let Some(title) = cpu.bus.cart_title() {
|
||||
let mut save_path = data_path().unwrap_or_else(|| PathBuf::from("."));
|
||||
save_path.push(title);
|
||||
save_path.set_extension("sav");
|
||||
|
||||
let mut file = File::create(save_path)?;
|
||||
file.write_all(ext_ram)?;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_boot_rom<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
|
||||
Ok(Self {
|
||||
cpu: Cpu::with_boot(Self::read_boot(path)?),
|
||||
timestamp: Default::default(),
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_boot<P: AsRef<Path>>(path: P) -> std::io::Result<[u8; BOOT_SIZE]> {
|
||||
let mut buf = [0; BOOT_SIZE];
|
||||
let mut file = File::open(path.as_ref())?;
|
||||
pub fn load_save(cpu: &mut Cpu) -> std::io::Result<()> {
|
||||
if let Some(cart) = &mut cpu.bus.cart {
|
||||
if let Some(title) = cart.title() {
|
||||
let mut save_path = data_path().unwrap_or_else(|| PathBuf::from("."));
|
||||
save_path.push(title);
|
||||
save_path.set_extension("sav");
|
||||
|
||||
file.read_exact(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
if let Ok(mut file) = File::open(&save_path) {
|
||||
tracing::info!("Load {:?}", save_path);
|
||||
|
||||
fn step(&mut self) -> Cycle {
|
||||
let cycles = self.cpu.step();
|
||||
self.timestamp += cycles;
|
||||
cycles
|
||||
}
|
||||
|
||||
pub fn read_game_rom<P: AsRef<Path>>(&mut self, path: P) -> std::io::Result<()> {
|
||||
self.load_rom(std::fs::read(path.as_ref())?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_rom(&mut self, rom: Vec<u8>) {
|
||||
self.cpu.bus.load_cart(rom);
|
||||
}
|
||||
|
||||
pub fn set_prod(&mut self, prod: SampleProducer<f32>) {
|
||||
self.cpu.bus.apu_mut().attach_producer(prod)
|
||||
}
|
||||
|
||||
pub fn title(&self) -> &str {
|
||||
self.cpu.bus.cart_title().unwrap_or(DEFAULT_TITLE)
|
||||
}
|
||||
|
||||
pub fn try_write_sav(&self) -> std::io::Result<()> {
|
||||
if let Some(ext_ram) = self.cpu.bus.cart.as_ref().map(|c| c.ext_ram()).flatten() {
|
||||
if let Some(title) = self.cpu.bus.cart_title() {
|
||||
let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from("."));
|
||||
save_path.push(title);
|
||||
save_path.set_extension("sav");
|
||||
|
||||
let mut file = File::create(save_path)?;
|
||||
file.write_all(ext_ram)?;
|
||||
let mut memory = Vec::new();
|
||||
file.read_to_end(&mut memory)?;
|
||||
cart.write_ext_ram(memory);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn try_load_sav(&mut self) -> std::io::Result<()> {
|
||||
if let Some(cart) = &mut self.cpu.bus.cart {
|
||||
if let Some(title) = cart.title() {
|
||||
let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from("."));
|
||||
save_path.push(title);
|
||||
save_path.set_extension("sav");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
if let Ok(mut file) = File::open(&save_path) {
|
||||
tracing::info!("Load {:?}", save_path);
|
||||
fn read_boot<P: AsRef<Path>>(path: P) -> std::io::Result<[u8; BOOT_SIZE]> {
|
||||
let mut buf = [0; BOOT_SIZE];
|
||||
let mut file = File::open(path.as_ref())?;
|
||||
|
||||
let mut memory = Vec::new();
|
||||
file.read_to_end(&mut memory)?;
|
||||
cart.write_ext_ram(memory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn data_path() -> Option<PathBuf> {
|
||||
match directories_next::ProjectDirs::from("dev", "musuka", crate_name!()) {
|
||||
Some(dirs) => {
|
||||
let data_local = dirs.data_local_dir();
|
||||
std::fs::create_dir_all(data_local).ok()?;
|
||||
Some(data_local.to_path_buf())
|
||||
}
|
||||
None => None,
|
||||
file.read_exact(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn data_path() -> Option<PathBuf> {
|
||||
match directories_next::ProjectDirs::from("dev", "musuka", crate_name!()) {
|
||||
Some(dirs) => {
|
||||
let data_local = dirs.data_local_dir();
|
||||
std::fs::create_dir_all(data_local).ok()?;
|
||||
Some(data_local.to_path_buf())
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user