diff --git a/Cargo.lock b/Cargo.lock index c74086f..db4e1e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,28 @@ dependencies = [ "memchr", ] +[[package]] +name = "alsa" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18" +dependencies = [ + "alsa-sys", + "bitflags", + "libc", + "nix 0.20.0", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "andrew" version = "0.3.1" @@ -68,6 +90,25 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "bindgen" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bit-set" version = "0.5.2" @@ -113,6 +154,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + [[package]] name = "calloop" version = "0.6.5" @@ -128,6 +175,24 @@ name = "cc" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom 5.1.2", +] [[package]] name = "cfg-if" @@ -147,6 +212,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "clang-sys" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" +dependencies = [ + "glob", + "libc", + "libloading 0.7.1", +] + [[package]] name = "cocoa" version = "0.24.0" @@ -188,6 +264,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "combine" +version = "4.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b2f5d0ee456f3928812dfc8c6d9a1d592b98678f6d56db9b0cd2b7bc6c8db5" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "copyless" version = "0.1.5" @@ -276,6 +362,50 @@ dependencies = [ "objc", ] +[[package]] +name = "coreaudio-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" +dependencies = [ + "bitflags", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b7e3347be6a09b46aba228d6608386739fb70beff4f61e07422da87b0bb31fa" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cpal" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f45f0a21f617cd2c788889ef710b63f075c949259593ea09c826f1e47a2418" +dependencies = [ + "alsa", + "core-foundation-sys 0.8.3", + "coreaudio-rs", + "jni", + "js-sys", + "lazy_static", + "libc", + "mach", + "ndk 0.3.0", + "ndk-glue 0.3.0", + "nix 0.20.0", + "oboe", + "parking_lot", + "stdweb", + "thiserror", + "web-sys", + "winapi", +] + [[package]] name = "crossbeam" version = "0.8.1" @@ -505,6 +635,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "glow" version = "0.11.0" @@ -626,12 +762,35 @@ dependencies = [ "web-sys", ] +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + [[package]] name = "jni-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.55" @@ -657,6 +816,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.105" @@ -701,6 +866,15 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -818,6 +992,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ndk" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64d6af06fde0e527b1ba5c7b79a6cc89cfc46325b0b2887dffe8f70197e0c3c" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + [[package]] name = "ndk-glue" version = "0.3.0" @@ -827,7 +1014,21 @@ dependencies = [ "lazy_static", "libc", "log", - "ndk", + "ndk 0.3.0", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-glue" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e9e94628f24e7a3cb5b96a2dc5683acd9230bf11991c2a1677b87695138420" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk 0.4.0", "ndk-macro", "ndk-sys", ] @@ -875,6 +1076,16 @@ dependencies = [ "libc", ] +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "nom" version = "7.0.0" @@ -895,6 +1106,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -945,6 +1167,29 @@ dependencies = [ "cc", ] +[[package]] +name = "oboe" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e15e22bc67e047fe342a32ecba55f555e3be6166b04dd157cd0f803dfa9f48e1" +dependencies = [ + "jni", + "ndk 0.4.0", + "ndk-glue 0.4.0", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338142ae5ab0aaedc8275aa8f67f460e43ae0fca76a695a742d56da0a269eadc" +dependencies = [ + "cc", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -985,6 +1230,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1167,6 +1418,7 @@ checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" name = "rmg-001" version = "0.1.0" dependencies = [ + "cpal", "env_logger", "log", "pixels", @@ -1175,6 +1427,12 @@ dependencies = [ "winit_input_helper", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rusttype" version = "0.9.2" @@ -1221,6 +1479,12 @@ version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + [[package]] name = "slotmap" version = "1.0.6" @@ -1265,6 +1529,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "stdweb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" + [[package]] name = "strsim" version = "0.9.3" @@ -1667,8 +1937,8 @@ dependencies = [ "log", "mio", "mio-misc", - "ndk", - "ndk-glue", + "ndk 0.3.0", + "ndk-glue 0.3.0", "ndk-sys", "objc", "parking_lot", @@ -1707,7 +1977,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" dependencies = [ - "nom", + "nom 7.0.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3644aeb..bbd6651 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ optimize = ["log/release_max_level_warn"] default = ["optimize"] [dependencies] -rand = "0.8" +cpal = "0.13" env_logger = "0.9" log = "0.4" pixels = "0.7" diff --git a/README.md b/README.md index 76decdd..2ad43e1 100644 --- a/README.md +++ b/README.md @@ -44,4 +44,5 @@ This project would have been completely impossible without all the documentation - Opcodes behaviour: https://rgbds.gbdev.io/docs/v0.5.1/gbz80.7 - Blargg's test ROMs: https://github.com/retrio/gb-test-roms - Mooneye test ROMs: https://github.com/Gekkio/mooneye-test-suite +- Sound emulation guide: https://nightshade256.github.io/2021/03/27/gb-sound-emulation.html - The Ultimate Gameboy talk: https://youtu.be/HyzD8pNlpwI diff --git a/src/bus.rs b/src/bus.rs index 3b118ed..efdca2d 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -10,6 +10,7 @@ use crate::ppu::{ use crate::cpu::{Interrupt}; use crate::timer::{Timer}; use crate::joypad::{Joypad, JOYPAD_ADDRESS}; +use crate::sound::{Sound}; pub const BANK_ZERO: RangeInclusive = 0x0000..=0x3FFF; pub const BANK_SWITCHABLE: RangeInclusive = 0x4000..=0x7FFF; @@ -32,6 +33,7 @@ pub struct Bus { pub ppu: PPU, pub joypad: Joypad, pub timer: Timer, + pub sound: Sound, } impl Bus { @@ -55,6 +57,7 @@ impl Bus { ppu: PPU::new(), joypad: Joypad::new(), timer: Timer::new(), + sound: Sound::new(), }; // Hardware registers after the bootrom @@ -94,6 +97,8 @@ impl Bus { return self.ppu.read_oam(address); } else if PPU::is_io_register(address) { return self.ppu.get_register(address); + } else if Sound::is_io_register(address) { + return self.sound.get_register(address); } else if address == JOYPAD_ADDRESS { return self.joypad.read(self.data[address as usize]); } else if Timer::is_io_register(address) { @@ -126,6 +131,8 @@ impl Bus { self.data[(WORK_RAM_1.min().unwrap() + (address - ECHO_RAM.min().unwrap())) as usize] = data; // Copy to the working RAM } else if Timer::is_io_register(address) { self.timer.set_register(address, data); + } else if Sound::is_io_register(address) { + self.sound.set_register(address, data); } else if address == JOYPAD_ADDRESS { let byte = self.data[address as usize]; self.data[address as usize] = (data & 0b11110000) | (byte & 0b00001111); diff --git a/src/sound.rs b/src/sound.rs index 2d9c72e..5b2cc5c 100644 --- a/src/sound.rs +++ b/src/sound.rs @@ -1,4 +1,5 @@ use std::ops::RangeInclusive; +use crate::cpu::Cycles; pub const NR10_ADDRESS: u16 = 0xFF10; pub const NR11_ADDRESS: u16 = 0xFF11; @@ -33,6 +34,12 @@ pub struct Sound { } impl Sound { + pub fn new() -> Self { + Self { + io_registers: [0; 48], + } + } + pub fn is_io_register(address: u16) -> bool { address >= 0xFF10 && address <= 0xFF3F } @@ -44,4 +51,15 @@ impl Sound { pub fn set_register(&mut self, address: u16, data: u8) { self.io_registers[(address - 0xFF10) as usize] = data; } + + pub fn do_cycles(&self, cycles: Cycles) { + let mut count = 0; + while count < cycles.0 { + self.cycle(); + count += 1; + } + } + + fn cycle(&self) { + } } diff --git a/src/timer.rs b/src/timer.rs index 7941b1b..f7c69b9 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -73,11 +73,6 @@ impl Timer { pub fn read_divider(&self) -> u8 { self.divider.to_be_bytes()[0] } - - pub fn reset(&mut self) { - println!("Reset divider"); - self.divider = 0; - } pub fn do_cycles(&mut self, cycles: Cycles) { self.is_enabled = self.is_timer_enabled();