rustboy_core/
emulator.rs

1use std::borrow::BorrowMut;
2use std::io::Cursor;
3use std::panic;
4
5use bincode::{deserialize_from, serialize_into};
6use log::info;
7
8use crate::audio::AudioDriver;
9use crate::cartridge_info::CartridgeInfo;
10use crate::cpu::CPUInfo;
11use crate::input::Button;
12use crate::internal::controllers::audio::AudioControllerImpl;
13use crate::internal::controllers::buttons::{ButtonController, ButtonControllerImpl};
14use crate::internal::controllers::dma::{DMAController, DMAControllerImpl};
15use crate::internal::controllers::lcd::LCDControllerImpl;
16use crate::internal::controllers::speed::{SpeedController, SpeedControllerImpl};
17use crate::internal::controllers::timer::{TimerController, TimerControllerImpl};
18use crate::internal::cpu::cpu::{CPU, CPUImpl};
19use crate::internal::cpu::interrupts::InterruptControllerImpl;
20use crate::internal::memory::bus::MemoryBus;
21use crate::internal::memory::control::ControlRegisters;
22use crate::internal::memory::cram::{CRAM, CRAMImpl};
23use crate::internal::memory::dma_bus::DMAMemoryBus;
24use crate::internal::memory::linear_memory::LinearMemory;
25use crate::internal::memory::mbc::MBC;
26use crate::internal::memory::mbc0::MBC0;
27use crate::internal::memory::mbc1::MBC1;
28use crate::internal::memory::mbc2::MBC2;
29use crate::internal::memory::mbc3::MBC3;
30use crate::internal::memory::mbc5::MBC5;
31use crate::internal::memory::memory::{Memory, MemoryAddress};
32use crate::internal::memory::oam::{OAM, OAMImpl, ObjectReference};
33use crate::internal::memory::stack::Stack;
34use crate::internal::memory::unmapped::UnmappedMemory;
35use crate::internal::memory::vram::VRAMImpl;
36use crate::internal::memory::wram::WRAMImpl;
37use crate::internal::util::compatibility_palette::CompatibilityPaletteLoader;
38use crate::internal::util::instruction_label_provider::InstructionLabelProvider;
39use crate::memory::{CartridgeType, CGBMode, OAMObject};
40use crate::renderer::{Renderer, RenderTarget};
41
42pub struct Emulator<A: AudioDriver, R: Renderer> {
43  rom: Box<dyn MBC>,
44  cartridge_info: CartridgeInfo,
45  cpu: CPUImpl,
46  cram: CRAMImpl,
47  vram: VRAMImpl,
48  wram: WRAMImpl,
49  oam: OAMImpl,
50  lcd: LCDControllerImpl,
51  timer: TimerControllerImpl,
52  dma: DMAControllerImpl,
53  renderer: R,
54  interrupt_controller: InterruptControllerImpl,
55  speed_controller: SpeedControllerImpl,
56  button_controller: ButtonControllerImpl,
57  audio_controller: AudioControllerImpl,
58  stack: Stack,
59  control_registers: ControlRegisters,
60  reserved_area_1: LinearMemory<0x1E00, 0xE000>,
61  reserved_area_2: LinearMemory<0x0060, 0xFEA0>,
62  unmapped_memory: UnmappedMemory,
63  audio_driver: A,
64  paused: bool,
65}
66
67impl<A: AudioDriver, R: Renderer> Emulator<A, R> {
68  pub fn new(rom_bytes: &[u8], audio_driver: A, renderer: R) -> Self {
69    info!("Creating new emulator");
70    let cartridge_info = CartridgeInfo::from_bytes(rom_bytes);
71    let rom = Emulator::<A, R>::create_rom(rom_bytes, &cartridge_info);
72    let mut cpu = CPUImpl::new();
73    cpu.init();
74    let mut cram = CRAMImpl::new();
75    let vram = VRAMImpl::new();
76    let wram = WRAMImpl::new();
77    let oam = OAMImpl::new();
78    let mut lcd = LCDControllerImpl::new();
79    let mut timer = TimerControllerImpl::new();
80    timer.write(MemoryAddress::TAC, 0xF8);
81    let dma = DMAControllerImpl::new();
82    let button_controller = ButtonControllerImpl::new();
83    let audio_controller = AudioControllerImpl::new();
84    let stack = Stack::new();
85    let mut control_registers = ControlRegisters::new();
86    let reserved_area_1 = LinearMemory::<0x1E00, 0xE000>::new();
87    let reserved_area_2 = LinearMemory::<0x0060, 0xFEA0>::new();
88    let interrupt_controller = InterruptControllerImpl::new();
89    let speed_controller = SpeedControllerImpl::new();
90    let unmapped_memory = UnmappedMemory::new();
91
92    // If we're in compatibility/color mode, write the compatibility flag as is to KEY0
93    // otherwise, write 0x04 to KEY0 and set the OPRI flag on the LCD to 0x01
94    if let CGBMode::Color = cartridge_info.cgb_mode {
95      control_registers.write(MemoryAddress::KEY0, rom_bytes[0x0143]);
96    } else {
97      let compatibility_palettes = CompatibilityPaletteLoader::get_compatibility_palettes(&cartridge_info);
98      cram.write_compatibility_palettes(compatibility_palettes);
99      control_registers.write(MemoryAddress::KEY0, 0x04);
100      lcd.write(MemoryAddress::OPRI, 0x01);
101    }
102
103    // Write 0x11 to BANK to indicate we're unmapping the boot rom
104    control_registers.write(MemoryAddress::BANK, 0x11);
105
106    Emulator {
107      cpu,
108      rom,
109      cartridge_info,
110      cram,
111      vram,
112      wram,
113      oam,
114      lcd,
115      timer,
116      dma,
117      stack,
118      button_controller,
119      audio_controller,
120      control_registers,
121      reserved_area_1,
122      reserved_area_2,
123      interrupt_controller,
124      speed_controller,
125      renderer,
126      unmapped_memory,
127      audio_driver,
128      paused: false,
129    }
130  }
131
132  pub fn get_cartridge_info(&self) -> &CartridgeInfo {
133    &self.cartridge_info
134  }
135
136  pub fn get_state(&self) -> Result<Vec<u8>, String> {
137    let mut buffer: Vec<u8> = Vec::new();
138
139    fn stringify_error(error: bincode::Error) -> String { format!("Error while serializing: {:?}", error) }
140
141    serialize_into(&mut buffer, &self.cpu).map_err(stringify_error)?;
142    serialize_into(&mut buffer, &self.cram).map_err(stringify_error)?;
143    serialize_into(&mut buffer, &self.vram).map_err(stringify_error)?;
144    serialize_into(&mut buffer, &self.wram).map_err(stringify_error)?;
145    serialize_into(&mut buffer, &self.oam).map_err(stringify_error)?;
146    serialize_into(&mut buffer, &self.lcd).map_err(stringify_error)?;
147    serialize_into(&mut buffer, &self.timer).map_err(stringify_error)?;
148    serialize_into(&mut buffer, &self.dma).map_err(stringify_error)?;
149    serialize_into(&mut buffer, &self.stack).map_err(stringify_error)?;
150    serialize_into(&mut buffer, &self.button_controller).map_err(stringify_error)?;
151    serialize_into(&mut buffer, &self.audio_controller).map_err(stringify_error)?;
152    serialize_into(&mut buffer, &self.control_registers).map_err(stringify_error)?;
153    serialize_into(&mut buffer, &self.reserved_area_1).map_err(stringify_error)?;
154    serialize_into(&mut buffer, &self.reserved_area_2).map_err(stringify_error)?;
155    serialize_into(&mut buffer, &self.interrupt_controller).map_err(stringify_error)?;
156    serialize_into(&mut buffer, &self.speed_controller).map_err(stringify_error)?;
157    serialize_into(&mut buffer, &self.unmapped_memory).map_err(stringify_error)?;
158    Ok(buffer)
159  }
160
161  pub fn load_state(&mut self, buffer: &[u8]) {
162    let mut cursor = Cursor::new(buffer);
163    self.cpu = deserialize_from(&mut cursor).unwrap();
164    self.cram = deserialize_from(&mut cursor).unwrap();
165    self.vram = deserialize_from(&mut cursor).unwrap();
166    self.wram = deserialize_from(&mut cursor).unwrap();
167    self.oam = deserialize_from(&mut cursor).unwrap();
168    self.lcd = deserialize_from(&mut cursor).unwrap();
169    self.timer = deserialize_from(&mut cursor).unwrap();
170    self.dma = deserialize_from(&mut cursor).unwrap();
171    self.stack = deserialize_from(&mut cursor).unwrap();
172    self.button_controller = deserialize_from(&mut cursor).unwrap();
173    self.audio_controller = deserialize_from(&mut cursor).unwrap();
174    self.control_registers = deserialize_from(&mut cursor).unwrap();
175    self.reserved_area_1 = deserialize_from(&mut cursor).unwrap();
176    self.reserved_area_2 = deserialize_from(&mut cursor).unwrap();
177    self.interrupt_controller = deserialize_from(&mut cursor).unwrap();
178    self.speed_controller = deserialize_from(&mut cursor).unwrap();
179    self.unmapped_memory = deserialize_from(&mut cursor).unwrap();
180  }
181
182  fn create_rom(rom_bytes: &[u8], cartridge_info: &CartridgeInfo) -> Box<dyn MBC> {
183    let rom_size = cartridge_info.rom_size;
184    let ram_size = cartridge_info.ram_size;
185    let mut rom: Box<dyn MBC> = match cartridge_info.cartridge_type {
186      CartridgeType::MBC => Box::new(MBC0::new(rom_size)),
187      CartridgeType::MBC1 => Box::new(MBC1::new(rom_size, ram_size)),
188      CartridgeType::MBC2 => Box::new(MBC2::new(rom_size)),
189      CartridgeType::MBC3 => Box::new(MBC3::new(rom_size, ram_size)),
190      CartridgeType::MBC5 => Box::new(MBC5::new(rom_size, ram_size)),
191      _ => panic!("This emulator currently does not support {:?} cartridges", cartridge_info.cartridge_type)
192    };
193    rom.load_bytes(0x0000, rom_bytes);
194    rom
195  }
196
197  pub fn press_button(&mut self, button: Button) {
198    self.button_controller.press_button(button, &mut self.interrupt_controller);
199  }
200
201  pub fn release_button(&mut self, button: Button) {
202    self.button_controller.release_button(button);
203  }
204
205  pub fn set_tile_atlas_rendering_enabled(&mut self, enabled: bool) {
206    self.renderer.set_render_target_enabled(RenderTarget::TileAtlas, enabled);
207  }
208
209  pub fn set_object_atlas_rendering_enabled(&mut self, enabled: bool) {
210    self.renderer.set_render_target_enabled(RenderTarget::ObjectAtlas, enabled);
211  }
212
213  pub fn is_paused(&self) -> bool {
214    self.paused
215  }
216
217  pub fn set_paused(&mut self, paused: bool) {
218    if paused {
219      self.audio_driver.mute_all();
220    } else {
221      self.audio_driver.unmute_all()
222    }
223    self.paused = paused;
224  }
225
226  pub fn cpu_info(&self) -> CPUInfo {
227    self.cpu.cpu_info()
228  }
229
230  pub fn get_instruction_label(mut self, address: u16) -> String {
231    let memory_bus = MemoryBus {
232      rom: self.rom.borrow_mut(),
233      vram: &mut self.vram,
234      wram: &mut self.wram,
235      reserved_area_1: &mut self.reserved_area_1,
236      oam: &mut self.oam,
237      reserved_area_2: &mut self.reserved_area_2,
238      button_controller: &mut self.button_controller,
239      timer: &mut self.timer,
240      interrupt_controller: &mut self.interrupt_controller,
241      speed_controller: &mut self.speed_controller,
242      audio_controller: &mut self.audio_controller,
243      lcd: &mut self.lcd,
244      dma: &mut self.dma,
245      cram: &mut self.cram,
246      control_registers: &mut self.control_registers,
247      stack: &mut self.stack,
248      unmapped_memory: &mut self.unmapped_memory,
249    };
250    InstructionLabelProvider::get_label(&memory_bus, address)
251  }
252
253  pub fn get_object(&self, object_index: u8) -> OAMObject {
254    self.oam.get_object(ObjectReference {
255      object_index,
256      use_bottom_tile: false,
257    }, self.lcd.use_8_x_16_tiles())
258  }
259
260  pub fn tick(&mut self) {
261    let double_speed = self.speed_controller.double_speed();
262    {
263      let mut memory_bus = MemoryBus {
264        rom: &mut self.rom,
265        vram: &mut self.vram,
266        wram: &mut self.wram,
267        reserved_area_1: &mut self.reserved_area_1,
268        oam: &mut self.oam,
269        reserved_area_2: &mut self.reserved_area_2,
270        button_controller: &mut self.button_controller,
271        timer: &mut self.timer,
272        interrupt_controller: &mut self.interrupt_controller,
273        speed_controller: &mut self.speed_controller,
274        audio_controller: &mut self.audio_controller,
275        lcd: &mut self.lcd,
276        dma: &mut self.dma,
277        cram: &mut self.cram,
278        control_registers: &mut self.control_registers,
279        stack: &mut self.stack,
280        unmapped_memory: &mut self.unmapped_memory,
281      };
282      self.cpu.tick(&mut memory_bus);
283    }
284    self.rom.tick(double_speed);
285    self.speed_controller.tick(&mut self.cpu);
286    self.button_controller.tick(&mut self.interrupt_controller);
287    self.audio_controller.tick(&mut self.audio_driver, &mut self.timer, double_speed);
288    self.timer.tick(&mut self.interrupt_controller);
289    self.lcd.tick(&self.vram, &self.cram, &self.oam, &mut self.renderer, &mut self.interrupt_controller, double_speed);
290    {
291      let mut dma_memory_bus = DMAMemoryBus {
292        rom: &mut self.rom,
293        vram: &mut self.vram,
294        wram: &mut self.wram,
295        oam: &mut self.oam,
296      };
297      self.dma.tick(&mut dma_memory_bus, &mut self.cpu, &self.lcd, double_speed);
298    }
299  }
300
301  pub fn execute_machine_cycle(&mut self) {
302    self.tick();
303  }
304
305  pub fn run_for_nanos(&mut self, nanos: u64) {
306    if !self.paused {
307      let mut remaining_nanos = nanos;
308      while remaining_nanos > 0 {
309        let double_speed = self.speed_controller.double_speed();
310        remaining_nanos = remaining_nanos.saturating_sub(if double_speed { 500 } else { 1000 });
311        self.tick();
312      }
313    }
314  }
315}