Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button shortcuts unusable with wireless controllers #25

Open
yo1dog opened this issue Aug 19, 2022 · 9 comments
Open

Button shortcuts unusable with wireless controllers #25

yo1dog opened this issue Aug 19, 2022 · 9 comments

Comments

@yo1dog
Copy link
Contributor

yo1dog commented Aug 19, 2022

Unlike a wired controller, input from wireless controllers (Wavebird, BlueRetro, etc.) is not available immediately on boot. This renders the shortcut button functionality unusable.

If we include support for config files, we could add an option flag to wait for a button to be pressed. Perhaps with a timeout. Regardless, this may be a generally useful option. For example, people who would rather not (or are incapable of) holding a controller button and pressing the power button at the same time.

I thought about using PAD_Read() and PAD_ERR_NO_CONTROLLER to detect if a controller is present, enabling us to optionally wait for a controller. However, according to this comment by @darthcloud:

data is sent as soon console is power on ... So blueretro simulated controller are present right away at boot.

I assume this means libogc will see the controller as present before the wireless controller is connected. However, that was 10 months ago so not sure if that is still the case. Also, AFAIK GameCube does support hot swapping of controllers so I wonder if the GameCube specific BlueRetro firmware does not or could not simulate the controller until it is connected. I digress.

@darthcloud
Copy link

With the internal mod if the console is powered via BT connect you would likely get the buttons press on fist read.

For external no, but I could change BR behavior, but my fear is that some random games might have a stupid check at boot and don't check again. Don't know if there one on GC like that, but its pretty much the norm with N64 which is quite annoying.

@yo1dog
Copy link
Contributor Author

yo1dog commented Aug 19, 2022

Off topic: What about games that use controller detection? For example, SSB Melee only shows character selector hands for each connected controller as seen here. Would all 4 hands always show?

@Extrems
Copy link
Collaborator

Extrems commented Aug 19, 2022

With the internal mod if the console is powered via BT connect you would likely get the buttons press on fist read.

For external no, but I could change BR behavior, but my fear is that some random games might have a stupid check at boot and don't check again. Don't know if there one on GC like that, but its pretty much the norm with N64 which is quite annoying.

Such a game would fail lotcheck. It's in violation of guidelines.

@darthcloud
Copy link

Off topic: What about games that use controller detection? For example, SSB Melee only shows character selector hands for each connected controller as seen here. Would all 4 hands always show?

Yes with BR all hands always show

@9ary
Copy link
Member

9ary commented Aug 19, 2022

As mentioned on IRC we can't rely on hotplug for wavebirds either, if the receiver is plugged in the GameCube will see a controller is connected regardless of whether the controller itself is on.
I'm not sure exactly how much delay would be reasonable to wait for the wavebird to be ready, but we can absolutely detect that a wavebird receiver is connected and predicate the delay on that condition.

For blueretro it would be preferable to have a proper hotplug implementation, because I expect bluetooth controllers to take significantly longer than wavebirds to establish a connection. As Extrems said, games are expected to support it anyway.

@yo1dog
Copy link
Contributor Author

yo1dog commented Aug 19, 2022

Such a game would fail lotcheck. It's in violation of guidelines.

Cool fact. Sounds like the GameCube BlueRetro firmware should be good to update to not emulate controllers until they are connected. That would solve a host of issues including this one, the SSB type ones, and makes BlueRetro internal install easier if you want to skip wired controller detection.

Agreed RE Wavebird. Was just looking into si.h from libogc2 and I see some things that look promising:

// GameCube specific
#define SI_GC_WIRELESS          0x80000000u
#define SI_GC_NOMOTOR           0x20000000u // no rumble motor
#define SI_GC_STANDARD          0x01000000u // dolphin standard controller

// WaveBird specific
#define SI_WIRELESS_RECEIVED    0x40000000u // 0: no wireless unit
//...

#define SI_GC_CONTROLLER        (SI_TYPE_GC | SI_GC_STANDARD)
#define SI_GC_RECEIVER          (SI_TYPE_GC | SI_GC_WIRELESS)
#define SI_GC_WAVEBIRD          (SI_TYPE_GC | SI_GC_WIRELESS | SI_GC_STANDARD | SI_WIRELESS_STATE | SI_WIRELESS_FIX_ID)

Just started looking into it, but sounds like we can detect and wait for Wavebird/wireless controllers to actually connect. Something like:

u32 type;
u8 wavebird_chan;
for (wavebird_chan = 0; i < 4; wavebird_chan++)
{
    PAD_GetType(wavebird_chan, &type);
    if (type == SI_GC_WAVEBIRD) break;
}

if (wavebird_chan < 4)
{
    kprint("Detected Wavebird controller in port %i", wavebird_chan + 1);
    kprint("Waiting for Wavebird to connect...");
    while (!SYS_GetWirelessID(wavebird_chan))
    {
        VIDEO_WaitVSync();
    }
    kprint("Wavebird connected");
}

I wonder if we could utilize generic sounding SI_GC_WIRELESS instead of SI_GC_WAVEBIRD. I don't really know anything about this yet.

@Extrems
Copy link
Collaborator

Extrems commented Aug 19, 2022

The type is SI_GC_RECEIVER until it's "connected". You also want to use SI_Probe for proper decoding.

@9ary 9ary pinned this issue Aug 19, 2022
@yo1dog
Copy link
Contributor Author

yo1dog commented Aug 19, 2022

Ah. So maybe something more like:

u8 receiver_chan;
for (receiver_chan = 0; i < 4; receiver_chan++)
{
    if (SI_Probe(receiver_chan) == SI_GC_RECEIVER) break;
}

if (receiver_chan < 4)
{
    kprint("Detected wireless controller in port %i", receiver_chan + 1);
    kprint("Waiting for wireless controller to connect...");
    u32 type;
    do
    {
        VIDEO_WaitVSync();
        type = SI_Probe(receiver_chan);
    }
    while(type == SI_GC_RECEIVER);
    
    switch (type)
    {
        case SI_ERROR_BUSY:
        case SI_ERROR_UNKNOWN:
        case SI_ERROR_NO_RESPONSE:
            kprint("Error: %s", SI_GetTypeString(type));
            break;
        default:
            // @Extrems looks like SI_GetTypeString also decodes. Is decoding twice an issue?
            kprint("%s connected", SI_GetTypeString(type));
    }
    
    // Is controller ready to scan or is delay required?
}

@Extrems
Copy link
Collaborator

Extrems commented Aug 19, 2022

Decoding twice is fine. SIGetType was a private Nintendo API, whereas SIProbe and SIGetTypeString were public.

@9ary 9ary mentioned this issue Dec 6, 2023
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants