use crate::{ cpu::Cpu, data::{DMG_BOOT, SGB_BOOT}, mmu::Mmu, pad::Pad, ppu::{Ppu, FRAME_BUFFER_SIZE}, util::read_file, }; #[cfg(feature = "wasm")] use wasm_bindgen::prelude::*; /// Top level structure that abstracts the usage of the /// Game Boy system under the Boytacean emulator. /// Should serve as the main entry-point API. #[cfg_attr(feature = "wasm", wasm_bindgen)] pub struct GameBoy { cpu: Cpu, } #[cfg_attr(feature = "wasm", wasm_bindgen)] impl GameBoy { #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))] pub fn new() -> Self { let pad = Pad::new(); let ppu = Ppu::new(); let mmu = Mmu::new(ppu, pad); let cpu = Cpu::new(mmu); Self { cpu: cpu } } pub fn pc(&self) -> u16 { self.cpu.pc() } pub fn clock(&mut self) -> u8 { let cycles = self.cpu_clock(); self.ppu_clock(cycles); cycles } pub fn cpu_clock(&mut self) -> u8 { self.cpu.clock() } pub fn ppu_clock(&mut self, cycles: u8) { self.ppu().clock(cycles) } pub fn load_rom(&mut self, data: &[u8]) { self.cpu.mmu().write_rom(0x0000, data); } pub fn load_rom_file(&mut self, path: &str) { let data = read_file(path); self.load_rom(&data); } pub fn load_boot(&mut self, data: &[u8]) { self.cpu.mmu().write_boot(0x0000, data); } pub fn load_boot_file(&mut self, path: &str) { let data = read_file(path); println!("{:?}", data); self.load_boot(&data); } pub fn load_boot_default(&mut self) { self.load_boot_file("./res/boot/dmg_boot.bin"); } pub fn load_boot_dmg(&mut self) { self.load_boot(&DMG_BOOT); } pub fn load_boot_sgb(&mut self) { self.load_boot(&SGB_BOOT); } pub fn frame_buffer_eager(&mut self) -> Vec<u8> { self.frame_buffer().to_vec() } } impl GameBoy { pub fn cpu(&mut self) -> &mut Cpu { &mut self.cpu } pub fn mmu(&mut self) -> &mut Mmu { self.cpu.mmu() } pub fn ppu(&mut self) -> &mut Ppu { self.cpu.ppu() } pub fn frame_buffer(&mut self) -> &Box<[u8; FRAME_BUFFER_SIZE]> { &(self.ppu().frame_buffer) } }