WiimoteEmu: Unbreak wiimote extensions.

This commit is contained in:
Jordan Woyak
2018-11-22 19:12:42 -06:00
parent ebc2e58fa4
commit 62b66580c3
3 changed files with 69 additions and 71 deletions

View File

@ -266,15 +266,7 @@ void Wiimote::WriteData(const wm_write_data* const wd)
return; 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) //else if (&m_reg_motion_plus == region_ptr)
//{ //{
// // activate/deactivate motion plus // // activate/deactivate motion plus
@ -345,25 +337,8 @@ void Wiimote::ReadData(const wm_read_data* const rd)
{ {
// Read from Control Register // 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); m_i2c_bus.BusRead(address >> 17, address & 0xff, rd->size, block);
// TODO: generate read errors // 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; break;
@ -458,11 +433,11 @@ void Wiimote::DoState(PointerWrap& p)
p.Do(m_sensor_bar_on_top); p.Do(m_sensor_bar_on_top);
p.Do(m_status); p.Do(m_status);
p.Do(m_adpcm_state); p.Do(m_adpcm_state);
p.Do(m_ext_key); p.Do(m_ext_logic.ext_key);
p.DoArray(m_eeprom); p.DoArray(m_eeprom);
p.Do(m_reg_motion_plus); p.Do(m_reg_motion_plus);
p.Do(m_camera_logic.reg_data); p.Do(m_camera_logic.reg_data);
p.Do(m_reg_ext); p.Do(m_ext_logic.reg_data);
p.Do(m_reg_speaker); p.Do(m_reg_speaker);
// Do 'm_read_requests' queue // Do 'm_read_requests' queue

View File

@ -329,9 +329,11 @@ void Wiimote::Reset()
// set up the register // set up the register
memset(&m_reg_speaker, 0, sizeof(m_reg_speaker)); 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_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)); 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)); 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; m_adpcm_state.step = 127;
// Initialize i2c bus // Initialize i2c bus
// TODO: kill magic numbers
m_i2c_bus.Reset();
m_i2c_bus.AddSlave(0x58, &m_camera_logic); 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) 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 // extension
groups.emplace_back(m_extension = new ControllerEmu::Extension(_trans("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::None(m_ext_logic.reg_data));
m_extension->attachments.emplace_back(new WiimoteEmu::Nunchuk(m_reg_ext)); m_extension->attachments.emplace_back(new WiimoteEmu::Nunchuk(m_ext_logic.reg_data));
m_extension->attachments.emplace_back(new WiimoteEmu::Classic(m_reg_ext)); m_extension->attachments.emplace_back(new WiimoteEmu::Classic(m_ext_logic.reg_data));
m_extension->attachments.emplace_back(new WiimoteEmu::Guitar(m_reg_ext)); m_extension->attachments.emplace_back(new WiimoteEmu::Guitar(m_ext_logic.reg_data));
m_extension->attachments.emplace_back(new WiimoteEmu::Drums(m_reg_ext)); m_extension->attachments.emplace_back(new WiimoteEmu::Drums(m_ext_logic.reg_data));
m_extension->attachments.emplace_back(new WiimoteEmu::Turntable(m_reg_ext)); m_extension->attachments.emplace_back(new WiimoteEmu::Turntable(m_ext_logic.reg_data));
// rumble // rumble
groups.emplace_back(m_rumble = new ControllerEmu::ControlGroup(_trans("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); // Write extension data to addr 0x00 of extension register
m_extension->GetState(m_ext_logic.reg_data.controller_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));
} }
void Wiimote::Update() void Wiimote::Update()
@ -871,7 +869,7 @@ void Wiimote::Update()
const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - RT_REPORT_CORE]; const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - RT_REPORT_CORE];
s8 rptf_size = rptf.size; s8 rptf_size = rptf.size;
if (Movie::IsPlayingInput() && 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) if (rptf.core)
m_status.buttons = *reinterpret_cast<wm_buttons*>(data + rptf.core); m_status.buttons = *reinterpret_cast<wm_buttons*>(data + rptf.core);
@ -910,18 +908,21 @@ void Wiimote::Update()
UpdateIRData(rptf.accel != 0); UpdateIRData(rptf.accel != 0);
if (rptf.ir) if (rptf.ir)
{ {
// TODO: kill magic numbers
m_i2c_bus.BusRead(0x58, 0x37, rptf.ir, feature_ptr); m_i2c_bus.BusRead(0x58, 0x37, rptf.ir, feature_ptr);
feature_ptr += rptf.ir; feature_ptr += rptf.ir;
} }
// extension // extension
UpdateExtData();
if (rptf.ext) 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; 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()) if (NetPlay::IsNetPlayRunning())
{ {
@ -930,7 +931,8 @@ void Wiimote::Update()
m_status.buttons = *reinterpret_cast<wm_buttons*>(data + rptf.core); m_status.buttons = *reinterpret_cast<wm_buttons*>(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 // don't send a data report if auto reporting is off
if (false == m_reporting_auto && data[1] >= RT_REPORT_CORE) if (false == m_reporting_auto && data[1] >= RT_REPORT_CORE)

View File

@ -8,11 +8,11 @@
#include <queue> #include <queue>
#include <string> #include <string>
#include "Common/Logging/Log.h"
#include "Core/HW/WiimoteCommon/WiimoteHid.h" #include "Core/HW/WiimoteCommon/WiimoteHid.h"
#include "Core/HW/WiimoteCommon/WiimoteReport.h" #include "Core/HW/WiimoteCommon/WiimoteReport.h"
#include "Core/HW/WiimoteEmu/Encryption.h" #include "Core/HW/WiimoteEmu/Encryption.h"
#include "InputCommon/ControllerEmu/ControllerEmu.h" #include "InputCommon/ControllerEmu/ControllerEmu.h"
#include "Common/Logging/Log.h"
// Registry sizes // Registry sizes
#define WIIMOTE_EEPROM_SIZE (16 * 1024) #define WIIMOTE_EEPROM_SIZE (16 * 1024)
@ -159,11 +159,10 @@ struct ADPCMState
struct ExtensionReg struct ExtensionReg
{ {
u8 unknown1[0x08]; // 16 bytes of possible extension data
u8 controller_data[0x10];
// address 0x08 u8 unknown2[0x10];
u8 controller_data[0x06];
u8 unknown2[0x12];
// address 0x20 // address 0x20
u8 calibration[0x10]; u8 calibration[0x10];
@ -182,6 +181,8 @@ struct ExtensionReg
}; };
#pragma pack(pop) #pragma pack(pop)
static_assert(0x100 == sizeof(ExtensionReg));
void UpdateCalibrationDataChecksum(std::array<u8, 0x10>& data); void UpdateCalibrationDataChecksum(std::array<u8, 0x10>& data);
void EmulateShake(AccelData* accel, ControllerEmu::Buttons* buttons_group, double intensity, void EmulateShake(AccelData* accel, ControllerEmu::Buttons* buttons_group, double intensity,
@ -244,20 +245,11 @@ public:
class I2CBus class I2CBus
{ {
public: public:
void AddSlave(u8 addr, I2CSlave* slave) void AddSlave(u8 addr, I2CSlave* slave) { m_slaves.insert(std::make_pair(addr, slave)); }
{
m_slaves.insert(std::make_pair(addr, slave));
}
void RemoveSlave(u8 addr) void RemoveSlave(u8 addr) { m_slaves.erase(addr); }
{
m_slaves.erase(addr);
}
void Reset() void Reset() { m_slaves.clear(); }
{
m_slaves.clear();
}
int BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) int BusRead(u8 slave_addr, u8 addr, int count, u8* data_out)
{ {
@ -338,7 +330,7 @@ protected:
void GetButtonData(u8* data); void GetButtonData(u8* data);
void GetAccelData(u8* data); void GetAccelData(u8* data);
void UpdateIRData(bool use_accel); void UpdateIRData(bool use_accel);
void GetExtData(u8* data); void UpdateExtData();
bool HaveExtension() const; bool HaveExtension() const;
bool WantExtension() const; bool WantExtension() const;
@ -371,6 +363,39 @@ private:
} m_camera_logic; } 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(&reg_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(&reg_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 struct ReadRequest
{ {
// u16 channel; // u16 channel;
@ -445,8 +470,6 @@ private:
// maybe read requests cancel any current requests // maybe read requests cancel any current requests
std::queue<ReadRequest> m_read_requests; std::queue<ReadRequest> m_read_requests;
wiimote_key m_ext_key;
#pragma pack(push, 1) #pragma pack(push, 1)
u8 m_eeprom[WIIMOTE_EEPROM_SIZE]; u8 m_eeprom[WIIMOTE_EEPROM_SIZE];
struct MotionPlusReg struct MotionPlusReg
@ -462,8 +485,6 @@ private:
u8 ext_identifier[6]; u8 ext_identifier[6];
} m_reg_motion_plus; } m_reg_motion_plus;
ExtensionReg m_reg_ext;
struct SpeakerReg struct SpeakerReg
{ {
u8 unused_0; u8 unused_0;