Compare commits
3 Commits
9b6c302890
...
18b790a777
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | 18b790a777 | |
Rekai Nyangadzayi Musuka | 39af03aebf | |
Rekai Nyangadzayi Musuka | 559cb54385 |
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
20
src/sound.rs
20
src/sound.rs
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue