A Nintendo 64 Rumble Pak so Bad that it's Good
I'm currently working on a game for the Nintendo 64.
Naturally, I wanted to support the N64 Rumble Pak. You know, this controller accesorry that gave you “force feedback” in a time where game controllers didn't have a vibration motor built in.
What looked like a straight forward endeavor lead me stumbling down a rabbit hole of “not sure if genius or really dumb”-engineering.
Libdragon, the truly excellent the system library I'm using, has this very convenient function joypad_set_rumble_active(port, active). Simple enough. You just call this function once to enable the rumble motor and call it again half a second later to turn it off.
Problem is, this didn't work for me. I just felt the tiniest motor movement when I activate the motor and then nothing.
Of course I first thought I'm doing something wrong. Or maybe my Rumble Pak is defective? I mean, it's a cheap third party “Gamester” Rumble Pak, not a Nintendo original.

But no, in Star Fox 64 and other original N64 games I tested, this thing worked just fine. However even in the official Libdragon examples my Rumble Pak only gave the faintest jolt. So this surely must be a bug in Libdragon then!
So I asked around in the N64Brew Discord and triggered a lot of confusion. The people maintaining Libdragon were absolutely positive that the rumble function works. They tested the code with A LOT of different third party Rumble Paks to make sure of it.

Since my cheap Gamester Rumble Pak was absent in their collection, they asked me to open it up and take some photos. Of course I obliged. At first glance this PCB looks extremely boring. It's basically empty. No ICs. Not even a glob top. Just a cheap capacitor and a few transistors.

Compare this to the original Nintendo Rumble Pak. Not only does it need batteries, it also has a real, custom(!) ASIC on the PCB to control the motor.
Original Nintendo 64 Rumble Pak – Photo from classicgamingstore.com
So how does the Gamester Pak even work? Controller accessories are memory mapped. Rumble Paks need to:
- respond with
0x80when the probe address0x8000is read and - they need to turn the motor on/off when your write 8 bytes of
0x01or0x00to the motor control address0xC000
Well, N64Brew user lidnariq traced the PCB based on my photos and determined that:
- There's always a weak pullup on
D7, faking the value0x80on reads - when
A15andD0are both high, it charges a capacitor and the vibration motor is fed from the 3V supply
Simulated Circut of the Gamester Rumble Pak – made by lidnariq
This thing is wildly out of spec! Any write >= 0x8000 with value 0x01 will rumble for a little while, until the capacitor is empty. There's no explicit off switch. You have to toggle it on every single frame. So how the hell did this work with Star Fox 64 then?
Well, turning the Rumble Pak on every single frame is exactly what a lot of the original N64 games did. You can see this behavior in the Star Fox 64 decompilation. osMotorStart() or osMotorStop() is called 60 times per second: github.com/sonicdcer/sf64/.../sys_joybus.c
This cheap Gamester Rumble Pak got away with this totally spec abusing design by relying on a quirk in a lot of games. Not all N64 games do that, though. Golden Eye 64 for instance relies more on the spec – and thus doesn't work well with my Gamester Rumble Pak.
But here's the kicker: the spec and the official Nintendo Rumble Pak does not allow you to control the motor speed. You can only turn the motor on or off. So many games opted for pulse width modulation to control rumble strength: e.g. toggling the motor on only every 2nd frame or so for a weaker rumble.
For any spec-compliant rumble pak, writing any number of 0x01 bytes (out ouf the 8 byte sequence) to 0xC000 will just turn the motor on full speed. But not with this bad boy: writing 3× 0x01 gives you a very slow rumble; 4× 0x01 a little bit faster and so on.
What happens is that there's two lowpass filters to stretch out the writes over a longer period of time. Amusingly enough, it means that writing different sequences to the accessory port (different total numbers of lsbits high) will correspond to different powers, unlike the OEM rumble pak
~ @lidnariq on the N64Brew Discord
So not only does this defective-by-design Gamester Rumble Pak get away without any IC, no, it also has speed control. Something no other N64 Rumble Pak has.
I'm in awe of whoever designed this thing. A true hacker!
Thanks again to @lidnariq and everyone else in the N64Brew discord for figuring this out. You guys are the best <3