From 6395f11d5d401b0de45b9ef0185f743aa8e2c2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Mon, 27 Feb 2023 00:05:39 +0000 Subject: [PATCH] feat: initial PPU read and write code --- src/apu.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/gb.rs | 3 +- src/mmu.rs | 4 +- 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/src/apu.rs b/src/apu.rs index dc25415c..f7932444 100644 --- a/src/apu.rs +++ b/src/apu.rs @@ -1,24 +1,121 @@ +use crate::warnln; + pub struct Apu { + ch1_sweep_slope: u8, + ch1_sweep_increase: bool, + ch1_sweep_pace: u8, + ch1_length_timer: u8, + ch1_wave_duty: u8, + ch1_pace: u8, + ch1_direction: u8, + ch1_volume: u8, + ch1_wave_length: u16, + ch1_sound_length: bool, + ch1_enabled: bool, + + ch2_length_timer: u8, + ch2_wave_duty: u8, + ch2_pace: u8, + ch2_direction: u8, + ch2_volume: u8, + ch2_wave_length: u16, + ch2_sound_length: bool, + ch2_enabled: bool, } impl Apu { pub fn new() -> Self { - Self {} + Self { + ch1_sweep_slope: 0x0, + ch1_sweep_increase: false, + ch1_sweep_pace: 0x0, + ch1_length_timer: 0x0, + ch1_wave_duty: 0x0, + ch1_pace: 0x0, + ch1_direction: 0x0, + ch1_volume: 0x0, + ch1_wave_length: 0x0, + ch1_sound_length: false, + ch1_enabled: false, + + ch2_length_timer: 0x0, + ch2_wave_duty: 0x0, + ch2_pace: 0x0, + ch2_direction: 0x0, + ch2_volume: 0x0, + ch2_wave_length: 0x0, + ch2_sound_length: false, + ch2_enabled: false, + } } pub fn read(&mut self, addr: u16) -> u8 { match addr { 0xff26 => 1 as u8, // todo implement this - _ => 0x00 + _ => { + warnln!("Reading from unknown APU location 0x{:04x}", addr); + 0xff + } } } pub fn write(&mut self, addr: u16, value: u8) { match addr { - 0xff26 => { - // @todo implement the logic here - }, - _ => {} + // 0xFF10 — NR10: Channel 1 length timer & duty cycle + 0xff10 => { + self.ch1_sweep_slope = value & 0x03; + self.ch1_sweep_increase = value & 0x04 == 0x04; + self.ch1_sweep_pace = (value & 0x70) >> 4; + } + // 0xFF11 — NR11: Channel 1 length timer & duty cycle + 0xff11 => { + self.ch1_length_timer = value & 0x3f; + self.ch1_wave_duty = (value & 0xc0) >> 6; + } + // 0xFF12 — NR12: Channel 1 volume & envelope + 0xff12 => { + self.ch1_pace = value & 0x07; + self.ch1_direction = (value & 0x08) >> 3; + self.ch1_volume = (value & 0xf0) >> 4; + } + // 0xFF13 — NR13: Channel 1 wavelength low + 0xff13 => { + self.ch1_wave_length = (self.ch1_wave_length & 0xff00) | value as u16; + } + // 0xFF14 — NR14: Channel 1 wavelength high & control + 0xff14 => { + self.ch1_wave_length = + (self.ch1_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8); + self.ch1_sound_length |= value & 0x40 == 0x40; + self.ch1_enabled |= value & 0x80 == 0x80; + println!("CH1 Enabled {}", self.ch1_enabled); + } + + // 0xFF16 — NR21: Channel 2 length timer & duty cycle + 0xff16 => { + self.ch2_length_timer = value & 0x3f; + self.ch2_wave_duty = (value & 0xc0) >> 6; + } + // 0xFF17 — NR22: Channel 2 volume & envelope + 0xff17 => { + self.ch2_pace = value & 0x07; + self.ch2_direction = (value & 0x08) >> 3; + self.ch2_volume = (value & 0xf0) >> 4; + } + // 0xFF18 — NR23: Channel 2 wavelength low + 0xff18 => { + self.ch2_wave_length = (self.ch2_wave_length & 0xff00) | value as u16; + } + // 0xFF19 — NR24: Channel 1 wavelength high & control + 0xff19 => { + self.ch2_wave_length = + (self.ch2_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8); + self.ch2_sound_length |= value & 0x40 == 0x40; + self.ch2_enabled |= value & 0x80 == 0x80; + println!("CH2 Enabled {}", self.ch2_enabled); + } + + _ => warnln!("Writing in unknown APU location 0x{:04x}", addr), } } } diff --git a/src/gb.rs b/src/gb.rs index e7a1952f..61e8afbc 100644 --- a/src/gb.rs +++ b/src/gb.rs @@ -1,4 +1,5 @@ use crate::{ + apu::Apu, cpu::Cpu, data::{BootRom, CGB_BOOT, DMG_BOOT, DMG_BOOTIX, MGB_BOOTIX, SGB_BOOT}, gen::{COMPILATION_DATE, COMPILATION_TIME, COMPILER, COMPILER_VERSION}, @@ -7,7 +8,7 @@ use crate::{ ppu::{Ppu, PpuMode, Tile, FRAME_BUFFER_SIZE}, rom::Cartridge, timer::Timer, - util::read_file, apu::Apu, + util::read_file, }; #[cfg(feature = "wasm")] diff --git a/src/mmu.rs b/src/mmu.rs index ed1324b0..f7916e8a 100644 --- a/src/mmu.rs +++ b/src/mmu.rs @@ -1,4 +1,4 @@ -use crate::{debugln, pad::Pad, ppu::Ppu, rom::Cartridge, timer::Timer, apu::Apu}; +use crate::{apu::Apu, debugln, pad::Pad, ppu::Ppu, rom::Cartridge, timer::Timer}; pub const BOOT_SIZE: usize = 2304; pub const RAM_SIZE: usize = 8192; @@ -162,6 +162,7 @@ impl Mmu { 0x00 } }, + 0x10..=26 | 0x30..=0x37 => self.apu.read(addr), 0x40 | 0x50 | 0x60 | 0x70 => self.ppu.read(addr), _ => { debugln!("Reading from unknown IO control 0x{:04x}", addr); @@ -232,6 +233,7 @@ impl Mmu { 0x04..=0x07 => self.timer.write(addr, value), _ => debugln!("Writing to unknown IO control 0x{:04x}", addr), }, + 0x10..=26 | 0x30..=0x37 => self.apu.write(addr, value), 0x40 | 0x60 | 0x70 => { match addr & 0x00ff { // 0xFF46 — DMA: OAM DMA source address & start -- GitLab