From 547740984746cc77bdb142c61f65a4994235ad3b Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Fri, 28 Jun 2019 13:24:01 -0700 Subject: [PATCH 1/3] Write the entirety of the Wiimote EEPROM, in a per-Wiimote file Previously, only Mii data was written. Additionally, the file containing mii data was shared for all Wiimotes, which made it a lot less useful. Additionally, the file was read/written on each Wiimote read, even though the whole EEPROM was kept in memory. This was bad for performance and not particularly necessary (it did enforce that the data was properly shared between all Wiimotes, but that's not something I want). --- .../Core/HW/WiimoteEmu/EmuSubroutines.cpp | 25 +--- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 119 ++++++++++++------ Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h | 1 + 3 files changed, 81 insertions(+), 64 deletions(-) diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index 76d5848336..8e1c6945c1 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -291,18 +291,7 @@ void Wiimote::HandleWriteData(const OutputReportWriteData& wd) else { std::copy_n(wd.data, wd.size, m_eeprom.data.data() + address); - - // Write mii data to file - if (address >= 0x0FCA && address < 0x12C0) - { - // TODO: Only write parts of the Mii block. - // TODO: Use different files for different wiimote numbers. - std::ofstream file; - File::OpenFStream(file, File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/mii.bin", - std::ios::binary | std::ios::out); - file.write((char*)m_eeprom.data.data() + 0x0FCA, 0x02f0); - file.close(); - } + m_eeprom_dirty = true; } } break; @@ -486,18 +475,6 @@ bool Wiimote::ProcessReadDataRequest() } else { - // Mii block handling: - // TODO: different filename for each wiimote? - if (m_read_request.address >= 0x0FCA && m_read_request.address < 0x12C0) - { - // TODO: Only read the Mii block parts required - std::ifstream file; - File::OpenFStream(file, (File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/mii.bin").c_str(), - std::ios::binary | std::ios::in); - file.read((char*)m_eeprom.data.data() + 0x0FCA, 0x02f0); - file.close(); - } - // Read memory to be sent to Wii std::copy_n(m_eeprom.data.data() + m_read_request.address, bytes_to_read, reply.data); reply.size_minus_one = bytes_to_read - 1; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index fcfbdb71c3..9c7e12e485 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -12,6 +12,7 @@ #include "Common/CommonTypes.h" #include "Common/Config/Config.h" +#include "Common/FileUtil.h" #include "Common/Logging/Log.h" #include "Common/MathUtil.h" #include "Common/MsgHandler.h" @@ -77,50 +78,86 @@ void Wiimote::Reset() m_speaker_mute = false; // EEPROM + std::string eeprom_file = (File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/" + GetName() + ".bin"); + if (m_eeprom_dirty) + { + // Write out existing EEPROM + INFO_LOG(WIIMOTE, "Wrote EEPROM for %s", GetName().c_str()); + std::ofstream file; + File::OpenFStream(file, eeprom_file, std::ios::binary | std::ios::out); + file.write(reinterpret_cast(m_eeprom.data.data()), EEPROM_FREE_SIZE); + file.close(); + + m_eeprom_dirty = false; + } m_eeprom = {}; - // IR calibration: - std::array ir_calibration = { - // Point 1 - IR_LOW_X & 0xFF, - IR_LOW_Y & 0xFF, - // Mix - ((IR_LOW_Y & 0x300) >> 2) | ((IR_LOW_X & 0x300) >> 4) | ((IR_LOW_Y & 0x300) >> 6) | - ((IR_HIGH_X & 0x300) >> 8), - // Point 2 - IR_HIGH_X & 0xFF, - IR_LOW_Y & 0xFF, - // Point 3 - IR_HIGH_X & 0xFF, - IR_HIGH_Y & 0xFF, - // Mix - ((IR_HIGH_Y & 0x300) >> 2) | ((IR_HIGH_X & 0x300) >> 4) | ((IR_HIGH_Y & 0x300) >> 6) | - ((IR_LOW_X & 0x300) >> 8), - // Point 4 - IR_LOW_X & 0xFF, - IR_HIGH_Y & 0xFF, - // Checksum - 0x00, - }; - UpdateCalibrationDataChecksum(ir_calibration, 1); - m_eeprom.ir_calibration_1 = ir_calibration; - m_eeprom.ir_calibration_2 = ir_calibration; + if (File::Exists(eeprom_file)) + { + // Read existing EEPROM + std::ifstream file; + File::OpenFStream(file, eeprom_file, std::ios::binary | std::ios::in); + file.read(reinterpret_cast(m_eeprom.data.data()), EEPROM_FREE_SIZE); + file.close(); + } + else + { + // Load some default data. - // Accel calibration: - // Last byte is a checksum. - std::array accel_calibration = { - ACCEL_ZERO_G, ACCEL_ZERO_G, ACCEL_ZERO_G, 0, ACCEL_ONE_G, ACCEL_ONE_G, ACCEL_ONE_G, 0, 0, 0, - }; - UpdateCalibrationDataChecksum(accel_calibration, 1); - m_eeprom.accel_calibration_1 = accel_calibration; - m_eeprom.accel_calibration_2 = accel_calibration; + // IR calibration: + std::array ir_calibration = { + // Point 1 + IR_LOW_X & 0xFF, + IR_LOW_Y & 0xFF, + // Mix + ((IR_LOW_Y & 0x300) >> 2) | ((IR_LOW_X & 0x300) >> 4) | ((IR_LOW_Y & 0x300) >> 6) | + ((IR_HIGH_X & 0x300) >> 8), + // Point 2 + IR_HIGH_X & 0xFF, + IR_LOW_Y & 0xFF, + // Point 3 + IR_HIGH_X & 0xFF, + IR_HIGH_Y & 0xFF, + // Mix + ((IR_HIGH_Y & 0x300) >> 2) | ((IR_HIGH_X & 0x300) >> 4) | ((IR_HIGH_Y & 0x300) >> 6) | + ((IR_LOW_X & 0x300) >> 8), + // Point 4 + IR_LOW_X & 0xFF, + IR_HIGH_Y & 0xFF, + // Checksum + 0x00, + }; + UpdateCalibrationDataChecksum(ir_calibration, 1); + m_eeprom.ir_calibration_1 = ir_calibration; + m_eeprom.ir_calibration_2 = ir_calibration; - // TODO: Is this needed? - // Data of unknown purpose: - constexpr std::array EEPROM_DATA_16D0 = {0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00, - 0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99, - 0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13}; - m_eeprom.unk_2 = EEPROM_DATA_16D0; + // Accel calibration: + // Last byte is a checksum. + std::array accel_calibration = { + ACCEL_ZERO_G, ACCEL_ZERO_G, ACCEL_ZERO_G, 0, ACCEL_ONE_G, ACCEL_ONE_G, ACCEL_ONE_G, 0, 0, 0, + }; + UpdateCalibrationDataChecksum(accel_calibration, 1); + m_eeprom.accel_calibration_1 = accel_calibration; + m_eeprom.accel_calibration_2 = accel_calibration; + + // TODO: Is this needed? + // Data of unknown purpose: + constexpr std::array EEPROM_DATA_16D0 = { + 0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00, 0x33, 0xCC, 0x44, 0xBB, + 0x00, 0x00, 0x66, 0x99, 0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13}; + m_eeprom.unk_2 = EEPROM_DATA_16D0; + + std::string mii_file = File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/mii.bin"; + if (File::Exists(mii_file)) + { + // Import from the existing mii.bin file, if present + std::ifstream file; + File::OpenFStream(file, mii_file, std::ios::binary | std::ios::in); + file.read(reinterpret_cast(m_eeprom.mii_data_1.data()), m_eeprom.mii_data_1.size()); + m_eeprom.mii_data_2 = m_eeprom.mii_data_1; + file.close(); + } + } m_read_request = {}; @@ -245,6 +282,8 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index) std::string Wiimote::GetName() const { + if (m_index == WIIMOTE_BALANCE_BOARD) + return "BalanceBoard"; return fmt::format("Wiimote{}", 1 + m_index); } diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index 0f627e619e..1f13d29d2e 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -291,6 +291,7 @@ private: bool m_is_motion_plus_attached; + bool m_eeprom_dirty = false; ReadRequest m_read_request; UsableEEPROMData m_eeprom; From a23609562dde3fba5d39406d5eb2c2e470a8866d Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 10 Nov 2019 12:55:29 -0800 Subject: [PATCH 2/3] Replace magic disconnect channel number with a constant --- Source/Core/Core/HW/Wiimote.h | 2 ++ Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 2 +- Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp | 2 +- Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/HW/Wiimote.h b/Source/Core/Core/HW/Wiimote.h index 0d23637563..10c953484e 100644 --- a/Source/Core/Core/HW/Wiimote.h +++ b/Source/Core/Core/HW/Wiimote.h @@ -63,6 +63,8 @@ enum class InitializeMode // The Real Wii Remote sends report every ~5ms (200 Hz). constexpr int UPDATE_FREQ = 200; +// Custom channel ID used in ControlChannel to indicate disconnects +constexpr int DOLPHIN_DISCONNET_CONTROL_CHANNEL = 99; void Shutdown(); void Initialize(InitializeMode init_mode); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index 9c7e12e485..5ffc8aaf98 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -572,7 +572,7 @@ void Wiimote::SendDataReport() void Wiimote::ControlChannel(const u16 channel_id, const void* data, u32 size) { // Check for custom communication - if (99 == channel_id) + if (channel_id == ::Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL) { // Wii Remote disconnected. Reset(); diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index a23752b792..09806a3808 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -143,7 +143,7 @@ void Wiimote::ClearReadQueue() void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size) { // Check for custom communication - if (channel == 99) + if (channel == ::Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL) { if (m_really_disconnect) { diff --git a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp index c35d094061..509347088c 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp @@ -218,7 +218,8 @@ void WiimoteDevice::EventConnectionAccepted() void WiimoteDevice::EventDisconnect() { // Send disconnect message to plugin - Wiimote::ControlChannel(m_connection_handle & 0xFF, 99, nullptr, 0); + Wiimote::ControlChannel(m_connection_handle & 0xFF, Wiimote::DOLPHIN_DISCONNET_CONTROL_CHANNEL, + nullptr, 0); m_connection_state = ConnectionState::Inactive; From 4d4a095c76501799767f70120fe86238f3fe8fb4 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 11 Nov 2019 18:05:53 -0800 Subject: [PATCH 3/3] Reset Wiimotes on force stop and when starting MIOS --- Source/Core/Core/Core.cpp | 1 + Source/Core/Core/IOS/MIOS.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 89259a0785..32a3919d35 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -290,6 +290,7 @@ void Stop() // - Hammertime! g_video_backend->Video_ExitLoop(); } + Wiimote::ResetAllWiimotes(); ResetRumble(); #ifdef USE_MEMORYWATCHER diff --git a/Source/Core/Core/IOS/MIOS.cpp b/Source/Core/Core/IOS/MIOS.cpp index c94c2ee957..d7de03d494 100644 --- a/Source/Core/Core/IOS/MIOS.cpp +++ b/Source/Core/Core/IOS/MIOS.cpp @@ -20,6 +20,7 @@ #include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/Memmap.h" #include "Core/HW/SystemTimers.h" +#include "Core/HW/Wiimote.h" #include "Core/Host.h" #include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PowerPC.h" @@ -35,6 +36,7 @@ static void ReinitHardware() // MIOS appears to only reset the DI and the PPC. DVDInterface::Reset(); PowerPC::Reset(); + Wiimote::ResetAllWiimotes(); // Note: this is specific to Dolphin and is required because we initialised it in Wii mode. DSP::Reinit(SConfig::GetInstance().bDSPHLE); DSP::GetDSPEmulator()->Initialize(SConfig::GetInstance().bWii, SConfig::GetInstance().bDSPThread);