From 6b35a0b0981a873db62c6a9fc32cbd15a433ded9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Mon, 11 Jul 2022 00:26:03 +0100 Subject: [PATCH] feat: support for MBC5 --- CHANGELOG.md | 1 + examples/sdl/src/main.rs | 3 +- src/ppu.rs | 16 +++++++++ src/rom.rs | 74 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2425423..f991c882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Support for 8x16 sprites +* Support for MBC5, think Pokemon Yellow ### Changed diff --git a/examples/sdl/src/main.rs b/examples/sdl/src/main.rs index b2f65017..a3411a55 100644 --- a/examples/sdl/src/main.rs +++ b/examples/sdl/src/main.rs @@ -162,7 +162,8 @@ fn main() { //let rom = game_boy.load_rom_file("../../res/roms.prop/super_mario.gb"); //let rom = game_boy.load_rom_file("../../res/roms.prop/super_mario_2.gb"); //let rom = game_boy.load_rom_file("../../res/roms.prop/pokemon_red.gb"); - let rom = game_boy.load_rom_file("../../res/roms.prop/zelda.gb"); + let rom = game_boy.load_rom_file("../../res/roms.prop/pokemon_yellow.gb"); + //let rom = game_boy.load_rom_file("../../res/roms.prop/zelda.gb"); //let rom = game_boy.load_rom_file("../../res/roms/firstwhite.gb"); //let rom = game_boy.load_rom_file("../../res/roms/opus5.gb"); diff --git a/src/ppu.rs b/src/ppu.rs index 14dcca66..efbb3a87 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -172,6 +172,10 @@ pub struct Ppu { /// The palette that is going to be used for sprites/objects #1. palette_obj_1: Palette, + /// The complete set of palettes in binary data so that they can + /// bre read if required by the system. + palettes: [u8; 3], + /// The scroll Y register that controls the Y offset /// of the background. scy: u8, @@ -282,6 +286,7 @@ impl Ppu { palette: [[0u8; RGB_SIZE]; PALETTE_SIZE], palette_obj_0: [[0u8; RGB_SIZE]; PALETTE_SIZE], palette_obj_1: [[0u8; RGB_SIZE]; PALETTE_SIZE], + palettes: [0u8; 3], scy: 0x0, scx: 0x0, wy: 0x0, @@ -317,6 +322,7 @@ impl Ppu { self.palette = [[0u8; RGB_SIZE]; PALETTE_SIZE]; self.palette_obj_0 = [[0u8; RGB_SIZE]; PALETTE_SIZE]; self.palette_obj_1 = [[0u8; RGB_SIZE]; PALETTE_SIZE]; + self.palettes = [0u8; 3]; self.scy = 0x0; self.scx = 0x0; self.ly = 0x0; @@ -432,8 +438,13 @@ impl Ppu { 0x0043 => self.scx, 0x0044 => self.ly, 0x0045 => self.lyc, + 0x0047 => self.palettes[0], + 0x0048 => self.palettes[1], + 0x0049 => self.palettes[2], 0x004a => self.wy, 0x004b => self.wx, + // VBK - CGB Mode Only + 0x004f => 0xff, _ => { warnln!("Reading from unknown PPU location 0x{:04x}", addr); 0xff @@ -485,6 +496,7 @@ impl Ppu { color_index => panic!("Invalid palette color index {:04x}", color_index), } } + self.palettes[0] = value; } 0x0048 => { for index in 0..PALETTE_SIZE { @@ -496,6 +508,7 @@ impl Ppu { color_index => panic!("Invalid palette color index {:04x}", color_index), } } + self.palettes[1] = value; } 0x0049 => { for index in 0..PALETTE_SIZE { @@ -507,9 +520,12 @@ impl Ppu { color_index => panic!("Invalid palette color index {:04x}", color_index), } } + self.palettes[2] = value; } 0x004a => self.wy = value, 0x004b => self.wx = value, + // VBK - CGB Mode Only + 0x004f => (), 0x007f => (), _ => warnln!("Writing in unknown PPU location 0x{:04x}", addr), } diff --git a/src/rom.rs b/src/rom.rs index e05b6386..d83821ec 100644 --- a/src/rom.rs +++ b/src/rom.rs @@ -4,7 +4,7 @@ use std::{ fmt::{Display, Formatter}, }; -use crate::debugln; +use crate::{debugln, warnln}; #[cfg(feature = "wasm")] use wasm_bindgen::prelude::*; @@ -267,6 +267,12 @@ impl Cartridge { RomType::Mbc3 => &MBC3, RomType::Mbc3Ram => &MBC3, RomType::Mbc3RamBattery => &MBC3, + RomType::Mbc5 => &MBC5, + RomType::Mbc5Ram => &MBC5, + RomType::Mbc5RamBattery => &MBC5, + RomType::Mbc5Rumble => &MBC5, + RomType::Mbc5RumbleRam => &MBC5, + RomType::Mbc5RumbleRamBattery => &MBC5, rom_type => panic!("No MBC controller available for {}", rom_type), } } @@ -418,7 +424,10 @@ pub static MBC1: Mbc = Mbc { 0x4000 | 0x5000 | 0x6000 | 0x7000 => { rom.rom_data[rom.rom_offset + (addr - 0x4000) as usize] } - _ => panic!("Reading from unknown Cartridge ROM location 0x{:04x}", addr), + _ => { + warnln!("Reading from unknown Cartridge ROM location 0x{:04x}", addr); + 0xff + } } }, write_rom: |rom: &mut Cartridge, addr: u16, value: u8| { @@ -447,7 +456,7 @@ pub static MBC1: Mbc = Mbc { unimplemented!("Advanced ROM banking mode for MBC1 is not implemented"); } } - _ => panic!("Writing to unknown Cartridge ROM location 0x{:04x}", addr), + _ => warnln!("Writing to unknown Cartridge ROM location 0x{:04x}", addr), } }, read_ram: |rom: &Cartridge, addr: u16| -> u8 { @@ -473,7 +482,10 @@ pub static MBC3: Mbc = Mbc { 0x4000 | 0x5000 | 0x6000 | 0x7000 => { rom.rom_data[rom.rom_offset + (addr - 0x4000) as usize] } - _ => panic!("Reading from unknown Cartridge ROM location 0x{:04x}", addr), + _ => { + warnln!("Reading from unknown Cartridge ROM location 0x{:04x}", addr); + 0xff + } } }, write_rom: |rom: &mut Cartridge, addr: u16, value: u8| { @@ -496,7 +508,59 @@ pub static MBC3: Mbc = Mbc { let ram_bank = value & 0x03; rom.set_ram_bank(ram_bank); } - _ => panic!("Writing to unknown Cartridge ROM location 0x{:04x}", addr), + _ => warnln!("Writing to unknown Cartridge ROM location 0x{:04x}", addr), + } + }, + read_ram: |rom: &Cartridge, addr: u16| -> u8 { + if !rom.ram_enabled { + return 0xff; + } + rom.ram_data[rom.ram_offset + (addr - 0xa000) as usize] + }, + write_ram: |rom: &mut Cartridge, addr: u16, value: u8| { + if !rom.ram_enabled { + debugln!("Attempt to write to ERAM while write protect is active"); + return; + } + rom.ram_data[rom.ram_offset + (addr - 0xa000) as usize] = value; + }, +}; + +pub static MBC5: Mbc = Mbc { + name: "MBC5", + read_rom: |rom: &Cartridge, addr: u16| -> u8 { + match addr & 0xf000 { + 0x0000 | 0x1000 | 0x2000 | 0x3000 => rom.rom_data[addr as usize], + 0x4000 | 0x5000 | 0x6000 | 0x7000 => { + rom.rom_data[rom.rom_offset + (addr - 0x4000) as usize] + } + _ => { + warnln!("Reading from unknown Cartridge ROM location 0x{:04x}", addr); + 0xff + } + } + }, + write_rom: |rom: &mut Cartridge, addr: u16, value: u8| { + match addr & 0xf000 { + // RAM enabled flag + 0x0000 | 0x1000 => { + rom.ram_enabled = (value & 0x0f) == 0x0a; + } + // ROM bank selection + 0x2000 => { + let mut rom_bank = value & 0xff; + rom_bank = rom_bank & (rom.rom_bank_count * 2 - 1) as u8; + if rom_bank == 0 { + rom_bank = 1; + } + rom.set_rom_bank(rom_bank); + } + // RAM bank selection + 0x4000 | 0x5000 => { + let ram_bank = value & 0x0f; + rom.set_ram_bank(ram_bank); + } + _ => warnln!("Writing to unknown Cartridge ROM location 0x{:04x}", addr), } }, read_ram: |rom: &Cartridge, addr: u16| -> u8 { -- GitLab