From 62b66580c3c3031a189607e5b1d57fdbd02659be Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 22 Nov 2018 19:12:42 -0600 Subject: [PATCH] WiimoteEmu: Unbreak wiimote extensions. --- .../Core/HW/WiimoteEmu/EmuSubroutines.cpp | 29 +-------- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 46 ++++++------- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h | 65 ++++++++++++------- 3 files changed, 69 insertions(+), 71 deletions(-) diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index eb532fb064..bec9920b00 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -266,15 +266,7 @@ void Wiimote::WriteData(const wm_write_data* const wd) return; - // TODO: extension register stuff.. - //if (false)//&m_reg_ext == region_ptr) - //{ - // // Run the key generation on all writes in the key area, it doesn't matter - // // that we send it parts of a key, only the last full key will have an effect - // if (address >= 0xa40040 && address <= 0xa4004c) - // WiimoteGenerateKey(&m_ext_key, m_reg_ext.encryption_key); - //} //else if (&m_reg_motion_plus == region_ptr) //{ // // activate/deactivate motion plus @@ -345,25 +337,8 @@ void Wiimote::ReadData(const wm_read_data* const rd) { // Read from Control Register - // ignore second byte for extension area - if (0xA4 == (address >> 16)) - address &= 0xFF00FF; - - const u8 region_offset = (u8)address; - void* region_ptr = nullptr; - //int region_size = 0; - m_i2c_bus.BusRead(address >> 17, address & 0xff, rd->size, block); - // TODO: generate read errors - - if (&m_reg_ext == region_ptr) - { - // Encrypt data read from extension register - // Check if encrypted reads is on - if (0xaa == m_reg_ext.encryption) - WiimoteEncrypt(&m_ext_key, block, address & 0xffff, (u8)size); - } } break; @@ -458,11 +433,11 @@ void Wiimote::DoState(PointerWrap& p) p.Do(m_sensor_bar_on_top); p.Do(m_status); p.Do(m_adpcm_state); - p.Do(m_ext_key); + p.Do(m_ext_logic.ext_key); p.DoArray(m_eeprom); p.Do(m_reg_motion_plus); p.Do(m_camera_logic.reg_data); - p.Do(m_reg_ext); + p.Do(m_ext_logic.reg_data); p.Do(m_reg_speaker); // Do 'm_read_requests' queue diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index bddd03de3c..93c985b300 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -329,9 +329,11 @@ void Wiimote::Reset() // set up the register memset(&m_reg_speaker, 0, sizeof(m_reg_speaker)); - // TODO: kill/move this + + // TODO: kill/move these memset(&m_camera_logic.reg_data, 0, sizeof(m_camera_logic.reg_data)); - memset(&m_reg_ext, 0, sizeof(m_reg_ext)); + memset(&m_ext_logic.reg_data, 0, sizeof(m_ext_logic.reg_data)); + memset(&m_reg_motion_plus, 0, sizeof(m_reg_motion_plus)); memcpy(&m_reg_motion_plus.ext_identifier, motion_plus_id, sizeof(motion_plus_id)); @@ -363,7 +365,10 @@ void Wiimote::Reset() m_adpcm_state.step = 127; // Initialize i2c bus + // TODO: kill magic numbers + m_i2c_bus.Reset(); m_i2c_bus.AddSlave(0x58, &m_camera_logic); + m_i2c_bus.AddSlave(0x52, &m_ext_logic); } Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1) @@ -421,12 +426,12 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1 // extension groups.emplace_back(m_extension = new ControllerEmu::Extension(_trans("Extension"))); - m_extension->attachments.emplace_back(new WiimoteEmu::None(m_reg_ext)); - m_extension->attachments.emplace_back(new WiimoteEmu::Nunchuk(m_reg_ext)); - m_extension->attachments.emplace_back(new WiimoteEmu::Classic(m_reg_ext)); - m_extension->attachments.emplace_back(new WiimoteEmu::Guitar(m_reg_ext)); - m_extension->attachments.emplace_back(new WiimoteEmu::Drums(m_reg_ext)); - m_extension->attachments.emplace_back(new WiimoteEmu::Turntable(m_reg_ext)); + m_extension->attachments.emplace_back(new WiimoteEmu::None(m_ext_logic.reg_data)); + m_extension->attachments.emplace_back(new WiimoteEmu::Nunchuk(m_ext_logic.reg_data)); + m_extension->attachments.emplace_back(new WiimoteEmu::Classic(m_ext_logic.reg_data)); + m_extension->attachments.emplace_back(new WiimoteEmu::Guitar(m_ext_logic.reg_data)); + m_extension->attachments.emplace_back(new WiimoteEmu::Drums(m_ext_logic.reg_data)); + m_extension->attachments.emplace_back(new WiimoteEmu::Turntable(m_ext_logic.reg_data)); // rumble groups.emplace_back(m_rumble = new ControllerEmu::ControlGroup(_trans("Rumble"))); @@ -835,17 +840,10 @@ void Wiimote::UpdateIRData(bool use_accel) } } -void Wiimote::GetExtData(u8* const data) +void Wiimote::UpdateExtData() { - m_extension->GetState(data); - - // i dont think anything accesses the extension data like this, but ill support it. Indeed, - // commercial games don't do this. - // i think it should be unencrpyted in the register, encrypted when read. - memcpy(m_reg_ext.controller_data, data, sizeof(wm_nc)); // TODO: Should it be nc specific? - - if (0xAA == m_reg_ext.encryption) - WiimoteEncrypt(&m_ext_key, data, 0x00, sizeof(wm_nc)); + // Write extension data to addr 0x00 of extension register + m_extension->GetState(m_ext_logic.reg_data.controller_data); } void Wiimote::Update() @@ -871,7 +869,7 @@ void Wiimote::Update() const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - RT_REPORT_CORE]; s8 rptf_size = rptf.size; if (Movie::IsPlayingInput() && - Movie::PlayWiimote(m_index, data, rptf, m_extension->active_extension, m_ext_key)) + Movie::PlayWiimote(m_index, data, rptf, m_extension->active_extension, m_ext_logic.ext_key)) { if (rptf.core) m_status.buttons = *reinterpret_cast(data + rptf.core); @@ -910,18 +908,21 @@ void Wiimote::Update() UpdateIRData(rptf.accel != 0); if (rptf.ir) { + // TODO: kill magic numbers m_i2c_bus.BusRead(0x58, 0x37, rptf.ir, feature_ptr); feature_ptr += rptf.ir; } // extension + UpdateExtData(); if (rptf.ext) { - // GetExtData(feature_ptr, rptf.ext); + // TODO: kill magic numbers + m_i2c_bus.BusRead(0x52, 0x00, rptf.ext, feature_ptr); feature_ptr += rptf.ext; } - Movie::CallWiiInputManip(data, rptf, m_index, m_extension->active_extension, m_ext_key); + Movie::CallWiiInputManip(data, rptf, m_index, m_extension->active_extension, m_ext_logic.ext_key); } if (NetPlay::IsNetPlayRunning()) { @@ -930,7 +931,8 @@ void Wiimote::Update() m_status.buttons = *reinterpret_cast(data + rptf.core); } - Movie::CheckWiimoteStatus(m_index, data, rptf, m_extension->active_extension, m_ext_key); + // TODO: need to fix usage of rptf probably + Movie::CheckWiimoteStatus(m_index, data, rptf, m_extension->active_extension, m_ext_logic.ext_key); // don't send a data report if auto reporting is off if (false == m_reporting_auto && data[1] >= RT_REPORT_CORE) diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index 8bf75d2712..622b6857aa 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -8,11 +8,11 @@ #include #include +#include "Common/Logging/Log.h" #include "Core/HW/WiimoteCommon/WiimoteHid.h" #include "Core/HW/WiimoteCommon/WiimoteReport.h" #include "Core/HW/WiimoteEmu/Encryption.h" #include "InputCommon/ControllerEmu/ControllerEmu.h" -#include "Common/Logging/Log.h" // Registry sizes #define WIIMOTE_EEPROM_SIZE (16 * 1024) @@ -159,11 +159,10 @@ struct ADPCMState struct ExtensionReg { - u8 unknown1[0x08]; + // 16 bytes of possible extension data + u8 controller_data[0x10]; - // address 0x08 - u8 controller_data[0x06]; - u8 unknown2[0x12]; + u8 unknown2[0x10]; // address 0x20 u8 calibration[0x10]; @@ -182,6 +181,8 @@ struct ExtensionReg }; #pragma pack(pop) +static_assert(0x100 == sizeof(ExtensionReg)); + void UpdateCalibrationDataChecksum(std::array& data); void EmulateShake(AccelData* accel, ControllerEmu::Buttons* buttons_group, double intensity, @@ -244,20 +245,11 @@ public: class I2CBus { public: - void AddSlave(u8 addr, I2CSlave* slave) - { - m_slaves.insert(std::make_pair(addr, slave)); - } + void AddSlave(u8 addr, I2CSlave* slave) { m_slaves.insert(std::make_pair(addr, slave)); } - void RemoveSlave(u8 addr) - { - m_slaves.erase(addr); - } + void RemoveSlave(u8 addr) { m_slaves.erase(addr); } - void Reset() - { - m_slaves.clear(); - } + void Reset() { m_slaves.clear(); } int BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) { @@ -338,7 +330,7 @@ protected: void GetButtonData(u8* data); void GetAccelData(u8* data); void UpdateIRData(bool use_accel); - void GetExtData(u8* data); + void UpdateExtData(); bool HaveExtension() const; bool WantExtension() const; @@ -371,6 +363,39 @@ private: } m_camera_logic; + struct ExtensionLogic : public I2CSlave + { + ExtensionReg reg_data; + wiimote_key ext_key; + + int BusRead(u8 addr, int count, u8* data_out) override + { + auto const result = raw_read(®_data, addr, count, data_out); + + // Encrypt data read from extension register + // Check if encrypted reads is on + if (0xaa == reg_data.encryption) + WiimoteEncrypt(&ext_key, data_out, addr, (u8)count); + + return result; + } + + int BusWrite(u8 addr, int count, const u8* data_in) override + { + auto const result = raw_write(®_data, addr, count, data_in); + + if (addr + count > 0x40 && addr < 0x50) + { + // Run the key generation on all writes in the key area, it doesn't matter + // that we send it parts of a key, only the last full key will have an effect + WiimoteGenerateKey(&ext_key, reg_data.encryption_key); + } + + return result; + } + + } m_ext_logic; + struct ReadRequest { // u16 channel; @@ -445,8 +470,6 @@ private: // maybe read requests cancel any current requests std::queue m_read_requests; - wiimote_key m_ext_key; - #pragma pack(push, 1) u8 m_eeprom[WIIMOTE_EEPROM_SIZE]; struct MotionPlusReg @@ -462,8 +485,6 @@ private: u8 ext_identifier[6]; } m_reg_motion_plus; - ExtensionReg m_reg_ext; - struct SpeakerReg { u8 unused_0;