From 3a889c35ad3169f05c7d01cc48dbb7e3b1f34262 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 2 Dec 2018 12:32:52 -0600 Subject: [PATCH] WiimoteEmu: Cleanups, Kill more magic numbers and use some enum classes. --- .../Core/HW/WiimoteCommon/WiimoteConstants.h | 17 +- .../Core/HW/WiimoteCommon/WiimoteReport.h | 6 +- .../Core/HW/WiimoteEmu/EmuSubroutines.cpp | 47 +++-- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 186 +++++++++--------- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h | 15 +- 5 files changed, 149 insertions(+), 122 deletions(-) diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h index 6e8d4332c2..8c732fac3e 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h @@ -41,17 +41,20 @@ enum WiimoteLED LED_4 = 0x80 }; -enum WiimoteSpace +enum class WiimoteAddressSpace : u8 { - WS_EEPROM = 0x00, - WS_REGS1 = 0x01, - WS_REGS2 = 0x02 + EEPROM = 0x00, + // 0x01 is never used but it does function on a real wiimote: + I2C_BUS_ALT = 0x01, + I2C_BUS = 0x02, }; -enum WiimoteReadError +enum class WiimoteErrorCode : u8 { - RDERR_WOREG = 7, - RDERR_NOMEM = 8 + SUCCESS = 0, + NACK = 7, + // TODO: Can there be a better name for this? + INVALID = 8, }; constexpr u8 MAX_PAYLOAD = 23; diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h index 51290a5c6a..282d9ddd29 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h @@ -427,7 +427,7 @@ static_assert(sizeof(wm_status_report) == 6, "Wrong size"); struct wm_write_data { u8 rumble : 1; - u8 space : 2; // see WM_SPACE_* + u8 space : 2; u8 : 5; // A real wiimote ignores the i2c read/write bit. u8 i2c_rw_ignored : 1; @@ -451,7 +451,7 @@ static_assert(sizeof(wm_acknowledge) == 4, "Wrong size"); struct wm_read_data { u8 rumble : 1; - u8 space : 2; // see WM_SPACE_* + u8 space : 2; u8 : 5; // A real wiimote ignores the i2c read/write bit. u8 i2c_rw_ignored : 1; @@ -466,7 +466,7 @@ static_assert(sizeof(wm_read_data) == 6, "Wrong size"); struct wm_read_data_reply { wm_buttons buttons; - u8 error : 4; // see WM_RDERR_* + u8 error : 4; u8 size_minus_one : 4; // big endian: u16 address; diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index 8bc69c7141..b514ea5767 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -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, 00 00 means nothing is pressed. 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 rpt; rpt.type = HID_TYPE_DATA; @@ -181,7 +181,7 @@ void Wiimote::SendAck(u8 report_id, u8 error_code) ack.buttons = m_status.buttons; ack.reportID = report_id; - ack.errorID = error_code; + ack.errorID = static_cast(error_code); Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(), rpt.GetSize()); @@ -266,11 +266,11 @@ void Wiimote::WriteData(const wm_write_data* const wd) return; } - u8 error_code = 0; + WiimoteErrorCode error_code = WiimoteErrorCode::SUCCESS; - switch (wd->space) + switch (static_cast(wd->space)) { - case WS_EEPROM: + case WiimoteAddressSpace::EEPROM: { // Write to EEPROM @@ -295,8 +295,8 @@ void Wiimote::WriteData(const wm_write_data* const wd) } break; - case WS_REGS1: - case WS_REGS2: + case WiimoteAddressSpace::I2C_BUS: + case WiimoteAddressSpace::I2C_BUS_ALT: { // Write to Control Register @@ -306,7 +306,7 @@ void Wiimote::WriteData(const wm_write_data* const wd) if (bytes_written != wd->size) { // 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; @@ -330,7 +330,7 @@ void Wiimote::ReadData(const wm_read_data* const rd) } // Save the request and process it on the next "Update()" calls - m_read_request.space = rd->space; + m_read_request.space = static_cast(rd->space); m_read_request.slave_address = rd->slave_address; m_read_request.address = Common::swap16(rd->address); // 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; auto reply = &rpt.data; - reply->error = 0; reply->buttons = m_status.buttons; 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) { - case WS_EEPROM: + case WiimoteAddressSpace::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_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 @@ -386,8 +390,8 @@ bool Wiimote::ProcessReadDataRequest() // 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 // usable space that ends at 0x16ff. - INFO_LOG(WIIMOTE, "Responding with read error 8."); - reply->error = 0x08; + //INFO_LOG(WIIMOTE, "Responding with read error 8."); + error_code = WiimoteErrorCode::INVALID; } else { @@ -410,8 +414,8 @@ bool Wiimote::ProcessReadDataRequest() } break; - case WS_REGS1: - case WS_REGS2: + case WiimoteAddressSpace::I2C_BUS: + case WiimoteAddressSpace::I2C_BUS_ALT: { // Read from Control Register @@ -426,7 +430,7 @@ bool Wiimote::ProcessReadDataRequest() // generate read error, 7 == no such slave (no ack) 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); - reply->error = 0x07; + error_code = WiimoteErrorCode::NACK; } } break; @@ -436,13 +440,12 @@ bool Wiimote::ProcessReadDataRequest() break; } - if (reply->error) + if (WiimoteErrorCode::SUCCESS != error_code) { // Stop processing request on read error: m_read_request.size = 0; - // TODO: what size does a real wiimote return on read error? - // it's 10 minus one (9) for some reason?? - // reply->size_minus_one = 0; + // Real wiimote seems to set size to max value on read errors: + reply->size_minus_one = 0xf; } else { @@ -451,6 +454,8 @@ bool Wiimote::ProcessReadDataRequest() m_read_request.size -= bytes_to_read; } + reply->error = static_cast(error_code); + // Send the data Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(), rpt.GetSize()); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index d6f8191291..88ad56871e 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -341,31 +341,25 @@ void Wiimote::Reset() 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)); - // calibration hackery - static const u8 c1[16] = {0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c, - 0xcf, 0xf0, 0x31, 0xad, 0xc8, 0x0b, 0x5e, 0x39}; - static const u8 c2[16] = {0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51, 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, - //0xbb, 0xbb, 0x35, 0x49, 0x32, 0x04, 0xfd, 0x29, 0x1d, 0xc1, 0xb7, 0x5a, 0x7c, - //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, - //0x49, 0x01, 0x7b, 0x2f, 0xb2, 0xc8, 0x5b, 0x12, 0x92, 0x47, 0xb8, 0x23 - - //0xf0, 0x89, 0x3b, 0xf7, 0x1b, 0x6c, 0x92, 0x95, 0xa0, 0x05, 0xd4, 0x03, 0x82, - //0x8e, 0xae, 0x73, 0x15, 0xc7, 0x95, 0xfb, 0xae, 0xee, 0xc0, 0x68, 0xbd, 0x49, - //0xf5, 0x32, 0x48, 0x8d, 0x33, 0x00, 0x94, 0x32, 0xf5, 0xf1, 0x30, 0x66, 0x68, - //0x9e, 0xf3, 0xe5, 0xfa, 0x9b, 0xb6, 0xe3, 0x0b, 0xa8, 0x07, 0xd5, 0x25, 0x38, - - 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, + // TODO: determine meaning of calibration data: + static const u8 mplus_cdata[32] = { + 0x78, 0xd9, 0x78, 0x38, 0x77, 0x9d, 0x2f, 0x0c, 0xcf, 0xf0, 0x31, + 0xad, 0xc8, 0x0b, 0x5e, 0x39, 0x6f, 0x81, 0x7b, 0x89, 0x78, 0x51, + 0x33, 0x60, 0xc9, 0xf5, 0x37, 0xc1, 0x2d, 0xe9, 0x15, 0x8d, + }; + + std::copy(std::begin(mplus_cdata), std::end(mplus_cdata), + m_motion_plus_logic.reg_data.calibration_data); + + // TODO: determine the meaning behind this: + static const u8 mp_cert[64] = { + 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); // status @@ -399,7 +393,7 @@ void Wiimote::Reset() // TODO: only add to bus when connected: // Address 0x52 (when motion plus is not activated) // Connected to motion plus i2c_bus (with passthrough by default) - //m_motion_plus_logic.extension_port.SetAttachment(&m_ext_logic); + // m_motion_plus_logic.extension_port.SetAttachment(&m_ext_logic); } Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1) @@ -795,11 +789,12 @@ void Wiimote::UpdateIRData(bool use_accel) } // IR data is read from offset 0x37 on real hardware - u8* const data = m_camera_logic.reg_data.camera_data; - // A maximum of 36 bytes. - std::fill_n(data, sizeof(wm_ir_full) * 4, 0xff); + auto& data = m_camera_logic.reg_data.camera_data; + // A maximum of 36 bytes: + std::fill(std::begin(data), std::end(data), 0xff); // Fill report with valid data when full handshake was done + // TODO: kill magic number: if (m_camera_logic.reg_data.data[0x30]) { // ir mode @@ -874,7 +869,8 @@ void Wiimote::UpdateIRData(bool use_accel) break; } 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; } } @@ -1009,7 +1005,13 @@ void Wiimote::Update() m_ext_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; } @@ -1231,14 +1233,14 @@ void Wiimote::MotionPlusLogic::Update() if (0x0 == reg_data.cert_ready) { - // 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 // 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}; - //std::copy(std::begin(init_data), std::end(init_data), data); + // My M+ non-inside gives: 61,46,45,aa,0,2 or b6,46,45,9a,0,2 + 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; - //return; + return; } if (0x2 == reg_data.cert_ready) @@ -1249,27 +1251,23 @@ void Wiimote::MotionPlusLogic::Update() if (0x18 == reg_data.cert_ready) { + // TODO: determine the meaning of this const u8 mp_cert2[64] = { - //0x39, 0x7c, 0xe9, 0x79, 0x15, 0x52, 0x0e, 0x4f, 0x28, 0x4d, 0x9d, 0x2c, 0xd3, - //0x2a, 0x1a, 0x28, 0xa1, 0x25, 0x55, 0xb4, 0x4e, 0xb1, 0xd5, 0xae, 0x9d, 0x99, - //0x96, 0x96, 0x1d, 0x94, 0xd1, 0x22, 0xca, 0x1f, 0x51, 0x1d, 0x55, 0xee, 0x4d, - //0x58, 0x97, 0xd4, 0xb9, 0x3f, 0x0d, 0x0a, 0x04, 0xd8, 0x01, 0x21, 0xf9, 0x17, - //0x45, 0xe4, 0x42, 0x58, 0x3f, 0x7c, 0x3c, 0x2c, 0x3a, 0xcd, 0xbd, 0x27, 0x3b, - - //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, + 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); + 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: reg_data.cert_ready = 0x1a; 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 // even when passthrough is enabled - switch (GetPassthroughMode()) + // 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) { - case PassthroughMode::PASSTHROUGH_DISABLED: - { - mplus_data.is_mp_data = true; - break; - } - case PassthroughMode::PASSTHROUGH_NUNCHUK: - { - // If we sent mplus data last time now we will try to send ext data. - if (mplus_data.is_mp_data) + switch (GetPassthroughMode()) { - // 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)) + case PassthroughMode::PASSTHROUGH_DISABLED: + { + // Passthrough disabled, always send M+ data: + mplus_data.is_mp_data = true; + break; + } + case PassthroughMode::PASSTHROUGH_NUNCHUK: + { + if (ext_amt == i2c_bus.BusRead(ext_slave, ext_addr, ext_amt, data)) { // Passthrough data modifications via wiibrew.org // Data passing through drops the least significant bit of the three accelerometer values @@ -1322,42 +1329,51 @@ void Wiimote::MotionPlusLogic::Update() // 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; } + else + { + // Read failed (extension unplugged), Send M+ data instead + mplus_data.is_mp_data = true; + } + break; } - break; - } - case PassthroughMode::PASSTHROUGH_CLASSIC: - { - // If we sent mplus data last time now we will try to send ext data. - if (mplus_data.is_mp_data) + case PassthroughMode::PASSTHROUGH_CLASSIC: { - if (6 == i2c_bus.BusRead(ACTIVE_DEVICE_ADDR, 0x00, 6, data)) + if (ext_amt == i2c_bus.BusRead(ext_slave, ext_addr, ext_amt, data)) { // Passthrough data modifications via wiibrew.org // 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 // 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[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. mplus_data.is_mp_data = false; } + else + { + // Read failed (extension unplugged), Send M+ data instead + mplus_data.is_mp_data = true; + } + break; + } + default: + PanicAlert("MotionPlus unknown passthrough-mode %d", GetPassthroughMode()); + break; } - break; - } - default: - PanicAlert("MotionPlus unknown passthrough-mode %d", GetPassthroughMode()); - 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) { // Wiibrew: "While the Wiimote is still, the values will be about 0x1F7F (8,063)" - u16 yaw_value = 0x1F7F; - u16 roll_value = 0x1F7F; - u16 pitch_value = 0x1F7F; + // high-velocity range should be about +/- 1500 or 1600 dps + // low-velocity range should be about +/- 400 dps + // 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.roll_slow = 1; @@ -1372,14 +1388,6 @@ void Wiimote::MotionPlusLogic::Update() mplus_data.yaw2 = yaw_value >> 8; mplus_data.roll2 = roll_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(); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index 4b335af3de..15a355fe9f 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -9,6 +9,7 @@ #include #include "Common/Logging/Log.h" +#include "Core/HW/WiimoteCommon/WiimoteConstants.h" #include "Core/HW/WiimoteCommon/WiimoteHid.h" #include "Core/HW/WiimoteCommon/WiimoteReport.h" #include "Core/HW/WiimoteEmu/Encryption.h" @@ -597,6 +598,7 @@ private: // address 0xF1 u8 cert_enable; + // Conduit 2 writes 1 byte to 0xf2 on calibration screen u8 unknown_0xf2[5]; // address 0xf7 @@ -696,6 +698,11 @@ private: // 0x1a is final value 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; } @@ -721,6 +728,10 @@ private: // TODO: kill magic number //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 // also do this if an extension is attached after activation. std::array data = {0x55}; @@ -753,7 +764,7 @@ private: } m_motion_plus_logic; 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 ReadData(const wm_read_data* rd); void WriteData(const wm_write_data* wd); @@ -812,7 +823,7 @@ private: struct ReadRequest { - u8 space; + WiimoteAddressSpace space; u8 slave_address; u16 address; u16 size;