Skip to content
Permalink
Browse files

WiimoteEmu: Unbreak wiimote extensions.

  • Loading branch information...
jordan-woyak committed Nov 23, 2018
1 parent ebc2e58 commit 62b66580c3c3031a189607e5b1d57fdbd02659be
@@ -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
@@ -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<wm_buttons*>(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<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
if (false == m_reporting_auto && data[1] >= RT_REPORT_CORE)
@@ -8,11 +8,11 @@
#include <queue>
#include <string>

#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<u8, 0x10>& data);

void EmulateShake(AccelData* accel, ControllerEmu::Buttons* buttons_group, double intensity,
@@ -244,20 +245,11 @@ class I2CSlave
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 @@ class Wiimote : public ControllerEmu::EmulatedController
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 @@ class Wiimote : public ControllerEmu::EmulatedController

} 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
{
// u16 channel;
@@ -445,8 +470,6 @@ class Wiimote : public ControllerEmu::EmulatedController
// maybe read requests cancel any current requests
std::queue<ReadRequest> m_read_requests;

wiimote_key m_ext_key;

#pragma pack(push, 1)
u8 m_eeprom[WIIMOTE_EEPROM_SIZE];
struct MotionPlusReg
@@ -462,8 +485,6 @@ class Wiimote : public ControllerEmu::EmulatedController
u8 ext_identifier[6];
} m_reg_motion_plus;

ExtensionReg m_reg_ext;

struct SpeakerReg
{
u8 unused_0;

0 comments on commit 62b6658

Please sign in to comment.
You can’t perform that action at this time.