From 8b902ffdd16f93e6e9f99586ffce7535e440083e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Tue, 11 Apr 2023 13:29:33 +0100
Subject: [PATCH] chore: support for clock_freq

---
 frontends/web/ts/gb.ts | 14 ++++++------
 src/apu.rs             | 19 +++++++++++----
 src/cpu.rs             |  8 +++----
 src/gb.rs              | 40 +++++++++++++++++++++++++-------
 src/inst.rs            | 52 +++++++++++++++++++++---------------------
 5 files changed, 84 insertions(+), 49 deletions(-)

diff --git a/frontends/web/ts/gb.ts b/frontends/web/ts/gb.ts
index b950b328..41554b48 100644
--- a/frontends/web/ts/gb.ts
+++ b/frontends/web/ts/gb.ts
@@ -562,22 +562,22 @@ export class GameboyEmulator extends EmulatorBase implements Emulator {
     get compiler(): Compiler | null {
         if (!this.gameBoy) return null;
         return {
-            name: this.gameBoy.get_compiler(),
-            version: this.gameBoy.get_compiler_version()
+            name: this.gameBoy.compiler(),
+            version: this.gameBoy.compiler_version()
         };
     }
 
     get compilation(): Compilation | null {
         if (!this.gameBoy) return null;
         return {
-            date: this.gameBoy.get_compilation_date(),
-            time: this.gameBoy.get_compilation_time()
+            date: this.gameBoy.compilation_date(),
+            time: this.gameBoy.compilation_time()
         };
     }
 
     get wasmEngine(): string | null {
         if (!this.gameBoy) return null;
-        return this.gameBoy.get_wasm_engine_ws() ?? null;
+        return this.gameBoy.wasm_engine_ws() ?? null;
     }
 
     get framerate(): number {
@@ -672,7 +672,7 @@ export class GameboyEmulator extends EmulatorBase implements Emulator {
     }
 
     getVideoState(): boolean {
-        return this.gameBoy?.get_ppu_enabled() ?? false;
+        return this.gameBoy?.ppu_enabled() ?? false;
     }
 
     pauseAudio() {
@@ -684,7 +684,7 @@ export class GameboyEmulator extends EmulatorBase implements Emulator {
     }
 
     getAudioState(): boolean {
-        return this.gameBoy?.get_apu_enabled() ?? false;
+        return this.gameBoy?.apu_enabled() ?? false;
     }
 
     getTile(index: number): Uint8Array {
diff --git a/src/apu.rs b/src/apu.rs
index 52554305..0473b30f 100644
--- a/src/apu.rs
+++ b/src/apu.rs
@@ -1,6 +1,6 @@
 use std::collections::VecDeque;
 
-use crate::warnln;
+use crate::{gb::GameBoy, warnln};
 
 const DUTY_TABLE: [[u8; 8]; 4] = [
     [0, 0, 0, 0, 0, 0, 0, 1],
@@ -93,10 +93,12 @@ pub struct Apu {
     output_timer: i16,
     audio_buffer: VecDeque<u8>,
     audio_buffer_max: usize,
+
+    clock_freq: u32,
 }
 
 impl Apu {
-    pub fn new(sampling_rate: u16, buffer_size: f32) -> Self {
+    pub fn new(sampling_rate: u16, buffer_size: f32, clock_freq: u32) -> Self {
         Self {
             ch1_timer: 0,
             ch1_sequence: 0,
@@ -184,6 +186,7 @@ impl Apu {
                 (sampling_rate as f32 * buffer_size) as usize * 2,
             ),
             audio_buffer_max: (sampling_rate as f32 * buffer_size) as usize * 2,
+            clock_freq: clock_freq,
         }
     }
 
@@ -312,7 +315,7 @@ impl Apu {
             // @TODO the CPU clock is hardcoded here, we must handle situations
             // where there's some kind of overclock, and for that to happen the
             // current CPU clock must be propagated here
-            self.output_timer += (4194304.0 / self.sampling_rate as f32) as i16;
+            self.output_timer += (self.clock_freq as f32 / self.sampling_rate as f32) as i16;
         }
     }
 
@@ -555,6 +558,14 @@ impl Apu {
         self.audio_buffer.clear();
     }
 
+    pub fn clock_freq(&self) -> u32 {
+        self.clock_freq
+    }
+
+    pub fn set_clock_freq(&mut self, value: u32) {
+        self.clock_freq = value;
+    }
+
     #[inline(always)]
     fn tick_length_all(&mut self) {
         self.tick_length(Channel::Ch1);
@@ -831,6 +842,6 @@ impl Apu {
 
 impl Default for Apu {
     fn default() -> Self {
-        Self::new(44100, 1.0)
+        Self::new(44100, 1.0, GameBoy::CPU_FREQ)
     }
 }
diff --git a/src/cpu.rs b/src/cpu.rs
index 8f9b95ff..9be9b169 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -427,7 +427,7 @@ impl Cpu {
     }
 
     #[inline(always)]
-    pub fn get_zero(&self) -> bool {
+    pub fn zero(&self) -> bool {
         self.zero
     }
 
@@ -437,7 +437,7 @@ impl Cpu {
     }
 
     #[inline(always)]
-    pub fn get_sub(&self) -> bool {
+    pub fn sub(&self) -> bool {
         self.sub
     }
 
@@ -447,7 +447,7 @@ impl Cpu {
     }
 
     #[inline(always)]
-    pub fn get_half_carry(&self) -> bool {
+    pub fn half_carry(&self) -> bool {
         self.half_carry
     }
 
@@ -457,7 +457,7 @@ impl Cpu {
     }
 
     #[inline(always)]
-    pub fn get_carry(&self) -> bool {
+    pub fn carry(&self) -> bool {
         self.carry
     }
 
diff --git a/src/gb.rs b/src/gb.rs
index c8a873b8..22a8b606 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -34,9 +34,23 @@ use std::{
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
 pub struct GameBoy {
     cpu: Cpu,
+
+    /// If the PPU is enabled, it will be clocked.
     ppu_enabled: bool,
+
+    /// If the APU is enabled, it will be clocked.
     apu_enabled: bool,
+
+    /// If the timer is enabled, it will be clocked.
     timer_enabled: bool,
+
+    /// The current frequency at which the Game Boy
+    /// emulator is being handled. This is a "hint" that
+    /// may help components to adjust their internal
+    /// logic to match the current frequency. For example
+    /// the APU will adjust its internal clock to match
+    /// this hint.
+    clock_freq: u32,
 }
 
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
@@ -79,6 +93,7 @@ impl GameBoy {
             ppu_enabled: true,
             apu_enabled: true,
             timer_enabled: true,
+            clock_freq: GameBoy::CPU_FREQ,
         }
     }
 
@@ -270,23 +285,23 @@ impl GameBoy {
     /// Obtains the name of the compiler that has been
     /// used in the compilation of the base Boytacean
     /// library. Can be used for diagnostics.
-    pub fn get_compiler(&self) -> String {
+    pub fn compiler(&self) -> String {
         String::from(COMPILER)
     }
 
-    pub fn get_compiler_version(&self) -> String {
+    pub fn compiler_version(&self) -> String {
         String::from(COMPILER_VERSION)
     }
 
-    pub fn get_compilation_date(&self) -> String {
+    pub fn compilation_date(&self) -> String {
         String::from(COMPILATION_DATE)
     }
 
-    pub fn get_compilation_time(&self) -> String {
+    pub fn compilation_time(&self) -> String {
         String::from(COMPILATION_TIME)
     }
 
-    pub fn get_ppu_enabled(&self) -> bool {
+    pub fn ppu_enabled(&self) -> bool {
         self.ppu_enabled
     }
 
@@ -294,7 +309,7 @@ impl GameBoy {
         self.ppu_enabled = value;
     }
 
-    pub fn get_apu_enabled(&self) -> bool {
+    pub fn apu_enabled(&self) -> bool {
         self.apu_enabled
     }
 
@@ -302,13 +317,22 @@ impl GameBoy {
         self.apu_enabled = value;
     }
 
-    pub fn get_timer_enabled(&self) -> bool {
+    pub fn timer_enabled(&self) -> bool {
         self.apu_enabled
     }
 
     pub fn set_timer_enabled(&mut self, value: bool) {
         self.timer_enabled = value;
     }
+
+    pub fn clock_freq(&self) -> u32 {
+        self.clock_freq
+    }
+
+    pub fn set_clock_freq(&mut self, value: u32) {
+        self.clock_freq = value;
+        self.apu().set_clock_freq(value);
+    }
 }
 
 /// Gameboy implementations that are meant with performance
@@ -426,7 +450,7 @@ impl GameBoy {
         self.ppu().set_palette_colors(&palette);
     }
 
-    pub fn get_wasm_engine_ws(&self) -> Option<String> {
+    pub fn wasm_engine_ws(&self) -> Option<String> {
         let dependencies = dependencies_map();
         if !dependencies.contains_key("wasm-bindgen") {
             return None;
diff --git a/src/inst.rs b/src/inst.rs
index b19487d5..8b059a59 100644
--- a/src/inst.rs
+++ b/src/inst.rs
@@ -711,7 +711,7 @@ fn ld_d_u8(cpu: &mut Cpu) {
 }
 
 fn rla(cpu: &mut Cpu) {
-    let carry = cpu.get_carry();
+    let carry = cpu.carry();
 
     cpu.set_carry(cpu.a & 0x80 == 0x80);
 
@@ -769,7 +769,7 @@ fn ld_e_u8(cpu: &mut Cpu) {
 }
 
 fn rra(cpu: &mut Cpu) {
-    let carry = cpu.get_carry();
+    let carry = cpu.carry();
 
     cpu.set_carry((cpu.a & 0x1) == 0x1);
 
@@ -783,7 +783,7 @@ fn rra(cpu: &mut Cpu) {
 fn jr_nz_i8(cpu: &mut Cpu) {
     let byte = cpu.read_u8() as i8;
 
-    if cpu.get_zero() {
+    if cpu.zero() {
         return;
     }
 
@@ -836,16 +836,16 @@ fn daa(cpu: &mut Cpu) {
     let a = cpu.a;
     let mut adjust = 0;
 
-    if cpu.get_half_carry() {
+    if cpu.half_carry() {
         adjust |= 0x06;
     }
 
-    if cpu.get_carry() {
+    if cpu.carry() {
         // Yes, we have to adjust it.
         adjust |= 0x60;
     }
 
-    let res = if cpu.get_sub() {
+    let res = if cpu.sub() {
         a.wrapping_sub(adjust)
     } else {
         if a & 0x0f > 0x09 {
@@ -869,7 +869,7 @@ fn daa(cpu: &mut Cpu) {
 fn jr_z_i8(cpu: &mut Cpu) {
     let byte = cpu.read_u8() as i8;
 
-    if !cpu.get_zero() {
+    if !cpu.zero() {
         return;
     }
 
@@ -933,7 +933,7 @@ fn ld_sp_u16(cpu: &mut Cpu) {
 fn jr_nc_i8(cpu: &mut Cpu) {
     let byte = cpu.read_u8() as i8;
 
-    if cpu.get_carry() {
+    if cpu.carry() {
         return;
     }
 
@@ -986,7 +986,7 @@ fn scf(cpu: &mut Cpu) {
 fn jr_c_i8(cpu: &mut Cpu) {
     let byte = cpu.read_u8() as i8;
 
-    if !cpu.get_carry() {
+    if !cpu.carry() {
         return;
     }
 
@@ -1039,7 +1039,7 @@ fn ld_a_u8(cpu: &mut Cpu) {
 fn ccf(cpu: &mut Cpu) {
     cpu.set_sub(false);
     cpu.set_half_carry(false);
-    cpu.set_carry(!cpu.get_carry());
+    cpu.set_carry(!cpu.carry());
 }
 
 fn ld_b_b(_cpu: &mut Cpu) {}
@@ -1676,7 +1676,7 @@ fn cp_a_a(cpu: &mut Cpu) {
 }
 
 fn ret_nz(cpu: &mut Cpu) {
-    if cpu.get_zero() {
+    if cpu.zero() {
         return;
     }
 
@@ -1692,7 +1692,7 @@ fn pop_bc(cpu: &mut Cpu) {
 fn jp_nz_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if cpu.get_zero() {
+    if cpu.zero() {
         return;
     }
 
@@ -1708,7 +1708,7 @@ fn jp_u16(cpu: &mut Cpu) {
 fn call_nz_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if cpu.get_zero() {
+    if cpu.zero() {
         return;
     }
 
@@ -1731,7 +1731,7 @@ fn rst_00h(cpu: &mut Cpu) {
 }
 
 fn ret_z(cpu: &mut Cpu) {
-    if !cpu.get_zero() {
+    if !cpu.zero() {
         return;
     }
 
@@ -1746,7 +1746,7 @@ fn ret(cpu: &mut Cpu) {
 fn jp_z_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if !cpu.get_zero() {
+    if !cpu.zero() {
         return;
     }
 
@@ -1757,7 +1757,7 @@ fn jp_z_u16(cpu: &mut Cpu) {
 fn call_z_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if !cpu.get_zero() {
+    if !cpu.zero() {
         return;
     }
 
@@ -1782,7 +1782,7 @@ fn rst_08h(cpu: &mut Cpu) {
 }
 
 fn ret_nc(cpu: &mut Cpu) {
-    if cpu.get_carry() {
+    if cpu.carry() {
         return;
     }
 
@@ -1798,7 +1798,7 @@ fn pop_de(cpu: &mut Cpu) {
 fn jp_nc_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if cpu.get_carry() {
+    if cpu.carry() {
         return;
     }
 
@@ -1809,7 +1809,7 @@ fn jp_nc_u16(cpu: &mut Cpu) {
 fn call_nc_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if cpu.get_carry() {
+    if cpu.carry() {
         return;
     }
 
@@ -1832,7 +1832,7 @@ fn rst_10h(cpu: &mut Cpu) {
 }
 
 fn ret_c(cpu: &mut Cpu) {
-    if !cpu.get_carry() {
+    if !cpu.carry() {
         return;
     }
 
@@ -1848,7 +1848,7 @@ fn reti(cpu: &mut Cpu) {
 fn jp_c_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if !cpu.get_carry() {
+    if !cpu.carry() {
         return;
     }
 
@@ -1859,7 +1859,7 @@ fn jp_c_u16(cpu: &mut Cpu) {
 fn call_c_u16(cpu: &mut Cpu) {
     let word = cpu.read_u16();
 
-    if !cpu.get_carry() {
+    if !cpu.carry() {
         return;
     }
 
@@ -3132,7 +3132,7 @@ fn res(value: u8, bit: u8) -> u8 {
 /// byte (probably from a register) and updates the
 /// proper flag registers.
 fn rl(cpu: &mut Cpu, value: u8) -> u8 {
-    let carry = cpu.get_carry();
+    let carry = cpu.carry();
 
     cpu.set_carry((value & 0x80) == 0x80);
 
@@ -3161,7 +3161,7 @@ fn rlc(cpu: &mut Cpu, value: u8) -> u8 {
 /// byte (probably from a register) and updates the
 /// proper flag registers.
 fn rr(cpu: &mut Cpu, value: u8) -> u8 {
-    let carry = cpu.get_carry();
+    let carry = cpu.carry();
 
     cpu.set_carry((value & 0x1) == 0x1);
 
@@ -3259,7 +3259,7 @@ fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
 fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
     let first = first as u32;
     let second = second as u32;
-    let carry = cpu.get_carry() as u32;
+    let carry = cpu.carry() as u32;
 
     let result = first.wrapping_add(second).wrapping_add(carry);
     let result_b = result as u8;
@@ -3290,7 +3290,7 @@ fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
 fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
     let first = first as u32;
     let second = second as u32;
-    let carry = cpu.get_carry() as u32;
+    let carry = cpu.carry() as u32;
 
     let result = first.wrapping_sub(second).wrapping_sub(carry);
     let result_b = result as u8;
-- 
GitLab