WiimoteEmu: Cleanups, Kill more magic numbers and use some enum classes.
This commit is contained in:
parent
86c94b8b22
commit
3a889c35ad
|
@ -41,17 +41,20 @@ enum WiimoteLED
|
||||||
LED_4 = 0x80
|
LED_4 = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
enum WiimoteSpace
|
enum class WiimoteAddressSpace : u8
|
||||||
{
|
{
|
||||||
WS_EEPROM = 0x00,
|
EEPROM = 0x00,
|
||||||
WS_REGS1 = 0x01,
|
// 0x01 is never used but it does function on a real wiimote:
|
||||||
WS_REGS2 = 0x02
|
I2C_BUS_ALT = 0x01,
|
||||||
|
I2C_BUS = 0x02,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum WiimoteReadError
|
enum class WiimoteErrorCode : u8
|
||||||
{
|
{
|
||||||
RDERR_WOREG = 7,
|
SUCCESS = 0,
|
||||||
RDERR_NOMEM = 8
|
NACK = 7,
|
||||||
|
// TODO: Can there be a better name for this?
|
||||||
|
INVALID = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr u8 MAX_PAYLOAD = 23;
|
constexpr u8 MAX_PAYLOAD = 23;
|
||||||
|
|
|
@ -427,7 +427,7 @@ static_assert(sizeof(wm_status_report) == 6, "Wrong size");
|
||||||
struct wm_write_data
|
struct wm_write_data
|
||||||
{
|
{
|
||||||
u8 rumble : 1;
|
u8 rumble : 1;
|
||||||
u8 space : 2; // see WM_SPACE_*
|
u8 space : 2;
|
||||||
u8 : 5;
|
u8 : 5;
|
||||||
// A real wiimote ignores the i2c read/write bit.
|
// A real wiimote ignores the i2c read/write bit.
|
||||||
u8 i2c_rw_ignored : 1;
|
u8 i2c_rw_ignored : 1;
|
||||||
|
@ -451,7 +451,7 @@ static_assert(sizeof(wm_acknowledge) == 4, "Wrong size");
|
||||||
struct wm_read_data
|
struct wm_read_data
|
||||||
{
|
{
|
||||||
u8 rumble : 1;
|
u8 rumble : 1;
|
||||||
u8 space : 2; // see WM_SPACE_*
|
u8 space : 2;
|
||||||
u8 : 5;
|
u8 : 5;
|
||||||
// A real wiimote ignores the i2c read/write bit.
|
// A real wiimote ignores the i2c read/write bit.
|
||||||
u8 i2c_rw_ignored : 1;
|
u8 i2c_rw_ignored : 1;
|
||||||
|
@ -466,7 +466,7 @@ static_assert(sizeof(wm_read_data) == 6, "Wrong size");
|
||||||
struct wm_read_data_reply
|
struct wm_read_data_reply
|
||||||
{
|
{
|
||||||
wm_buttons buttons;
|
wm_buttons buttons;
|
||||||
u8 error : 4; // see WM_RDERR_*
|
u8 error : 4;
|
||||||
u8 size_minus_one : 4;
|
u8 size_minus_one : 4;
|
||||||
// big endian:
|
// big endian:
|
||||||
u16 address;
|
u16 address;
|
||||||
|
|
|
@ -170,7 +170,7 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack)
|
||||||
The first two bytes are the core buttons data,
|
The first two bytes are the core buttons data,
|
||||||
00 00 means nothing is pressed.
|
00 00 means nothing is pressed.
|
||||||
The last byte is the success code 00. */
|
The last byte is the success code 00. */
|
||||||
void Wiimote::SendAck(u8 report_id, u8 error_code)
|
void Wiimote::SendAck(u8 report_id, WiimoteErrorCode error_code)
|
||||||
{
|
{
|
||||||
TypedHidPacket<wm_acknowledge> rpt;
|
TypedHidPacket<wm_acknowledge> rpt;
|
||||||
rpt.type = HID_TYPE_DATA;
|
rpt.type = HID_TYPE_DATA;
|
||||||
|
@ -181,7 +181,7 @@ void Wiimote::SendAck(u8 report_id, u8 error_code)
|
||||||
|
|
||||||
ack.buttons = m_status.buttons;
|
ack.buttons = m_status.buttons;
|
||||||
ack.reportID = report_id;
|
ack.reportID = report_id;
|
||||||
ack.errorID = error_code;
|
ack.errorID = static_cast<u8>(error_code);
|
||||||
|
|
||||||
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(),
|
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(),
|
||||||
rpt.GetSize());
|
rpt.GetSize());
|
||||||
|
@ -266,11 +266,11 @@ void Wiimote::WriteData(const wm_write_data* const wd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 error_code = 0;
|
WiimoteErrorCode error_code = WiimoteErrorCode::SUCCESS;
|
||||||
|
|
||||||
switch (wd->space)
|
switch (static_cast<WiimoteAddressSpace>(wd->space))
|
||||||
{
|
{
|
||||||
case WS_EEPROM:
|
case WiimoteAddressSpace::EEPROM:
|
||||||
{
|
{
|
||||||
// Write to EEPROM
|
// Write to EEPROM
|
||||||
|
|
||||||
|
@ -295,8 +295,8 @@ void Wiimote::WriteData(const wm_write_data* const wd)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WS_REGS1:
|
case WiimoteAddressSpace::I2C_BUS:
|
||||||
case WS_REGS2:
|
case WiimoteAddressSpace::I2C_BUS_ALT:
|
||||||
{
|
{
|
||||||
// Write to Control Register
|
// Write to Control Register
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ void Wiimote::WriteData(const wm_write_data* const wd)
|
||||||
if (bytes_written != wd->size)
|
if (bytes_written != wd->size)
|
||||||
{
|
{
|
||||||
// A real wiimote gives error 7 for failed write to i2c bus (mainly a non-existant slave)
|
// A real wiimote gives error 7 for failed write to i2c bus (mainly a non-existant slave)
|
||||||
error_code = 0x07;
|
error_code = WiimoteErrorCode::NACK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -330,7 +330,7 @@ void Wiimote::ReadData(const wm_read_data* const rd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the request and process it on the next "Update()" calls
|
// Save the request and process it on the next "Update()" calls
|
||||||
m_read_request.space = rd->space;
|
m_read_request.space = static_cast<WiimoteAddressSpace>(rd->space);
|
||||||
m_read_request.slave_address = rd->slave_address;
|
m_read_request.slave_address = rd->slave_address;
|
||||||
m_read_request.address = Common::swap16(rd->address);
|
m_read_request.address = Common::swap16(rd->address);
|
||||||
// A zero size request is just ignored, like on the real wiimote.
|
// A zero size request is just ignored, like on the real wiimote.
|
||||||
|
@ -362,20 +362,24 @@ bool Wiimote::ProcessReadDataRequest()
|
||||||
rpt.report_id = RT_READ_DATA_REPLY;
|
rpt.report_id = RT_READ_DATA_REPLY;
|
||||||
|
|
||||||
auto reply = &rpt.data;
|
auto reply = &rpt.data;
|
||||||
reply->error = 0;
|
|
||||||
reply->buttons = m_status.buttons;
|
reply->buttons = m_status.buttons;
|
||||||
reply->address = Common::swap16(m_read_request.address);
|
reply->address = Common::swap16(m_read_request.address);
|
||||||
|
|
||||||
|
// Pre-fill with zeros in case of read-error or read < 16-bytes:
|
||||||
|
std::fill(std::begin(reply->data), std::end(reply->data), 0x00);
|
||||||
|
|
||||||
|
WiimoteErrorCode error_code = WiimoteErrorCode::SUCCESS;
|
||||||
|
|
||||||
switch (m_read_request.space)
|
switch (m_read_request.space)
|
||||||
{
|
{
|
||||||
case WS_EEPROM:
|
case WiimoteAddressSpace::EEPROM:
|
||||||
{
|
{
|
||||||
// Read from EEPROM
|
// Read from EEPROM
|
||||||
if (m_read_request.address + m_read_request.size >= WIIMOTE_EEPROM_FREE_SIZE)
|
if (m_read_request.address + m_read_request.size >= WIIMOTE_EEPROM_FREE_SIZE)
|
||||||
{
|
{
|
||||||
if (m_read_request.address + m_read_request.size > WIIMOTE_EEPROM_SIZE)
|
if (m_read_request.address + m_read_request.size > WIIMOTE_EEPROM_SIZE)
|
||||||
{
|
{
|
||||||
PanicAlert("ReadData: address + size out of bounds");
|
ERROR_LOG(WIIMOTE, "ReadData: address + size out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a read error, even if the start of the block is readable a real wiimote just sends
|
// generate a read error, even if the start of the block is readable a real wiimote just sends
|
||||||
|
@ -386,8 +390,8 @@ bool Wiimote::ProcessReadDataRequest()
|
||||||
// read the calibration data at the beginning of Eeprom. I think this
|
// read the calibration data at the beginning of Eeprom. I think this
|
||||||
// error is supposed to occur when we try to read above the freely
|
// error is supposed to occur when we try to read above the freely
|
||||||
// usable space that ends at 0x16ff.
|
// usable space that ends at 0x16ff.
|
||||||
INFO_LOG(WIIMOTE, "Responding with read error 8.");
|
//INFO_LOG(WIIMOTE, "Responding with read error 8.");
|
||||||
reply->error = 0x08;
|
error_code = WiimoteErrorCode::INVALID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -410,8 +414,8 @@ bool Wiimote::ProcessReadDataRequest()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WS_REGS1:
|
case WiimoteAddressSpace::I2C_BUS:
|
||||||
case WS_REGS2:
|
case WiimoteAddressSpace::I2C_BUS_ALT:
|
||||||
{
|
{
|
||||||
// Read from Control Register
|
// Read from Control Register
|
||||||
|
|
||||||
|
@ -426,7 +430,7 @@ bool Wiimote::ProcessReadDataRequest()
|
||||||
// generate read error, 7 == no such slave (no ack)
|
// generate read error, 7 == no such slave (no ack)
|
||||||
INFO_LOG(WIIMOTE, "Responding with read error 7 @ 0x%x @ 0x%x (%d)",
|
INFO_LOG(WIIMOTE, "Responding with read error 7 @ 0x%x @ 0x%x (%d)",
|
||||||
m_read_request.slave_address, m_read_request.address, m_read_request.size);
|
m_read_request.slave_address, m_read_request.address, m_read_request.size);
|
||||||
reply->error = 0x07;
|
error_code = WiimoteErrorCode::NACK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -436,13 +440,12 @@ bool Wiimote::ProcessReadDataRequest()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reply->error)
|
if (WiimoteErrorCode::SUCCESS != error_code)
|
||||||
{
|
{
|
||||||
// Stop processing request on read error:
|
// Stop processing request on read error:
|
||||||
m_read_request.size = 0;
|
m_read_request.size = 0;
|
||||||
// TODO: what size does a real wiimote return on read error?
|
// Real wiimote seems to set size to max value on read errors:
|
||||||
// it's 10 minus one (9) for some reason??
|
reply->size_minus_one = 0xf;
|
||||||
// reply->size_minus_one = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -451,6 +454,8 @@ bool Wiimote::ProcessReadDataRequest()
|
||||||
m_read_request.size -= bytes_to_read;
|
m_read_request.size -= bytes_to_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reply->error = static_cast<u8>(error_code);
|
||||||
|
|
||||||
// Send the data
|
// Send the data
|
||||||
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(),
|
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(),
|
||||||
rpt.GetSize());
|
rpt.GetSize());
|
||||||
|
|
|
@ -341,31 +341,25 @@ void Wiimote::Reset()
|
||||||
memset(&m_motion_plus_logic.reg_data, 0x00, sizeof(m_motion_plus_logic.reg_data));
|
memset(&m_motion_plus_logic.reg_data, 0x00, sizeof(m_motion_plus_logic.reg_data));
|
||||||
memcpy(&m_motion_plus_logic.reg_data.ext_identifier, motion_plus_id, sizeof(motion_plus_id));
|
memcpy(&m_motion_plus_logic.reg_data.ext_identifier, motion_plus_id, sizeof(motion_plus_id));
|
||||||
|
|
||||||
// calibration hackery
|
// TODO: determine meaning of calibration data:
|
||||||
static const u8 c1[16] = {0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c,
|
static const u8 mplus_cdata[32] = {
|
||||||
0xcf, 0xf0, 0x31, 0xad, 0xc8, 0x0b, 0x5e, 0x39};
|
0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c, 0xcf, 0xf0, 0x31,
|
||||||
static const u8 c2[16] = {0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51, 0x33, 0x60,
|
0xad, 0xc8, 0x0b, 0x5e, 0x39, 0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51,
|
||||||
0xc9, 0xf5, 0x37, 0xc1, 0x2d, 0xe9, 0x15, 0x8d};
|
0x33, 0x60, 0xc9, 0xf5, 0x37, 0xc1, 0x2d, 0xe9, 0x15, 0x8d,
|
||||||
|
};
|
||||||
static const u8 mp_cert[64] = {
|
|
||||||
//0x50, 0xc3, 0x0c, 0xab, 0x16, 0x07, 0xf6, 0x89, 0x51, 0x93, 0xbe, 0xa5, 0xb2,
|
std::copy(std::begin(mplus_cdata), std::end(mplus_cdata),
|
||||||
//0xbb, 0xbb, 0x35, 0x49, 0x32, 0x04, 0xfd, 0x29, 0x1d, 0xc1, 0xb7, 0x5a, 0x7c,
|
m_motion_plus_logic.reg_data.calibration_data);
|
||||||
//0x85, 0xb9, 0x78, 0x14, 0xf4, 0xfe, 0x21, 0x30, 0xa2, 0x5f, 0xb2, 0xc2, 0x8b,
|
|
||||||
//0x72, 0x02, 0xf8, 0x60, 0xdf, 0x03, 0x30, 0xdc, 0xb6, 0x86, 0xa4, 0x41, 0xdd,
|
// TODO: determine the meaning behind this:
|
||||||
//0x49, 0x01, 0x7b, 0x2f, 0xb2, 0xc8, 0x5b, 0x12, 0x92, 0x47, 0xb8, 0x23
|
static const u8 mp_cert[64] = {
|
||||||
|
0x99, 0x1a, 0x07, 0x1b, 0x97, 0xf1, 0x11, 0x78, 0x0c, 0x42, 0x2b, 0x68, 0xdf,
|
||||||
//0xf0, 0x89, 0x3b, 0xf7, 0x1b, 0x6c, 0x92, 0x95, 0xa0, 0x05, 0xd4, 0x03, 0x82,
|
0x44, 0x38, 0x0d, 0x2b, 0x7e, 0xd6, 0x84, 0x84, 0x58, 0x65, 0xc9, 0xf2, 0x95,
|
||||||
//0x8e, 0xae, 0x73, 0x15, 0xc7, 0x95, 0xfb, 0xae, 0xee, 0xc0, 0x68, 0xbd, 0x49,
|
0xd9, 0xaf, 0xb6, 0xc4, 0x87, 0xd5, 0x18, 0xdb, 0x67, 0x3a, 0xc0, 0x71, 0xec,
|
||||||
//0xf5, 0x32, 0x48, 0x8d, 0x33, 0x00, 0x94, 0x32, 0xf5, 0xf1, 0x30, 0x66, 0x68,
|
0x3e, 0xf4, 0xe6, 0x7e, 0x35, 0xa3, 0x29, 0xf8, 0x1f, 0xc5, 0x7c, 0x3d, 0xb9,
|
||||||
//0x9e, 0xf3, 0xe5, 0xfa, 0x9b, 0xb6, 0xe3, 0x0b, 0xa8, 0x07, 0xd5, 0x25, 0x38,
|
0x56, 0x22, 0x95, 0x98, 0x8f, 0xfb, 0x66, 0x3e, 0x9a, 0xdd, 0xeb, 0x7e,
|
||||||
|
|
||||||
0x99, 0x1a, 0x07, 0x1b, 0x97, 0xf1, 0x11, 0x78, 0x0c, 0x42, 0x2b, 0x68, 0xdf, 0x44, 0x38, 0x0d,
|
|
||||||
0x2b, 0x7e, 0xd6, 0x84, 0x84, 0x58, 0x65, 0xc9, 0xf2, 0x95, 0xd9, 0xaf, 0xb6, 0xc4, 0x87, 0xd5,
|
|
||||||
0x18, 0xdb, 0x67, 0x3a, 0xc0, 0x71, 0xec, 0x3e, 0xf4, 0xe6, 0x7e, 0x35, 0xa3, 0x29, 0xf8, 0x1f,
|
|
||||||
0xc5, 0x7c, 0x3d, 0xb9, 0x56, 0x22, 0x95, 0x98, 0x8f, 0xfb, 0x66, 0x3e, 0x9a, 0xdd, 0xeb, 0x7e,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::copy(std::begin(c1), std::end(c1), m_motion_plus_logic.reg_data.calibration_data);
|
|
||||||
std::copy(std::begin(mp_cert), std::end(mp_cert), m_motion_plus_logic.reg_data.cert_data);
|
std::copy(std::begin(mp_cert), std::end(mp_cert), m_motion_plus_logic.reg_data.cert_data);
|
||||||
|
|
||||||
// status
|
// status
|
||||||
|
@ -795,11 +789,12 @@ void Wiimote::UpdateIRData(bool use_accel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IR data is read from offset 0x37 on real hardware
|
// IR data is read from offset 0x37 on real hardware
|
||||||
u8* const data = m_camera_logic.reg_data.camera_data;
|
auto& data = m_camera_logic.reg_data.camera_data;
|
||||||
// A maximum of 36 bytes.
|
// A maximum of 36 bytes:
|
||||||
std::fill_n(data, sizeof(wm_ir_full) * 4, 0xff);
|
std::fill(std::begin(data), std::end(data), 0xff);
|
||||||
|
|
||||||
// Fill report with valid data when full handshake was done
|
// Fill report with valid data when full handshake was done
|
||||||
|
// TODO: kill magic number:
|
||||||
if (m_camera_logic.reg_data.data[0x30])
|
if (m_camera_logic.reg_data.data[0x30])
|
||||||
{
|
{
|
||||||
// ir mode
|
// ir mode
|
||||||
|
@ -874,7 +869,8 @@ void Wiimote::UpdateIRData(bool use_accel)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
WARN_LOG(WIIMOTE, "Game is requesting IR data before setting IR mode.");
|
// This is fairly normal, 0xff data is sent in this case:
|
||||||
|
// WARN_LOG(WIIMOTE, "Game is requesting IR data before setting IR mode.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1009,7 +1005,13 @@ void Wiimote::Update()
|
||||||
m_ext_logic.Update();
|
m_ext_logic.Update();
|
||||||
m_motion_plus_logic.Update();
|
m_motion_plus_logic.Update();
|
||||||
|
|
||||||
m_i2c_bus.BusRead(ExtensionLogic::DEVICE_ADDR, 0x00, rptf.ext_size, feature_ptr);
|
const u8 slave_addr = ExtensionLogic::DEVICE_ADDR;
|
||||||
|
if (rptf.ext_size != m_i2c_bus.BusRead(slave_addr, 0x00, rptf.ext_size, feature_ptr))
|
||||||
|
{
|
||||||
|
// Real wiimote seems to fill with 0xff on failed bus read
|
||||||
|
std::fill_n(feature_ptr, rptf.ext_size, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
feature_ptr += rptf.ext_size;
|
feature_ptr += rptf.ext_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1231,14 +1233,14 @@ void Wiimote::MotionPlusLogic::Update()
|
||||||
|
|
||||||
if (0x0 == reg_data.cert_ready)
|
if (0x0 == reg_data.cert_ready)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Without sending this nonsense, inputs are unresponsive.. even regular buttons
|
// Without sending this nonsense, inputs are unresponsive.. even regular buttons
|
||||||
// Device still operates when changing the data slightly so its not any sort of encrpytion
|
// Device still operates when changing the data slightly so its not any sort of encrpytion
|
||||||
// It even works when removing the is_mp_data bit in the last byte
|
// It even works when removing the is_mp_data bit in the last byte
|
||||||
static const u8 init_data[6] = {0x8e, 0xb0, 0x4f, 0x5a, 0xfc, 0x02};
|
// My M+ non-inside gives: 61,46,45,aa,0,2 or b6,46,45,9a,0,2
|
||||||
//std::copy(std::begin(init_data), std::end(init_data), data);
|
static const u8 init_data[6] = {0x8e, 0xb0, 0x4f, 0x5a, 0xfc | 0x01, 0x02};
|
||||||
|
std::copy(std::begin(init_data), std::end(init_data), data);
|
||||||
reg_data.cert_ready = 0x2;
|
reg_data.cert_ready = 0x2;
|
||||||
//return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0x2 == reg_data.cert_ready)
|
if (0x2 == reg_data.cert_ready)
|
||||||
|
@ -1249,27 +1251,23 @@ void Wiimote::MotionPlusLogic::Update()
|
||||||
|
|
||||||
if (0x18 == reg_data.cert_ready)
|
if (0x18 == reg_data.cert_ready)
|
||||||
{
|
{
|
||||||
|
// TODO: determine the meaning of this
|
||||||
const u8 mp_cert2[64] = {
|
const u8 mp_cert2[64] = {
|
||||||
//0x39, 0x7c, 0xe9, 0x79, 0x15, 0x52, 0x0e, 0x4f, 0x28, 0x4d, 0x9d, 0x2c, 0xd3,
|
0xa5, 0x84, 0x1f, 0xd6, 0xbd, 0xdc, 0x7a, 0x4c, 0xf3, 0xc0, 0x24, 0xe0, 0x92,
|
||||||
//0x2a, 0x1a, 0x28, 0xa1, 0x25, 0x55, 0xb4, 0x4e, 0xb1, 0xd5, 0xae, 0x9d, 0x99,
|
0xef, 0x19, 0x28, 0x65, 0xe0, 0x62, 0x7c, 0x9b, 0x41, 0x6f, 0x12, 0xc3, 0xac,
|
||||||
//0x96, 0x96, 0x1d, 0x94, 0xd1, 0x22, 0xca, 0x1f, 0x51, 0x1d, 0x55, 0xee, 0x4d,
|
0x78, 0xe4, 0xfc, 0x6b, 0x7b, 0x0a, 0xb4, 0x50, 0xd6, 0xf2, 0x45, 0xf7, 0x93,
|
||||||
//0x58, 0x97, 0xd4, 0xb9, 0x3f, 0x0d, 0x0a, 0x04, 0xd8, 0x01, 0x21, 0xf9, 0x17,
|
0x04, 0xaf, 0xf2, 0xb7, 0x26, 0x94, 0xee, 0xad, 0x92, 0x05, 0x6d, 0xe5, 0xc6,
|
||||||
//0x45, 0xe4, 0x42, 0x58, 0x3f, 0x7c, 0x3c, 0x2c, 0x3a, 0xcd, 0xbd, 0x27, 0x3b,
|
0xd6, 0x36, 0xdc, 0xa5, 0x69, 0x0f, 0xc8, 0x99, 0xf2, 0x1c, 0x4e, 0x0d,
|
||||||
|
|
||||||
//0xea, 0x7c, 0x25, 0xaf, 0xcc, 0xc8, 0xef, 0x22, 0x99, 0xb3, 0x79, 0x72, 0x60,
|
|
||||||
//0xe8, 0x16, 0x4f, 0x5a, 0x47, 0x07, 0x04, 0x02, 0x14, 0x7b, 0xd0, 0xf6, 0xc9,
|
|
||||||
//0x77, 0x28, 0x9f, 0x77, 0x78, 0xce, 0x19, 0x74, 0x89, 0xe3, 0x56, 0x3a, 0x23,
|
|
||||||
//0x13, 0x63, 0xbb, 0x86, 0xf9, 0x13, 0x0e, 0x62, 0xfb, 0x61, 0xf5, 0x42, 0x65,
|
|
||||||
//0x48, 0x8e, 0xed, 0xc2, 0xc4, 0xc1, 0x18, 0xd0, 0x19, 0x9c, 0xe5, 0x1e
|
|
||||||
|
|
||||||
0xa5, 0x84, 0x1f, 0xd6, 0xbd, 0xdc, 0x7a, 0x4c, 0xf3, 0xc0, 0x24, 0xe0, 0x92, 0xef, 0x19, 0x28,
|
|
||||||
0x65, 0xe0, 0x62, 0x7c, 0x9b, 0x41, 0x6f, 0x12, 0xc3, 0xac, 0x78, 0xe4, 0xfc, 0x6b, 0x7b, 0x0a,
|
|
||||||
0xb4, 0x50, 0xd6, 0xf2, 0x45, 0xf7, 0x93, 0x04, 0xaf, 0xf2, 0xb7, 0x26, 0x94, 0xee, 0xad, 0x92,
|
|
||||||
0x05, 0x6d, 0xe5, 0xc6, 0xd6, 0x36, 0xdc, 0xa5, 0x69, 0x0f, 0xc8, 0x99, 0xf2, 0x1c, 0x4e, 0x0d,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::copy(std::begin(mp_cert2), std::end(mp_cert2), reg_data.cert_data);
|
std::copy(std::begin(mp_cert2), std::end(mp_cert2), reg_data.cert_data);
|
||||||
|
|
||||||
|
if (0x01 != reg_data.cert_enable)
|
||||||
|
{
|
||||||
|
PanicAlert("M+ Failure! Game requested cert2 with value other than 0x01. M+ will disconnect "
|
||||||
|
"shortly unfortunately. Reconnect wiimote and hope for the best.");
|
||||||
|
}
|
||||||
|
|
||||||
// A real wiimote takes about 2 seconds to reach this state:
|
// A real wiimote takes about 2 seconds to reach this state:
|
||||||
reg_data.cert_ready = 0x1a;
|
reg_data.cert_ready = 0x1a;
|
||||||
INFO_LOG(WIIMOTE, "M+ cert 2 ready!", reg_data.cert_ready);
|
INFO_LOG(WIIMOTE, "M+ cert 2 ready!", reg_data.cert_ready);
|
||||||
|
@ -1288,23 +1286,32 @@ void Wiimote::MotionPlusLogic::Update()
|
||||||
// If an extension is not attached the data is always mplus data
|
// If an extension is not attached the data is always mplus data
|
||||||
// even when passthrough is enabled
|
// even when passthrough is enabled
|
||||||
|
|
||||||
|
// Real M+ seems to only ever read 6 bytes from the extension.
|
||||||
|
// Data after 6 bytes seems to be zero-filled.
|
||||||
|
// After reading, the real M+ uses that data for the next frame.
|
||||||
|
// But we are going to use it for the current frame instead.
|
||||||
|
const int ext_amt = 6;
|
||||||
|
// Always read from 0x52 @ 0x00:
|
||||||
|
const u8 ext_slave = ACTIVE_DEVICE_ADDR;
|
||||||
|
const u8 ext_addr = 0x00;
|
||||||
|
|
||||||
|
// Try to alternate between M+ and EXT data:
|
||||||
|
mplus_data.is_mp_data ^= true;
|
||||||
|
|
||||||
|
// If the last frame had M+ data try to send some non-M+ data:
|
||||||
|
if (!mplus_data.is_mp_data)
|
||||||
|
{
|
||||||
switch (GetPassthroughMode())
|
switch (GetPassthroughMode())
|
||||||
{
|
{
|
||||||
case PassthroughMode::PASSTHROUGH_DISABLED:
|
case PassthroughMode::PASSTHROUGH_DISABLED:
|
||||||
{
|
{
|
||||||
|
// Passthrough disabled, always send M+ data:
|
||||||
mplus_data.is_mp_data = true;
|
mplus_data.is_mp_data = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PassthroughMode::PASSTHROUGH_NUNCHUK:
|
case PassthroughMode::PASSTHROUGH_NUNCHUK:
|
||||||
{
|
{
|
||||||
// If we sent mplus data last time now we will try to send ext data.
|
if (ext_amt == i2c_bus.BusRead(ext_slave, ext_addr, ext_amt, data))
|
||||||
if (mplus_data.is_mp_data)
|
|
||||||
{
|
|
||||||
// The real mplus seems to only ever read 6 bytes from the extension
|
|
||||||
// bytes after 6 seem to be zero filled
|
|
||||||
// The real hardware uses these 6 bytes for the next frame,
|
|
||||||
// but we aren't going to do that
|
|
||||||
if (6 == i2c_bus.BusRead(ACTIVE_DEVICE_ADDR, 0x00, 6, data))
|
|
||||||
{
|
{
|
||||||
// Passthrough data modifications via wiibrew.org
|
// Passthrough data modifications via wiibrew.org
|
||||||
// Data passing through drops the least significant bit of the three accelerometer values
|
// Data passing through drops the least significant bit of the three accelerometer values
|
||||||
|
@ -1322,27 +1329,31 @@ void Wiimote::MotionPlusLogic::Update()
|
||||||
// Bit 0 and 1 of byte 5 contain a M+ flag and a zero bit which is set below.
|
// Bit 0 and 1 of byte 5 contain a M+ flag and a zero bit which is set below.
|
||||||
mplus_data.is_mp_data = false;
|
mplus_data.is_mp_data = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Read failed (extension unplugged), Send M+ data instead
|
||||||
|
mplus_data.is_mp_data = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PassthroughMode::PASSTHROUGH_CLASSIC:
|
case PassthroughMode::PASSTHROUGH_CLASSIC:
|
||||||
{
|
{
|
||||||
// If we sent mplus data last time now we will try to send ext data.
|
if (ext_amt == i2c_bus.BusRead(ext_slave, ext_addr, ext_amt, data))
|
||||||
if (mplus_data.is_mp_data)
|
|
||||||
{
|
|
||||||
if (6 == i2c_bus.BusRead(ACTIVE_DEVICE_ADDR, 0x00, 6, data))
|
|
||||||
{
|
{
|
||||||
// Passthrough data modifications via wiibrew.org
|
// Passthrough data modifications via wiibrew.org
|
||||||
// Data passing through drops the least significant bit of the axes of the left (or only)
|
// Data passing through drops the least significant bit of the axes of the left (or only)
|
||||||
// joystick Bit 0 of Byte 4 is overwritten [by the 'extension_connected' flag] Bits 0 and 1
|
// joystick Bit 0 of Byte 4 is overwritten [by the 'extension_connected' flag] Bits 0 and 1
|
||||||
// of Byte 5 are moved to bit 0 of Bytes 0 and 1, overwriting what was there before
|
// of Byte 5 are moved to bit 0 of Bytes 0 and 1, overwriting what was there before
|
||||||
|
|
||||||
SetBit(data[0], 0, Common::ExtractBit(data[5], 0));
|
SetBit(data[0], 0, Common::ExtractBit(data[5], 0));
|
||||||
SetBit(data[1], 0, Common::ExtractBit(data[5], 1));
|
SetBit(data[1], 0, Common::ExtractBit(data[5], 1));
|
||||||
|
|
||||||
// Bit 0 and 1 of byte 5 contain a M+ flag and a zero bit which is set below.
|
// Bit 0 and 1 of byte 5 contain a M+ flag and a zero bit which is set below.
|
||||||
mplus_data.is_mp_data = false;
|
mplus_data.is_mp_data = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Read failed (extension unplugged), Send M+ data instead
|
||||||
|
mplus_data.is_mp_data = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1350,14 +1361,19 @@ void Wiimote::MotionPlusLogic::Update()
|
||||||
PanicAlert("MotionPlus unknown passthrough-mode %d", GetPassthroughMode());
|
PanicAlert("MotionPlus unknown passthrough-mode %d", GetPassthroughMode());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the above logic determined this should be mp data, update it here
|
// If the above logic determined this should be M+ data, update it here
|
||||||
if (mplus_data.is_mp_data)
|
if (mplus_data.is_mp_data)
|
||||||
{
|
{
|
||||||
// Wiibrew: "While the Wiimote is still, the values will be about 0x1F7F (8,063)"
|
// Wiibrew: "While the Wiimote is still, the values will be about 0x1F7F (8,063)"
|
||||||
u16 yaw_value = 0x1F7F;
|
// high-velocity range should be about +/- 1500 or 1600 dps
|
||||||
u16 roll_value = 0x1F7F;
|
// low-velocity range should be about +/- 400 dps
|
||||||
u16 pitch_value = 0x1F7F;
|
// Wiibrew implies it shoould be +/- 595 and 2700
|
||||||
|
|
||||||
|
u16 yaw_value = 0x2000;
|
||||||
|
u16 roll_value = 0x2000;
|
||||||
|
u16 pitch_value = 0x2000;
|
||||||
|
|
||||||
mplus_data.yaw_slow = 1;
|
mplus_data.yaw_slow = 1;
|
||||||
mplus_data.roll_slow = 1;
|
mplus_data.roll_slow = 1;
|
||||||
|
@ -1372,14 +1388,6 @@ void Wiimote::MotionPlusLogic::Update()
|
||||||
mplus_data.yaw2 = yaw_value >> 8;
|
mplus_data.yaw2 = yaw_value >> 8;
|
||||||
mplus_data.roll2 = roll_value >> 8;
|
mplus_data.roll2 = roll_value >> 8;
|
||||||
mplus_data.pitch2 = pitch_value >> 8;
|
mplus_data.pitch2 = pitch_value >> 8;
|
||||||
|
|
||||||
// hax:
|
|
||||||
//data[0] = 0x6d;
|
|
||||||
//data[1] = 0xfa;
|
|
||||||
//data[2] = 0x13;
|
|
||||||
//data[3] = 0x7f;
|
|
||||||
//data[4] = 0x83;
|
|
||||||
//data[5] = 0x7e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mplus_data.extension_connected = extension_port.IsDeviceConnected();
|
mplus_data.extension_connected = extension_port.IsDeviceConnected();
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Core/HW/WiimoteCommon/WiimoteConstants.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"
|
||||||
|
@ -597,6 +598,7 @@ private:
|
||||||
// address 0xF1
|
// address 0xF1
|
||||||
u8 cert_enable;
|
u8 cert_enable;
|
||||||
|
|
||||||
|
// Conduit 2 writes 1 byte to 0xf2 on calibration screen
|
||||||
u8 unknown_0xf2[5];
|
u8 unknown_0xf2[5];
|
||||||
|
|
||||||
// address 0xf7
|
// address 0xf7
|
||||||
|
@ -696,6 +698,11 @@ private:
|
||||||
// 0x1a is final value
|
// 0x1a is final value
|
||||||
reg_data.cert_ready = 0x18;
|
reg_data.cert_ready = 0x18;
|
||||||
}
|
}
|
||||||
|
// TODO: kill magic number
|
||||||
|
else if (0xf2 == addr)
|
||||||
|
{
|
||||||
|
INFO_LOG(WIIMOTE, "M+ calibration ?? : 0x%x", reg_data.unknown_0xf2[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -721,6 +728,10 @@ private:
|
||||||
// TODO: kill magic number
|
// TODO: kill magic number
|
||||||
//reg_data.cert_ready = 0x2;
|
//reg_data.cert_ready = 0x2;
|
||||||
|
|
||||||
|
// A real M+ is unresponsive on the bus for some time during activation
|
||||||
|
// Reads fail to ack and ext data gets filled with 0xff for a frame or two
|
||||||
|
// I don't think we need to emulate that.
|
||||||
|
|
||||||
// TODO: activate extension and disable encrption
|
// TODO: activate extension and disable encrption
|
||||||
// also do this if an extension is attached after activation.
|
// also do this if an extension is attached after activation.
|
||||||
std::array<u8, 1> data = {0x55};
|
std::array<u8, 1> data = {0x55};
|
||||||
|
@ -753,7 +764,7 @@ private:
|
||||||
} m_motion_plus_logic;
|
} m_motion_plus_logic;
|
||||||
|
|
||||||
void ReportMode(const wm_report_mode* dr);
|
void ReportMode(const wm_report_mode* dr);
|
||||||
void SendAck(u8 report_id, u8 error_code = 0x0);
|
void SendAck(u8 report_id, WiimoteErrorCode error_code = WiimoteErrorCode::SUCCESS);
|
||||||
void RequestStatus(const wm_request_status* rs = nullptr);
|
void RequestStatus(const wm_request_status* rs = nullptr);
|
||||||
void ReadData(const wm_read_data* rd);
|
void ReadData(const wm_read_data* rd);
|
||||||
void WriteData(const wm_write_data* wd);
|
void WriteData(const wm_write_data* wd);
|
||||||
|
@ -812,7 +823,7 @@ private:
|
||||||
|
|
||||||
struct ReadRequest
|
struct ReadRequest
|
||||||
{
|
{
|
||||||
u8 space;
|
WiimoteAddressSpace space;
|
||||||
u8 slave_address;
|
u8 slave_address;
|
||||||
u16 address;
|
u16 address;
|
||||||
u16 size;
|
u16 size;
|
||||||
|
|
Loading…
Reference in New Issue