Hacking Hacking the WiiU gamepad

  • Thread starter Thread starter Arisotura
  • Start date Start date
  • Views Views 101,119
  • Replies Replies 161
  • Likes Likes 46
An end user implementation of this will also need an emergency escape just in case you bork your GamePad's ability to connect to the Wii U, which would likely need extra work on the Wii U side as well if you want to eat into the backup installation of stock firmware. (Alternately, just verifying and using said installation would work)

But, honestly, it's not surprising that the GamePad has so little ability to interface with its own expansion connector and such. It's just a step or two removed from being a dumb terminal, honestly.
 
My plan is to make a sort of boot menu -- it would allow to install small homebrew 'apps', but also retain the stock firmware and launch that. I aim at implementing my stuff in a way that it doesn't conflict with stock functionality, and also allows to restore the gamepad to stock functionality.
 
Speaking of, little progress report, with screenshots of the real deal, running on the FPGApad.

IMG20250328180639.jpg


This is the main screen. The options are obviously still phony, but most of the stuff is in place, including status icons for wifi and battery/power.

IMG20250328180647.jpg


Hardware info screen.

Hardware ID is 0x00041040 on every gamepad board I've tested so far. I really want to know if there are any gamepads out there with a different hardware ID.

Specifically, if it ends in 41, it means trouble -- that means the board has the Samsung I2C controller instead of the Renesas one. I haven't really added support for the Samsung controller, because it's a pretty nontrivial difference (completely different controller) and I can't test it. I think this is prototype stuff (the service firmware doesn't support the Samsung controller), but, who knows.

It means trouble because no I2C means no screen, no audio, no camera. I intend to have a failsafe in the installer if this case is encountered, so it would revert to the previous firmware instead of rendering the gamepad unusable...

IMG20250328180707.jpg IMG20250328180720.jpg IMG20250328180729.jpg

Wifi configuration screen. Most of it is done at this point, and the wifi driver seems pretty solid.

IMG20250328180655.jpg


This is the "Dump FLASH" feature I was working on. Basically, what it does is start a TFTP server, then you connect to it and retrieve your FLASH dump with a "get whatever.bin". The file name doesn't matter, TFTP is just used as a means of transferring the data.

I ran into a couple of issues with this though.

First one, I always get a "Wrong block number" error after a while. I looked into it and it seems at some point the ack message for a given block is received twice, which it doesn't like. I'll need to investigate more and see how to properly address this.

Second one, the transfer is painfully slow. This is a 5GHz network and the FLASH is 32MB, so it shouldn't take as long as it does. I think I know why that is: due to the way this app is programmed, it checks for wifi frames every ~5ms. And a TFTP frame is 512 bytes. You guess how this goes...

The proper way to address this is to add threading, so I don't rely on a "check stuff every N milliseconds" model. Instead I could have a wifi thread that would get waken up whenever the IRQ fires, and handles received data as it comes in. I think I'll bite the bullet and get this going... this is probably going to be "fun". I kinda want to write my own thing. I don't know yet.

-

Regardless, that's it for what's currently being done. Among the missing functionality, we have:

* "Install app" and "Wifi boot". These will work the same way as the "Dump FLASH" screen, but the other way around -- connect to the gamepad's TFTP server and send a file to it. "Install app" would install the received file in FLASH memory, while "Wifi boot" would store it in memory and boot it right away. The latter would be useful for testing code without writing to FLASH a billion times.

* "Boot settings" would be whether to show this boot screen every time or require a special key combination (and maybe let you choose said combo).

* "About" would be a simple about screen, with some options to install an update to melonpad, or uninstall it entirely and restore the gamepad to stock functionality.

* And obviously, I need to have the boot menu screen actually list what's installed, instead of bullshit entries.
 
Absolutely phenomenal work! It looks great!!!

Also that vibrator app LMAO WHAT

You deserve another break aswell if needed. Great job! Of course we understand the whole your brain focusing on whatever thing 👍
 
Thanks! I'm using LVGL to make the UI. I was going to make my own, but I was introducted to LVGL and I figured that given the kind of stuff I'd need (text areas, on-screen keyboard, ...), I might as well use that. Works pretty well.
 
Oh, that's great, thank you!

Regarding the melonpad project: I did build the thread scheduler, and it's mostly working, so that's nice. I had a fun little challenge building that threading scheduler and stuff.

I'm adding networking code now. Basically, proper TFTP code. TFTP is still going to be slow (especially for dumping the entire Flash), but it should do the job just fine. This has also been revealing some oddball issues in my code: cache issues, threading bugs, etc. Fun shit.

I also need to rework the codebase a bit to make proper use of this threading stuff. For example, the audio code I added could call stream callbacks from a dedicated thread instead of calling them straight from IRQ handlers, which would enable them to do more stuff.

As a change of pace, I also wanna give the whole "dump gamepad boot ROM" project another go. I can atleast lay some groundwork until I receive the adequate supplies... that'll be a change of pace, from the networking stuff.
 
I'm learning here and I'm curious, how are you reverse engineering the memory map? Are you using logic analyzer to capture the address lines and replay them?
 
There's two main parts to this.

I look at the stock bootloader/firmware code in a disassembler. When you have some base knowledge of how things should work and what to expect, you can recognize the patterns in the code you're looking at, and infer a theoretical understanding of the hardware.

When I have enough of a theoretical understanding, I write my own code to test the hardware I want to figure out. I start by copying the original code to get things going, then try to change various things to understand what they do and what is what.

Most things are observable in software, but not all. I was glad to have the oscilloscope when reverse-engineering, say, clock registers, or the I2S parameters in the audio registers.

As for the address lines, I don't think the address/data bus are exposed outside of the DRC SoC. It's completely self-contained, even the RAM is part of it. Much like a microcontroller.
 
Been spending the last hours/days banging my head against a really annoying and obscure problem with the wifi driver. Essentially, during a TFTP transfer, it would choke at some point and get stuck. It was hard to really track it down...

I think I've just figured it out. It's related to IRQs, sometimes it would miss the "end of DMA transfer" IRQ and report failure because of that, as if the IRQ didn't occur at all.

I quickly tried changing the trigger type for the SDIO IRQ to 5. That seems to have fixed it... I don't really know how the 'trigger type' values work, but I think 5 is level-triggered and 1 is edge-triggered. Maybe there's something else I'm missing (like a situation where the IRQ controller has multiple interrupts queued? it would seem weird if it's possible to miss an IRQ entirely).

Atleast I have a lead on this problem now...

Edit- just gave it a real try and it seems to be fixed, so that's great.

It takes 10 minutes to transfer a full FLASH dump (32MB) over TFTP, which seems acceptable. That's about 56KB/s. TFTP isn't exactly an efficient protocol, but it has the advantage that it's simple enough for this application and doesn't require custom apps to interface with it. For the purposes of uploading programs to the gamepad, it should be more than enough.

I also considered FTP, but the main issue is that the gamepad's storage doesn't really have a filesystem, which makes it awkward to adapt a filesystem-oriented protocol like FTP.
 
Last edited by Arisotura,
Atleast ya got it somewhat fixed! Some progress 👍
And oh no! Sorry its annoying to work with / track it down. Hope future developement isnt too stressful like this.
 
Thanks!

Atleast ya got it somewhat fixed! Some progress 👍
And oh no! Sorry its annoying to work with / track it down. Hope future developement isnt too stressful like this.
Sometimes it be like that, heh. It gives me flashbacks to 2014, when I was riding the early 3DS homebrew wave. It's a bit similar in that I don't really have real debugging facilities as I'm working with retail hardware.

Back then, on the 3DS, when I ran into issues I couldn't printf() to blargSNES's debug console, I resorted to using the "fill LCD with fixed color" registers to figure out what was going on.

Similar tricks here. Atleast, I have the FPGApad debug output, but that has its issues too. It's kinda slow (I have to run the bus at 2MHz to avoid overwhelming the FPGA's serial interface), can't really be interjected everywhere without consequences, and can also cause oddball issues under certain situations because the SPI bus is shared with the UIC.

Oh well, as long as I'm able to figure things out :P Still having a lot of fun with this!
 
  • Like
Reactions: I pwned U!
Might be that it occurred while another SDIO-related IRQ was being handled, and got missed because it was set to edge trigger.

Seemed weird to me that changing the trigger type fixed it, because the stock firmware has it set to edge trigger. However it only really uses the IRQ for the card IRQ. During SDIO transfers, it just polls the IRQ status register in a busy loop.

That's where my code differs, since it uses IRQs to sense transfer completion too. I guess that explains it.
 
  • Like
Reactions: I pwned U!
Unrelated but did you see that Switch2/Switch is supposedly using Wii U techniques to pull off their Game Share Multiplayer? I hope it’s that close so your project and MattKC’s can serve as a starting point for whoever in their Howmebrew scene gets behind that
 
I don't know how much the Switch 2 would have in common with the WiiU stuff... we'll see, I guess.

Regardless, a bit of a progress update. I thought I'd work on the actual boot menu thing, and loading. So I did just that.

I ran into issues with the wifi card (again).

The way I do the loading is as follows: I load a small "Flash loader" at 0x3F0000 and invoke it with a Flash address. It then loads whatever is installed at that address, and does a soft reset to actually start running that binary. Much like how the bootloader does it... However, doing so doesn't cycle power to the gamepad peripherals (like changing the UIC state might).

For most gamepad peripherals, it isn't hard to properly reset them, just a matter of toggling bits in register 0xF0000058. The SDIO host controller can be reset this way too, but not the wifi card itself.

So I ran into issues due to not resetting the wifi card properly, which would cause the startup sequence to fail. It's real fun because the Broadcom stuff isn't really documented besides the driver source code... In the end, after some fumbling, I did figure out how to properly reset the wifi card.

I then gave it a test with a stock firmware, and it works, so that's great.

This gives us a somewhat clear view of what's left to do:
* the app install functionality
* wifi boot
* boot settings screen
* finish the FLASH dump stuff
* make sure wifi stuff works fine (ie. handles disconnects, etc)
* about screen

And minor stuff like cleaning up the code, making it a bit less messy and more consistent, removing unneeded stuff to reduce the code size, etc...

When it's somewhat ready, I'll give out a beta for whoever is interested in testing (and has means to flash it to their gamepad).

I'll also need to touch up the custom bootloader (which seems mostly functional now) and build the installer app thing.
 
You'd need a way to directly connect to the gamepad's Flash memory. For example, Gary has a clip that can attach to the Flash chip and be used to program it.

Atleast until I make the actual installer, which would let you install this from a WiiU.
Post automatically merged:

Felt like doing some RE work, it's a nice change of pace from the UI work...

Namely, looked at DMA stuff.

Bit 2-5 in the DMA control registers, I thought those were for incrementing/decrementing the source address but in some weird ways... I had thought that because of the data I was testing DMA with, back then.

Turns out, they aren't that at all! They are logic operators. The DMA engine can do logic-op blending, which is interesting.

Ended up figuring out all the unknown bits in there, and also some unknown registers, so that's nice. Still bummed that there's apparently no way to do alpha blending or keyed/masked copy, though...
 
Last edited by Arisotura,
SInce the Wii U communicates with the Gamepad, there is chance in the future that we can deploy the custom firmware via the Wii U? Or the communication between the two doesnt envolve any data, only streaming?
 

Site & Scene News

Popular threads in this forum