N64 Output Interface¶
Emulates an N64 controller connected to an N64 console via the single-wire joybus protocol. Includes rumble pak emulation so games detect a rumble pak and forward vibration to the connected Bluetooth controller.
Protocol¶
- Wire protocol: Single-wire bidirectional joybus at 250kHz
- PIO program:
joybus.pio(fromlib/joybus-pio) - Clock: Standard clock speed (no overclock needed, unlike GameCube)
- Data pin: GPIO 7 (default), GPIO 2 (Pico W builds)
- Core: Runs on Core 1, entirely from RAM (
__not_in_flash_func)
On Pico 2 W (RP2350), Core 1's joybus handler must be fully RAM-resident to avoid flash contention with CYW43 Bluetooth bonding storage on Core 0.
N64 Controller Port Pinout¶

| Pin | Signal | Description |
|---|---|---|
| 1 | +3.6V | Power from console |
| 2 | DATA | Bidirectional joybus data (3.3V logic, open-drain with pull-up) |
| 3 | GND | Ground |
Adapter Wiring¶
| N64 Port | Signal | Adapter |
|---|---|---|
| Pin 1 | +3.6V | VSYS — power the adapter from the console |
| Pin 2 | DATA | Data GPIO (e.g., GPIO 7) — bidirectional joybus, needs pull-up |
| Pin 3 | GND | GND |
Player Support¶
- Max players: 1 per adapter (no multitap support)
Button Mapping¶
Uses N64_BUTTON_* aliases defined in n64_buttons.h:
| JP_BUTTON_* | N64 Button | Notes |
|---|---|---|
JP_BUTTON_B1 |
A | Primary action |
JP_BUTTON_B3 |
B | Secondary action |
JP_BUTTON_B2 |
C-Down | C-button |
JP_BUTTON_B4 |
C-Left | C-button |
JP_BUTTON_L1 |
L | Left shoulder |
JP_BUTTON_R1 |
R | Right shoulder |
JP_BUTTON_L2 |
Z | Z trigger (under controller) |
JP_BUTTON_R2 |
C-Up | C-button |
JP_BUTTON_R3 |
C-Right | C-button |
JP_BUTTON_S2 |
Start | Start button |
JP_BUTTON_DU/DD/DL/DR |
D-pad | Direct mapping |
Right stick is converted to C-buttons using a threshold.
Analog Mapping¶
| Input | N64 Output | Notes |
|---|---|---|
| Left stick X/Y | Control Stick | Y-axis inverted (HID 0=up to N64 convention) |
The N64 analog stick reports signed values (-80 to +80 range). The adapter scales from HID 0-255 range.
Feedback¶
Rumble Pak¶
The adapter emulates a rumble pak using deferred advertisement — pak is hidden during the first 32 controller polls (~500ms) to avoid incompatible pak detection in some games (e.g., Cruisin' USA), then advertised for rumble support. When a game activates rumble, the vibration is forwarded to the Bluetooth controller with a heartbeat to prevent Xbox BLE auto-stop.
Also handles PixelFX N64Digital Game ID command (0x1D) for consoles with N64Digital mods.
Profiles¶
Profiles are defined at the app level (e.g., src/apps/bt2n64/profiles.h):
- Default: Standard N64 mapping with right stick as C-buttons
- FPS: Optimized for GoldenEye, Perfect Dark
- Mario: Optimized for Super Mario 64 and platformers
Apps Using This Output¶
| App | Description |
|---|---|
bt2n64 |
Bluetooth controllers to N64 (Pico W / Pico 2 W) |
lodgenet2n64 |
LodgeNet hotel controllers to N64 (Pico) |