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