Skip to content
Snippets Groups Projects
Verified Commit 03a14fc8 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: initial support for CGB rom banking

parent c71b625a
No related branches found
No related tags found
1 merge request!16Support for Game Boy Color (CGB) 😎🖍️
Pipeline #1608 passed
......@@ -113,7 +113,7 @@ impl Emulator {
},
Event::DropFile { filename, .. } => {
self.system.reset();
self.system.load_boot_default();
self.system.load_cgb(true);
self.load_rom(&filename);
}
_ => (),
......@@ -185,7 +185,7 @@ 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();
game_boy.load_boot_default();
game_boy.load_cgb(true);
let mut emulator = Emulator::new(game_boy, SCREEN_SCALE);
emulator.load_rom("../../res/roms.prop/super_mario.gb");
......
......@@ -109,6 +109,27 @@ impl GameBoy {
self.cpu.boot();
}
pub fn load_default(&mut self, boot: bool) {
self.mmu().allocate_default();
if boot {
self.load_boot_default();
}
}
pub fn load_dmg(&mut self, boot: bool) {
self.mmu().allocate_dmg();
if boot {
self.load_boot_dmg();
}
}
pub fn load_cgb(&mut self, boot: bool) {
self.mmu().allocate_cgb();
if boot {
self.load_boot_cgb();
}
}
pub fn load_boot(&mut self, data: &[u8]) {
self.cpu.mmu().write_boot(0x0000, data);
}
......
use crate::{debugln, pad::Pad, ppu::Ppu, rom::Cartridge, timer::Timer};
pub const BOOT_SIZE: usize = 2304;
pub const RAM_SIZE: usize = 8192;
pub const BOOT_SIZE_DMG: usize = 256;
pub const BOOT_SIZE_CGB: usize = 2304;
pub const RAM_SIZE_DMG: usize = 8192;
pub const RAM_SIZE_CGB: usize = 32768;
pub struct Mmu {
/// Register that controls the interrupts that are considered
......@@ -38,9 +41,15 @@ pub struct Mmu {
/// the bios which is 2308 bytes long is in fact only 2048 bytes
/// as the 256 bytes in range 0x100-0x1FF are meant to be
/// overwritten byte the cartridge header.
boot: [u8; BOOT_SIZE],
boot: Vec<u8>,
ram: Vec<u8>,
ram: [u8; RAM_SIZE],
/// The RAM bank to be used in the read and write operation of
/// the 0xD000-0xDFFF memory range. CGB Only
ram_bank: u8,
ram_offset: u16,
}
impl Mmu {
......@@ -51,8 +60,10 @@ impl Mmu {
timer,
rom: Cartridge::new(),
boot_active: true,
boot: [0u8; BOOT_SIZE],
ram: [0u8; RAM_SIZE],
boot: vec![],
ram: vec![],
ram_bank: 0x1,
ram_offset: 0x1000,
ie: 0x0,
}
}
......@@ -60,11 +71,27 @@ impl Mmu {
pub fn reset(&mut self) {
self.rom = Cartridge::new();
self.boot_active = true;
self.boot = [0u8; BOOT_SIZE];
self.ram = [0u8; RAM_SIZE];
self.boot = vec![];
self.ram = vec![];
self.ram_bank = 0x1;
self.ram_offset = 0x1000;
self.ie = 0x0;
}
pub fn allocate_default(&mut self) {
self.allocate_dmg();
}
pub fn allocate_dmg(&mut self) {
self.boot = vec![0x00; BOOT_SIZE_DMG];
self.ram = vec![0x00; RAM_SIZE_DMG];
}
pub fn allocate_cgb(&mut self) {
self.boot = vec![0x00; BOOT_SIZE_CGB];
self.ram = vec![0x00; RAM_SIZE_CGB];
}
pub fn ppu(&mut self) -> &mut Ppu {
&mut self.ppu
}
......@@ -106,7 +133,7 @@ impl Mmu {
// ROM 0 (12 KB/16 KB)
0x1000 | 0x2000 | 0x3000 => self.rom.read(addr),
// ROM 1 (Unbanked) (16 KB)
// ROM 1 (Banked) (16 KB)
0x4000 | 0x5000 | 0x6000 | 0x7000 => self.rom.read(addr),
// Graphics: VRAM (8 KB)
......@@ -115,8 +142,11 @@ impl Mmu {
// External RAM (8 KB)
0xa000 | 0xb000 => self.rom.read(addr),
// Working RAM (8 KB)
0xc000 | 0xd000 => self.ram[(addr & 0x1fff) as usize],
// Working RAM 0 (4 KB)
0xc000 => self.ram[(addr & 0x0fff) as usize],
// Working RAM 1 (Banked) (4KB)
0xd000 => self.ram[(self.ram_offset + (addr & 0x0fff)) as usize],
// Working RAM Shadow
0xe000 => self.ram[(addr & 0x1fff) as usize],
......@@ -182,7 +212,7 @@ impl Mmu {
// ROM 0 (12 KB/16 KB)
0x1000 | 0x2000 | 0x3000 => self.rom.write(addr, value),
// ROM 1 (Unbanked) (16 KB)
// ROM 1 (Banked) (16 KB)
0x4000 | 0x5000 | 0x6000 | 0x7000 => self.rom.write(addr, value),
// Graphics: VRAM (8 KB)
......@@ -224,6 +254,16 @@ impl Mmu {
// 0xFF50 - Boot active flag
0x50 => self.boot_active = false,
// 0xFF70 - SVBK: WRAM bank (CGB Mode only)
0x70 => {
let mut ram_bank = value & 0x7;
if ram_bank == 0x0 {
ram_bank = 0x1;
}
self.ram_bank = ram_bank;
self.ram_offset = self.ram_bank as u16 * 0x1000;
}
// 0xFF80-0xFFFE - High RAM (HRAM)
0x80..=0xfe => self.ppu.hram[(addr & 0x007f) as usize] = value,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment