mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 07:09:48 -06:00
WiimoteEmu: Unbreak wiimote extensions.
This commit is contained in:
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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(®_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
|
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;
|
||||||
|
Reference in New Issue
Block a user