From d62e3f3362dad31485c06665d079560a4dfb509c Mon Sep 17 00:00:00 2001
From: byuu <2107894+byuu@users.noreply.github.com>
Date: Wed, 11 Dec 2019 21:40:07 +0900
Subject: [PATCH] v112.14

Finally corrected Super Game Boy 2 audio [LIJI]
---
 bsnes/emulator/emulator.hpp       |  2 +-
 bsnes/sfc/coprocessor/icd/icd.cpp | 22 ++++++++--------------
 bsnes/sfc/coprocessor/icd/icd.hpp |  1 +
 bsnes/sfc/coprocessor/icd/io.cpp  |  3 ++-
 4 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp
index 56bccd26..cc62821a 100644
--- a/bsnes/emulator/emulator.hpp
+++ b/bsnes/emulator/emulator.hpp
@@ -29,7 +29,7 @@ using namespace nall;
 
 namespace Emulator {
   static const string Name    = "bsnes";
-  static const string Version = "112.13";
+  static const string Version = "112.14";
   static const string Author  = "byuu";
   static const string License = "GPLv3";
   static const string Website = "https://byuu.org";
diff --git a/bsnes/sfc/coprocessor/icd/icd.cpp b/bsnes/sfc/coprocessor/icd/icd.cpp
index d084e45a..1b5199c4 100644
--- a/bsnes/sfc/coprocessor/icd/icd.cpp
+++ b/bsnes/sfc/coprocessor/icd/icd.cpp
@@ -58,14 +58,6 @@ auto ICD::Enter() -> void {
 }
 
 auto ICD::main() -> void {
-  #if 0
-  static uint n = 0;
-  float x = sin((2 * 3.141592 * n++ * 1000.0) / 44100.0) * 0.1;
-  apuWrite(x, x);
-  step(256);
-  return synchronizeCPU();
-  #endif
-
   if(r6003 & 0x80) {
     auto clocks = GB_run(&sameboy);
     step(clocks >> 1);
@@ -80,6 +72,12 @@ auto ICD::step(uint clocks) -> void {
   clock += clocks * (uint64_t)cpu.frequency;
 }
 
+//SGB1 uses the CPU oscillator (~2.4% faster than a real Game Boy)
+//SGB2 uses a dedicated oscillator (same speed as a real Game Boy)
+auto ICD::clockFrequency() const -> uint {
+  return Frequency ? Frequency : system.cpuFrequency();
+}
+
 auto ICD::load() -> bool {
   information = {};
 
@@ -87,12 +85,11 @@ auto ICD::load() -> bool {
   if(Frequency == 0) {
     GB_init(&sameboy, GB_MODEL_SGB_NO_SFC);
     GB_load_boot_rom_from_buffer(&sameboy, (const unsigned char*)&SGB1BootROM[0], 256);
-    GB_set_sample_rate(&sameboy, 32768);
   } else {
     GB_init(&sameboy, GB_MODEL_SGB2_NO_SFC);
     GB_load_boot_rom_from_buffer(&sameboy, (const unsigned char*)&SGB2BootROM[0], 256);
-    GB_set_sample_rate(&sameboy, 32000);
   }
+  GB_set_sample_rate_by_clocks(&sameboy, 256);
   GB_set_highpass_filter_mode(&sameboy, GB_HIGHPASS_ACCURATE);
   GB_set_icd_hreset_callback(&sameboy, &SameBoy::hreset);
   GB_set_icd_vreset_callback(&sameboy, &SameBoy::vreset);
@@ -145,12 +142,9 @@ auto ICD::unload() -> void {
 }
 
 auto ICD::power(bool reset) -> void {
-  uint frequency = (Frequency ? Frequency : system.cpuFrequency()) / 5.0;
-  //SGB1 uses CPU oscillator; SGB2 uses dedicated oscillator
+  auto frequency = clockFrequency() / 5;
   create(ICD::Enter, frequency);
   if(!reset) stream = Emulator::audio.createStream(2, frequency / 128);
-//dsp.stream->reset();
-//icd.stream->reset();
 
   for(auto& packet : this->packet) packet = {};
   packetSize = 0;
diff --git a/bsnes/sfc/coprocessor/icd/icd.hpp b/bsnes/sfc/coprocessor/icd/icd.hpp
index 1a98849b..baef0ec6 100644
--- a/bsnes/sfc/coprocessor/icd/icd.hpp
+++ b/bsnes/sfc/coprocessor/icd/icd.hpp
@@ -8,6 +8,7 @@ struct ICD : Emulator::Platform, Thread {
   static auto Enter() -> void;
   auto main() -> void;
   auto step(uint clocks) -> void;
+  auto clockFrequency() const -> uint;
 
   auto load() -> bool;
   auto save() -> void;
diff --git a/bsnes/sfc/coprocessor/icd/io.cpp b/bsnes/sfc/coprocessor/icd/io.cpp
index 8a87257a..4c4f0b6e 100644
--- a/bsnes/sfc/coprocessor/icd/io.cpp
+++ b/bsnes/sfc/coprocessor/icd/io.cpp
@@ -55,13 +55,14 @@ auto ICD::writeIO(uint addr, uint8 data) -> void {
     if((r6003 & 0x80) == 0x00 && (data & 0x80) == 0x80) {
       power(true);  //soft reset
     }
-    auto frequency = system.cpuFrequency();
+    auto frequency = clockFrequency();
     switch(data & 3) {
     case 0: this->frequency = frequency / 4; break;  //fast (glitchy, even on real hardware)
     case 1: this->frequency = frequency / 5; break;  //normal
     case 2: this->frequency = frequency / 7; break;  //slow
     case 3: this->frequency = frequency / 9; break;  //very slow
     }
+    stream->setFrequency(this->frequency / 128);
     r6003 = data;
     return;
   }