Birdman64
Birdman64 is a native PC port of Pilotwings 64 for Windows and Linux that supports widescreen, high refresh rates, and modern gamepads.
- Type: PC port
- Game: Pilotwings 64
- Runs on Windows and Linux
- By NoahVl
- Latest release v1.0.0, 2026-10-03
- Source: https://github.com/NoahVl/Birdman64
README
Birdman64
Pilotwings 64 as a native PC game for Windows and Linux. Widescreen up to 21:9, your monitor's full refresh rate (144 Hz and beyond), modern gamepads, rebindable controls and an in-game settings menu. No emulator: the game's own code, built for your PC from your own cartridge dump (ROM).
Download the latest release, then follow the Quick start. An unofficial fan project; see Legal.
Screenshots
Holiday Island at 1080p, 16:9, 8x MSAA.

The original 4:3 image (left) and Birdman64 at 16:9 (right). Widescreen shows more of the world instead of stretching it.

The rocket belt at 21:9.

A test briefing at 16:9.

More screenshots: controls and first-time setup
Every key and button can be rebound in the settings menu.

The one-time setup on first start takes about a minute.

System requirements
Windows: Windows 10 or 11, 64 bit. A graphics card that supports DirectX 12 or Vulkan (almost every PC from the last ten years); keep the graphics driver up to date: NVIDIA, AMD or Intel. Nothing else to install: no Visual C++ runtime, no .NET, no emulator. An internet connection once, for the one-time setup. About 200 MB of free disk space. A keyboard or a gamepad (Xbox, PlayStation, Switch Pro and most USB/Bluetooth pads work).
Linux: a 64 bit distro from 2022 or newer (Ubuntu 22.04, Fedora 36,
Debian 12, Steam Deck desktop mode, or newer). Vulkan or OpenGL graphics
drivers (Mesa, already installed on most desktops). For the AppImage:
libfuse2 (Ubuntu/Debian: sudo apt install libfuse2; or start it with
--appimage-extract-and-run). Sound uses ALSA/PipeWire (already there on
desktops). Internet once, about 200 MB of disk.
macOS: not supported: the port needs a memory layout macOS on Apple Silicon does not allow.
Quick start
- On the Releases page, download
Birdman64-windows-x64.zip (Windows) or the Birdman64
.AppImage(Linux). The other files (debug symbols, checksums) are for bug reports and verification. - Right-click the zip, choose Extract All and open the extracted
folder. Never run
Birdman64.exefrom inside the zip. Keep thetoolchainfolder (the bundled compiler) next to the exe: the first start needs it. - Run
Birdman64.exe(Linux: the AppImage). Windows may show "Windows protected your PC" (SmartScreen, because the program is not code signed): click More info, then Run anyway. - On first start, choose your Pilotwings 64 ROM when the game asks (a
.z64,.n64or.v64file, or a.zipcontaining one; see What's a ROM?). Put the file next toBirdman64.exeand it is found automatically. Only the US (USA) version of the game works. - Wait for the one-time preparation step: the game downloads about 1 MB of the open source decompilation from GitHub and builds it on your machine (a progress window, usually under a minute depending on your PC; it needs about 200 MB of disk space). Internet is only needed the first time. After that the game starts normally every time.
- Play! The first launch shows a card with the basic keys: move with W A S D, A = Space, B = Left Shift, Start = Enter, camera with I J K L, F11 for fullscreen, Esc or F10 for settings.
Controls
Keyboard (defaults; rebind everything on the settings screen's Controls
page, or in pw64.toml under [input.keyboard], for example A = "Space"):
| Input | N64 action | What it does |
|---|---|---|
| W, A, S, D or arrow keys | Control stick | Steer · move in menus |
| Space | A | Confirm · thrust, flap, jump, fire |
| Left Shift | B | Back · gentle thrust, parachute |
| Z or Left Ctrl | Z | Hold to aim camera/missile, release to shoot |
| E | R | Change camera view |
| Enter | Start | Pause · confirm |
| I, J, K, L | C up, C left, C down, C right | Look around |
| T, F, G, H | D-pad | Not used in this game |
| Q | L | Not used in this game |
| Esc | Settings | Open or close the settings screen (when Esc is not bound to a game input) |
| F10 | Settings | Open or close the settings screen |
| F11 or Alt+Enter | Fullscreen | Switch between the window and fullscreen |
Gamepad (Nintendo layout pads match by position, so on a Switch pad the button printed B is the N64 A):
| Input | N64 action | What it does |
|---|---|---|
| Left stick | Control stick | Steer · move in menus |
| South button (Xbox: A, PlayStation: Cross, Nintendo: B) | A | Confirm · thrust, flap, jump, fire |
| West/East buttons (Xbox: X/B, PlayStation: Square/Circle, Nintendo: Y/A) | B | Back · gentle thrust, parachute |
| North button (Xbox: Y, PlayStation: Triangle, Nintendo: X) | C up | Look around |
| Right stick (beyond halfway) | C buttons | Look around |
| Left trigger or ZL (Xbox: LT, PlayStation: L2, Nintendo: ZL) | Z | Hold to aim camera/missile, release to shoot |
| LB / L (Xbox: LB, PlayStation: L1, Nintendo: L) | L | Not used in this game |
| RB / R and RT / ZR (Xbox: RB, RT, PlayStation: R1, R2, Nintendo: R, ZR) | R | Change camera view |
| Start (Xbox: Menu, PlayStation: Options, Nintendo: +) | Start | Pause · confirm |
| D-pad | D-pad | Not used in this game |
| Select (Xbox: View, PlayStation: Create, Nintendo: minus) | Settings screen | Open or close the settings screen |
Features
- Widescreen by default on wide monitors (any ratio up to 21:9, menu backgrounds stay 4:3 by design); fill the screen without letterbox bars
- Window, borderless fullscreen or exclusive fullscreen with a chosen video mode
- High frame rate: runs at your monitor's refresh rate, 144 Hz and beyond
- MSAA (1x, 4x, 8x) and render scale (supersampling or upscale) with a linear or nearest filter
- The N64's 3-point texture filter (set the filter to
n64, seePW64_FILTERbelow) - Texture packs (PNG files, keyed by content hash)
- Optional V-Sync style pacing to remove judder
- OLED care: the HUD drifts and the screen dims a little to spread wear
- Gamepads (including Switch 2 controllers over Bluetooth, experimental)
- An in-game settings screen (F10, Esc or pad Select) that rebinds every
key and button and saves to
pw64.toml - One-time setup that builds the game from your own ROM: nothing but our own code ships in the download
How it was made
Birdman64 went from an empty repository to a 1.0 release in six days (27 September to 3 October 2026). NoahVl designed and led it, directing a team of AI coding agents:
- Orchestrator and workers: a lead agent (Claude Opus 5.5) plans the work, delegates it and reviews every change. A fast, low-cost model (GLM 5.3-Flash) runs the routine tasks in parallel and wrote 44% of the commits, which keeps the expensive model for architecture, debugging and review.
- Human in the loop: product and design decisions, legal ground rules, and play-testing every build.
- Verified, not trusted: CI on Windows and Linux with warnings as errors, 321 tests, and scripted flights whose frames are checked before a change lands.
The result: about 47,000 lines of Rust in 12 crates and roughly 250 commits. That covers a replacement for the N64 operating system, graphics and audio engines, asset tools and a one-click launcher. The design notes are the agents' shared memory, so every session picks up where the last one stopped.
Settings and files
Settings screen: press F10, Esc (or pad Select) to pause the game and change options. Changes are saved when you close the screen; volume and most graphics options apply immediately, a few (MSAA, widescreen, fill screen) are marked "(restart)" and need the game restarted to apply. Reset rows restore the defaults.
pw64.toml example (all keys optional, the same options exist as
environment variables):
[graphics]
msaa = 4 # 1, 4 or 8
scale = 2.0 # render scale, 0.5 or more (1 = window size)
scale_filter = "linear" # or "nearest"
filter = "n64" # N64 3-point texture filter, or "bilinear"
widescreen = "16:9" # 1, "w:h", a ratio like "2.33", or 0 (off)
fps = "monitor" # "monitor", 30..1000, or 0 (uncapped)
vsync = false # display-paced pacing (less judder, more latency)
display_mode = "windowed" # "windowed", "borderless" or "exclusive"
fullscreen_resolution = "1920x1080@60" # exclusive video mode WxH[@Hz]
show_fps = false # frame rate in the window title
no_audio = true # no audio output device
volume = 0.8 # 0.0..1.0
[input.ble]
enabled = true # Switch 2 pads over Bluetooth LE
[oled]
drift = false # HUD drift for OLED burn-in care
brightness = 1.0 # 1.0, 0.85, 0.8, 0.75 or 0.7
[ui]
pause_in_background = true # pause when you switch windows or unplug the controller
Where files live: everything goes in one folder. How that folder is chosen is described under Save files below.
The one-time setup cache (the downloaded decompilation and the compiled game
module) lives in a cache folder next to them: next to the exe in a portable
install, else %LOCALAPPDATA%\Birdman64\cache (Windows) or ~/.cache/birdman64
(Linux). The Linux AppImage always uses the per-user locations above. Deleting
the cache is safe: the next start just builds the game once more.
Save files: the folder holds the save (pw64.eep), the settings
(pw64.toml) and crash.log. It is chosen once at start, in this order: the
PW64_DATA_DIR environment variable when set; next to the exe when that
folder holds portable.txt or pw64.eep and is writable
(portable use, for example on a USB stick: create an empty portable.txt
there; a folder like C:\Program Files is not writable); otherwise the
per-user folder, %APPDATA%\Birdman64 (Windows) or
$XDG_DATA_HOME/birdman64, else ~/.local/share/birdman64 (Linux). A fresh
extraction has no marker next to the exe, so it uses the per-user folder:
updating stays a matter of unzipping the new version anywhere, and saves,
settings and the remembered ROM carry over. The Linux AppImage always uses
the per-user location. The start-up log prints [paths] data dir: <path> with
the folder that was chosen. To edit pw64.toml by hand, open that folder from
the settings screen ("Open save folder"); outside a portable install, a
pw64.toml placed next to the exe is not used.
The save itself, pw64.eep, is a raw N64 EEPROM image: no header and no byte
swapping (unlike .v64 ROM files). It is written as 2048 bytes. The game's
two save files sit at offsets 0x000 and 0x100 inside it (Birdman64 emulates a
4 Kbit EEPROM, so the first 512 bytes are the part the game uses).
Using an emulator save: quit Birdman64 and back up your pw64.eep first,
then copy the emulator's save file over it. A Project64, mupen64plus or
simple64 .eep file (512 or 2048 bytes) works as it is. A RetroArch
Mupen64Plus-Next .srm file starts with the EEPROM contents, so a copy
renamed to pw64.eep works too (only the first 2048 bytes are read; the next
save writes a 2048-byte file). To go back to an emulator, copy pw64.eep
under the emulator's save file name, or set PW64_EEP=<path> and Birdman64
uses (and updates) that file directly. Never replace the save file while the
game is running: the game keeps the save in memory and overwrites the whole
file at the next save.
Useful environment variables for players: every option in pw64.toml
also exists as a PW64_* environment variable, which wins over the file
when both are set:
| Variable | Effect |
|---|---|
PW64_MSAA=<1|4|8> | MSAA sample count (restart) |
PW64_SCALE=<f> | render resolution as a fraction of the window (below 1 upscales) |
PW64_SCALE_FILTER=<linear|nearest> | filter for the blit when the render resolution differs |
PW64_FILTER=<bilinear|n64> | texture filter (the N64 look is n64) |
PW64_WIDESCREEN=<1|w:h|0> | widescreen aspect; the default is your monitor's aspect when it is wider than 4:3 (up to 21:9) |
PW64_FILL_SCREEN=<0|1> | no letterbox bars around world views (default: follows widescreen) |
PW64_FPS=<monitor|N|0> | frame rate (uncapped with 0) |
PW64_VSYNC=<0|1> | display-paced pacing (V-Sync) |
PW64_DISPLAY_MODE=<windowed|borderless|exclusive> | window, borderless fullscreen or exclusive fullscreen |
PW64_FULLSCREEN_RES=WxH[@Hz] | the exclusive fullscreen video mode |
PW64_OLED=<0|1> | HUD drift and dimming for OLED screens |
PW64_BLE=<1|0> | Switch 2 controllers over Bluetooth LE |
PW64_ROM=<path> | which ROM file to use |
PW64_DATA_DIR=<path> | folder for saves and settings |
PW64_EEP=<path> | exact save file to use instead of pw64.eep |
PW64_TEX_PACKS=<dir> | replace textures from a PNG pack |
PW64_NO_AUDIO=1 | run without an audio device |
The developer variables live in Developing.
What's a ROM?
A ROM is a copy of the game cartridge's data, made with a cartridge dumper from a cartridge you own. We can't provide or link one. Birdman64 needs the US version of Pilotwings 64: Troubleshooting shows how to check which file you have.
Updating
Download the new zip and extract it anywhere. Saves, settings and the
remembered ROM live in your user folder (see Save files above), so the
new version picks them up automatically. Keep the toolchain folder next
to the exe: the first start of the new version rebuilds the game once,
briefly showing the setup screen again.
Uninstalling
Delete the folder you extracted, then delete the per-user folder:
%APPDATA%\Birdman64 and %LOCALAPPDATA%\Birdman64 on Windows,
~/.local/share/birdman64 (or $XDG_DATA_HOME/birdman64) and
~/.cache/birdman64 on Linux. That removes your saves and settings too,
so back up pw64.eep first if you want to keep them.
Troubleshooting
- "The ROM does not work" or the game refuses to start: only the
US (USA) version of Pilotwings 64 is supported. European or Japanese
cartridges and ROMs from other regions will not work. To check which file
you have, compute its SHA-1 hash: on Windows,
certutil -hashfile rom.z64 SHA1; on Linux,sha1sum rom.z64. The US version in.z64byte order has SHA-1ec771aedf54ee1b214c25404fb4ec51cfd43191a(.n64/.v64files have a different hash but are converted automatically). - Windows shows a SmartScreen warning: the program is not code signed. Click More info, then Run anyway.
- "No compatible graphics adapter was found": the renderer needs Vulkan, DirectX 12 or OpenGL support on your GPU. Update your graphics driver from your GPU vendor's website (links in System requirements) and try again.
- The one-time build step fails or your antivirus intervenes: the game
compiles the decompiled game on your machine once, which looks like a
compiler to antivirus software. Allow it in your antivirus, or add an
exclusion for the game folder, then try again. If the bundled compiler
(the
toolchainfolder next to the exe) was removed or blocked, re-extract the zip, keeping the exe and the folder together. - The setup screen shows an error: it has a Retry button and shows
the path of a
build.logfile. Try Retry first; if it keeps failing, open an issue and attach thebuild.logit points to (bug reports about the setup without that log are hard to diagnose). - Linux: the AppImage does not start: it needs
libfuse2, which recent distributions (Ubuntu 22.04 and newer) no longer install by default. Either installlibfuse2or run it with--appimage-extract-and-run. - Verify a download: every release file carries a build provenance
attestation. With the GitHub
ghCLI:gh attestation verify <file> --repo <owner>/<repo>. - Where are my saves? in the save file
pw64.eep(see Settings and files). To back a save up, copy that file somewhere safe while the game is not running. - The game crashes: a
crash.logfile is written in the same folder as your saves. To report a bug, open an issue and attachcrash.log, the output ofBirdman64.exe --version, your GPU model, your OS and the SHA-1 of your ROM. Never attach the ROM itself.
Building from source
You need:
- Rust stable (https://rustup.rs), any of the usual toolchains (Windows: the MSVC one). No Python and no LLVM install needed.
- Linux x86_64:
libasound2-dev,libudev-dev,libdbus-1-dev,pkg-configandxz-utils. - The C compiler, zig 0.16.0 (the same one the release uses to build the game
on players' machines): one command downloads it into
tools/zig/and checks its sha256. Or pointPW64_ZIGat your own zig 0.16.0.
The decompilation is a git submodule, so clone recursively:
git clone --recursive https://github.com/USER/Birdman64
cd Birdman64
cargo run -p pw64-cbuild --example get_zig --features fetch
cargo run --release -p birdman64
Pass your ROM path as the argument, drop it next to the exe, or let the first-run picker find it. macOS is not supported.
Developing
How it works:
- Native game: the game logic from the
Pilotwings 64 decompilation
is compiled natively (zig's bundled clang, the same compiler players use, driven by
pw64-game's build script) and runs on a Rust replacement for libultra (pw64-platform): coroutine threads, PI/SI/AI/VI devices, message queues. - Rust renderer and audio: the display lists the game builds are
interpreted by
pw64-gfx(Fast3D + RDP HLE on wgpu); the RSP audio microcode (aspMain) is HLE'd bypw64-audio. - Full Rust (long-term): C modules are replaced one at a time by Rust equivalents, each checked against the C behaviour, until no C remains.
Documentation: ROADMAP.md is the roadmap and status; the
docs/notes/*.md files are topic notes (formats, graphics, audio, input,
native build, the Rust port).
Testing and linting:
cargo test --workspace
cargo clippy --workspace --all-targets
A scripted headless flight check (drives the title menu into a flight and
dumps PNG frames to tmp/):
PW64_INPUT_SCRIPT=crates/birdman64/scripts/fly_hang_glider.txt \
PW64_MAX_RETRACES=2700 PW64_NO_THROTTLE=1 PW64_NO_INPUT=1 \
PW64_DUMP_FRAMES=150 cargo run --release -p birdman64
C patches: fixes and small changes to the decompiled C live in
crates/pw64-game/patches/ as unified diffs applied at build time.
*