Hacking WPAD_ButtonsHeld() bug: stuck button!? [with solution]

revvv

Well-Known Member
OP
Newcomer
Joined
May 11, 2019
Messages
73
Trophies
0
XP
391
Country
Germany
I'm new to Wii programming and @Mr_Reaper found an interesting bug in my games:

If you press very shortly a direction button, it happens that WPAD_ButtonsHeld() reports that the button is held forever.
This sounds like a newbie problem (which I am), but I have a test case. :evil:

@Mr_Reaper found out what I did wrong: I did not call WPAD_SetDataFormat().
It surprised me, that I saw so many examples without it. My conclusion is, that it works as long as you call WPAD_ButtonsHeld() very often.
My game logic consumes 44 millis, which is too long. I could also reproduce it with 20 millis.

And I also wonder if there are other games in the wild with this bug.
Without @Mr_Reaper I would probably think my WiiMote is dead or something. Thanks a lot!

Hopefully this will help other programmers... :yaywii:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <sys/time.h>
#include <sys/unistd.h>
#include <wiiuse/wpad.h>

static u32 *xfb;
static GXRModeObj *rmode;

void Initialise() {
    
    VIDEO_Init();
    WPAD_Init();
    // This line fixes the stuck button problem (by Mr_Reaper)
    //WPAD_SetDataFormat(WPAD_CHAN_ALL, WPAD_FMT_BTNS_ACC_IR);
    
    rmode = VIDEO_GetPreferredMode(NULL);
    
    xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
    console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
    
    VIDEO_Configure(rmode);
    VIDEO_SetNextFramebuffer(xfb);
    VIDEO_SetBlack(FALSE);
    VIDEO_Flush();
    VIDEO_WaitVSync();
    if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}

int main() {
    Initialise();

    printf("\n\nTest stuck button...\n\n");
    printf("Press a direction button on your Wiimote for a very short moment...\n");
    printf("And held is fired forever...\n\n");
    while (true)
    {
        WPAD_ScanPads();
        u16 buttonsDown = WPAD_ButtonsDown(0);
        u16 buttonsHeld = WPAD_ButtonsHeld(0);
        u16 buttonsUp = WPAD_ButtonsUp(0);

        printf("down=%04d held=%04d up=%04d\r", buttonsDown, buttonsHeld, buttonsUp);

        // reproducible with 44 millis
        usleep(1000 * 44);

        if (buttonsDown & WPAD_BUTTON_HOME)
        {
            exit(0);
        }
    }

    return 0;
}

You can find my games here:
VVVV4K
MEG4kMAN
 

revvv

Well-Known Member
OP
Newcomer
Joined
May 11, 2019
Messages
73
Trophies
0
XP
391
Country
Germany
@Mr_Reaper told me
Just to be accurate, WPAD_SetDataFormat() takes the following parameters depending on what you want to read from the wiimote:

WPAD_FMT_BTNS
WPAD_FMT_BTNS_ACC
WPAD_FMT_BTNS_ACC_IR

If you only wanted to read the buttons, you should only need to use WPAD_FMT_BTNS, except then you still get the bug!

I tried and the bug is still there...

I guess the default format (used when you don't specify another one by calling the function) behaves similarly (bugged).

You have to use the full parameter WPAD_FMT_BTNS_ACC_IR to prevent the bug.

Actually I didn't try the middle parameter, WPAD_FMT_BTNS_ACC

So I don't know if the bug shows up when you use that one.

I am guessing that when you're reading the full information from the Wiimote, it polls for information more often so it never gets stuck in an improper state without noticing the state changed.

(You might wanna add this info to your post.)
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Sicklyboy @ Sicklyboy: sup nerds