1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
pub mod step_result; pub mod traits; use self::step_result::StepResult; use self::traits::{PixelMapper, RTC}; use crate::cpu::Cpu; use crate::gpu::GPU; use crate::joypad::Controller; use crate::mmu::cartridge::Cartridge; use crate::mmu::interrupt::Interrupt; use crate::mmu::Memory; use crate::timer::Timer; pub struct Emulator { cpu: Cpu, gpu: GPU, timer: Timer, memory: Memory, } impl Emulator { pub fn from_cartridge(cartridge: Cartridge, rtc: Box<dyn RTC>) -> Emulator { let is_cgb = cartridge.is_cgb(); Emulator { cpu: Cpu::new(is_cgb), gpu: GPU::new(is_cgb), timer: Timer::new(), memory: Memory::from_cartridge(cartridge, rtc, is_cgb), } } pub fn emulate( &mut self, system: &mut impl PixelMapper, controller: &mut Controller, ) -> StepResult { let cycles = self.cpu.step(&mut self.memory); self.timer.update(cycles, &mut self.memory); let audio_buffer_full = self.memory.get_sound_mut().step(cycles); let vblank = self.gpu.step(cycles, &mut self.memory, system); controller.update(&mut self.memory); self.handle_interrupts(); if audio_buffer_full { StepResult::AudioBufferFull } else if vblank { StepResult::VBlank } else { StepResult::Nothing } } fn handle_interrupts(&mut self) { if let Some(interrupt) = self.memory.get_interrupts() { self.process_interrupt(interrupt); } } fn process_interrupt(&mut self, interrupt: Interrupt) { if self.cpu.are_interrupts_enabled() { self.cpu.disable_interrupts(); match interrupt { Interrupt::Vblank => self.cpu.rst_40(&mut self.memory), Interrupt::Lcd => self.cpu.rst_48(&mut self.memory), Interrupt::Timer => self.cpu.rst_50(&mut self.memory), Interrupt::Serial => self.cpu.rst_58(&mut self.memory), Interrupt::Joypad => self.cpu.rst_60(&mut self.memory), } self.memory.remove_interrupt(interrupt); } self.cpu.unhalt(); } pub fn get_cartridge(&self) -> &Cartridge { &self.memory.get_cartridge() } pub fn set_ram_change_callback(&mut self, f: Box<dyn FnMut(usize, u8)>) { self.memory.set_ram_change_callback(f); } pub fn get_cartridge_mut(&mut self) -> &mut Cartridge { self.memory.get_cartridge_mut() } pub fn get_audio_buffer(&self) -> &[f32] { self.memory.get_sound().get_audio_buffer() } }