diff --git a/Cargo.toml b/Cargo.toml index ef4b65745deac225ab54cd0532b8f681eae467d3..4653eaf26f3c041a2ec4d9a3a95888ab90597cf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ crate-type = ["cdylib", "rlib"] [features] wasm = ["wasm-bindgen"] debug = [] +cpulog = [] gen-mock = [] [dependencies] diff --git a/frontends/sdl/Cargo.toml b/frontends/sdl/Cargo.toml index 0a07c0b6c22341ef812dfa436a70959ccf3b4463..c291cf055255f5e92be105d84475e68882765184 100644 --- a/frontends/sdl/Cargo.toml +++ b/frontends/sdl/Cargo.toml @@ -8,7 +8,9 @@ keywords = ["gameboy", "emulator", "rust", "sdl"] edition = "2018" [features] +slow = [] debug = ["boytacean/debug"] +cpulog = ["boytacean/cpulog"] [dependencies.boytacean] path = "../.." diff --git a/frontends/sdl/README.md b/frontends/sdl/README.md index 163d1b2e9ff09f07c11d104e7a28e0beea1101c3..b98904b655ae2e238c0dbebe691b4391b14eea3f 100644 --- a/frontends/sdl/README.md +++ b/frontends/sdl/README.md @@ -29,3 +29,11 @@ There are some feature flags that control the verbosity of the emulator to run i ```bash cargo run --features debug ``` + +## Features + +| Provider | Description | +| -------- | --------------------------------------------------------------------------- | +| `debug` | Activates the base `debug` feature from Boytacean. | +| `slow` | Runs the emulator at a very slow page 60x slower to allow visual debugging. | +| `cpulog` | Prints a log of the CPU instruction executed. | diff --git a/frontends/sdl/src/main.rs b/frontends/sdl/src/main.rs index 61d8d5438362af307cf0c9d94ece8f085f906b39..a31475eb966499c10a55db1537e6812207068186 100644 --- a/frontends/sdl/src/main.rs +++ b/frontends/sdl/src/main.rs @@ -143,7 +143,10 @@ impl Emulator { } pub fn start(&mut self, screen_scale: f32) { + self.start_base(); + let sdl = sdl2::init().unwrap(); + if self.features.contains(&"video") { self.start_graphics(&sdl, screen_scale); } @@ -152,6 +155,14 @@ impl Emulator { } } + #[cfg(not(feature = "slow"))] + pub fn start_base(&mut self) {} + + #[cfg(feature = "slow")] + pub fn start_base(&mut self) { + self.logic_frequency = 100; + } + pub fn start_graphics(&mut self, sdl: &Sdl, screen_scale: f32) { self.graphics = Some(Graphics::new( sdl, @@ -446,7 +457,7 @@ impl Emulator { fn main() { // creates a new Game Boy instance and loads both the boot ROM // and the initial game ROM to "start the engine" - let mut game_boy = GameBoy::new(GameBoyMode::Dmg); + let mut game_boy = GameBoy::new(GameBoyMode::Cgb); let mut printer = Box::<PrinterDevice>::default(); printer.set_callback(|image_buffer| { let file_name = format!("printer-{}.png", Utc::now().format("%Y%m%d-%H%M%S")); diff --git a/src/cpu.rs b/src/cpu.rs index 262704a10bca9d24e541855092f9d9fa2cb32e90..63798bb0d0af8ac68bc6b6b188ac853d79ea53e3 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -279,6 +279,9 @@ impl Cpu { ); } + #[cfg(feature = "cpulog")] + println!("[0x{:04x}] {}", self.pc - 1, inst_str); + // calls the current instruction and increments the number of // cycles executed by the instruction time of the instruction // that has just been executed diff --git a/src/gb.rs b/src/gb.rs index b65aec3d89f7818d5957a8d2f3e3a0b96d35a70e..602468dc7fd93f772a6e3815048d78ddb44dfeec 100644 --- a/src/gb.rs +++ b/src/gb.rs @@ -235,7 +235,7 @@ impl GameBoy { let pad = Pad::default(); let timer = Timer::default(); let serial = Serial::default(); - let mmu = Mmu::new(ppu, apu, pad, timer, serial, gbc.clone()); + let mmu = Mmu::new(ppu, apu, pad, timer, serial, mode, gbc.clone()); let cpu = Cpu::new(mmu, gbc.clone()); Self { @@ -492,6 +492,7 @@ impl GameBoy { pub fn set_mode(&mut self, value: GameBoyMode) { self.mode = value; (*self.gbc).borrow_mut().set_mode(value); + self.mmu().set_mode(value); } pub fn ppu_enabled(&self) -> bool { diff --git a/src/mmu.rs b/src/mmu.rs index bfd8047a4991af39fa69862df5237bc9436056b2..3584df47e206f471e951032d9bbb4494304066de 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,7 +1,13 @@ use std::{cell::RefCell, rc::Rc}; use crate::{ - apu::Apu, debugln, gb::GameBoyConfig, pad::Pad, ppu::Ppu, rom::Cartridge, serial::Serial, + apu::Apu, + debugln, + gb::{GameBoyConfig, GameBoyMode}, + pad::Pad, + ppu::Ppu, + rom::Cartridge, + serial::Serial, timer::Timer, }; @@ -65,6 +71,8 @@ pub struct Mmu { ram_offset: u16, + mode: GameBoyMode, + gbc: Rc<RefCell<GameBoyConfig>>, } @@ -75,6 +83,7 @@ impl Mmu { pad: Pad, timer: Timer, serial: Serial, + mode: GameBoyMode, gbc: Rc<RefCell<GameBoyConfig>>, ) -> Self { Self { @@ -90,6 +99,7 @@ impl Mmu { ram_bank: 0x1, ram_offset: 0x1000, ie: 0x0, + mode, gbc, } } @@ -165,6 +175,13 @@ impl Mmu { } return self.boot[addr as usize]; } + if self.boot_active + && self.mode == GameBoyMode::Cgb + && addr >= 0x0200 + && addr <= 0x08ff + { + return self.boot[(addr - 0x0100) as usize]; + } self.rom.read(addr) } @@ -381,4 +398,12 @@ impl Mmu { pub fn set_rom(&mut self, rom: Cartridge) { self.rom = rom; } + + pub fn mode(&self) -> GameBoyMode { + self.mode + } + + pub fn set_mode(&mut self, value: GameBoyMode) { + self.mode = value; + } }