From dadddf5c4e28587173716474eb55d0c17890f1a1 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 11 Oct 2025 18:29:51 -0500 Subject: [PATCH] HW/Wiimote: Speaker logic accuracy fixes, comments, and code cleanups. --- Source/Core/AudioCommon/Mixer.cpp | 4 + Source/Core/AudioCommon/Mixer.h | 1 + .../Core/HW/WiimoteEmu/EmuSubroutines.cpp | 31 +-- Source/Core/Core/HW/WiimoteEmu/Speaker.cpp | 187 ++++++++++++------ Source/Core/Core/HW/WiimoteEmu/Speaker.h | 147 +++++++++++--- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 13 +- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h | 4 - .../Core/Core/HW/WiimoteReal/WiimoteReal.cpp | 11 +- Source/Core/Core/HW/WiimoteReal/WiimoteReal.h | 4 - 9 files changed, 278 insertions(+), 124 deletions(-) diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index eab73fb17c9..d1aabbaa16b 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -264,6 +264,9 @@ void Mixer::PushWiimoteSpeakerSamples(const s16* samples, std::size_t num_sample if (!IsOutputSampleRateValid()) return; + if (!m_config_wiimote_enable_speaker) + return; + // Max 20 bytes/speaker report, may be 4-bit ADPCM so multiply by 2 static constexpr std::size_t MAX_SPEAKER_SAMPLES = 20 * 2; std::array samples_stereo; @@ -432,6 +435,7 @@ void Mixer::RefreshConfig() m_config_emulation_speed = Config::Get(Config::MAIN_EMULATION_SPEED); m_config_fill_audio_gaps = Config::Get(Config::MAIN_AUDIO_FILL_GAPS); m_config_audio_buffer_ms = Config::Get(Config::MAIN_AUDIO_BUFFER_SIZE); + m_config_wiimote_enable_speaker = Config::Get(Config::MAIN_WIIMOTE_ENABLE_SPEAKER); } void Mixer::MixerFifo::DoState(PointerWrap& p) diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index 808ce540ec6..baa02175b88 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -165,6 +165,7 @@ private: float m_config_emulation_speed; bool m_config_fill_audio_gaps; int m_config_audio_buffer_ms; + bool m_config_wiimote_enable_speaker; Config::ConfigChangedCallbackID m_config_changed_callback_id; }; diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index 46a4c417d8f..83a058b43c5 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -363,6 +363,8 @@ void Wiimote::HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature& { m_speaker_mute = rpt.enable; + m_speaker_logic.SetMuted(m_speaker_mute); + if (rpt.ack) SendAck(OutputReportID::SpeakerMute, ErrorCode::Success); } @@ -371,27 +373,23 @@ void Wiimote::HandleSpeakerEnable(const WiimoteCommon::OutputReportEnableFeature { m_status.speaker = rpt.enable; + m_speaker_logic.SetEnabled(m_status.speaker); + if (rpt.ack) SendAck(OutputReportID::SpeakerEnable, ErrorCode::Success); } void Wiimote::HandleSpeakerData(const WiimoteCommon::OutputReportSpeakerData& rpt) { - // TODO: Does speaker_mute stop speaker data processing? - // and what about speaker_enable? - // (important to keep decoder in proper state) - if (!m_speaker_mute) + if (rpt.length > std::size(rpt.data)) { - if (rpt.length > std::size(rpt.data)) - { - ERROR_LOG_FMT(WIIMOTE, "Bad speaker data length: {}", rpt.length); - } - else - { - // Speaker data reports result in a write to the speaker hardware at offset 0x00. - m_i2c_bus.BusWrite(SpeakerLogic::I2C_ADDR, SpeakerLogic::SPEAKER_DATA_OFFSET, rpt.length, - std::data(rpt.data)); - } + ERROR_LOG_FMT(WIIMOTE, "Bad speaker data length: {}", rpt.length); + } + else + { + // Speaker data reports result in a write to the speaker hardware at offset 0x00. + m_i2c_bus.BusWrite(SpeakerLogic::I2C_ADDR, SpeakerLogic::SPEAKER_DATA_OFFSET, rpt.length, + std::data(rpt.data)); } // FYI: Speaker data reports normally do not ACK but I have seen them ACK with error codes @@ -553,7 +551,12 @@ void Wiimote::DoState(PointerWrap& p) m_camera_logic.DoState(p); if (p.IsReadMode()) + { + m_speaker_logic.SetEnabled(m_status.speaker); + m_speaker_logic.SetMuted(m_speaker_mute); + m_camera_logic.SetEnabled(m_status.ir); + } p.Do(m_is_motion_plus_attached); p.Do(m_active_extension); diff --git a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp index 0394ae9236c..173c9b0902d 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp @@ -54,66 +54,95 @@ static s16 adpcm_yamaha_expand_nibble(ADPCMState& s, u8 nibble) return s.predictor; } -void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan) +static constexpr auto ExpandS8ToS16(s8 sample) { - // TODO: should we still process samples for the decoder state? - if (!m_speaker_enabled) - return; + return s16(sample * 0x100); +} - if (reg_data.sample_rate == 0 || length == 0) +void SpeakerLogic::ProcessSpeakerData(std::span data) +{ + // There seem to be multiple flags that can skip input entirely. + if ((m_register_data.speaker_flags & SPEAKER_STOP_BIT) != 0x00) + return; + if ((m_register_data.audio_input_enable & 0x01) == 0x00) return; - - // Even if volume is zero we process samples to maintain proper decoder state. // Potentially 40 resulting samples. std::array samples; - assert(length * 2 <= static_cast(samples.size())); + assert(data.size() * 2 <= samples.size()); - unsigned int sample_rate_dividend, sample_length; - u8 volume_divisor; + std::size_t sample_count = 0; - if (reg_data.format == SpeakerLogic::DATA_FORMAT_PCM) + const u8 effective_audio_format = m_register_data.audio_format & 0xe0; + switch (effective_audio_format) { - // 8 bit PCM - for (int i = 0; i < length; ++i) + // 4bit Yamaha ADPCM (same as dreamcast) + // Games only use this. + case 0x00: + for (u8 value : data) { - samples[i] = ((s16)(s8)data[i]) * 0x100; + samples[sample_count++] = adpcm_yamaha_expand_nibble(m_adpcm_state, value >> 4); + samples[sample_count++] = adpcm_yamaha_expand_nibble(m_adpcm_state, value & 0xf); } + break; - // Following details from http://wiibrew.org/wiki/Wiimote#Speaker - sample_rate_dividend = 12000000; - volume_divisor = 0xff; - sample_length = (unsigned int)length; - } - else if (reg_data.format == SpeakerLogic::DATA_FORMAT_ADPCM) - { - // 4 bit Yamaha ADPCM (same as dreamcast) - for (int i = 0; i < length; ++i) + // s8 PCM + case 0x40: + for (u8 value : data) { - samples[i * 2] = adpcm_yamaha_expand_nibble(adpcm_state, (data[i] >> 4) & 0xf); - samples[i * 2 + 1] = adpcm_yamaha_expand_nibble(adpcm_state, data[i] & 0xf); + samples[sample_count++] = ExpandS8ToS16(s8(value)); } + break; - // Following details from http://wiibrew.org/wiki/Wiimote#Speaker - sample_rate_dividend = 6000000; - volume_divisor = 0x7F; - sample_length = (unsigned int)length * 2; + // s16le PCM (both of these?) + case 0x60: + case 0xe0: + if ((data.size() % sizeof(s16)) != 0) + { + // I assume the real hardware properly buffers odd-sized writes ? + ERROR_LOG_FMT(IOS_WIIMOTE, "Unhandled odd audio data size"); + } + sample_count = data.size() / sizeof(s16); + std::ranges::copy(data, Common::AsWritableU8Span(samples).data()); + break; + + default: + ERROR_LOG_FMT(IOS_WIIMOTE, "Unknown audio format {:x}", m_register_data.audio_format); + break; } - else - { - ERROR_LOG_FMT(IOS_WIIMOTE, "Unknown speaker format {:x}", reg_data.format); + + if (sample_count == 0) return; - } - if (reg_data.volume > volume_divisor) + m_register_data.decoder_flags |= DECODER_PROCESSED_DATA_BIT; + + // When output isn't enabled, we drop the samples after running data through the decoder. + // I think the real hardware buffers the pre-decoded data and decodes/plays only when this is set. + // And I think the above bit is not actually set until that happens. + // We aren't emulating any of that buffering, though. + if ((m_register_data.audio_playback_enable & 0x01) == 0x00) + return; + + if (m_is_muted) + return; + + // If the 0x01 bit is set here then no audio is produced. + if ((m_register_data.audio_format & 0x01) != 0x00) + return; + + // Despite wiibrew claims, the hardware volume can go all the way to 0xff. + // But since games never set the volume beyond 0x7f we'll use that as the maximum. + constexpr auto volume_divisor = 0x7f; + + if (m_register_data.volume > volume_divisor) { - DEBUG_LOG_FMT(IOS_WIIMOTE, "Wiimote volume is higher than suspected maximum!"); - volume_divisor = reg_data.volume; + // We could potentially amplify the samples in this situation? + DEBUG_LOG_FMT(IOS_WIIMOTE, "Wiimote volume is higher than suspected maximum."); } // SetWiimoteSpeakerVolume expects values from 0 to 255. // Multiply by 256, floor to int, and clamp to 255 for a uniformly mapped conversion. - const double volume = float(reg_data.volume) * 256.f / volume_divisor; + const double volume = float(m_register_data.volume) * 256.f / volume_divisor; // This used the "Constant Power Pan Law", but it is undesirable // if the pan is 0, and it implied that the loudness of a wiimote speaker @@ -122,7 +151,7 @@ void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan) // We should play the samples from the wiimote at the native volume they came with, // because you can lower their volume from the Wii settings and because they are // already extremely low quality, so any additional quality loss isn't welcome. - speaker_pan = std::clamp(speaker_pan, -1.f, 1.f); + const auto speaker_pan = std::clamp(float(m_speaker_pan_setting.GetValue()) / 100, -1.f, 1.f); const u32 l_volume = std::min(u32(std::min(1.f - speaker_pan, 1.f) * volume), 255u); const u32 r_volume = std::min(u32(std::min(1.f + speaker_pan, 1.f) * volume), 255u); @@ -130,31 +159,51 @@ void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan) SoundStream* sound_stream = system.GetSoundStream(); sound_stream->GetMixer()->SetWiimoteSpeakerVolume(l_volume, r_volume); - - // ADPCM sample rate is thought to be x2.(3000 x2 = 6000). - const unsigned int sample_rate = sample_rate_dividend / reg_data.sample_rate; sound_stream->GetMixer()->PushWiimoteSpeakerSamples( - samples.data(), sample_length, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / (sample_rate * 2)); + samples.data(), sample_count, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / GetCurrentSampleRate()); +} + +u32 SpeakerLogic::GetCurrentSampleRate() const +{ + auto sr_divisor = m_register_data.sample_rate_divisor; + if (sr_divisor == 0) + { + // Real hardware seems to interpret 0x000 as 0xfff. + // i.e. ~183 samples per second, based buffer "readiness" timing. + sr_divisor = std::numeric_limits::max(); + } + + return SAMPLE_RATE_DIVIDEND / sr_divisor; } void SpeakerLogic::Reset() { - reg_data = {}; + m_register_data = {}; - // Yamaha ADPCM state initialize - adpcm_state.predictor = 0; - adpcm_state.step = 127; + m_register_data.decoder_flags |= DECODER_READY_FOR_DATA_BIT; + + m_adpcm_state = {}; + + m_is_enabled = false; + m_is_muted = false; } void SpeakerLogic::DoState(PointerWrap& p) { - p.Do(adpcm_state); - p.Do(reg_data); + p.Do(m_adpcm_state); + p.Do(m_register_data); + + // FYI: `m_is_enabled` and `m_is_muted` are handled by the Wiimote class. } -void SpeakerLogic::SetSpeakerEnabled(bool enabled) +void SpeakerLogic::SetEnabled(bool enabled) { - m_speaker_enabled = enabled; + m_is_enabled = enabled; +} + +void SpeakerLogic::SetMuted(bool muted) +{ + m_is_muted = muted; } int SpeakerLogic::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) @@ -162,7 +211,13 @@ int SpeakerLogic::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) if (I2C_ADDR != slave_addr) return 0; - return RawRead(®_data, addr, count, data_out); + // FYI: Real hardware returns a stream of 0xff when reading from addr:0x00. + // Reads at other addresses also return mostly 0xff except: + // addr:0x07 returns some decoder state flags. + // addr:0xff returns 0x00. + // Games never read from this device so this isn't implemented. + + return RawRead(&m_register_data, addr, count, data_out); } int SpeakerLogic::BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) @@ -170,17 +225,37 @@ int SpeakerLogic::BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) if (I2C_ADDR != slave_addr) return 0; + // It seems writes while not "enabled" succeed but have no effect. + if (!m_is_enabled) + return count; + if (addr == SPEAKER_DATA_OFFSET) { - SpeakerData(data_in, count, m_speaker_pan_setting.GetValue() / 100); + ProcessSpeakerData(std::span(data_in, count)); return count; } - else + + // Allow writes to clear some bits. + const auto prev_flags = std::exchange(m_register_data.decoder_flags, 0x00); + RawWrite(&m_register_data, addr, count, data_in); + const auto written_bits = std::exchange(m_register_data.decoder_flags, prev_flags); + + constexpr u8 CLEARABLE_BITS = DECODER_DROPPED_DATA_BIT | DECODER_PROCESSED_DATA_BIT; + + m_register_data.decoder_flags &= ~(written_bits & CLEARABLE_BITS); + + if ((written_bits & DECODER_RESET_BIT) != 0x00) { - // TODO: Does writing immediately change the decoder config even when active - // or does a write to 0x08 activate the new configuration or something? - return RawWrite(®_data, addr, count, data_in); + // The real hardware also sets bits 0x04 and 0x08 here if data was buffered. + + m_adpcm_state = {}; + DEBUG_LOG_FMT(IOS_WIIMOTE, "ADPCM decoder reset via i2c write."); } + + if ((m_register_data.speaker_flags & SPEAKER_DISABLE_PLAYBACK_BIT) != 0x00) + Common::SetBit<0>(m_register_data.audio_playback_enable, false); + + return count; } } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/Speaker.h b/Source/Core/Core/HW/WiimoteEmu/Speaker.h index 9a6a652bb1f..edcc61eca49 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Speaker.h +++ b/Source/Core/Core/HW/WiimoteEmu/Speaker.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Core/HW/WiimoteEmu/I2CBus.h" @@ -12,7 +14,8 @@ namespace WiimoteEmu { struct ADPCMState { - s32 predictor, step; + s32 predictor = 0; + s32 step = 127; }; class Wiimote; @@ -29,34 +32,130 @@ public: void Reset(); void DoState(PointerWrap& p); - void SetSpeakerEnabled(bool enabled); + void SetEnabled(bool enabled); + void SetMuted(bool muted); private: - // Pan is -1.0 to +1.0 - void SpeakerData(const u8* data, int length, float speaker_pan); + void ProcessSpeakerData(std::span); - // TODO: enum class - static const u8 DATA_FORMAT_ADPCM = 0x00; - static const u8 DATA_FORMAT_PCM = 0x40; + u32 GetCurrentSampleRate() const; + + // Much of the information here comes from reverse engineering of an original (non-TR) Wii remote. + // -TR Wii remotes, for whatever reason, seem to perform better buffering of data, + // resulting in fewer dropped packets and notably better audio playback. + // However, the situation is still not ideal unless "sniff mode" is enabled. + + // Despite wiibrew claims, this dividend seems to be constant, regardless of the PCM/ADPCM mode. + static constexpr u32 SAMPLE_RATE_DIVIDEND = 12'000'000; + + // There are 2 somewhat understood bits at addr:0x01. + + // Setting bit:0x01 seems to stop basically everything. + // Written audio data is dropped (not buffered). + // Already buffered audio data does not play. + // The speaker audibly "clicks" off/on. + static constexpr u8 SPEAKER_STOP_BIT = 0x01; + + // Setting bit 0x80 seems to halt playback. + // Written audio data is buffered, but it will not decode/play. + // The effect is perhaps indirect, because this also seems to clear the state at addr:0x08. + // Restoring playback after this bit is written requires *first* clearing it, + // then afterward setting bit:0x01 at addr:0x08. + static constexpr u8 SPEAKER_DISABLE_PLAYBACK_BIT = 0x80; + + // FYI: There seems to be a whopping 127 byte buffer for undecoded data regardless of format. + // This buffering isn't at all implemented by us. + + // There are 4 somewhat understood bits at addr:0x07. + + // Unlike an original remote, reading this byte on a -TR remote seems to always produce 0x00. + // Therefore, much of this is not applicable to -TR (and maybe other versions) of remotes. + // The audio decoder IC has changed at least once from a ROHM BU7849 to a BU8849. + + // Seems to set/unset itself when the buffer has room for data. + // Writing exactly 64 bytes of speaker data without output enabled will clear the bit. + // Letting some samples play will set the bit again. + // I think when the bit is observed, 64 more bytes of speaker data may be safely written. + static constexpr u8 DECODER_READY_FOR_DATA_BIT = 0x01; + + // Writing this bit resets the ADPCM decoder. + // This, expectedly, does work on a -TR remote. + // It also sets the above "ready" bit so I assume it resets the buffer. + // And, if any data was buffered, it sets bit 0x08 (processed data). + // And, if 64 or more bytes were buffered, it sets bit 0x04 (dropped? data). Odd.. + // That happens even when also writting those bits (to clear them), + // so actually clearing all the bits can take two writes. + static constexpr u8 DECODER_RESET_BIT = 0x02; + + // Seems to latch on after data was dropped, or something like that? + // Writing 128 bytes or more of speaker data without output enabled will set the bit. + // This also sets the above "ready" bit, allowing overwrite of existing data I suppose? + // Resetting the decoder with 64 bytes or more buffered will set this bit. Odd.. + // Enabling output with with 64 bytes or more buffered will set this bit. Odd.. + // Those two are unusual and make me think this isn't really a "dropped data" flag. + // This bit can be cleared by writing to it. + static constexpr u8 DECODER_DROPPED_DATA_BIT = 0x04; + + // Seems to latch on after any playback. + // This bit can be cleared by writing to it. + static constexpr u8 DECODER_PROCESSED_DATA_BIT = 0x08; - // TODO: It seems reading address 0x00 should always return 0xff. #pragma pack(push, 1) struct Register { // Speaker reports result in a write of samples to addr 0x00 (which also plays sound) u8 speaker_data; - u8 unk_1; - u8 format; - // seems to always play at 6khz no matter what this is set to? - // or maybe it only applies to pcm input - // Little-endian: - u16 sample_rate; + + // Note: Even though games always write the entire configuration as 7-bytes, + // it seems all of the parameters can be individually altered on the fly. + + // Games write 0x80 here when enabling speaker and 0x01 when disabling. + // They also write 0x00 here in their 7-byte "configuration" of this and the following bytes. + // In testing, it seems 0x80 and 0x01 are the only bits here that stop sound. + u8 speaker_flags; + + // While the audio hardware itself appers to support 16bit samples, it's not practical + // because of the Wii remote's pitiful Bluetooth communication throughput. + // One could maybe approach 32Kb/s (20bytes every 5ms) with "sniff mode" properly enabled. + // Wii games only ever use 4bit Yamaha ADPCM at 24Kb/s (20bytes every ~6.66ms). + // + // If the 0x01 bit is set then no audio is produced, + // but it seems to be otherwise processed normally based on the decoder flags. + // + // The unknown format bit sizes are calculated from buffer "readiness" timing. + // All these guesses come from testing on an original (non-TR) Wii remote. + // + // 0x00-0x1e = 4bit Yamaha ADPCM + // 0x20-0x3e = 8bit? Plays static atop signal when given PCM ? + // 0x40-0x5e = 8bit signed PCM + // 0x60-0x7e = Seems to be 16bit signed little-endian PCM. + // 0x80-0x9e = 8bit? PCM-like but quiet and different ? + // 0xa0-0xbe = 8bit? Sounds overdriven when given PCM ? + // 0xc0-0xde = 8bit? + // 0xe0-0xfe = Seems to also be s16le PCM ? + u8 audio_format; + + // Little-endian. 12,000,000 dividend. + u16 sample_rate_divisor; + + // Games never set a value higher than 0x7f. u8 volume; - u8 unk_5; - u8 unk_6; - // Reading this byte on real hardware seems to return 0x09: - u8 unk_7; - u8 unk_8; + + // Games write 0x0c here when enabling the speaker. + // Purpose is entirely unknown. Real hardware seems unaffected by this. + u8 unknown_flags; + + // Games write 0x0e here when enabling the speaker to clear the decoder state. + u8 decoder_flags; + + // Games write 0x01 here to enable playback. + // When this bit is cleared, data can be buffered, but decoding/playback is paused. + u8 audio_playback_enable; + + // Games write 0x01 to enable speaker and 0x00 to disable. + // When this bit is cleared, written audio data is ignored. + u8 audio_input_enable; + u8 unknown[0xf6]; }; #pragma pack(pop) @@ -66,15 +165,15 @@ private: int BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) override; int BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) override; - Register reg_data{}; + Register m_register_data{}; - // TODO: What actions reset this state? - // Is this actually in the register somewhere? - ADPCMState adpcm_state{}; + ADPCMState m_adpcm_state{}; ControllerEmu::SettingValue m_speaker_pan_setting; - bool m_speaker_enabled = false; + // FYI: Real hardware seems to be not-enabled and not-muted on power up. + bool m_is_enabled = false; + bool m_is_muted = false; }; } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index 98f52a09f14..cecd389f772 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -306,15 +306,9 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), m_bt_device_index(i {SIDEWAYS_OPTION, nullptr, nullptr, _trans("Sideways Wii Remote")}, false); Reset(); - - m_config_changed_callback_id = Config::AddConfigChangedCallback([this] { RefreshConfig(); }); - RefreshConfig(); } -Wiimote::~Wiimote() -{ - Config::RemoveConfigChangedCallback(m_config_changed_callback_id); -} +Wiimote::~Wiimote() = default; std::string Wiimote::GetName() const { @@ -823,11 +817,6 @@ void Wiimote::SetRumble(bool on) m_rumble->controls.front()->control_ref->State(on); } -void Wiimote::RefreshConfig() -{ - m_speaker_logic.SetSpeakerEnabled(Config::Get(Config::MAIN_WIIMOTE_ENABLE_SPEAKER)); -} - void Wiimote::StepDynamics() { EmulateSwing(&m_swing_state, m_swing, 1.f / ::Wiimote::UPDATE_FREQ); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index 94da0a563c7..2013ce737ef 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -187,8 +187,6 @@ private: // This is the region exposed over bluetooth: static constexpr int EEPROM_FREE_SIZE = 0x1700; - void RefreshConfig(); - void StepDynamics(); void UpdateButtonsStatus(const DesiredWiimoteState& target_state); void BuildDesiredWiimoteState(DesiredWiimoteState* target_state, SensorBarState sensor_bar_state); @@ -348,7 +346,5 @@ private: PositionalState m_shake_state; IMUCursorState m_imu_cursor_state; - - Config::ConfigChangedCallbackID m_config_changed_callback_id; }; } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index 7451c5d02b6..dc33cd1e65d 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -185,14 +185,6 @@ void Wiimote::WriteReport(Report rpt) return; break; - case OutputReportID::SpeakerEnable: - m_speaker_enable = (rpt[2] & 0x4) != 0; - break; - - case OutputReportID::SpeakerMute: - m_speaker_mute = (rpt[2] & 0x4) != 0; - break; - default: break; } @@ -283,8 +275,7 @@ void Wiimote::InterruptDataOutput(const u8* data, const u32 size) leds_rpt.leds = 0xf; } } - else if (rpt[1] == u8(OutputReportID::SpeakerData) && - (!m_speaker_enabled_in_dolphin_config || !m_speaker_enable || m_speaker_mute)) + else if (rpt[1] == u8(OutputReportID::SpeakerData) && !m_speaker_enabled_in_dolphin_config) { rpt.resize(3); // Translate undesired speaker data reports into rumble reports. diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index dd0f699aed9..6a004d93475 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -152,10 +152,6 @@ private: std::atomic m_is_linked = false; - // We track the speaker state to convert unnecessary speaker data into rumble reports. - bool m_speaker_enable = false; - bool m_speaker_mute = false; - // And we track the rumble state to drop unnecessary rumble reports. bool m_rumble_state = false;