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

Nintendo Switch Online N64 Controller + 8bitdo Adapter = Wrong/Missing Button Mappings #57

Open
SubElement opened this issue Mar 20, 2022 · 25 comments

Comments

@SubElement
Copy link

Hello,

I'm suing a USB64 (Latest build-202110290732) with the 8bitdo Adapter (Latest firmware, v2.02) with the Nintendo Switch Online N64 Controller. It mostly works okay, but some of the button mappings are incorrect. This is tested on an N64 with Controller Test Tool by sanni.

Here's what works correctly:

D-Pad (Up, Down, Left and Right)
Analogue Stick
Start Button
L Button
R Button

Important buttons that don't work work or have no mapping

B - Mapped as Z
A - Mapped as Z
C-Left - Mapped as B
C-Down - Mapped as A
C-Right - No Mapping
C-Up - No Mapping
Z-Trigger - No Mapping

Non-important buttons

ZR - No Mapping
Screenshot Button - No Mapping
Home Button - No Mapping

Is there anyway this can be corrected?

Please let me know if you need any more information or if I can help fix this in any way.

Thank you!

@Ryzee119
Copy link
Owner

Ryzee119 commented Mar 20, 2022

Thanks for raising this usse.
It definitely can be corrected. Could you just try this build quickly? Its from https://github.com/Ryzee119/usb64/actions/runs/1769804523 and based on current master which has alot of changes from that release build. If the issue is still present we'll go from there

test-firmware-teensy41.zip
Disregard that. I tested it myself and its not working, Ill have to investigate a bit

@Ryzee119
Copy link
Owner

Are you able to compile the code yourself?

The mapping is here:

usb64/src/input.cpp

Lines 280 to 325 in c3dae9b

case JoystickController::XBOX360_WIRED:
//Digital usb_buttons
//FIXME Modifier to make A,B,X,Y be C buttons
if (_buttons & (1 << 0)) state->dButtons |= N64_DU; //DUP
if (_buttons & (1 << 1)) state->dButtons |= N64_DD; //DDOWN
if (_buttons & (1 << 2)) state->dButtons |= N64_DL; //DLEFT
if (_buttons & (1 << 3)) state->dButtons |= N64_DR; //DRIGHT
if (_buttons & (1 << 4)) state->dButtons |= N64_ST; //START
if (_buttons & (1 << 5)) state->dButtons |= 0; //BACK
if (_buttons & (1 << 6)) state->dButtons |= 0; //LS
if (_buttons & (1 << 7)) state->dButtons |= 0; //RS
if (_buttons & (1 << 8)) state->dButtons |= N64_LB; //LB
if (_buttons & (1 << 9)) state->dButtons |= N64_RB; //RB
if (_buttons & (1 << 10)) state->dButtons |= 0; //XBOX BUTTON
if (_buttons & (1 << 11)) state->dButtons |= 0; //XBOX SYNC
if (_buttons & (1 << 12)) state->dButtons |= N64_A; //A
if (_buttons & (1 << 13)) state->dButtons |= N64_B; //B
if (_buttons & (1 << 14)) state->dButtons |= N64_B; //X
if (_buttons & (1 << 15)) state->dButtons |= 0; //Y
if (_buttons & (1 << 7)) state->dButtons |= N64_CU | //RS triggers
N64_CD | //all C usb_buttons
N64_CL |
N64_CR;
//Analog stick (Normalise 0 to +/-100)
state->x_axis = _axis[0] * 100 / 32768;
state->y_axis = _axis[1] * 100 / 32768;
//Z button
if (_axis[4] > 10) state->dButtons |= N64_Z; //LT
if (_axis[5] > 10) state->dButtons |= N64_Z; //RT
//C usb_buttons
if (_axis[2] > 16000) state->dButtons |= N64_CR;
if (_axis[2] < -16000) state->dButtons |= N64_CL;
if (_axis[3] > 16000) state->dButtons |= N64_CU;
if (_axis[3] < -16000) state->dButtons |= N64_CD;
//Button to hold for 'combos'
if (combo_pressed)
*combo_pressed = (_buttons & (1 << 5)); //back
//Map right axis for dual stick mode
right_axis[0] = _axis[2] * 100 / 32768;
right_axis[1] = _axis[3] * 100 / 32768;
break;

It might need a bit of trial and error to get it correct

@SubElement
Copy link
Author

Uhh, I’ve never compiled code of any variety I’m sorry. 😅

I assume it wouldn’t be noob friendly to do?

@SubElement
Copy link
Author

Okay here is an update. With the 8bitdo adapter plugged in to my PC, I can map the buttons are in relation to an Xbox 360 controller if that's helpful:

N64                        X-Box 360
-----------------------------------------
D-Pad Up                   D-Pad Up
D-Pad Down                 D-Pad Down
D-Pad Left                 D-Pad Left
D-Pad Right                D-Pad Right
Analogue Stick             Analogue Stick
Start Button               Start Button
L Button                   L Button
R Button                   R Button
B                          Left Trigger
A                          Right Trigger
C-Left                     X
C-Down                     A
C-Right                    B
C-Up                       Y
Z-Trigger                  Back

@Ryzee119
Copy link
Owner

That is helpful thanks. No wonder its being wacky... why tf did 8bitdo decide on that mapping 🤔

I should be able to have a look tomorrow (late here)

@SubElement
Copy link
Author

Yeah, I have NFI why they chose that combination?

By the way I downloaded the code and visual studio to try and compile myself but I don't quite understand the code to button correlation... I tried! XD

Either way, I appreciate your help!

@Ryzee119
Copy link
Owner

Ryzee119 commented Mar 21, 2022

I've added this conditional to the mapping based on your handy table. Please test and let me know how it goes!
usb64_8bitdo_n64fix.zip

The biggest problem is that this will replace the mapping for the 8bitdov2 adaptor for ALL controllers not just the n64 switch controller. The mapping does make some sense as I am looking at it more but not very intuitive if using other controllers now.
Im not sure it is possible to determine if the connected controller is a n64 switch controller or not through the 8bitdo adaptor. That will need investigating.

if (joy->idVendor() == 0x2dc8 && joy->idProduct() == 0x3106)
{
    if (_buttons & (1 << 0))  state->dButtons |= N64_DU;  //DUP
    if (_buttons & (1 << 1))  state->dButtons |= N64_DD;  //DDOWN
    if (_buttons & (1 << 2))  state->dButtons |= N64_DL;  //DLEFT
    if (_buttons & (1 << 3))  state->dButtons |= N64_DR;  //DRIGHT

    //Analog stick (Normalise 0 to +/-100)
    state->x_axis = _axis[0] * 100 / 32768;
    state->y_axis = _axis[1] * 100 / 32768;

    if (_buttons & (1 << 4))  state->dButtons |= N64_ST;  //START
    if (_buttons & (1 << 8))  state->dButtons |= N64_LB;  //LB
    if (_buttons & (1 << 9))  state->dButtons |= N64_RB;  //RB

    if (_buttons & (1 << 6))  state->dButtons |= N64_B;   //LS
    if (_buttons & (1 << 7))  state->dButtons |= N64_A;   //RS

    if (_axis[4] > 10) state->dButtons |= N64_B; //LT
    if (_axis[5] > 10) state->dButtons |= N64_A; //RT

    if (_buttons & (1 << 12)) state->dButtons |= N64_CD;  //A
    if (_buttons & (1 << 13)) state->dButtons |= N64_CR;  //B
    if (_buttons & (1 << 14)) state->dButtons |= N64_CL;  //X
    if (_buttons & (1 << 15)) state->dButtons |= N64_CU;  //Y

    if (_buttons & (1 << 5))  state->dButtons |= N64_Z;  //BACK
    break;
}

@SubElement
Copy link
Author

SubElement commented Mar 22, 2022

Hey! Thanks, so I just tried this before leaving for work and it's weirdly made no difference at all? The buttons seem to be working as before.

Unsure whats going on, and pretty sure it's flashed correctly.

Thoughts?

Edit: Oh, as perhaps as a solution to the exclusive mapping. Maybe have an option in a menu, or a key combo to enable NSO N64 more or something? Unsure how complicated something like that would be?

@Ryzee119
Copy link
Owner

Can you confirm the device PID/VID? do they match joy->idVendor() == 0x2dc8 && joy->idProduct() == 0x3106)

@SubElement
Copy link
Author

Hello! I plugged the 8bitdo Receiver into my MacBook Air to get a PID and VID in the same format as yours and they appear to be different.

PID = 0x028e
VID = 0x045e

Screen Shot 2022-03-22 at 6 50 18 pm

@Ryzee119
Copy link
Owner

Try this one. My mistake, I thought you had the 8bitdo adaptor V2, but its V1 with V2 firmware :)

usb64_n64switch_fix.zip

@SubElement
Copy link
Author

Try this one. My mistake, I thought you had the 8bitdo adaptor V2, but its V1 with V2 firmware :)

Haha, no worries, easy mistake to make.

I just have it a try and all buttons work as expected, thank you! I greatly appreciate it.

Now, is there any chance I could use this mapping while also having other controllers plugged in?

@Ryzee119
Copy link
Owner

Yea thanks for confirming the mapping. Ill add some kind of button combo to switch the layout as you suggested.

@SubElement
Copy link
Author

SubElement commented Mar 23, 2022

Yea thanks for confirming the mapping. Ill add some kind of button combo to switch the layout as you suggested.

Legend, thanks!

Edit: Just a thought, it would have to be a button combo that is accessible to the limited buttons available before the fix.

@IonBlade2K
Copy link

IonBlade2K commented Sep 13, 2024

@Ryzee119 is there any chance you still have a working buildchain?

I've got the 8bitdo N64 modkit to make my OEM controllers Bluetooth + hall effect sticks.

The modkit has practically the same behavior as documented above when used with the 8bitdo v1 adapter on the 2.05 firmware, except that:

  • The B/A buttons don't set the bit at (1 << 6) (Xbox LS) and (1 << 7) (Xbox RS) as in your above code - they only send Axis5 values (which you also have sending B/A). (I'm not sure if the OEM N64 Online controllers set the 6 / 7 either - don't have N64 Online controllers to test, but 8bitdo seems to have cloned them with the modkit, so perhaps the Nintendo ones don't either?)
  • They have a "ZR" labeled button on the controller pak that sets the bit at (1 << 6) (Xbox LS)
  • They have a "*" button on the controller pak that sets the bit at (1 << 10) (Xbox Guide)

Flashing the build in #57 (comment) above works perfect for this controller, therefore, except that there's no way to switch away from the default rumble pak to memory pak / virtual pak / transfer pack, or flush to SD, because the code seems to have stripped out the " if (combo_pressed) *combo_pressed = " line.

Since there's an extra button "ZR" on the memory pak, I'd wanted to customize a build for the modkit being used with the 8bitdo v1 receiver on v2 firmware, as you did above, as follows:

    if (_buttons & (1 << 0))  state->dButtons |= N64_DU;  //DUP
    if (_buttons & (1 << 1))  state->dButtons |= N64_DD;  //DDOWN
    if (_buttons & (1 << 2))  state->dButtons |= N64_DL;  //DLEFT
    if (_buttons & (1 << 3))  state->dButtons |= N64_DR;  //DRIGHT

    //Analog stick (Normalise 0 to +/-100)
    state->x_axis = _axis[0] * 100 / 32768;
    state->y_axis = _axis[1] * 100 / 32768;

    if (_buttons & (1 << 4))  state->dButtons |= N64_ST;  //START
    if (_buttons & (1 << 8))  state->dButtons |= N64_LB;  //LB
    if (_buttons & (1 << 9))  state->dButtons |= N64_RB;  //RB

    if (_axis[4] > 10) state->dButtons |= N64_B; //LT
    if (_axis[5] > 10) state->dButtons |= N64_A; //RT

    if (_buttons & (1 << 12)) state->dButtons |= N64_CD;  //A
    if (_buttons & (1 << 13)) state->dButtons |= N64_CR;  //B
    if (_buttons & (1 << 14)) state->dButtons |= N64_CL;  //X
    if (_buttons & (1 << 15)) state->dButtons |= N64_CU;  //Y

    if (_buttons & (1 << 5))  state->dButtons |= N64_Z;  //BACK

    // Button to hold for 'combos'
    if (combo_pressed) *combo_pressed = (_buttons & (1 << 6)); //LS ("ZR" button on modkit's pak)
    break;

I've spent 10 hours now trying to get the code to compile like it did a few years ago, but it seems like the dependency on teensy 4.13.1 means it no longer compiles unless you have it cached locally, because the platformio repository has removed that version.

I tried to change the platformio.ini to "platform = https://github.com/platformio/platform-teensy.git#v4.13.1" to get around this, but that in turn depends on framework-arduinoteensy 1.54, which has also been removed from the platformio repository.

I then tried to download 1.54 of framework-arduinoteensy from github and then add a platorm_packages reference for framework-arduinoteensy @ file://path to resolve that. I then get an error about not being able to find other source files.

GPT has led me around in circles all day, and I'm at my wit's end not knowing enough about platformio to sort out the broken repo dependencies to compile it myself. I'm hoping you might still have the toolchain to be able to throw the above in place of the same spot you threw the code for #57 (comment) so I could use these modkit controllers with the USB64 fully, while still being able to trigger pak swaps.

Even blueretro can't handle rumble on the real system with these like the USB64 can, and these modkits support decent Hall effect sticks, so getting a way to swap paks as above into USB64 would make USB64 + these the best OEM-feeling wireless setup for wireless N64 use!

Willing to throw some cash your way for the time!

@supavgx
Copy link

supavgx commented Sep 13, 2024

Im also willing to pitch in some cash to help fix this and also the nso n64 controller id like rumble and be able to switch paks i prefer this over bkueretro

@IonBlade2K
Copy link

IonBlade2K commented Sep 13, 2024

@supavgx Think I got it, by using an older firmware as a base for the customizations.

If (and only if) you use the 8bitdo modkit with 8bitdo v1 receivers on the latest firmware, try the USB64 firmware in the zip below for full functionality (Rumble, all buttons, and all features but dual analog... since there's only one analog stick :) ).

8bitdomodkit-build-202109040414-base.hex.zip

Note: it uses new hotkey mappings for easier reachability. See below.

I've been using it the last hour with my 8bitdo modkit on a v1 8bitdo receiver on the latest 2.05 firmware, and everything seems to work great!

Controller Compatibility

  • This custom version is intended only for users of the 8bitdo modkit with 8bitdo hardware 1 receivers on the latest firmware.
  • It might also work on N64 Online controllers with the same 8bitdo hardware 1 receiver on the latest firmware, but no guarantees
    - When using this firmware, ALL Xbox 360 controllers (even if not behind an 8bitdo adapter) and all controllers behind an 8bitdo v1 adapter will use the remappings intended for 8bitdo N64 modkit controllers, so you'll want to use this only if you exclusively use the 8bitdo modkit controllers on 8bitdo v1 adapters. It also strips out the dual analog button mapping, so it's not intended for non-N64 controllers' cases.

Button mapping changes

Since the button on the modkit's controller pak is in a funky spot compared to "back" on 360 controllers, I redid the mappings to be more reachable by the right thumb while you use your index finger to reach for the ZR button, without having to change your left hand between prongs on the controller.

New mappings with this firmware are all triggered via the ZR (far right button on the transfer pak) of the 8bitdo modkit:

  • ZR + C-buttons - memory pak 1-4
  • ZR + R - Transfer pak
  • ZR + A - Rumble pak
  • ZR + B - Virtual pak
  • ZR + Start - Backup buffered memory to SD card

Note: uses a slightly older firmware as base

  • I had to use the older https://github.com/Ryzee119/usb64/releases/tag/build-202109040414 version as the basis - that is missing a few upgrades to SD compatibility / bugfixes in output that Ryzee had mentioned in newer releases. The older version I had to use is the newest whose dependencies are still available so I could compile it.

I've also attached the source containing the changes I made from the 202109040414 version for Ryzee's benefit, in case they are able to build the same build on the newer versions as a base. I couldn't get the newer bases to compile because of the dependencies that are no longer available. All changes were made in main.cpp and input.cpp, using the 202109040414 build as a basis.

Source-Based-On-202109040414.zip

@Ryzee119
Copy link
Owner

Ryzee119 commented Sep 13, 2024

is there any chance you still have a working buildchain?

@IonBlade2K this gets it compiling for me although I'm unable to test

-platform = teensy@~4.13.1
+platform = teensy@~5.0.0

@IonBlade2K
Copy link

IonBlade2K commented Sep 13, 2024

Thanks! Tried it with teensy 5.0.0 earlier today, but the LCD screen just shows up as blinding white. (Interestingly enough, got the same with a newer 4.x).

On the bright side, I was able to get it working by modifying the older 202109040414 build, so it's at least working well enough for my needs now. :)

@Ryzee119
Copy link
Owner

okay no worries, ill investigate it tomorrow

@Ryzee119
Copy link
Owner

Can you try this? I don't immediately have my N64 handy but I was able to replicate the white screen and it appears fixed now

firmwareteensy50.zip

Changes:
https://github.com/Ryzee119/usb64/tree/buildfix

Can build yourself with

git clone https://github.com/Ryzee119/usb64.git
cd usb64
git checkout buildifx
git submodule init
git submodule update

Then build as per normal.

@supavgx
Copy link

supavgx commented Oct 3, 2024

@supavgx Think I got it, by using an older firmware as a base for the customizations.

If (and only if) you use the 8bitdo modkit with 8bitdo v1 receivers on the latest firmware, try the USB64 firmware in the zip below for full functionality (Rumble, all buttons, and all features but dual analog... since there's only one analog stick :) ).

8bitdomodkit-build-202109040414-base.hex.zip

Note: it uses new hotkey mappings for easier reachability. See below.

I've been using it the last hour with my 8bitdo modkit on a v1 8bitdo receiver on the latest 2.05 firmware, and everything seems to work great!

Controller Compatibility

  • This custom version is intended only for users of the 8bitdo modkit with 8bitdo hardware 1 receivers on the latest firmware.
  • It might also work on N64 Online controllers with the same 8bitdo hardware 1 receiver on the latest firmware, but no guarantees
    - When using this firmware, ALL Xbox 360 controllers (even if not behind an 8bitdo adapter) and all controllers behind an 8bitdo v1 adapter will use the remappings intended for 8bitdo N64 modkit controllers, so you'll want to use this only if you exclusively use the 8bitdo modkit controllers on 8bitdo v1 adapters. It also strips out the dual analog button mapping, so it's not intended for non-N64 controllers' cases.

Button mapping changes

Since the button on the modkit's controller pak is in a funky spot compared to "back" on 360 controllers, I redid the mappings to be more reachable by the right thumb while you use your index finger to reach for the ZR button, without having to change your left hand between prongs on the controller.

New mappings with this firmware are all triggered via the ZR (far right button on the transfer pak) of the 8bitdo modkit:

  • ZR + C-buttons - memory pak 1-4
  • ZR + R - Transfer pak
  • ZR + A - Rumble pak
  • ZR + B - Virtual pak
  • ZR + Start - Backup buffered memory to SD card

Note: uses a slightly older firmware as base

  • I had to use the older https://github.com/Ryzee119/usb64/releases/tag/build-202109040414 version as the basis - that is missing a few upgrades to SD compatibility / bugfixes in output that Ryzee had mentioned in newer releases. The older version I had to use is the newest whose dependencies are still available so I could compile it.

I've also attached the source containing the changes I made from the 202109040414 version for Ryzee's benefit, in case they are able to build the same build on the newer versions as a base. I couldn't get the newer bases to compile because of the dependencies that are no longer available. All changes were made in main.cpp and input.cpp, using the 202109040414 build as a basis.

Source-Based-On-202109040414.zip

thanks ill give it a try

@IonBlade2K
Copy link

IonBlade2K commented Oct 11, 2024

Thank you Ryzee! Was able to compile a new fork on 5.0 perfectly with that fix that works perfectly, just sent a donation over your way.

This makes USB64 + the 8bitdo modkit the first way I know of to support near perfect to original accuracy, original OEM construction, rumble, mempaks (through USB64), wireless, and Hall effect sticks that won't wear out over time.

Image attached of the controller test on the 8bitdo modkit with the Hall Effect stick installed, with virtual pak settings set to:

  • Sensitivity 2
  • Deadzone 1
  • Snap toggle 0
  • Octa toggle 1

Near perfect to original OEM, and should last ages!

image

I've uploaded the fork with the button mappings for the 8bitdo (and probably the switch online controller. Don't have one to test) based on this over at https://github.com/IonBlade2K/usb64/tree/buildfix. I'll have to see if I can find some time to make some enhancements to allow SD card-based custom mappings before I make a pull request, as this build does overwrite default xbox 360 button behavior to be right for the 8bitdo. Going to take a while to digest the code in full to implement something like that, so no promises, but will be a fun weekend or two project when I can find some free weekends. :)

@supavgx, attached is a version based on the latest USB 64 build, and updated to Teensy 5.0 firmware. Ignore what I said in the last one about remapping the combo buttons. This build uses the stock USB64 combos (d-pad = mempak, L = rumble, start = virtual pak, etc.) for functionality, and just uses the ZR button on the pak for the 8bitdo as the "hotkey".

usb64-teensy5.0-8bitdomodkit.hex.zip

@Ryzee119
Copy link
Owner

Ryzee119 commented Oct 11, 2024

Thanks for testing it out. Amazing job on the button mapping fix
If you want absolute perfection you can tweak this to adjust the magnitude at the 45degree segments. Maybe it could be tweaked up a bit based on your screenshot

I've merged the teensy 5 fix into master branch

#define MAG_AT_45DEG 1.1f //Octagonal shape has a larger magnitude at the 45degree points. 1.1 times larger seems about right

Really appreciate your donation too

@IonBlade2K
Copy link

TY! Setting that to 1.15 got me to where I’m ant about perfect overlap with the OEM graph! I do have one small issue left, but it’s nothing I can’t work around by plugging the adapters in one by one. I’ll open an issue in case you’re interested, but honesty it’s not worth the time to solve. 😀

Thank you again!

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

No branches or pull requests

4 participants