Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flashing arbitrary 8BitDo firmware from macOS

8BitDo ships beta and support-issued firmware as .dat files, but their macOS updater only flashes firmware it downloads from their own server — there is no "choose a local file" option, and the standalone Windows firmware tool is not available for macOS.

This repo makes the official 8BitDo Ultimate Software V2 for macOS flash a .dat file of your choosing. It does not reimplement the flashing protocol. The official app still does the flashing, exactly as it normally would; it is simply handed your file instead of the one it meant to download.

Because the real app performs the actual flash, this works for any controller that app supports, not just the one it was developed against.


Read this first

  • No firmware is included here, and none should be. Firmware is 8BitDo's intellectual property. Bring your own .dat, from 8BitDo support or an official beta programme. Do not flash files from strangers.
  • Flashing can brick a controller. Boot mode is entered by a hardware button combination and does not depend on the installed firmware, so a failed flash is normally recoverable by flashing again. "Normally" is not "always".
  • Only flash firmware built for your exact model. inspect_firmware.py prints a model id; compare it against the official firmware for your device before flashing. A mismatched image is the most likely way to cause real harm.
  • This modifies /etc/hosts and temporarily adds a certificate authority to your System keychain. stop.sh reverses both and verifies the result.

Developed and tested on an 8BitDo Ultimate 2C Wireless with Ultimate Software V2 build 20 on macOS 15. Nothing here is endorsed by 8BitDo.


Firmware

Firmware is not in this repository. Known files are identified by hash in FIRMWARE.md, so you can confirm a .dat you obtained elsewhere is genuine before flashing it.

One file is archived as a release asset, because it is not available through any normal channel:

  • Ultimate 2C Wireless 1.06 beta — support-issued, not published through the updater. Download from Releases · SHA-256 11c8d195d3ca76da24a33ba92ad9d7ae8ad6f455244864bed4c66898e9074bfb

Everything else your controller might need, the official app already downloads by itself — you do not need this project for those. Note that the beta is numerically older than the current 1.09 release, so it is a downgrade onto a separate branch; try official 1.09 first.

Firmware remains 8BitDo's property and is archived here only because it is otherwise unobtainable. It will be removed on request from 8BitDo.

Requirements

  • macOS with python3 and openssl (both ship with the system or Xcode tools)
  • 8BitDo Ultimate Software V2 installed
  • Your firmware .dat
  • Administrator access

Usage

Check that your firmware targets your device:

python3 inspect_firmware.py /path/to/firmware.dat

Compare the reported model id with the official firmware for your controller. The official file is cached by the app at:

~/Library/Containers/com.8BitDo.UltimateV2/Data/Documents/https:/support.8bitdo.com/bd-uploads/files/old/

Start the intercept:

sudo ./start.sh /path/to/firmware.dat

Leave that terminal open. Then quit the 8BitDo app completely and relaunch it, put the controller in boot mode, and start the firmware update as usual.

Watch the terminal. This line is your confirmation that your file was used:

>> SERVING OUR FIRMWARE (74780 bytes) for GET /bd-uploads/files/old/....dat

If you do not see it, your firmware was not flashed — see Troubleshooting.

When the flash finishes, press Ctrl-C and clean up:

sudo ./stop.sh

How it works

The updater fetches firmware over plain HTTPS from support.8bitdo.com and performs no integrity check on what it receives, so substituting the file is enough.

start.sh:

  1. Resolves the real IP of support.8bitdo.com before redirecting anything.
  2. Generates a throwaway CA and a certificate for that hostname, valid 30 days, and trusts the CA in the System keychain. The app does no certificate pinning, so this is sufficient.
  3. Adds 127.0.0.1 support.8bitdo.com to /etc/hosts.
  4. Restarts nsurlsessiond (see Troubleshooting — this step is essential).
  5. Runs a local HTTPS server on port 443 that proxies every request to the real server so the firmware list, authentication and analytics behave normally, except for firmware .dat requests, which return your file.

Only the firmware bytes are substituted. Everything else the app does is real.


What the app actually validates

Nothing that matters. Its firmware list looks like this:

{
  "fileName": "Ultimate 2C",
  "file_version": "1.09",
  "fileSize": 74780,
  "fileURL": "https://support.8bitdo.com/bd-uploads/files/old/7f93201d-....dat",
  "beta": 0,
  "md5": "57FBA9942000BE57BEB94FD0C217236D"
}

That md5 field is a placeholder: the API returns the same value for different firmware versions, and it matches none of the actual files. The downloaded file is flashed as-is.


The .dat header

Firmware is a 28-byte header followed by the payload. Field meanings are inferred by diffing several official files, not from documentation.

Offset Size Meaning
0 u16 version × 100 (106 = 1.06)
2 u16 beta flag (1 = beta build)
4 u32 flash destination address
8 u32 payload length (file size − 28)
12 u32 model id
16 u32 checksum over the payload
20 8 reserved, observed as zero

Real examples from the Ultimate 2C:

file version beta model payload
official factory 1.06 0 0x301B 74752
official latest 1.09 0 0x301B 74752
support-issued beta 1.06 1 0x301B 74752

The beta and the official firmware share a model id, flash address and payload length, differing only in the beta flag and the payload — which is exactly what you want to confirm before flashing anything.


Troubleshooting

No SERVING OUR FIRMWARE line, but the flash completed. The official firmware was flashed, not yours. The usual cause is nsurlsessiond, the macOS daemon that performs background downloads on behalf of apps. It is long-lived and keeps its own connection and DNS state, so it happily fetches from the real server while every request the app makes in its own process goes through the intercept. start.sh restarts it for you; if you changed /etc/hosts by hand, run killall nsurlsessiond yourself.

"Firmware download failed, please try again later". The app could not reach the download URL. Confirm the server is running, that dscacheutil -q host -a name support.8bitdo.com reports 127.0.0.1, and that nothing else is bound to port 443.

The app reflashes the same version and nothing changes. Pick a version the app considers an upgrade. The substituted file is served for whichever entry is chosen, so the label in the list is irrelevant — only the bytes matter.

Verifying after the fact. The app writes what it downloaded into its container. Comparing that file's md5 with your .dat tells you which bytes it received:

md5 -q ~/Library/Containers/com.8BitDo.UltimateV2/Data/Documents/https:/support.8bitdo.com/bd-uploads/files/old/*.dat
md5 -q /path/to/your/firmware.dat

Approaches that do not work

Recorded so nobody repeats them.

  • Replacing the cached .dat before flashing. The app re-downloads unconditionally at the start of every update, overwriting the swap.
  • Marking the cached file immutable with chflags uchg. The download then fails and the app aborts with an error instead of using the existing file.
  • Racing the download with a filesystem watcher. Works occasionally, produces no evidence of which file was actually flashed, and cannot be trusted for something that writes to flash memory.
  • Driving the bootloader directly over USB HID. The controller enumerates in boot mode as 2DC8:3208, a vendor HID device with 64-byte reports. Writing reports succeeds, but no replies are ever delivered to a third-party process on macOS, so the protocol could not be confirmed. Letting the official app own the protocol sidesteps this entirely.

Legal

For interoperability and repair on hardware you own. No 8BitDo code or firmware is included or redistributed here. Trademarks belong to their owners. You are responsible for what you flash onto your own device.

MIT licensed — see LICENSE.

About

Flash arbitrary 8BitDo firmware (.dat) from macOS by feeding your own file to the official 8BitDo Ultimate Software V2 updater

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages