ndeadly / MissionControl

Use controllers from other consoles natively on your Nintendo Switch via Bluetooth. No dongles or other external hardware neccessary.
GNU General Public License v2.0
2.58k stars 141 forks source link

N64 Controller Remap / Label as Pro Controller #481

Open shmuga9 opened 2 years ago

shmuga9 commented 2 years ago

Feature Description

The N64 controller doesn't allow button remapping. I'd like to see one of these options become available.

1) Relabel the N64 controller as a Pro controller. This would automatically unlock the ability to remap buttons, as it's available for pro controllers.

2) Native support. This would allow you to remap the C-buttons as extra buttons, rather than only being seen as the 2nd joystick.

I'm completely fine with #1, which should be easy to implement. #2 I'm throwing out there as an idea, but I have no clue how much work that would take, if possible.

Rationale

It would allow compatibility for more games.

The N64 lacks the X/Y face buttons, but plenty of games don't need ZL/ZR or L/R (or stick clicks). So being able to remap buttons as replacements for X/Y would mean the controller could be used for more than just the N64 Online app. And you would be able to close apps from the home menu (it requires the X button).

Games like Mario Party Superstars (a remake of the N64 games), New Super Lucky's Tale, and Kirby and the Forgotten Land are some examples that only need access to X or Y to be fully compatible, if the unused buttons could be used in their place.

Additional Details

No response

ndeadly commented 2 years ago

See if this build does what you want. It may be as simple as changing a few of the identifying fields like I have done, but there may be more to it depending on what the input data reports etc look like.

Also, be careful not to attempt any firmware updates or similar, as I have not yet added any safeguards against potentially writing a firmware for the wrong controller.

MissionControl-0.7.0-n64-as-pro-controller-ea799f6.zip

shmuga9 commented 2 years ago

Thanks for the quick response. I made sure to "uninstall" the previous version and cleared my bluetooth pairing database (I had the N64 controller paired before this), and rebooted to make sure I tested it cleanly. Unfortunately, while all the markers show it as a pro controller, it still says you can't remap buttons.

I'm guessing there's some other signifier where it knows it's not a pro controller. For instance, before I cleared my bluetooth database, I tried this test. It showed a pro controller icon in all places (bottom menu, change grip, etc), except the top left notification when you reconnect a (previously paired) controller. Up there it appeared as an N64 controller. After I deleted the database and restarted, it would pair... but there was no top-left notification at all. If you were in the controller applet it would just pop up in one of the squares. Whereas any other controller (including the N64 one when normal) would have the top left notification to accompany it.

Thought I'd mention that in case it leads to something. Also, I'm running 14.1.1 if that makes a difference. I updated some time ago, so it's not something I could've avoided for this.

ndeadly commented 2 years ago

Ok, that's a start. Maybe there are more identifiers used to determine whether the controls can be remapped. Here I've changed it to also modify the device name string presented to the system. I think this should bring it in line with the other non-nintendo controllers I support.

MissionControl-0.7.0-n64-as-pro-controller-e09f6e8.zip

shmuga9 commented 2 years ago

Tried it, but I didn't notice any differences on my end.

shmuga9 commented 2 years ago

How does making the other controllers compatible work? Do you edit a file to tell the switch that the Playstation circle button is the Switch's B?

If that's the case, you could make (or explain how to make) a few presets instead. Circumventing having the system read it as a proper pro controller that allows button remapping. Just a thought. Not sure how any of this works, lol.

ndeadly commented 2 years ago

There is source code defining how to map the incoming data format to the one the Switch recognises. We also need to fake a bunch of responses to make the console think it's talking to a legitimate controller. Currently I am letting most of the original data from the controller pass, but taking this to the extreme, we would end up with an emulated controller handler like the others. I don't think it needs to be that extreme though, there is probably just some small thing missing. I've been sick with covid this past week or so and haven't been able to look at this further. I will take another look at it in an hour or two when I get home

shmuga9 commented 2 years ago

No worries, and get better. Just spitballing ideas. Would've tested myself, but I couldn't figure out how to edit any of this stuff.

ndeadly commented 2 years ago

Try this one. I'm now faking the MCU data response too. This is required for spoofing joycons, so maybe it's the missing piece. If this doesn't work I think I'll need to enable some logging and get you to log what your controller is sending to the console.

MissionControl-0.7.0-n64-as-pro-controller-ed92189.zip

shmuga9 commented 2 years ago

Ya... looks like we'll have to try logging, lol.

ndeadly commented 2 years ago

Ya... looks like we'll have to try logging, lol.

Damn, thought this would be easy...

Try connecting the controller with this one, no need to verify whether remapping works - I haven't changed anything in that regard. This will log the responses from the controller to a file on the root of your sd card mc-mitm.log. Upload it here for me to take a look at and compare to a pro controller.

MissionControl-0.7.0-n64-logging-dbb1ef1.zip

shmuga9 commented 2 years ago

Okay done. I'm not sure if it matters what buttons I press (if the log has unique identifiers for each button) but I'll write out the order just in case. Looking it over, there aren't enough entries for that to make sense... but I already wrote it down anyway, lol.

mc-mitm.log

N64 controller connects A, B, L, R, ZL, ZR, Screen Capture, Home, Start, D-Pad (L/R/U/D), C-Buttons (L/R/U/D), Joystick Up (each direction pressed, clockwise). Home button (Joycon), Touch screen (album icon).

ndeadly commented 2 years ago

Nah, button inputs aren't important as I'm not logging them currently. It could be interesting to see which input format it's using though. You can view the raw data in real-time with this app I wrote https://github.com/ndeadly/MissionControl/files/7628384/hid_report_viewer.zip

shmuga9 commented 2 years ago

Neat. The shoulder buttons place an @ in specific parts of the code. Didn't see any other buttons trigger anything. Unless it was in the spots where it was randomly cycling letters/numbers. I'm guessing that's par for the course of one device connecting to another.

shmuga9 commented 2 years ago

It's been a bit. Just curious if you were able to decipher anything from that log.

ndeadly commented 2 years ago

Hey sorry, been a bit busy IRL lately. I took a bit of a look at the log and couldn't immediately see anything interesting. I will spend some more time on it tonight and try to figure it out.

shmuga9 commented 2 years ago

Were you able to find any other leads? Is there something I can help with?

Odd how a Nintendo controller is harder to customize/connect than a PlayStation/Xbox controller. You’d figure it would be the other way around, lol.

shmuga9 commented 2 years ago

Accidentally closed, but re-opened. Didn’t realize how that button worked.

ndeadly commented 2 years ago

Were you able to find any other leads? Is there something I can help with?

No, sorry. Still haven't had much time for anything. I will let you know if I need anything else from you.

Odd how a Nintendo controller is harder to customize/connect than a PlayStation/Xbox controller. You’d figure it would be the other way around, lol.

It's more of a question of how I handle the controller. I could easily make it work if I just handled it in the same way as I do unofficial controllers, but for official controllers I want to leave the communication as untouched as possible to avoid creating any issues or degrading performance. The only issue here is finding the right balance between original and faked communications to make the console allow modifying the button mappings. There is obviously something still getting through that makes it decide that this is not possible.

shmuga9 commented 2 years ago

Darn. Would this work as stop-gap alternative, modify buttons on the back end? As in, you wouldn’t be able to button remap natively, but when you connect the controller button 1 acts like button 2. Basically a preset. Or does that have the same/similar issues as well?

ndeadly commented 2 years ago

If by backend you mean on the Mission Control side of things, you could modify the source code to take the inputs and remap them to something else, sure. The problem with this method is that without a framework in place to allow it to be configurable (which is considerably more effort to implement) it is completely inflexible. You would either have to target a specific controller based on its bluetooth address, or force every N64 controller that connects through mission control to be remapped in the same way. You likely personally don't want the controls to be remapped 100% of the time either.

This is not something I would ever include in official code, as it would impact other users. I still believe the current approach is the best one. I just need time to figure out why remapping is still not being allowed.

shmuga9 commented 2 years ago

Ya I wouldn’t suggest that as an official release, but personally I wouldn’t mind if that applied to all N64 controllers, because I only have one connected anyway. Sure it might be annoying to clear MissionControl if I want the default back, but I’d sacrifice that convenience for the option to use it in other games. I was just curious if that was easy because I’d still use that.

ndeadly commented 2 years ago

Yeah it would be pretty straightforward to hardcode a remapping for the N64 controller. Basically just need to modify this function to check the controller type and remap the inputs you want before copying the input data over.

shmuga9 commented 2 years ago

That’s great!

…how would I modify it to check the controller type?

What is the name for the 2nd stick and it’s directions? Since the c-buttons registers as the second stick I imagine it’s the same, but I don’t know what they call it as opposed to face buttons.

ndeadly commented 2 years ago

…how would I modify it to check the controller type?

A quick and dirty way to do it would be just checking the vendor and product id.

if ((m_id.vid == 0x057e) && (m_id.pid == 0x2019)) {
     // Your remapping code here
}

You could probably even get away with only checking the product id, since this function should only be called for officially supported controllers anyway.

What is the name for the 2nd stick and it’s directions?

I'm actually not sure how this controller maps its inputs to the usual input report format (or whether it even uses the same one). I haven't defined any structure to handle the N64 controller specifically. C buttons might just be mapped as right stick values.

It's what I was asking you to check here. If you pay close attention to the output from that application, you should notice single digits changing in the numeric values for each button press, and possibly a chunk of numeric changes for analog controls like sticks and triggers.

A single screenshot of this output would be a good starting point for me to know the report id, but ideally noting down the numeric output for each button press (or at least the c stick) would give me a clearer picture of how it sends its inputs.

shmuga9 commented 2 years ago

Good News! I'm an idiot.

You were right. Taking a second look at your viewer, I did notice differences with more than the L/R buttons, and was able to get all the inputs! To simplify, I'll use this singular screenshot as an example, and highlight a spot/digit where each button is pressed along with it's value.

viewer data chart

The red squares act regardless of controller input. It's basically the default. I'm not sure if you need this, but it's too late. If you don't need it just scroll past to the buttons.

1 = "30" is constant. 2 = Left digit counts [abcdef0123456789], and it looks like the right one does too. So it starts at aa and ends at 99. 3 = Static number, it said 60 and now says 40 after exiting the app a few times. Not sure why. This happened for some other red squares too. To prevent this from getting too long, I won't bother mentioning it again unless you say it's needed. 4 = "e" is static, while "d" counts from a to f. 5 = "c" cycles (I think) from a to f as well (seems a bit random), while "7" is constant. 6 = "08" is constant. 7 = "." counts through various characters, numbers, lower-case and upper-case letters, then pauses on "." for a few seconds before starting again. 8 = "@" is constant. ++++++++++++++++++++++++++++++++++++

The blue squares do change based on button input and multiple buttons will share the same square, but have different values, which I'll put in parentheses.

A = A (08), B (04), R (40), C-Up (01), C-Left (02), C-Down (80) B = C-Right (01), ZR (08), Home (10), Start (02), Capture (20) C = L (40), ZL (80), D-Pad... Up (02), Right (04), Down (01), Left (08) E = L (@) F = R (@)

Buttons L (C & E) and R (A & F) highlight two digits at the same time, but are the only buttons to do that.

Here are the alternate D-Pad directions too, if that helps... Up-Right (06), Down-Right (05), Down-Left (09), Up-Left (0a).

D = "85" is the default, but changes when you move the joystick. It might be a little off, but here's the values for each direction at full tilt, and in the pocket (of the plastic hoousing) for all 8 directions. I'll abbreviate the directions with Up, Down, Left, Right, and going clockwise.

U = df UR = cd R = 86 (although sometimes it goes up to 89) DR = 3f D = 2d DL = 3f L = 87 UL = cd

G = The values change as you rotate the joystick around. It's a bit random to to say anything clear/definitive, unlike D. If you need that though, I'll look back at it. ++++++++++++++++++++++++++++++++++++

Now, I don't know if that'll help with native button mapping (not even sure if you can do that with the other controllers you've configured). But at the very least, the straightforward option should be possible now.

I tried editing that CPP file (as well as just using the base version there) but the button combinations here and here didn't do anything. So I'm not sure how to test that properly. I put the file in "config > MissionControl > controllers" based on where it appears in the github page, but I'm not sure if that's correct. Don't know if knowing all the button inputs changes how this is approached now.

shmuga9 commented 2 years ago

I don't know if the numbers on the back of the controller could be the vendor/product ID, but here they are just in case.

R-C-NIN-HAC-043 IC: 4360A-HAC043 FCC ID: BKEHAC043 S2SH100*

*I don't have a second controller, but based on another video, that's unique to each controller. So maybe that would appear in some code as the ID it uses to differentiate if (x2) N64 controllers connected to one console. Because the other ID's look like standard bluetooth addresses you'd see if you connect it to your PC. Those are also the same on all N64 controllers.

shmuga9 commented 2 years ago

If there's a better way I can format this, let me know. Not sure how you use/enter this data (the whole line? individual value changes?) as far as coding/implementation goes, and if there's something I could do to make it easier.

shmuga9 commented 2 years ago

Just curious if this info is any good? Even if you're not able to work on it right now.

shmuga9 commented 2 years ago

I noticed you made an update and back to updating MC. Just a reminder/check if you're still interested in adding this feature.

ndeadly commented 2 years ago

Hey, sorry, I genuinely forgot about this one. I've since rewrote my debugging build to give more meaningful and complete output. Please make another log with this build for me to take a look at.

shmuga9 commented 2 years ago

No problem. Hopefully it doesn't matter if I updated to HOS 15.0. Did it before checking this and then noticed you returned. mc-mitm.log

ndeadly commented 2 years ago

No, it shouldn't matter you're using 15.0.0. Worst case if it does I just need to do my testing on 15.0.0 also. Thanks for the log, I will try to look at it over the next week after I'm done with the 15.0.0 exefs patches for the final 0.8.0 release

Banz99 commented 2 years ago

@shmuga9 I may have found what was missing from the attempts done the last time. Can you try out the build I posted in my pull request above?

(The actual mapping itself might be broken, haven't looked at that yet, it's mostly to see if it gets recognized as a proper Pro Controller)

shmuga9 commented 2 years ago

That works! It recognizes it as a pro controller and you can remap buttons (and that also works).

...however there is another potential roadblock. Unfortunately unlike, say, Steam, you don't remap buttons by the system listening for a button press/movement. Instead, if gives you a list of buttons to choose from. The left/right sticks aren't listed, and since the C-buttons are effectively the "right stick" it currently can't be remapped. Although maybe that's possible, just not with the default version.

Banz99 commented 2 years ago

No potential roadblocks, it just needs to be done! I was actually thinking of implementing the mappings in this way, let me know what you think: image

shmuga9 commented 2 years ago

Looks good to me!

Curious, if say you use this setup for one game, and then want to play the NSO N64 games with the normal layout, is there a way to toggle it on/off in Mission Control or some other settings? Or do you have to delete/copy the Mission Control app folder manually each time to disable/enable it? Worst case, it’s at least works now.

Also, I can make an N64 controller vector image for the button remap screen if need be. Last I checked, only the small icon exists (when it’s connected) and no larger one because it’s not officially configurable, so they didn’t need it. It may not be necessary depending how it connects in the end, but just throwing it out there.

Banz99 commented 2 years ago

Looks good to me!

Curious, if say you use this setup for one game, and then want to play the NSO N64 games with the normal layout, is there a way to toggle it on/off in Mission Control or some other settings? Or do you have to delete/copy the Mission Control app folder manually each time to disable/enable it? Worst case, it’s at least works now.

Also, I can make an N64 controller vector image for the button remap screen if need be. Last I checked, only the small icon exists (when it’s connected) and no larger one because it’s not officially configurable, so they didn’t need it. It may not be necessary depending how it connects in the end, but just throwing it out there.

User toggable layout switching will be possible once ndeadly's Tesla overlay is finished and working, for now you'll have to change "spoof_nso_as_pro_controller" to true/false inside config\MissionControl\missioncontrol.ini (it could also become a per-controller option instead of a global one) and restart your switch. There is asbolutely no need to delete Mission Control.

Anyway I made a new test build with the updated default remapping in mind (delete the one you made in the switch settings if you did), can you tell me if everything is working as it's supposed to?

shmuga9 commented 2 years ago

Okay so for now you still have to connect it to the computer and make changes to toggle it, but it'll have an option in the future. Cool.

Alright I tested it. Version "8a3dc14" works! The special button to change the left analog stick to the right works, so long as you're holding it. It's not a toggle (that's how I read it), but I think it works better as a hold option anyway. It's not something where you'll need to use the right stick (or analog clicks) for extensive periods, just quick adjustments. The analog clicks also work. Thankfully, they're rarely used in games to matter. I had to look up what games even use them to test, lol.

The "spoofing test" version however, doesn't work. It's recognized as an N64 controller, can't be remapped, and the buttons don't work as configured in your image.

shmuga9 commented 2 years ago

Update, you made an error. You changed ZR to be left stick click by default by accident. You can tell in a game like Rocket League where you can remap buttons in-game. The rest are fine though.

Banz99 commented 2 years ago

Can you check if things are fixed with the new test build?

shmuga9 commented 2 years ago

Checked. It still operates like a normal N64 controller where nothing's changed.

Banz99 commented 2 years ago

Not really sure what's going on here. Can you try again with the newer one? Also, what does your file in config\MissionControl\missioncontrol.ini look like?

Also, this is getting kinda pointlessly long, want to jump in ndeadly's discord server for a faster message exchange and less github spamming? https://discord.gg/gegfNZ5Ucz

shmuga9 commented 2 years ago

So the ZR button is fixed, but now C-Up works as if you held the right stick up (although if you hold it with L/R it will still act as those stick clicks).

Here's the ini, btw.

[general] ; Enable vibration support for unofficial controllers [default true] ;enable_rumble=true ; Enable motion controls support for unoffical controllers [default true] ;enable_motion=true

[bluetooth] ; Override host name of Bluetooth adapter ;host_name=Nintendo Switch! ; Override host mac address of Bluetooth adapter ;host_address=04:20:69:04:20:69

[misc] ; Enable the LED lightbar on Sony Dualshock 4 controllers [default true] ;enable_dualshock4_lightbar=false ; Enable the LED lightbar on Sony Dualsense controllers [default true] ;enable_dualsense_lightbar=false ; Enable the white player indicator LEDs below the Dualsense touchpad [default true] ;enable_dualsense_player_leds=false ; Set Dualsense vibration intensity, 12.5% per increment. Valid range [1-8] where 1=12.5%, 8=100% [default 4(50%)] ;dualsense_vibration_intensity=4 ; Change the controller type reported by NSO controllers, allowing to be completely remapped as valid pro controllers spoof_nso_as_pro_controller=true

Banz99 commented 2 years ago

Ok, I think I found what was wrong with all the problems before. Can you try the last one and see if problems are gone?

shmuga9 commented 2 years ago

The C-Up button is fixed now. It appears as a pro controller and can be remapped.

Some questions. Do I have to disconnect (in "Settings > Controllers") before I try out a new version? I have just in case, but wondering because it would save me a few steps.

Does it even matter if it registers as a pro controller since the button layout works anyway? Or are you trying to do that so when the Tesla overlay is done, it can be remapped (within the system) independently from pro controllers? To be clear, in version "8a3dc14" it was also recognized as a pro controller. Forgot to mention that, but clarifying now in case that's what you're doing. Otherwise I'm not sure what else you were trying to do with "8a3dc14" and "spoofing test".

Banz99 commented 2 years ago

The C-Up button is fixed now. It appears as a pro controller and can be remapped.

Some questions. Do I have to disconnect (in "Settings > Controllers") before I try out a new version? I have just in case, but wondering because it would save me a few steps.

Does it even matter if it registers as a pro controller since the button layout works anyway? Or are you trying to do that so when the Tesla overlay is done, it can be remapped (within the system) independently from pro controllers? To be clear, in version "8a3dc14" it was also recognized as a pro controller. Forgot to mention that, but clarifying now in case that's what you're doing. Otherwise I'm not sure what else you were trying to do with "8a3dc14" and "spoofing test".

There was no need for a disconnection as what I was doing was more higher level compared to the things that could mess with that. In any case the choice of making it a pro controller is that so; 1, Official remapping via system settings can be done

  1. Almost every game allows Pro Controllers, but may decide to exclude NSO controllers
  2. My Mission Control mapping of the N64 controller works BECAUSE it reports as a Pro Controller, despite the format being very similar if the official software decides to ignore the right stick on a n64 controller because there can't be one, I can't just throw that in and expect it to read it.

In any case the difference between the two versions was that the test was a rewrite of the approach to be more in line with ndeadly's more sensible code style requests.

shmuga9 commented 2 years ago

Whoops, I wasn't clear. I thought you were trying to get it registered as an N64 controller, despite that it works fine as a pro controller.

In any case the difference between the two versions was that the test was a rewrite of the approach to be more in line with ndeadly's more sensible code style requests.

Gotcha. I wasn't sure why I was testing something to get to the exact same place as before (from my perspective), lol. I know there's other work yet to be done, but it's awesome you guys were able to get this working! Thanks! Can't wait to play non-NSO games with it.

Banz99 commented 2 years ago

Can you try this latest build to see if it's still working as it was yesterday?

shmuga9 commented 2 years ago

Yep it works fine.

gjimenezf commented 1 year ago

@shmuga9 how did you make it work the C buttons as the right analog stick? My n64 controller gets recognized as Pro controller but there is not option to remap the c buttons to right analog stick