From c53c2728ec30e347d6bf38a831d81504497c0548 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 21:32:10 +0000 Subject: [PATCH] refactor: small set of simplifications --- frontends/sdl/src/main.rs | 49 +++++++++++++++++++++++---------------- src/apu.rs | 28 ++++++++-------------- src/gb.rs | 10 ++------ 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/frontends/sdl/src/main.rs b/frontends/sdl/src/main.rs index a5cf1c02..59dca70b 100644 --- a/frontends/sdl/src/main.rs +++ b/frontends/sdl/src/main.rs @@ -42,6 +42,7 @@ pub struct Emulator { system: GameBoy, graphics: Option<Graphics>, audio: Option<Audio>, + title: &'static str, logic_frequency: u32, visual_frequency: f32, next_tick_time: f32, @@ -57,11 +58,12 @@ impl Emulator { system, graphics: None, audio: None, + title: TITLE, logic_frequency: GameBoy::CPU_FREQ, - visual_frequency: GameBoy::VISUAL_FREQ * 2.0, + visual_frequency: GameBoy::VISUAL_FREQ, next_tick_time: 0.0, next_tick_time_i: 0, - features: vec!["no-vsync"], + features: vec!["video", "audio", "no-vsync"], palettes: [ PaletteInfo::new( "basic", @@ -97,14 +99,18 @@ impl Emulator { pub fn start(&mut self, screen_scale: f32) { let sdl = sdl2::init().unwrap(); - self.start_graphics(&sdl, screen_scale); - self.start_audio(&sdl); + if self.features.contains(&"video") { + self.start_graphics(&sdl, screen_scale); + } + if self.features.contains(&"audio") { + self.start_audio(&sdl); + } } pub fn start_graphics(&mut self, sdl: &Sdl, screen_scale: f32) { self.graphics = Some(Graphics::new( &sdl, - TITLE, + self.title, DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32, screen_scale, @@ -127,7 +133,7 @@ impl Emulator { .as_mut() .unwrap() .window_mut() - .set_title(format!("{} [{}]", TITLE, rom.title()).as_str()) + .set_title(format!("{} [{}]", self.title, rom.title()).as_str()) .unwrap(); } @@ -299,20 +305,23 @@ impl Emulator { last_frame = self.system.ppu_frame(); } - // obtains the new audio buffer and queues it into the audio - // subsystem ready to be processed - let audio_buffer = self - .system - .audio_buffer() - .iter() - .map(|v| *v as f32 / 7.0) - .collect::<Vec<f32>>(); - self.audio - .as_mut() - .unwrap() - .device - .queue_audio(&audio_buffer) - .unwrap(); + match self.audio.as_mut() { + Some(audio) => { + // obtains the new audio buffer and queues it into the audio + // subsystem ready to be processed + let audio_buffer = self + .system + .audio_buffer() + .iter() + .map(|v| *v as f32 / 14.0) + .collect::<Vec<f32>>(); + audio.device.queue_audio(&audio_buffer).unwrap(); + } + None => (), + } + + // clears the audio buffer to prevent it from + // "exploding" in size self.system.clear_audio_buffer(); } diff --git a/src/apu.rs b/src/apu.rs index 924e348c..871907b5 100644 --- a/src/apu.rs +++ b/src/apu.rs @@ -48,7 +48,7 @@ pub struct Apu { wave_ram: [u8; 16], output_timer: u16, - output_buffer: Vec<u8> + output_buffer: Vec<u8>, } impl Apu { @@ -94,18 +94,14 @@ impl Apu { wave_ram: [0u8; 16], output_timer: 0, - output_buffer: Vec::new() + output_buffer: Vec::new(), } } pub fn clock(&mut self, cycles: u8) { - self.clock_f(cycles, 4194304); - } - - pub fn clock_f(&mut self, cycles: u8, freq: u32) { - // @todo the performance here requires improvement + // @TODO the performance here requires improvement for _ in 0..cycles { - self.cycle(freq); + self.cycle(); } } @@ -147,7 +143,6 @@ impl Apu { (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 @@ -174,9 +169,8 @@ impl Apu { if value & 0x80 == 0x80 { //self.ch2_timer = 0; //self.ch2_sequence = 0; - //@todo improve this reset operation + //@TODO improve this reset operation } - //println!("CH2 Enabled {}", self.ch2_enabled); } // 0xFF1A — NR30: Channel 3 DAC enable @@ -201,7 +195,6 @@ impl Apu { (self.ch3_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8); self.ch3_sound_length |= value & 0x40 == 0x40; self.ch3_enabled |= value & 0x80 == 0x80; - //println!("CH3 Enabled {}", self.ch3_enabled); } // 0xFF30-0xFF3F — Wave pattern RAM @@ -214,11 +207,10 @@ impl Apu { } #[inline(always)] - pub fn cycle(&mut self, freq: u32) { + pub fn cycle(&mut self) { self.ch1_timer = self.ch1_timer.saturating_sub(1); if self.ch1_timer == 0 { - let target_freq = 1048576.0 / (2048.0 - self.ch1_wave_length as f32); - self.ch1_timer = (freq as f32 / target_freq) as u16; + self.ch1_timer = (2048 - self.ch1_wave_length) << 2; self.ch1_sequence = (self.ch1_sequence + 1) & 7; if self.ch1_enabled { @@ -235,8 +227,7 @@ impl Apu { self.ch2_timer = self.ch2_timer.saturating_sub(1); if self.ch2_timer == 0 { - let target_freq = 1048576.0 / (2048.0 - self.ch2_wave_length as f32); - self.ch2_timer = (freq as f32 / target_freq) as u16; + self.ch2_timer = (2048 - self.ch2_wave_length) << 2; self.ch2_sequence = (self.ch2_sequence + 1) & 7; if self.ch2_enabled { @@ -254,7 +245,8 @@ impl Apu { self.output_timer = self.output_timer.saturating_sub(1); if self.output_timer == 0 { self.output_buffer.push(self.output()); - self.output_timer = (freq as f32 / 44100.0) as u16; // @todo target sampling rate is hardcoded + // @TODO target sampling rate is hardcoded, need to softcode this + self.output_timer = (4194304.0 / 44100.0) as u16; } } diff --git a/src/gb.rs b/src/gb.rs index 7bb4b788..efed7c4e 100644 --- a/src/gb.rs +++ b/src/gb.rs @@ -54,8 +54,7 @@ pub struct Registers { } pub trait AudioProvider { - fn output_apu(&self) -> u8; - fn output_clock_apu(&mut self, cycles: u8, freq: u32) -> u8; + fn audio_output(&self) -> u8; fn audio_buffer(&self) -> &Vec<u8>; fn clear_audio_buffer(&mut self); } @@ -384,12 +383,7 @@ pub fn hook_impl(info: &PanicInfo) { } impl AudioProvider for GameBoy { - fn output_apu(&self) -> u8 { - self.apu_i().output() - } - - fn output_clock_apu(&mut self, cycles: u8, freq: u32) -> u8 { - self.apu().clock_f(cycles, freq); + fn audio_output(&self) -> u8 { self.apu_i().output() } -- GitLab