From e22167cf8200b563639c11bba15abbbfae5b427d Mon Sep 17 00:00:00 2001 From: byuu <2107894+byuu@users.noreply.github.com> Date: Sun, 6 Oct 2019 10:14:30 +0900 Subject: [PATCH] v111.1 More improvements to SameBoy audio interface for Super Game Boy. Added a fix for a very rare crashing issue with SDL 2.0 joypad support. --- bsnes/emulator/audio/audio.hpp | 3 ++- bsnes/emulator/audio/stream.cpp | 11 +++++++++-- bsnes/emulator/emulator.hpp | 2 +- bsnes/sfc/coprocessor/icd/icd.cpp | 19 ++++++++++--------- bsnes/sfc/dsp/dsp.cpp | 4 +++- bsnes/target-bsnes/input/input.cpp | 17 ++++++++++++++--- nall/dsp/resampler/cubic.hpp | 4 ++-- nall/queue.hpp | 2 +- 8 files changed, 42 insertions(+), 20 deletions(-) diff --git a/bsnes/emulator/audio/audio.hpp b/bsnes/emulator/audio/audio.hpp index be3e9cf6..11a044ee 100644 --- a/bsnes/emulator/audio/audio.hpp +++ b/bsnes/emulator/audio/audio.hpp @@ -55,6 +55,7 @@ struct Filter { struct Stream { auto reset(uint channels, double inputFrequency, double outputFrequency) -> void; + auto reset() -> void; auto frequency() const -> double; auto setFrequency(double inputFrequency, maybe outputFrequency = nothing) -> void; @@ -63,7 +64,7 @@ struct Stream { auto addLowPassFilter(double cutoffFrequency, Filter::Order order, uint passes = 1) -> void; auto addHighPassFilter(double cutoffFrequency, Filter::Order order, uint passes = 1) -> void; - auto pending() const -> bool; + auto pending() const -> uint; auto read(double samples[]) -> uint; auto write(const double samples[]) -> void; diff --git a/bsnes/emulator/audio/stream.cpp b/bsnes/emulator/audio/stream.cpp index 5a697527..c0a4e923 100644 --- a/bsnes/emulator/audio/stream.cpp +++ b/bsnes/emulator/audio/stream.cpp @@ -9,6 +9,12 @@ auto Stream::reset(uint channelCount, double inputFrequency, double outputFreque setFrequency(inputFrequency, outputFrequency); } +auto Stream::reset() -> void { + for(auto& channel : channels) { + channel.resampler.reset(this->inputFrequency, this->outputFrequency); + } +} + auto Stream::frequency() const -> double { return inputFrequency; } @@ -81,8 +87,9 @@ auto Stream::addHighPassFilter(double cutoffFrequency, Filter::Order order, uint } } -auto Stream::pending() const -> bool { - return channels && channels[0].resampler.pending(); +auto Stream::pending() const -> uint { + if(!channels) return 0; + return channels[0].resampler.pending(); } auto Stream::read(double samples[]) -> uint { diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp index c5b34bc5..9137e90d 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 = "111"; + static const string Version = "111.1"; 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 eb334d6d..480bdce8 100644 --- a/bsnes/sfc/coprocessor/icd/icd.cpp +++ b/bsnes/sfc/coprocessor/icd/icd.cpp @@ -40,6 +40,7 @@ namespace SameBoy { float left = sample->left / 32768.0f; float right = sample->right / 32768.0f; icd.apuWrite(left, right); + //print(dsp.stream->pending(), " ", icd.stream->pending(), "\n"); } static auto vblank(GB_gameboy_t*) -> void { @@ -63,7 +64,7 @@ auto ICD::main() -> void { step(clocks >> 1); } else { //DMG halted apuWrite(0.0, 0.0); - step(256); + step(128); } synchronizeCPU(); } @@ -75,16 +76,15 @@ auto ICD::step(uint clocks) -> void { auto ICD::load() -> bool { information = {}; -//todo: connect to SFC random enable setting -//GB_random_set_enabled(false); + GB_random_set_enabled(configuration.hacks.entropy != "None"); 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, uint(system.cpuFrequency() / 5.0 / 128.0)); + 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, uint(Frequency / 5.0 / 128.0)); + GB_set_sample_rate(&sameboy, 32000); } GB_set_highpass_filter_mode(&sameboy, GB_HIGHPASS_ACCURATE); GB_set_icd_hreset_callback(&sameboy, &SameBoy::hreset); @@ -138,11 +138,12 @@ 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 - create(ICD::Enter, (Frequency ? Frequency : system.cpuFrequency()) / 5.0); - if(!reset) { - stream = Emulator::audio.createStream(2, uint((Frequency ? Frequency : system.cpuFrequency()) / 5.0 / 128.0)); - } + 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/dsp/dsp.cpp b/bsnes/sfc/dsp/dsp.cpp index 56e62266..c41a80c4 100644 --- a/bsnes/sfc/dsp/dsp.cpp +++ b/bsnes/sfc/dsp/dsp.cpp @@ -19,7 +19,9 @@ auto DSP::main() -> void { int count = spc_dsp.sample_count(); if(count > 0) { for(uint n = 0; n < count; n += 2) { - stream->sample(samplebuffer[n + 0] / 32768.0f, samplebuffer[n + 1] / 32768.0f); + float left = samplebuffer[n + 0] / 32768.0f; + float right = samplebuffer[n + 1] / 32768.0f; + stream->sample(left, right); } spc_dsp.set_output(samplebuffer, 8192); } diff --git a/bsnes/target-bsnes/input/input.cpp b/bsnes/target-bsnes/input/input.cpp index 1fa9e78c..fb93bd23 100644 --- a/bsnes/target-bsnes/input/input.cpp +++ b/bsnes/target-bsnes/input/input.cpp @@ -170,13 +170,23 @@ auto InputMapping::Binding::icon() -> image { } auto InputMapping::Binding::name() -> string { - if(device && device->isKeyboard()) { + //if ruby drivers cannot report accurate vendor/product IDs (eg SDL), + //and the user closes the emulator, changes gamepads, and restarts it, + //it is possible the wrong device will now be mapped to the input IDs. + //that could potentially make the group/input IDs go out of bounds. + if(!device) return {}; + if(group >= device->size()) return {}; + if(input >= device->group(group).size()) return {}; + + if(device->isKeyboard()) { return device->group(group).input(input).name(); } - if(device && device->isMouse()) { + + if(device->isMouse()) { return device->group(group).input(input).name(); } - if(device && device->isJoypad()) { + + if(device->isJoypad()) { string name{Hash::CRC16(string{device->id()}).digest().upcase()}; name.append(" ", device->group(group).name()); name.append(" ", device->group(group).input(input).name()); @@ -185,6 +195,7 @@ auto InputMapping::Binding::name() -> string { if(qualifier == Qualifier::Rumble) name.append(" Rumble"); return name; } + return {}; } diff --git a/nall/dsp/resampler/cubic.hpp b/nall/dsp/resampler/cubic.hpp index 1b184a69..362ec429 100644 --- a/nall/dsp/resampler/cubic.hpp +++ b/nall/dsp/resampler/cubic.hpp @@ -8,7 +8,7 @@ namespace nall::DSP::Resampler { struct Cubic { inline auto reset(double inputFrequency, double outputFrequency = 0, uint queueSize = 0) -> void; inline auto setInputFrequency(double inputFrequency) -> void; - inline auto pending() const -> bool; + inline auto pending() const -> uint; inline auto read() -> double; inline auto write(double sample) -> void; @@ -37,7 +37,7 @@ auto Cubic::setInputFrequency(double inputFrequency) -> void { ratio = inputFrequency / outputFrequency; } -auto Cubic::pending() const -> bool { +auto Cubic::pending() const -> uint { return samples.pending(); } diff --git a/nall/queue.hpp b/nall/queue.hpp index 062eda77..1a380d42 100644 --- a/nall/queue.hpp +++ b/nall/queue.hpp @@ -41,7 +41,7 @@ struct queue { template auto capacity() const -> uint { return _capacity * sizeof(T) / sizeof(U); } template auto size() const -> uint { return _size * sizeof(T) / sizeof(U); } auto empty() const -> bool { return _size == 0; } - auto pending() const -> bool { return _size > 0; } + auto pending() const -> uint { return _size; } auto full() const -> bool { return _size >= (int)_capacity; } auto underflow() const -> bool { return _size < 0; } auto overflow() const -> bool { return _size > (int)_capacity; }