chore: begin refactor of public api
This commit is contained in:
146
src/emu.rs
146
src/emu.rs
@@ -1,8 +1,7 @@
|
||||
use crate::cpu::Cpu as SM83;
|
||||
use crate::joypad;
|
||||
use crate::ppu::Ppu;
|
||||
use crate::Cycle;
|
||||
use anyhow::Result;
|
||||
use crate::apu::gen::SampleProducer;
|
||||
use crate::cpu::Cpu;
|
||||
use crate::joypad::{self, Joypad};
|
||||
use crate::{Cycle, GB_HEIGHT, GB_WIDTH};
|
||||
use gilrs::Gilrs;
|
||||
use std::time::Duration;
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
@@ -12,56 +11,111 @@ 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 init(boot_path: Option<&str>, rom_path: &str) -> Result<SM83> {
|
||||
let mut cpu = match boot_path {
|
||||
Some(path) => SM83::boot_new(path)?,
|
||||
None => SM83::new(),
|
||||
};
|
||||
|
||||
eprintln!("Initialized GB Emulator");
|
||||
|
||||
cpu.load_cartridge(rom_path)?;
|
||||
Ok(cpu)
|
||||
}
|
||||
|
||||
pub fn rom_title(game_boy: &SM83) -> &str {
|
||||
game_boy.rom_title().unwrap_or(DEFAULT_TITLE)
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
game_boy: &mut SM83,
|
||||
gamepad: &mut Gilrs,
|
||||
input: &WinitInputHelper,
|
||||
target: Cycle,
|
||||
) -> Cycle {
|
||||
pub fn run_frame(emu: &mut Emulator, gamepad: &mut Gilrs, key: &WinitInputHelper) -> Cycle {
|
||||
let mut elapsed = 0;
|
||||
|
||||
if let Some(event) = gamepad.next_event() {
|
||||
joypad::handle_gamepad_input(game_boy.joypad_mut(), event);
|
||||
}
|
||||
joypad::handle_keyboard_input(game_boy.joypad_mut(), input);
|
||||
|
||||
while elapsed < target {
|
||||
elapsed += game_boy.step();
|
||||
joypad::handle_gamepad_input(emu.joyp_mut(), event);
|
||||
}
|
||||
|
||||
elapsed
|
||||
}
|
||||
|
||||
pub fn run_frame(game_boy: &mut SM83, gamepad: &mut Gilrs, input: &WinitInputHelper) -> Cycle {
|
||||
let mut elapsed = 0;
|
||||
|
||||
if let Some(event) = gamepad.next_event() {
|
||||
joypad::handle_gamepad_input(game_boy.joypad_mut(), event);
|
||||
}
|
||||
joypad::handle_keyboard_input(game_boy.joypad_mut(), input);
|
||||
joypad::handle_keyboard_input(emu.joyp_mut(), key);
|
||||
while elapsed < CYCLES_IN_FRAME {
|
||||
elapsed += game_boy.step();
|
||||
elapsed += emu.step();
|
||||
}
|
||||
|
||||
elapsed
|
||||
}
|
||||
|
||||
pub fn draw(ppu: &Ppu, frame: &mut [u8]) {
|
||||
ppu.copy_to_gui(frame);
|
||||
pub fn draw_frame(emu: &Emulator, buf: &mut [u8; GB_HEIGHT * GB_WIDTH * 4]) {
|
||||
buf.copy_from_slice(emu.cpu.bus().ppu.frame_buf());
|
||||
}
|
||||
|
||||
pub struct Emulator {
|
||||
cpu: Cpu,
|
||||
timestamp: Cycle,
|
||||
}
|
||||
|
||||
impl Emulator {
|
||||
fn new(cpu: Cpu) -> Self {
|
||||
Self {
|
||||
cpu,
|
||||
timestamp: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn step(&mut self) -> Cycle {
|
||||
self.cpu.step()
|
||||
}
|
||||
|
||||
fn load_cart(&mut self, rom: Vec<u8>) {
|
||||
self.cpu.bus_mut().load_cart(rom)
|
||||
}
|
||||
|
||||
fn joyp_mut(&mut self) -> &mut Joypad {
|
||||
&mut self.cpu.bus_mut().joypad
|
||||
}
|
||||
|
||||
pub fn set_prod(&mut self, prod: SampleProducer<f32>) {
|
||||
self.cpu.bus_mut().apu.attach_producer(prod)
|
||||
}
|
||||
|
||||
pub fn title(&self) -> &str {
|
||||
self.cpu.bus().cart_title().unwrap_or(DEFAULT_TITLE)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod build {
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Result};
|
||||
use std::path::Path;
|
||||
|
||||
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<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl EmulatorBuilder {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn with_boot<P: AsRef<Path>>(mut self, path: P) -> Result<Self> {
|
||||
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<P: AsRef<Path>>(mut self, path: P) -> Result<Self> {
|
||||
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) => Cpu::with_boot(rom),
|
||||
None => Cpu::without_boot(),
|
||||
});
|
||||
|
||||
if let Some(rom) = self.cart.take() {
|
||||
emu.load_cart(rom)
|
||||
}
|
||||
|
||||
emu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user