Compare commits

...

3 Commits

Author SHA1 Message Date
Rekai Nyangadzayi Musuka 18b790a777 chore(cartridge): update MBC1 (still broken)
continuous-integration/drone/push Build is passing Details
2021-07-05 00:14:56 -05:00
Rekai Nyangadzayi Musuka 39af03aebf chore(bus): stub 0xFF4D 2021-07-01 23:09:02 -05:00
Rekai Nyangadzayi Musuka 559cb54385 chore(snd): add enabled property to all channels
Also, rename lsfr property to shift_register
2021-07-01 22:27:42 -05:00
3 changed files with 52 additions and 35 deletions

View File

@ -247,6 +247,7 @@ impl BusIo for Bus {
0x49 => self.ppu.monochrome.obj_palette_1.into(), 0x49 => self.ppu.monochrome.obj_palette_1.into(),
0x4A => self.ppu.pos.window_y, 0x4A => self.ppu.pos.window_y,
0x4B => self.ppu.pos.window_x, 0x4B => self.ppu.pos.window_x,
0x4D => 0xFF, // CGB Specific Register
_ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr), _ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr),
} }
} }
@ -376,7 +377,7 @@ impl BusIo for Bus {
0x49 => self.ppu.monochrome.obj_palette_1 = byte.into(), 0x49 => self.ppu.monochrome.obj_palette_1 = byte.into(),
0x4A => self.ppu.pos.window_y = byte, 0x4A => self.ppu.pos.window_y = byte,
0x4B => self.ppu.pos.window_x = byte, 0x4B => self.ppu.pos.window_x = byte,
0x4D => {} // Writing to this address is useful on the CGB only 0x4D => {} // CGB Specific Register
0x50 => { 0x50 => {
// Disable Boot ROM // Disable Boot ROM
if byte != 0 { if byte != 0 {

View File

@ -157,7 +157,18 @@ impl Mbc1 {
match self.bank_count { match self.bank_count {
None | Four | Eight | Sixteen | ThirtyTwo => 0x00, None | Four | Eight | Sixteen | ThirtyTwo => 0x00,
SixtyFour => (self.ram_bank & 0x01) << 5, SixtyFour => (self.ram_bank & 0x01) << 5,
OneHundredTwentyEight => self.ram_bank << 5, OneHundredTwentyEight => (self.ram_bank & 0x03) << 5,
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
}
}
fn mbcm_zero_bank(&self) -> u8 {
use BankCount::*;
match self.bank_count {
None | Four | Eight | Sixteen | ThirtyTwo => 0x00,
SixtyFour => (self.ram_bank & 0x03) << 4,
OneHundredTwentyEight => (self.ram_bank & 0x03) << 5,
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
@ -165,39 +176,39 @@ impl Mbc1 {
fn high_bank(&self) -> u8 { fn high_bank(&self) -> u8 {
use BankCount::*; use BankCount::*;
let base = self.rom_bank & self.rom_bank_bitmask(); let base = self.rom_bank & self.rom_size_mask();
match self.bank_count { match self.bank_count {
None | Four | Eight | Sixteen | ThirtyTwo => base, None | Four | Eight | Sixteen | ThirtyTwo => base,
SixtyFour => (base & !(0x01 << 5)) | (self.ram_bank & 0x01) << 5, SixtyFour => base & !(0x01 << 5) | ((self.ram_bank & 0x01) << 5),
OneHundredTwentyEight => (base & !(0x03 << 5)) | (self.ram_bank & 0x03) << 5, OneHundredTwentyEight => base & !(0x03 << 5) | ((self.ram_bank & 0x03) << 5),
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
fn rom_bank_bitmask(&self) -> u8 { fn rom_size_mask(&self) -> u8 {
use BankCount::*; use BankCount::*;
match self.bank_count { match self.bank_count {
None => 0x1, None => 0b00000001,
Four => 0x03, Four => 0b00000011,
Eight => 0x07, Eight => 0b00000111,
Sixteen => 0x0F, Sixteen => 0b00001111,
ThirtyTwo | SixtyFour | OneHundredTwentyEight => 0x1F, ThirtyTwo | SixtyFour | OneHundredTwentyEight => 0b00011111,
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
fn ram_addr(&self, addr: u16) -> usize { fn ram_addr(&self, addr: u16) -> u16 {
use RamSize::*; use RamSize::*;
match self.ram_size { match self.ram_size {
_2KB | _8KB => (addr as usize - 0xA000) % self.ram_size.len() as usize, _2KB | _8KB => (addr - 0xA000) % self.ram_size.len() as u16,
_32KB => { _32KB => {
if self.mode { if self.mode {
0x2000 * self.ram_bank as usize + (addr as usize - 0xA000) 0x2000 * self.ram_bank as u16 + (addr - 0xA000)
} else { } else {
addr as usize - 0xA000 addr - 0xA000
} }
} }
_ => unreachable!("RAM size can not be greater than 32KB on MBC1"), _ => unreachable!("RAM size can not be greater than 32KB on MBC1"),
@ -212,19 +223,17 @@ impl MemoryBankController for Mbc1 {
match addr { match addr {
0x0000..=0x3FFF => { 0x0000..=0x3FFF => {
if self.mode { if self.mode {
let zero_bank = self.zero_bank() as usize; Address((0x4000 * self.zero_bank() as usize) + addr as usize)
Address(0x4000 * zero_bank + addr as usize)
} else { } else {
Address(addr as usize) Address(addr as usize)
} }
} }
0x4000..=0x7FFF => { 0x4000..=0x7FFF => {
let high_bank = self.high_bank() as usize; Address((0x4000 * self.high_bank() as usize) + (addr as usize - 0x4000))
Address(0x4000 * high_bank + (addr as usize - 0x4000))
} }
0xA000..=0xBFFF => { 0xA000..=0xBFFF => {
if self.ram_enabled { if self.ram_enabled {
Value(self.ram[self.ram_addr(addr)]) Value(self.ram[self.ram_addr(addr) as usize])
} else { } else {
Value(0xFF) Value(0xFF)
} }
@ -240,17 +249,18 @@ impl MemoryBankController for Mbc1 {
self.rom_bank = if byte == 0x00 { self.rom_bank = if byte == 0x00 {
0x01 0x01
} else { } else {
byte & self.rom_bank_bitmask() byte & self.rom_size_mask()
} };
self.rom_bank &= 0x1F;
} }
0x4000..=0x5FFF => self.ram_bank = byte & 0x03, 0x4000..=0x5FFF => self.ram_bank = byte & 0x03,
0x6000..=0x7FFF => self.mode = (byte & 0x01) == 0x01, 0x6000..=0x7FFF => self.mode = (byte & 0x01) == 0x01,
0xA000..=0xBFFF => { 0xA000..=0xBFFF if self.ram_enabled => {
if self.ram_enabled { let ram_addr = self.ram_addr(addr) as usize;
let ram_addr = self.ram_addr(addr); self.ram[ram_addr] = byte;
self.ram[ram_addr] = byte;
}
} }
0xA000..=0xBFFF => {} // Ram isn't enabled, ignored write
_ => unreachable!("A write to {:#06X} should not be handled by MBC1", addr), _ => unreachable!("A write to {:#06X} should not be handled by MBC1", addr),
} }
} }
@ -432,7 +442,7 @@ impl From<u8> for RamSize {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum BankCount { enum BankCount {
None = 0x00, // 32KB None = 0x00, // 32KB (also called Two)
Four = 0x01, // 64KB Four = 0x01, // 64KB
Eight = 0x02, // 128KB Eight = 0x02, // 128KB
Sixteen = 0x03, // 256KB Sixteen = 0x03, // 256KB

View File

@ -58,7 +58,7 @@ impl Sound {
// Check in this scope ensures (only) the above subtraction // Check in this scope ensures (only) the above subtraction
// made length_timer 0 // made length_timer 0
if self.ch1.length_timer == 0 { if self.ch1.length_timer == 0 {
todo!("Disable Channel 1 until next trigger event"); self.ch1.enabled = false;
} }
} }
@ -68,7 +68,7 @@ impl Sound {
// Check in this scope ensures (only) the above subtraction // Check in this scope ensures (only) the above subtraction
// made length_timer 0 // made length_timer 0
if self.ch2.length_timer == 0 { if self.ch2.length_timer == 0 {
todo!("Disable Channel 2 until next trigger event"); self.ch2.enabled = false;
} }
} }
@ -78,7 +78,7 @@ impl Sound {
// Check in this scope ensures (only) the above subtraction // Check in this scope ensures (only) the above subtraction
// made length_timer 0 // made length_timer 0
if self.ch3.length_timer == 0 { if self.ch3.length_timer == 0 {
todo!("Disable Channel 3 until next trigger event"); self.ch3.enabled = false;
} }
} }
@ -88,7 +88,7 @@ impl Sound {
// Check in this scope ensures (only) the above subtraction // Check in this scope ensures (only) the above subtraction
// made length_timer 0 // made length_timer 0
if self.ch4.length_timer == 0 { if self.ch4.length_timer == 0 {
todo!("Disable Channel 4 until next trigger event"); self.ch4.enabled = false;
} }
} }
} }
@ -311,6 +311,8 @@ pub(crate) struct Channel1 {
// Length Functionality // Length Functionality
length_timer: u16, length_timer: u16,
enabled: bool,
} }
impl Channel1 { impl Channel1 {
@ -374,7 +376,7 @@ impl Channel1 {
// Overflow check // Overflow check
if new_freq > 2047 { if new_freq > 2047 {
todo!("Frequency failed the overflow check. Disable the channel"); self.enabled = false;
} }
new_freq new_freq
@ -464,6 +466,8 @@ pub(crate) struct Channel2 {
// Length Functionality // Length Functionality
length_timer: u16, length_timer: u16,
enabled: bool,
} }
impl Channel2 { impl Channel2 {
@ -743,7 +747,9 @@ pub(crate) struct Channel4 {
length_timer: u16, length_timer: u16,
/// Linear Feedback Shift Register (15-bit) /// Linear Feedback Shift Register (15-bit)
lfsr: u16, shift_register: u16,
enabled: bool,
} }
impl Channel4 { impl Channel4 {
@ -778,7 +784,7 @@ impl Channel4 {
} }
// LFSR behaviour during trigger event // LFSR behaviour during trigger event
self.lfsr = 0x7FFF; self.shift_register = 0x7FFF;
} }
} }
} }