Compare commits

..

No commits in common. "0af95a1dd3e22fc5dde3b86fad09eb101459b203" and "4658a0d106dd1a3a874a34e764064c0948855422" have entirely different histories.

2 changed files with 169 additions and 187 deletions

View File

@ -33,22 +33,58 @@ impl Cartridge {
} }
fn detect_mbc(memory: &[u8]) -> Box<dyn MBCIo> { fn detect_mbc(memory: &[u8]) -> Box<dyn MBCIo> {
let ram_size = Self::detect_ram_size(memory); let ram_size = Self::find_ram_size(memory);
let rom_size = Self::detect_rom_size(memory); let bank_count = Self::find_bank_count(memory);
let mbc_kind = Self::find_mbc(memory); let mbc_kind = Self::find_mbc(memory);
let ram_byte_count = ram_size.len();
eprintln!("Cartridge Ram Size: {} bytes", ram_size.len()); eprintln!("Cartridge Ram Size: {} bytes", ram_size.len());
eprintln!("Cartridge ROM Size: {} bytes", rom_size.size()); eprintln!("Cartridge ROM Size: {} bytes", bank_count.size());
eprintln!("MBC Type: {:?}", mbc_kind); eprintln!("MBC Type: {:?}", mbc_kind);
match mbc_kind { match mbc_kind {
MBCKind::None => Box::new(NoMBC), MBCKind::None => Box::new(NoMBC {}),
MBCKind::MBC1 => Box::new(MBC1::new(ram_size, rom_size)), MBCKind::MBC1 => {
MBCKind::MBC1WithBattery => Box::new(MBC1::new(ram_size, rom_size)), // TODO: Implement Saving let mbc = MBC1 {
MBCKind::MBC3 => Box::new(MBC3::new(ram_size)), ram_size,
MBCKind::MBC3WithBattery => Box::new(MBC3::new(ram_size)), // TODO: Implement Saving ram: vec![0; ram_byte_count as usize],
MBCKind::MBC5 => Box::new(MBC5::new(ram_size)), bank_count,
MBCKind::MBC5WithBattery => Box::new(MBC5::new(ram_size)), // TDO: Implement Saving ..Default::default()
};
Box::new(mbc)
}
MBCKind::MBC1WithBattery => {
// TODO: Implement Saving
let mbc = MBC1 {
ram_size,
ram: vec![0; ram_byte_count as usize],
bank_count,
..Default::default()
};
Box::new(mbc)
}
MBCKind::MBC3WithBattery => {
// TODO: Implement Saving
let mbc = MBC3 {
ram_size,
ram: vec![0; ram_byte_count as usize],
..Default::default()
};
Box::new(mbc)
}
MBCKind::MBC3 => {
let mbc = MBC3 {
ram_size,
ram: vec![0; ram_byte_count as usize],
..Default::default()
};
Box::new(mbc)
}
MBCKind::MBC5 => todo!("Implement MBC5"),
} }
} }
@ -67,12 +103,12 @@ impl Cartridge {
self.title.as_deref() self.title.as_deref()
} }
fn detect_ram_size(memory: &[u8]) -> RamSize { fn find_ram_size(memory: &[u8]) -> RamSize {
let id = memory[RAM_SIZE_ADDRESS]; let id = memory[RAM_SIZE_ADDRESS];
id.into() id.into()
} }
fn detect_rom_size(memory: &[u8]) -> RomSize { fn find_bank_count(memory: &[u8]) -> BankCount {
let id = memory[ROM_SIZE_ADDRESS]; let id = memory[ROM_SIZE_ADDRESS];
id.into() id.into()
} }
@ -80,12 +116,12 @@ impl Cartridge {
fn find_mbc(memory: &[u8]) -> MBCKind { fn find_mbc(memory: &[u8]) -> MBCKind {
match memory[MBC_TYPE_ADDRESS] { match memory[MBC_TYPE_ADDRESS] {
0x00 => MBCKind::None, 0x00 => MBCKind::None,
0x01 | 0x02 => MBCKind::MBC1, 0x01 => MBCKind::MBC1,
0x02 => MBCKind::MBC1,
0x03 => MBCKind::MBC1WithBattery, 0x03 => MBCKind::MBC1WithBattery,
0x19 | 0x1A => MBCKind::MBC5, 0x19 => MBCKind::MBC5,
0x1B => MBCKind::MBC5WithBattery,
0x13 => MBCKind::MBC3WithBattery, 0x13 => MBCKind::MBC3WithBattery,
0x11 | 0x12 => MBCKind::MBC3, 0x11 => MBCKind::MBC3,
id => unimplemented!("id {:#04X} is an unsupported MBC", id), id => unimplemented!("id {:#04X} is an unsupported MBC", id),
} }
} }
@ -114,69 +150,71 @@ struct MBC1 {
ram_bank: u8, ram_bank: u8,
mode: bool, mode: bool,
ram_size: RamSize, ram_size: RamSize,
memory: Vec<u8>, ram: Vec<u8>,
rom_size: RomSize, bank_count: BankCount,
mem_enabled: bool, ram_enabled: bool,
}
impl Default for MBC1 {
fn default() -> Self {
Self {
rom_bank: 0x01,
ram_bank: Default::default(),
mode: Default::default(),
ram_size: Default::default(),
ram: Default::default(),
bank_count: Default::default(),
ram_enabled: Default::default(),
}
}
} }
impl MBC1 { impl MBC1 {
fn new(ram_size: RamSize, rom_size: RomSize) -> Self {
Self {
rom_bank: 0x01,
memory: vec![0; ram_size.len() as usize],
ram_size,
rom_size,
ram_bank: Default::default(),
mode: Default::default(),
mem_enabled: Default::default(),
}
}
fn zero_bank(&self) -> u8 { fn zero_bank(&self) -> u8 {
use RomSize::*; use BankCount::*;
match self.rom_size { 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,
OneTwentyEight => (self.ram_bank & 0x03) << 5, OneHundredTwentyEight => (self.ram_bank & 0x03) << 5,
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.rom_size), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
fn _mbcm_zero_bank(&self) -> u8 { fn _mbcm_zero_bank(&self) -> u8 {
use RomSize::*; use BankCount::*;
match self.rom_size { match self.bank_count {
None | Four | Eight | Sixteen | ThirtyTwo => 0x00, None | Four | Eight | Sixteen | ThirtyTwo => 0x00,
SixtyFour => (self.ram_bank & 0x03) << 4, SixtyFour => (self.ram_bank & 0x03) << 4,
OneTwentyEight => (self.ram_bank & 0x03) << 5, OneHundredTwentyEight => (self.ram_bank & 0x03) << 5,
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.rom_size), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
fn high_bank(&self) -> u8 { fn high_bank(&self) -> u8 {
use RomSize::*; use BankCount::*;
let base = self.rom_bank & self.rom_size_mask(); let base = self.rom_bank & self.rom_size_mask();
match self.rom_size { 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),
OneTwentyEight => 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.rom_size), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
fn rom_size_mask(&self) -> u8 { fn rom_size_mask(&self) -> u8 {
use RomSize::*; use BankCount::*;
match self.rom_size { match self.bank_count {
None => 0b00000001, None => 0b00000001,
Four => 0b00000011, Four => 0b00000011,
Eight => 0b00000111, Eight => 0b00000111,
Sixteen => 0b00001111, Sixteen => 0b00001111,
ThirtyTwo | SixtyFour | OneTwentyEight => 0b00011111, ThirtyTwo | SixtyFour | OneHundredTwentyEight => 0b00011111,
_ => unreachable!("{:?} is not a valid MBC1 BankCount", self.rom_size), _ => unreachable!("{:?} is not a valid MBC1 BankCount", self.bank_count),
} }
} }
@ -184,8 +222,8 @@ impl MBC1 {
use RamSize::*; use RamSize::*;
match self.ram_size { match self.ram_size {
Two | Eight => (addr - 0xA000) % self.ram_size.len() as u16, _2KB | _8KB => (addr - 0xA000) % self.ram_size.len() as u16,
ThirtyTwo => { _32KB => {
if self.mode { if self.mode {
0x2000 * self.ram_bank as u16 + (addr - 0xA000) 0x2000 * self.ram_bank as u16 + (addr - 0xA000)
} else { } else {
@ -213,8 +251,8 @@ impl MBCIo for MBC1 {
Address(0x4000 * self.high_bank() as usize + (addr as usize - 0x4000)) Address(0x4000 * self.high_bank() as usize + (addr as usize - 0x4000))
} }
0xA000..=0xBFFF => { 0xA000..=0xBFFF => {
if self.mem_enabled { if self.ram_enabled {
Value(self.memory[self.ram_addr(addr) as usize]) Value(self.ram[self.ram_addr(addr) as usize])
} else { } else {
Value(0xFF) Value(0xFF)
} }
@ -225,7 +263,7 @@ impl MBCIo for MBC1 {
fn handle_write(&mut self, addr: u16, byte: u8) { fn handle_write(&mut self, addr: u16, byte: u8) {
match addr { match addr {
0x0000..=0x1FFF => self.mem_enabled = (byte & 0x0F) == 0x0A, 0x0000..=0x1FFF => self.ram_enabled = (byte & 0x0F) == 0x0A,
0x2000..=0x3FFF => { 0x2000..=0x3FFF => {
self.rom_bank = if byte == 0x00 { self.rom_bank = if byte == 0x00 {
0x01 0x01
@ -237,9 +275,9 @@ impl MBCIo for MBC1 {
} }
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 if self.mem_enabled => { 0xA000..=0xBFFF if self.ram_enabled => {
let ram_addr = self.ram_addr(addr) as usize; let ram_addr = self.ram_addr(addr) as usize;
self.memory[ram_addr] = byte; self.ram[ram_addr] = byte;
} }
0xA000..=0xBFFF => {} // Ram isn't enabled, ignored write 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),
@ -253,34 +291,22 @@ enum MBC3Device {
RealTimeClock, RealTimeClock,
} }
#[derive(Debug)] #[derive(Debug, Default)]
struct MBC3 { struct MBC3 {
/// 7-bit Number /// 7-bit Number
rom_bank: u8, rom_bank: u8,
/// 2-bit Number /// 2-bit Number
ram_bank: u8, ram_bank: u8,
devs_enabled: bool, devices_enabled: bool,
mapped: Option<MBC3Device>, currently_mapped: Option<MBC3Device>,
memory: Vec<u8>, ram_size: RamSize,
ram: Vec<u8>,
// RTC Data Latch Previous Write // RTC Data Latch Previous Write
prev_latch_write: Option<u8>, prev_latch_write: Option<u8>,
} }
impl MBC3 {
fn new(ram_size: RamSize) -> Self {
Self {
memory: vec![0; ram_size.len() as usize],
rom_bank: Default::default(),
ram_bank: Default::default(),
devs_enabled: Default::default(),
mapped: Default::default(),
prev_latch_write: Default::default(),
}
}
}
impl MBCIo for MBC3 { impl MBCIo for MBC3 {
fn handle_read(&self, addr: u16) -> MBCResult { fn handle_read(&self, addr: u16) -> MBCResult {
use MBCResult::*; use MBCResult::*;
@ -288,11 +314,11 @@ impl MBCIo for MBC3 {
let res = match addr { let res = match addr {
0x0000..=0x3FFF => Address(addr as usize), 0x0000..=0x3FFF => Address(addr as usize),
0x4000..=0x7FFF => Address(0x4000 * self.rom_bank as usize + (addr as usize - 0x4000)), 0x4000..=0x7FFF => Address(0x4000 * self.rom_bank as usize + (addr as usize - 0x4000)),
0xA000..=0xBFFF => match self.mapped { 0xA000..=0xBFFF => match self.currently_mapped {
Some(MBC3Device::ExternalRam) if self.devs_enabled => { Some(MBC3Device::ExternalRam) if self.devices_enabled => {
Value(self.memory[0x2000 * self.ram_bank as usize + (addr as usize - 0xA000)]) Value(self.ram[0x2000 * self.ram_bank as usize + (addr as usize - 0xA000)])
} }
Some(MBC3Device::RealTimeClock) if self.devs_enabled => { Some(MBC3Device::RealTimeClock) if self.devices_enabled => {
todo!("Return Latched value of register") todo!("Return Latched value of register")
} }
_ => Value(0xFF), _ => Value(0xFF),
@ -305,7 +331,7 @@ impl MBCIo for MBC3 {
fn handle_write(&mut self, addr: u16, byte: u8) { fn handle_write(&mut self, addr: u16, byte: u8) {
match addr { match addr {
0x000..=0x1FFF => self.devs_enabled = (byte & 0x0F) == 0x0A, // Enable External RAM and Access to RTC if there is one 0x000..=0x1FFF => self.devices_enabled = (byte & 0x0F) == 0x0A, // Enable External RAM and Access to RTC if there is one
0x2000..=0x3FFF => { 0x2000..=0x3FFF => {
self.rom_bank = match byte { self.rom_bank = match byte {
0x00 => 0x01, 0x00 => 0x01,
@ -315,10 +341,10 @@ impl MBCIo for MBC3 {
0x4000..=0x5FFF => match byte { 0x4000..=0x5FFF => match byte {
0x00 | 0x01 | 0x02 | 0x03 => { 0x00 | 0x01 | 0x02 | 0x03 => {
self.ram_bank = byte & 0x03; self.ram_bank = byte & 0x03;
self.mapped = Some(MBC3Device::ExternalRam); self.currently_mapped = Some(MBC3Device::ExternalRam);
} }
0x08 | 0x09 | 0x0A | 0x0B | 0x0C => { 0x08 | 0x09 | 0x0A | 0x0B | 0x0C => {
self.mapped = Some(MBC3Device::RealTimeClock); self.currently_mapped = Some(MBC3Device::RealTimeClock);
} }
_ => {} _ => {}
}, },
@ -330,11 +356,11 @@ impl MBCIo for MBC3 {
} }
self.prev_latch_write = Some(byte); self.prev_latch_write = Some(byte);
} }
0xA000..=0xBFFF => match self.mapped { 0xA000..=0xBFFF => match self.currently_mapped {
Some(MBC3Device::ExternalRam) if self.devs_enabled => { Some(MBC3Device::ExternalRam) if self.devices_enabled => {
self.memory[0x2000 * self.ram_bank as usize + (addr as usize - 0xA000)] = byte self.ram[0x2000 * self.ram_bank as usize + (addr as usize - 0xA000)] = byte
} }
Some(MBC3Device::RealTimeClock) if self.devs_enabled => { Some(MBC3Device::RealTimeClock) if self.devices_enabled => {
todo!("Write to RTC") todo!("Write to RTC")
} }
_ => {} _ => {}
@ -345,59 +371,7 @@ impl MBCIo for MBC3 {
} }
#[derive(Debug)] #[derive(Debug)]
struct MBC5 { struct NoMBC {}
/// 9-bit number
rom_bank: u16,
/// 4-bit number
ram_bank: u8,
memory: Vec<u8>,
mem_enabled: bool,
}
impl MBC5 {
fn new(ram_size: RamSize) -> Self {
Self {
rom_bank: 0x01,
memory: vec![0; ram_size.len() as usize],
ram_bank: Default::default(),
mem_enabled: Default::default(),
}
}
}
impl MBCIo for MBC5 {
fn handle_read(&self, addr: u16) -> MBCResult {
use MBCResult::*;
match addr {
0x0000..=0x3FFF => Address(addr as usize),
0x4000..=0x7FFF => Address(0x4000 * self.rom_bank as usize + (addr as usize - 0x4000)),
0xA000..=0xBFFF if self.mem_enabled => {
Value(self.memory[0x2000 * self.ram_bank as usize + (addr as usize - 0xA000)])
}
0xA000..=0xBFFF => Value(0xFF),
_ => unreachable!("A read from {:#06X} should not be handled by MBC5", addr),
}
}
fn handle_write(&mut self, addr: u16, byte: u8) {
match addr {
0x0000..=0x1FFF => self.mem_enabled = (byte & 0x0F) == 0x0A,
0x2000..=0x2FFF => self.rom_bank = (self.rom_bank & 0x0100) | byte as u16,
0x3000..=0x3FFF => self.rom_bank = (self.rom_bank & 0x00FF) | (byte as u16 & 0x01) << 8,
0x4000..=0x5FFF => self.ram_bank = byte & 0x0F,
0xA000..=0xBFFF if self.mem_enabled => {
self.memory[0x2000 * self.ram_bank as usize + (addr as usize - 0xA000)] = byte;
}
0xA000..=0xBFFF => {}
_ => unreachable!("A write to {:#06X} should not be handled by MBC5", addr),
}
}
}
#[derive(Debug)]
struct NoMBC;
impl MBCIo for NoMBC { impl MBCIo for NoMBC {
fn handle_read(&self, addr: u16) -> MBCResult { fn handle_read(&self, addr: u16) -> MBCResult {
@ -425,10 +399,9 @@ enum MBCKind {
None, None,
MBC1, MBC1,
MBC1WithBattery, MBC1WithBattery,
MBC3,
MBC3WithBattery,
MBC5, MBC5,
MBC5WithBattery, MBC3WithBattery,
MBC3,
} }
impl Default for MBCKind { impl Default for MBCKind {
@ -440,11 +413,11 @@ impl Default for MBCKind {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum RamSize { enum RamSize {
None = 0x00, None = 0x00,
Two = 0x01, _2KB = 0x01,
Eight = 0x02, _8KB = 0x02,
ThirtyTwo = 0x03, // Split into 4 RAM banks _32KB = 0x03, // Split into 4 RAM banks
OneHundredTwentyEight = 0x04, // Split into 16 RAM banks _128KB = 0x04, // Split into 16 RAM banks
SixtyFour = 0x05, // Split into 8 RAm Banks _64KB = 0x05, // Split into 8 RAm Banks
} }
impl RamSize { impl RamSize {
@ -453,11 +426,11 @@ impl RamSize {
match *self { match *self {
None => 0, None => 0,
Two => 2_048, _2KB => 2_048,
Eight => 8_192, _8KB => 8_192,
ThirtyTwo => 32_768, _32KB => 32_768,
OneHundredTwentyEight => 131_072, _128KB => 131_072,
SixtyFour => 65_536, _64KB => 65_536,
} }
} }
} }
@ -474,40 +447,53 @@ impl From<u8> for RamSize {
match byte { match byte {
0x00 => None, 0x00 => None,
0x01 => Two, 0x01 => _2KB,
0x02 => Eight, 0x02 => _8KB,
0x03 => ThirtyTwo, 0x03 => _32KB,
0x04 => OneHundredTwentyEight, 0x04 => _128KB,
0x05 => SixtyFour, 0x05 => _64KB,
_ => unreachable!("{:#04X} is not a valid value for RAMSize", byte), _ => unreachable!("{:#04X} is not a valid value for RAMSize", byte),
} }
} }
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum RomSize { enum BankCount {
None = 0x00, // 32KB (also called Two) None = 0x00, // 32KB (also called Two)
Four = 0x01, // 64KB Four = 0x01, // 64KB
Eight = 0x02, // 128KB Eight = 0x02, // 128KB
Sixteen = 0x03, // 256KB Sixteen = 0x03, // 256KB
ThirtyTwo = 0x04, // 512KB ThirtyTwo = 0x04, // 512KB
SixtyFour = 0x05, // 1MB SixtyFour = 0x05, // 1MB
OneTwentyEight = 0x06, // 2MB OneHundredTwentyEight = 0x06, // 2MB
TwoFiftySix = 0x07, // 4MB TwoHundredFiftySix = 0x07, // 4MB
FiveHundredTwelve = 0x08, // 8MB FiveHundredTwelve = 0x08, // 8MB
SeventyTwo = 0x52, // 1.1MB SeventyTwo = 0x52, // 1.1MB
Eighty = 0x53, // 1.2MB Eighty = 0x53, // 1.2MB
NinetySix = 0x54, // 1.5MB NinetySix = 0x54, // 1.5MB
} }
impl RomSize { impl Default for BankCount {
fn default() -> Self {
Self::None
}
}
impl BankCount {
// https://hacktix.github.io/GBEDG/mbcs/#rom-size // https://hacktix.github.io/GBEDG/mbcs/#rom-size
fn size(&self) -> u32 { fn size(&self) -> u32 {
use RomSize::*; use BankCount::*;
match self { match self {
None | Four | Eight | Sixteen | ThirtyTwo | SixtyFour | OneTwentyEight None => 32_768,
| TwoFiftySix | FiveHundredTwelve => 2 << (14 + *self as u8), Four => 65_536,
Eight => 131_072,
Sixteen => 262_144,
ThirtyTwo => 524_288,
SixtyFour => 1_048_576,
OneHundredTwentyEight => 2_097_152,
TwoHundredFiftySix => 4_194_304,
FiveHundredTwelve => 8_388_608,
SeventyTwo => 1_179_648, SeventyTwo => 1_179_648,
Eighty => 1_310_720, Eighty => 1_310_720,
NinetySix => 1_572_864, NinetySix => 1_572_864,
@ -515,9 +501,9 @@ impl RomSize {
} }
} }
impl From<u8> for RomSize { impl From<u8> for BankCount {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
use RomSize::*; use BankCount::*;
match byte { match byte {
0x00 => None, 0x00 => None,
@ -526,8 +512,8 @@ impl From<u8> for RomSize {
0x03 => Sixteen, 0x03 => Sixteen,
0x04 => ThirtyTwo, 0x04 => ThirtyTwo,
0x05 => SixtyFour, 0x05 => SixtyFour,
0x06 => OneTwentyEight, 0x06 => OneHundredTwentyEight,
0x07 => TwoFiftySix, 0x07 => TwoHundredFiftySix,
0x08 => FiveHundredTwelve, 0x08 => FiveHundredTwelve,
0x52 => SeventyTwo, 0x52 => SeventyTwo,
0x53 => Eighty, 0x53 => Eighty,
@ -545,6 +531,6 @@ impl std::fmt::Debug for Box<dyn MBCIo> {
impl Default for Box<dyn MBCIo> { impl Default for Box<dyn MBCIo> {
fn default() -> Self { fn default() -> Self {
Box::new(NoMBC) Box::new(MBC1::default())
} }
} }

View File

@ -12,7 +12,6 @@ use winit::window::{Window, WindowBuilder};
use winit_input_helper::WinitInputHelper; use winit_input_helper::WinitInputHelper;
const WINDOW_SCALE: f64 = 2.0; const WINDOW_SCALE: f64 = 2.0;
const AUDIO_ENABLED: bool = true;
fn main() -> Result<()> { fn main() -> Result<()> {
let app = App::new(crate_name!()) let app = App::new(crate_name!())
@ -64,11 +63,9 @@ fn main() -> Result<()> {
}; };
// Initialize Audio // Initialize Audio
let (_stream, stream_handle) = OutputStream::try_default().expect("Initialized Audio");
if AUDIO_ENABLED {
let spsc: AudioSPSC<f32> = Default::default(); let spsc: AudioSPSC<f32> = Default::default();
let (prod, cons) = spsc.init(); let (prod, cons) = spsc.init();
let (_stream, stream_handle) = OutputStream::try_default().expect("Initialized Audio");
let sink = Sink::try_new(&stream_handle)?; let sink = Sink::try_new(&stream_handle)?;
sink.append(cons); sink.append(cons);
game_boy.apu_mut().attach_producer(prod); game_boy.apu_mut().attach_producer(prod);
@ -76,7 +73,6 @@ fn main() -> Result<()> {
std::thread::spawn(move || { std::thread::spawn(move || {
sink.sleep_until_end(); sink.sleep_until_end();
}); });
}
let mut start = Instant::now(); let mut start = Instant::now();
let frame_time = Duration::from_secs_f64(1.0 / 59.73); // 59.73 Hz on Host let frame_time = Duration::from_secs_f64(1.0 / 59.73); // 59.73 Hz on Host