Skip to content
Permalink
Browse files

WiimoteEmu: Motion plus now works half of the time in Wii Sports Resort.

  • Loading branch information...
jordan-woyak committed Nov 29, 2018
1 parent 0b4329e commit 86c94b8b22e547a9445683258e9f36a1a1b793ef
@@ -63,6 +63,8 @@ union wm_buttons // also just called "core data"
u8 down : 1;
u8 up : 1;
u8 plus : 1;
// For most input reports this is the 2 LSbs of accel.x:
// For interleaved reports this is alternating bits of accel.z:
u8 acc_bits : 2;
u8 unknown : 1;

@@ -71,6 +73,8 @@ union wm_buttons // also just called "core data"
u8 b : 1;
u8 a : 1;
u8 minus : 1;
// For most input reports this is bits of accel.y/z:
// For interleaved reports this is alternating bits of accel.z:
u8 acc_bits2 : 2;
u8 home : 1;
};
@@ -425,8 +429,10 @@ struct wm_write_data
u8 rumble : 1;
u8 space : 2; // see WM_SPACE_*
u8 : 5;
// used only for register space (i2c bus)
u8 slave_address;
// A real wiimote ignores the i2c read/write bit.
u8 i2c_rw_ignored : 1;
// Used only for register space (i2c bus) (7-bits):
u8 slave_address : 7;
// big endian:
u8 address[2];
u8 size;
@@ -447,8 +453,10 @@ struct wm_read_data
u8 rumble : 1;
u8 space : 2; // see WM_SPACE_*
u8 : 5;
// used only for register space (i2c bus)
u8 slave_address;
// A real wiimote ignores the i2c read/write bit.
u8 i2c_rw_ignored : 1;
// Used only for register space (i2c bus) (7-bits):
u8 slave_address : 7;
// big endian:
u8 address[2];
u8 size[2];
@@ -460,6 +468,7 @@ struct wm_read_data_reply
wm_buttons buttons;
u8 error : 4; // see WM_RDERR_*
u8 size_minus_one : 4;
// big endian:
u16 address;
u8 data[16];
};
@@ -40,7 +40,7 @@ namespace WiimoteEmu
void Wiimote::ReportMode(const wm_report_mode* const dr)
{
if (dr->mode < RT_REPORT_CORE || dr->mode > RT_REPORT_INTERLEAVE2 ||
(dr->mode > RT_REPORT_CORE_ACCEL_IR10_EXT6 && dr->mode < RT_REPORT_EXT21))
(dr->mode > RT_REPORT_CORE_ACCEL_IR10_EXT6 && dr->mode < RT_REPORT_EXT21))
{
// A real wiimote ignores the entire message if the mode is invalid.
WARN_LOG(WIIMOTE, "Game requested invalid report mode: 0x%02x", dr->mode);
@@ -177,11 +177,11 @@ void Wiimote::SendAck(u8 report_id, u8 error_code)
rpt.param = HID_PARAM_INPUT;
rpt.report_id = RT_ACK_DATA;

auto ack = &rpt.data;
auto& ack = rpt.data;

ack->buttons = m_status.buttons;
ack->reportID = report_id;
ack->errorID = error_code;
ack.buttons = m_status.buttons;
ack.reportID = report_id;
ack.errorID = error_code;

Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(),
rpt.GetSize());
@@ -194,12 +194,22 @@ void Wiimote::HandleExtensionSwap()
{
// if an extension is currently connected and we want to switch to a different extension
if ((m_extension->active_extension > 0) && m_extension->switch_extension)
{
// detach extension first, wait til next Update() or RequestStatus() call to change to the new
// extension
m_extension->active_extension = 0;
}
else
{
// set the wanted extension
m_extension->active_extension = m_extension->switch_extension;
}

// TODO: this is a bit ugly:
if (m_extension->active_extension != 0)
m_motion_plus_logic.extension_port.SetAttachment(&m_ext_logic);
else
m_motion_plus_logic.extension_port.SetAttachment(nullptr);

// reset register
((WiimoteEmu::Attachment*)m_extension->attachments[m_extension->active_extension].get())
@@ -209,7 +219,7 @@ void Wiimote::HandleExtensionSwap()

void Wiimote::RequestStatus(const wm_request_status* const rs)
{
INFO_LOG(WIIMOTE, "Wiimote::RequestStatus");
// INFO_LOG(WIIMOTE, "Wiimote::RequestStatus");

// update status struct
m_status.extension = m_extension_port.IsDeviceConnected();
@@ -247,7 +257,8 @@ void Wiimote::WriteData(const wm_write_data* const wd)
return;
}

INFO_LOG(WIIMOTE, "Wiimote::WriteData: 0x%02x @ 0x%02x @ 0x%02x (%d)", wd->space, wd->slave_address, address, wd->size);
INFO_LOG(WIIMOTE, "Wiimote::WriteData: 0x%02x @ 0x%02x @ 0x%02x (%d)", wd->space,
wd->slave_address, address, wd->size);

if (wd->size > 16)
{
@@ -290,7 +301,8 @@ void Wiimote::WriteData(const wm_write_data* const wd)
// Write to Control Register

// Top byte of address is ignored on the bus.
auto const bytes_written = m_i2c_bus.BusWrite(wd->slave_address >> 1, (u8)address, wd->size, wd->data);
auto const bytes_written =
m_i2c_bus.BusWrite(wd->slave_address, (u8)address, wd->size, wd->data);
if (bytes_written != wd->size)
{
// A real wiimote gives error 7 for failed write to i2c bus (mainly a non-existant slave)
@@ -325,7 +337,7 @@ void Wiimote::ReadData(const wm_read_data* const rd)
m_read_request.size = Common::swap16(rd->size);

INFO_LOG(WIIMOTE, "Wiimote::ReadData: %d @ 0x%02x @ 0x%02x (%d)", m_read_request.space,
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);

// Send up to one read-data-reply.
// If more data needs to be sent it will happen on the next "Update()"
@@ -336,7 +348,7 @@ bool Wiimote::ProcessReadDataRequest()
{
// Limit the amt to 16 bytes
// AyuanX: the MTU is 640B though... what a waste!
u16 const bytes_to_read = std::min((u16)16, m_read_request.size);
const u16 bytes_to_read = std::min<u16>(16, m_read_request.size);

if (0 == bytes_to_read)
{
@@ -404,28 +416,40 @@ bool Wiimote::ProcessReadDataRequest()
// Read from Control Register

// Top byte of address is ignored on the bus, but it IS maintained in the read-reply.
auto const bytes_read = m_i2c_bus.BusRead(m_read_request.slave_address >> 1,
(u8)m_read_request.address, bytes_to_read, reply->data);
auto const bytes_read = m_i2c_bus.BusRead(
m_read_request.slave_address, (u8)m_read_request.address, bytes_to_read, reply->data);

reply->size_minus_one = bytes_read - 1;

if (bytes_read != bytes_to_read)
{
// generate read error, 7 == no such slave (no ack)
INFO_LOG(WIIMOTE, "Responding with read error 7.");
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;
}
}
break;

default:
PanicAlert("Wiimote::ReadData: unimplemented address space (space: 0x%x)!", m_read_request.space);
PanicAlert("Wiimote::ReadData: invalid address space (space: 0x%x)!", m_read_request.space);
break;
}

// Modify the read request, zero size == complete
m_read_request.address += bytes_to_read;
m_read_request.size -= bytes_to_read;
if (reply->error)
{
// 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;
}
else
{
// Modify the read request, zero size == complete
m_read_request.address += bytes_to_read;
m_read_request.size -= bytes_to_read;
}

// Send the data
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, rpt.GetData(),

0 comments on commit 86c94b8

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