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

feat: initial support for config

parent d07e7f09
No related branches found
No related tags found
1 merge request!16Support for Game Boy Color (CGB) 😎🖍️
Pipeline #2557 failed
use core::panic; use core::panic;
use std::{cell::RefCell, rc::Rc};
use crate::{ use crate::{
apu::Apu, apu::Apu,
debugln, debugln,
gb::GameBoyConfig,
inst::{EXTENDED, INSTRUCTIONS}, inst::{EXTENDED, INSTRUCTIONS},
mmu::Mmu, mmu::Mmu,
pad::Pad, pad::Pad,
...@@ -38,10 +40,15 @@ pub struct Cpu { ...@@ -38,10 +40,15 @@ pub struct Cpu {
/// Temporary counter used to control the number of cycles /// Temporary counter used to control the number of cycles
/// taken by the current or last CPU operation. /// taken by the current or last CPU operation.
pub cycles: u8, pub cycles: u8,
/// The pointer to the parent configuration of the running
/// Game Boy emulator, that can be used to control the behaviour
/// of Game Boy emulation.
gbc: Rc<RefCell<GameBoyConfig>>,
} }
impl Cpu { impl Cpu {
pub fn new(mmu: Mmu) -> Self { pub fn new(mmu: Mmu, gbc: Rc<RefCell<GameBoyConfig>>) -> Self {
Self { Self {
pc: 0x0, pc: 0x0,
sp: 0x0, sp: 0x0,
...@@ -60,6 +67,7 @@ impl Cpu { ...@@ -60,6 +67,7 @@ impl Cpu {
halted: false, halted: false,
mmu, mmu,
cycles: 0, cycles: 0,
gbc: gbc,
} }
} }
......
...@@ -13,7 +13,7 @@ use crate::{ ...@@ -13,7 +13,7 @@ use crate::{
util::read_file, util::read_file,
}; };
use std::collections::VecDeque; use std::{cell::RefCell, collections::VecDeque, rc::Rc};
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
...@@ -32,28 +32,22 @@ use std::{ ...@@ -32,28 +32,22 @@ use std::{
/// Enumeration that describes the multiple running /// Enumeration that describes the multiple running
// modes of the Game Boy emulator. // modes of the Game Boy emulator.
#[cfg_attr(feature = "wasm", wasm_bindgen)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum GBMode { pub enum GBMode {
Dmg = 1, Dmg = 1,
Cgb = 2, Cgb = 2,
Sgb = 3, Sgb = 3,
} }
/// Top level structure that abstracts the usage of the
/// Game Boy system under the Boytacean emulator.
/// Should serve as the main entry-point API.
#[cfg_attr(feature = "wasm", wasm_bindgen)] #[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct GameBoy { #[derive(Clone, Copy, PartialEq, Eq)]
pub struct GameBoyConfig {
/// The current running mode of the emulator, this /// The current running mode of the emulator, this
/// may affect many aspects of the emulation, like /// may affect many aspects of the emulation, like
/// CPU frequency, PPU frequency, Boot rome size, etc. /// CPU frequency, PPU frequency, Boot rome size, etc.
mode: GBMode, mode: GBMode,
/// Reference to the Game Boy CPU component to be
/// used as the main element of the system, when
/// clocked, the amount of ticks from it will be
/// used as reference or the rest of the components.
cpu: Cpu,
/// If the PPU is enabled, it will be clocked. /// If the PPU is enabled, it will be clocked.
ppu_enabled: bool, ppu_enabled: bool,
...@@ -75,6 +69,98 @@ pub struct GameBoy { ...@@ -75,6 +69,98 @@ pub struct GameBoy {
clock_freq: u32, clock_freq: u32,
} }
#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl GameBoyConfig {
#[inline(always)]
pub fn is_dmg(&self) -> bool {
self.mode == GBMode::Dmg
}
#[inline(always)]
pub fn is_cgb(&self) -> bool {
self.mode == GBMode::Cgb
}
#[inline(always)]
pub fn is_sgb(&self) -> bool {
self.mode == GBMode::Sgb
}
#[inline(always)]
pub fn mode(&self) -> GBMode {
self.mode
}
#[inline(always)]
pub fn set_mode(&mut self, value: GBMode) {
self.mode = value;
}
#[inline(always)]
pub fn ppu_enabled(&self) -> bool {
self.ppu_enabled
}
#[inline(always)]
pub fn set_ppu_enabled(&mut self, value: bool) {
self.ppu_enabled = value;
}
#[inline(always)]
pub fn apu_enabled(&self) -> bool {
self.apu_enabled
}
#[inline(always)]
pub fn set_apu_enabled(&mut self, value: bool) {
self.apu_enabled = value;
}
#[inline(always)]
pub fn timer_enabled(&self) -> bool {
self.timer_enabled
}
#[inline(always)]
pub fn set_timer_enabled(&mut self, value: bool) {
self.timer_enabled = value;
}
#[inline(always)]
pub fn serial_enabled(&self) -> bool {
self.serial_enabled
}
#[inline(always)]
pub fn set_serial_enabled(&mut self, value: bool) {
self.serial_enabled = value;
}
#[inline(always)]
pub fn clock_freq(&self) -> u32 {
self.clock_freq
}
#[inline(always)]
pub fn set_clock_freq(&mut self, value: u32) {
self.clock_freq = value;
}
}
/// Top level structure that abstracts the usage of the
/// Game Boy system under the Boytacean emulator.
/// Should serve as the main entry-point API.
#[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct GameBoy {
/// Reference to the Game Boy CPU component to be
/// used as the main element of the system, when
/// clocked, the amount of ticks from it will be
/// used as reference or the rest of the components.
cpu: Cpu,
gbc: Rc<RefCell<GameBoyConfig>>,
}
#[cfg_attr(feature = "wasm", wasm_bindgen)] #[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct Registers { pub struct Registers {
pub pc: u16, pub pc: u16,
...@@ -104,22 +190,24 @@ pub trait AudioProvider { ...@@ -104,22 +190,24 @@ pub trait AudioProvider {
impl GameBoy { impl GameBoy {
#[cfg_attr(feature = "wasm", wasm_bindgen(constructor))] #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
pub fn new(mode: GBMode) -> Self { pub fn new(mode: GBMode) -> Self {
let ppu = Ppu::default(); let gbc = Rc::new(RefCell::new(GameBoyConfig {
let apu = Apu::default();
let pad = Pad::default();
let timer = Timer::default();
let serial = Serial::default();
let mmu = Mmu::new(ppu, apu, pad, timer, serial);
let cpu = Cpu::new(mmu);
Self {
mode, mode,
cpu,
ppu_enabled: true, ppu_enabled: true,
apu_enabled: true, apu_enabled: true,
timer_enabled: true, timer_enabled: true,
serial_enabled: true, serial_enabled: true,
clock_freq: GameBoy::CPU_FREQ, clock_freq: GameBoy::CPU_FREQ,
} }));
let ppu = Ppu::default();
let apu = Apu::default();
let pad = Pad::default();
let timer = Timer::default();
let serial = Serial::default();
let mmu = Mmu::new(ppu, apu, pad, timer, serial, gbc.clone());
let cpu = Cpu::new(mmu, gbc.clone());
Self { cpu, gbc }
} }
pub fn reset(&mut self) { pub fn reset(&mut self) {
...@@ -133,16 +221,16 @@ impl GameBoy { ...@@ -133,16 +221,16 @@ impl GameBoy {
pub fn clock(&mut self) -> u8 { pub fn clock(&mut self) -> u8 {
let cycles = self.cpu_clock(); let cycles = self.cpu_clock();
if self.ppu_enabled { if self.ppu_enabled() {
self.ppu_clock(cycles); self.ppu_clock(cycles);
} }
if self.apu_enabled { if self.apu_enabled() {
self.apu_clock(cycles); self.apu_clock(cycles);
} }
if self.timer_enabled { if self.timer_enabled() {
self.timer_clock(cycles); self.timer_clock(cycles);
} }
if self.serial_enabled { if self.serial_enabled() {
self.serial_clock(cycles); self.serial_clock(cycles);
} }
cycles cycles
...@@ -193,7 +281,7 @@ impl GameBoy { ...@@ -193,7 +281,7 @@ impl GameBoy {
} }
pub fn load(&mut self, boot: bool) { pub fn load(&mut self, boot: bool) {
match self.mode { match self.mode() {
GBMode::Dmg => self.load_dmg(boot), GBMode::Dmg => self.load_dmg(boot),
GBMode::Cgb => self.load_cgb(boot), GBMode::Cgb => self.load_cgb(boot),
GBMode::Sgb => todo!(), GBMode::Sgb => todo!(),
...@@ -357,44 +445,58 @@ impl GameBoy { ...@@ -357,44 +445,58 @@ impl GameBoy {
String::from(COMPILATION_TIME) String::from(COMPILATION_TIME)
} }
#[inline(always)]
pub fn mode(&self) -> GBMode {
(*self.gbc).borrow().mode()
}
pub fn set_mode(&mut self, value: GBMode) {
(*self.gbc).borrow_mut().set_mode(value);
}
#[inline(always)]
pub fn ppu_enabled(&self) -> bool { pub fn ppu_enabled(&self) -> bool {
self.ppu_enabled (*self.gbc).borrow().ppu_enabled()
} }
pub fn set_ppu_enabled(&mut self, value: bool) { pub fn set_ppu_enabled(&mut self, value: bool) {
self.ppu_enabled = value; (*self.gbc).borrow_mut().set_ppu_enabled(value);
} }
#[inline(always)]
pub fn apu_enabled(&self) -> bool { pub fn apu_enabled(&self) -> bool {
self.apu_enabled (*self.gbc).borrow().apu_enabled
} }
pub fn set_apu_enabled(&mut self, value: bool) { pub fn set_apu_enabled(&mut self, value: bool) {
self.apu_enabled = value; (*self.gbc).borrow_mut().set_apu_enabled(value);
} }
#[inline(always)]
pub fn timer_enabled(&self) -> bool { pub fn timer_enabled(&self) -> bool {
self.timer_enabled (*self.gbc).borrow().timer_enabled()
} }
pub fn set_timer_enabled(&mut self, value: bool) { pub fn set_timer_enabled(&mut self, value: bool) {
self.timer_enabled = value; (*self.gbc).borrow_mut().set_timer_enabled(value);
} }
#[inline(always)]
pub fn serial_enabled(&self) -> bool { pub fn serial_enabled(&self) -> bool {
self.serial_enabled (*self.gbc).borrow().serial_enabled()
} }
pub fn set_serial_enabled(&mut self, value: bool) { pub fn set_serial_enabled(&mut self, value: bool) {
self.serial_enabled = value; (*self.gbc).borrow_mut().set_serial_enabled(value);
} }
#[inline(always)]
pub fn clock_freq(&self) -> u32 { pub fn clock_freq(&self) -> u32 {
self.clock_freq (*self.gbc).borrow().clock_freq()
} }
pub fn set_clock_freq(&mut self, value: u32) { pub fn set_clock_freq(&mut self, value: u32) {
self.clock_freq = value; (*self.gbc).borrow_mut().set_clock_freq(value);
self.apu().set_clock_freq(value); self.apu().set_clock_freq(value);
} }
......
...@@ -3119,11 +3119,13 @@ fn set_7_a(cpu: &mut Cpu) { ...@@ -3119,11 +3119,13 @@ fn set_7_a(cpu: &mut Cpu) {
} }
/// Helper function to set one bit in a u8. /// Helper function to set one bit in a u8.
#[inline(always)]
fn set(value: u8, bit: u8) -> u8 { fn set(value: u8, bit: u8) -> u8 {
value | (1u8 << (bit as usize)) value | (1u8 << (bit as usize))
} }
/// Helper function to clear one bit in a u8. /// Helper function to clear one bit in a u8.
#[inline(always)]
fn res(value: u8, bit: u8) -> u8 { fn res(value: u8, bit: u8) -> u8 {
value & !(1u8 << (bit as usize)) value & !(1u8 << (bit as usize))
} }
...@@ -3131,6 +3133,7 @@ fn res(value: u8, bit: u8) -> u8 { ...@@ -3131,6 +3133,7 @@ fn res(value: u8, bit: u8) -> u8 {
/// Helper function that rotates (shifts) left the given /// Helper function that rotates (shifts) left the given
/// byte (probably from a register) and updates the /// byte (probably from a register) and updates the
/// proper flag registers. /// proper flag registers.
#[inline(always)]
fn rl(cpu: &mut Cpu, value: u8) -> u8 { fn rl(cpu: &mut Cpu, value: u8) -> u8 {
let carry = cpu.carry(); let carry = cpu.carry();
...@@ -3145,6 +3148,7 @@ fn rl(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3145,6 +3148,7 @@ fn rl(cpu: &mut Cpu, value: u8) -> u8 {
result result
} }
#[inline(always)]
fn rlc(cpu: &mut Cpu, value: u8) -> u8 { fn rlc(cpu: &mut Cpu, value: u8) -> u8 {
cpu.set_carry((value & 0x80) == 0x80); cpu.set_carry((value & 0x80) == 0x80);
...@@ -3160,6 +3164,7 @@ fn rlc(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3160,6 +3164,7 @@ fn rlc(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function that rotates (shifts) right the given /// Helper function that rotates (shifts) right the given
/// byte (probably from a register) and updates the /// byte (probably from a register) and updates the
/// proper flag registers. /// proper flag registers.
#[inline(always)]
fn rr(cpu: &mut Cpu, value: u8) -> u8 { fn rr(cpu: &mut Cpu, value: u8) -> u8 {
let carry = cpu.carry(); let carry = cpu.carry();
...@@ -3174,6 +3179,7 @@ fn rr(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3174,6 +3179,7 @@ fn rr(cpu: &mut Cpu, value: u8) -> u8 {
result result
} }
#[inline(always)]
fn rrc(cpu: &mut Cpu, value: u8) -> u8 { fn rrc(cpu: &mut Cpu, value: u8) -> u8 {
cpu.set_carry((value & 0x1) == 0x1); cpu.set_carry((value & 0x1) == 0x1);
...@@ -3188,52 +3194,61 @@ fn rrc(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3188,52 +3194,61 @@ fn rrc(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function to test one bit in a u8. /// Helper function to test one bit in a u8.
/// Returns true if bit is 0. /// Returns true if bit is 0.
#[inline(always)]
fn bit_zero(val: u8, bit: u8) -> bool { fn bit_zero(val: u8, bit: u8) -> bool {
(val & (1u8 << (bit as usize))) == 0 (val & (1u8 << (bit as usize))) == 0
} }
#[inline(always)]
fn bit_a(cpu: &mut Cpu, bit: u8) { fn bit_a(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.a, bit)); cpu.set_zero(bit_zero(cpu.a, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_b(cpu: &mut Cpu, bit: u8) { fn bit_b(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.b, bit)); cpu.set_zero(bit_zero(cpu.b, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_c(cpu: &mut Cpu, bit: u8) { fn bit_c(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.c, bit)); cpu.set_zero(bit_zero(cpu.c, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_d(cpu: &mut Cpu, bit: u8) { fn bit_d(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.d, bit)); cpu.set_zero(bit_zero(cpu.d, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_e(cpu: &mut Cpu, bit: u8) { fn bit_e(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.e, bit)); cpu.set_zero(bit_zero(cpu.e, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_h(cpu: &mut Cpu, bit: u8) { fn bit_h(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.h, bit)); cpu.set_zero(bit_zero(cpu.h, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_l(cpu: &mut Cpu, bit: u8) { fn bit_l(cpu: &mut Cpu, bit: u8) {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.l, bit)); cpu.set_zero(bit_zero(cpu.l, bit));
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn bit_mhl(cpu: &mut Cpu, bit: u8) { fn bit_mhl(cpu: &mut Cpu, bit: u8) {
let byte = cpu.mmu.read(cpu.hl()); let byte = cpu.mmu.read(cpu.hl());
cpu.set_sub(false); cpu.set_sub(false);
...@@ -3241,6 +3256,7 @@ fn bit_mhl(cpu: &mut Cpu, bit: u8) { ...@@ -3241,6 +3256,7 @@ fn bit_mhl(cpu: &mut Cpu, bit: u8) {
cpu.set_half_carry(true); cpu.set_half_carry(true);
} }
#[inline(always)]
fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
let first = first as u32; let first = first as u32;
let second = second as u32; let second = second as u32;
...@@ -3256,6 +3272,7 @@ fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { ...@@ -3256,6 +3272,7 @@ fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b result_b
} }
#[inline(always)]
fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
let first = first as u32; let first = first as u32;
let second = second as u32; let second = second as u32;
...@@ -3272,6 +3289,7 @@ fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { ...@@ -3272,6 +3289,7 @@ fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b result_b
} }
#[inline(always)]
fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
let first = first as u32; let first = first as u32;
let second = second as u32; let second = second as u32;
...@@ -3287,6 +3305,7 @@ fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { ...@@ -3287,6 +3305,7 @@ fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b result_b
} }
#[inline(always)]
fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
let first = first as u32; let first = first as u32;
let second = second as u32; let second = second as u32;
...@@ -3303,6 +3322,7 @@ fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 { ...@@ -3303,6 +3322,7 @@ fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b result_b
} }
#[inline(always)]
fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 { fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 {
let first = first as u32; let first = first as u32;
let second = second as u32; let second = second as u32;
...@@ -3315,6 +3335,7 @@ fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 { ...@@ -3315,6 +3335,7 @@ fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 {
result as u16 result as u16
} }
#[inline(always)]
fn swap(cpu: &mut Cpu, value: u8) -> u8 { fn swap(cpu: &mut Cpu, value: u8) -> u8 {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(value == 0); cpu.set_zero(value == 0);
...@@ -3326,6 +3347,7 @@ fn swap(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3326,6 +3347,7 @@ fn swap(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function to shift an `u8` to the left and update CPU /// Helper function to shift an `u8` to the left and update CPU
/// flags. /// flags.
#[inline(always)]
fn sla(cpu: &mut Cpu, value: u8) -> u8 { fn sla(cpu: &mut Cpu, value: u8) -> u8 {
let result = value << 1; let result = value << 1;
...@@ -3337,6 +3359,7 @@ fn sla(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3337,6 +3359,7 @@ fn sla(cpu: &mut Cpu, value: u8) -> u8 {
result result
} }
#[inline(always)]
fn sra(cpu: &mut Cpu, value: u8) -> u8 { fn sra(cpu: &mut Cpu, value: u8) -> u8 {
let result = (value >> 1) | (value & 0x80); let result = (value >> 1) | (value & 0x80);
...@@ -3348,6 +3371,7 @@ fn sra(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3348,6 +3371,7 @@ fn sra(cpu: &mut Cpu, value: u8) -> u8 {
result result
} }
#[inline(always)]
fn srl(cpu: &mut Cpu, value: u8) -> u8 { fn srl(cpu: &mut Cpu, value: u8) -> u8 {
let result = value >> 1; let result = value >> 1;
...@@ -3362,6 +3386,7 @@ fn srl(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -3362,6 +3386,7 @@ fn srl(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function for RST instructions, pushes the /// Helper function for RST instructions, pushes the
/// current PC to the stack and jumps to the provided /// current PC to the stack and jumps to the provided
/// address. /// address.
#[inline(always)]
fn rst(cpu: &mut Cpu, addr: u16) { fn rst(cpu: &mut Cpu, addr: u16) {
cpu.push_word(cpu.pc); cpu.push_word(cpu.pc);
cpu.pc = addr; cpu.pc = addr;
......
use crate::{apu::Apu, debugln, pad::Pad, ppu::Ppu, rom::Cartridge, serial::Serial, timer::Timer}; use std::{cell::RefCell, rc::Rc};
use crate::{
apu::Apu, debugln, gb::GameBoyConfig, pad::Pad, ppu::Ppu, rom::Cartridge, serial::Serial,
timer::Timer,
};
pub const BOOT_SIZE_DMG: usize = 256; pub const BOOT_SIZE_DMG: usize = 256;
pub const BOOT_SIZE_CGB: usize = 2304; pub const BOOT_SIZE_CGB: usize = 2304;
...@@ -55,14 +60,23 @@ pub struct Mmu { ...@@ -55,14 +60,23 @@ pub struct Mmu {
ram: Vec<u8>, ram: Vec<u8>,
/// The RAM bank to be used in the read and write operation of /// The RAM bank to be used in the read and write operation of
/// the 0xD000-0xDFFF memory range. CGB Only /// the 0xD000-0xDFFF memory range (CGB Only).
ram_bank: u8, ram_bank: u8,
ram_offset: u16, ram_offset: u16,
gbc: Rc<RefCell<GameBoyConfig>>,
} }
impl Mmu { impl Mmu {
pub fn new(ppu: Ppu, apu: Apu, pad: Pad, timer: Timer, serial: Serial) -> Self { pub fn new(
ppu: Ppu,
apu: Apu,
pad: Pad,
timer: Timer,
serial: Serial,
gbc: Rc<RefCell<GameBoyConfig>>,
) -> Self {
Self { Self {
ppu, ppu,
apu, apu,
...@@ -76,6 +90,7 @@ impl Mmu { ...@@ -76,6 +90,7 @@ impl Mmu {
ram_bank: 0x1, ram_bank: 0x1,
ram_offset: 0x1000, ram_offset: 0x1000,
ie: 0x0, ie: 0x0,
gbc: gbc,
} }
} }
......
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