Skip to content

Wii Motion Plus Fixed#260

Open
gitman123323 wants to merge 3 commits intodevkitPro:masterfrom
gitman123323:master
Open

Wii Motion Plus Fixed#260
gitman123323 wants to merge 3 commits intodevkitPro:masterfrom
gitman123323:master

Conversation

@gitman123323
Copy link

Hey,

I was messing around with Motion Plus on my Wii and noticed it never worked in any homebrew app. Looked into the libogc source and found some bugs in motion_plus.c that explain why.

The probe function was reading from WM_EXP_MOTION_PLUS_MODE (0x04A600FE) instead of WM_EXP_ID (0x04A400FA) which are completely different memory banks on the Wiimote. On top of that it was only reading 2 bytes when the identifier is 6 bytes long, which meant data[5] was always an out of bounds read. And then it was checking data[1] != 0x05 when the correct byte to check is data[5] since 0x05 is the last byte of the Motion Plus identifier (00 00 A6 20 00 05).

Fixed all three in motion_plus.c. Also added WPAD_HasMotionPlus() in wpad.c since there was no public way to check if Motion Plus is present, and added WPAD_EXP_MOTION_PLUS as a constant to match the existing WPAD_EXP_NUNCHUK and WPAD_EXP_CLASSIC.

Tested on real Wii hardware with both the original Motion Plus accessory and a built-in Wiimote Plus. Gyro data works and detection works correctly.

Copy link
Member

@DacoTaco DacoTaco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a glance from far away. im not that educated on wpad stuff. i think @Zarithya or @mardy have more functional knowledge of how the stuff works :)

bool WPAD_IsBatteryCritical(int chan);

s32 WPAD_HasMotionPlus(s32 chan);
#define WPAD_EXP_MOTION_PLUS 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused define?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #define WPAD_EXP_MOTION_PLUS 5 is important because it exposes Motion Plus as an official public API constant. Now that Motion Plus actually works, external code needs to know what the value 5 represents. Without it in the header, 5 stays an undocumented magic number. The constant makes Motion Plus a discoverable, documented part of the API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't add this: we already have EXP_MOTION_PLUS defined in a public header, and there's a way of checking if the motion plus is available, using the currently public API: just check the exp.type field of the WPADData structure.

If you really want to make it even more convenient, you could add this to the wpad.h header:

static inline bool WPAD_HasMotionPlus(s32 chan) {
     return WPAD_Data(chan)->exp.type == EXP_MOTION_PLUS;
}

Copy link
Author

@gitman123323 gitman123323 Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi mardy,

Just to clarify what my new code actually does: it ensures that the Wii MotionPlus can be reliably detected as physically present using libogc. Before these changes, detection wasn’t consistent, and the gyroscope values from MotionPlus were all zeros, so motion data wasn’t accessible at all. With my fixes, the MotionPlus now responds correctly to motion, and developers can safely detect and use it.

That’s why I added the new header — it’s directly tied to these fixes and makes the feature work reliably in practice.

Thanks for taking a look.

@gitman123323 gitman123323 requested a review from DacoTaco March 23, 2026 13:33
bool WPAD_IsBatteryCritical(int chan);

s32 WPAD_HasMotionPlus(s32 chan);
#define WPAD_EXP_MOTION_PLUS 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't add this: we already have EXP_MOTION_PLUS defined in a public header, and there's a way of checking if the motion plus is available, using the currently public API: just check the exp.type field of the WPADData structure.

If you really want to make it even more convenient, you could add this to the wpad.h header:

static inline bool WPAD_HasMotionPlus(s32 chan) {
     return WPAD_Data(chan)->exp.type == EXP_MOTION_PLUS;
}

{
ubyte *buf = __lwp_wkspace_allocate(MAX_PAYLOAD);
wiiuse_read_data(wm, buf, WM_EXP_MOTION_PLUS_MODE, 2, wiiuse_probe_motion_plus_check1);
wiiuse_read_data(wm, buf, WM_EXP_ID, 6, wiiuse_probe_motion_plus_check1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't test this very code in libogc, but when I ported it in my wpad2 branch I followed the same logic and it was working fine. Are you sure that the old code is not working?

Also, according to the documentation, the old code is correct, because the motion plus, until you activate it, is found at 0xA60000: https://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, just to make sure we're talking about the same thing — if you mean Motion Plus connectivity, yeah that might be fine. What I'm fixing here is actually reading the gyro data, because right now the values just come back as 0.00 no matter what even when Motion Plus is attached and active. That's the bug I ran into and what this PR addresses. Maybe we were just confused about which problem we were each referring to?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because i mean, could you clarify what you were talking about? because what my new code fixes is the following: wii motion plus can now be detected as wheter it is physically present or not using libogc and it also now allow access to the wii motion plus gyros which weren't accessible at all before because the values returned all zeros and now they actually respond to motion correctly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Let's try to address one issue at a time, since your PR seems to relate to several different issues.

With the unmodified libogc, is the motion plus detected correctly? I mean, what is the value of WPAD_Data(chan)->exp.type, if you connect the Motion plus? And does this change, if you call WPAD_SetMotionPlus(chan, true)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the value of WPAD_Data(chan)->exp.type returns nothing because i don't know, somehow it doesn't work right, and also yes directly setting WPAD_SetMotionPlus(chan, true) does do something but it's just forcefully telling the system that there is a motion plus present when there isn't one, not actually detecting wheter it got connected to the wiimote or not. Does that help you?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm... Are you calling WPAD_ScanPads() at every frame? This is the function responsible for updating the wiimotes structures.

Copy link
Author

@gitman123323 gitman123323 Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am calling WPAD_ScanPads() every frame as expected, and all standard input handling works correctly (Wiimote buttons, Nunchuk detection, etc.).

The issue seems to be specific to Wii MotionPlus. Before applying my changes, MotionPlus could not be reliably detected or used, even though the rest of the input system behaved normally.

From my testing, this appears to be unrelated to how often PAD_ScanPads() is called, and more likely tied to how MotionPlus data or registers are currently handled in libogc. After patching the relevant parts, MotionPlus detection and usage started working as expected.

I really appreciate you taking the time to look into this.

Copy link
Author

@gitman123323 gitman123323 Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some showcase videos demonstrating the fix working in real time:

https://youtube.com/shorts/dbdM1a0HkyI?feature=share

https://youtube.com/shorts/va6WUNGnWXY?feature=share

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants