Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
b59122a
Rewrapped code in input.c
skadge Oct 18, 2016
8fa1bdb
Document keys on command-line
skadge Oct 18, 2016
b4175bb
Merge pull request #4 from severin-lemaignan/master
rnconrad Oct 19, 2016
458839b
Suggest reliable method to get console address
ThatsJustCheesy Aug 10, 2020
74e894f
Merge pull request #8 from ThatsJustCheesy/patch-1
rnconrad Aug 18, 2020
498e370
major refactoring
rnconrad Jan 29, 2021
c37efc5
fix input esc handler
rnconrad Jan 30, 2021
f558110
automatically reconnect to host properly
rnconrad Jan 30, 2021
68f7788
fix gitignore
rnconrad Jan 30, 2021
12c9119
emulate Wiimote's device class
rnconrad Jan 30, 2021
5a8d8d1
remove unnecessary gitattributes
rnconrad Jan 30, 2021
7a2c376
input improvements
rnconrad Jan 30, 2021
1cb4cde
fix sdp record issues
rnconrad Jan 30, 2021
c3277ab
remove unnecessary poll flags
rnconrad Jan 30, 2021
b9b15a1
prevent warning for unimplemented function
rnconrad Jan 30, 2021
befab3d
fix custom build
rnconrad Feb 6, 2021
77ca21e
warn instead of abort on bdaddr failure
rnconrad Feb 6, 2021
1e1d477
detect if bdaddr is already usable
rnconrad Feb 7, 2021
fbda994
support cypress vendor id
rnconrad Feb 7, 2021
b7ae25b
add support for powering off wii
rnconrad Feb 7, 2021
8cff17f
code cleanup, bug fixes
rnconrad Feb 14, 2021
0240185
added wmmitm utility
rnconrad Feb 14, 2021
a6f1e89
clarify build/usage instructions
rnconrad Feb 14, 2021
0aefd19
fix makefile
rnconrad Mar 3, 2021
9246eb4
Add socket input as alternative to SDL GUI
ThatsJustCheesy May 13, 2021
c97c088
Simplify command usage, and actually init SDL
ThatsJustCheesy May 14, 2021
ccf101e
Add missing break statements
ThatsJustCheesy May 14, 2021
d885377
Fix syntax issue
ThatsJustCheesy May 16, 2021
57e9101
Merge pull request #15 from ThatsJustCheesy/socket-input
rnconrad May 17, 2021
8190a92
fix incorrect error response
rnconrad May 17, 2021
2ddf238
set simple pairing mode to fix Wii U connection
rnconrad Jun 6, 2021
ca3eec1
don't send empty reports to fix Wii U crashing
rnconrad Jun 6, 2021
8aadff1
use multiple adapters for better functionality
rnconrad Jun 6, 2021
d15cd6a
some emulator response corrections
rnconrad Jun 6, 2021
400d626
remove unnecessary portions of eeprom
rnconrad Jun 7, 2021
e8207da
clean up dependencies
rnconrad Jun 7, 2021
b85017f
move report printing out of wiimote
rnconrad Jun 7, 2021
ca3db73
search for wiimotes in wmmitm for convenience
rnconrad Jun 7, 2021
61f0db2
Allow specifying 'pair' on command line
ThatsJustCheesy Jun 9, 2021
1da5c1f
Merge pull request #16 from ThatsJustCheesy/explicit-pair-argument
rnconrad Jun 12, 2021
09d1a76
remove debug input printing
rnconrad Feb 15, 2022
1dca033
fix incorrect extension response code
rnconrad Feb 15, 2022
258d0ad
add extension hotplug delay
rnconrad Feb 15, 2022
4412e8d
fix report mode printing bug
rnconrad Feb 15, 2022
5524369
fix inverted nunchuk buttons
rnconrad Feb 18, 2022
dac3c8d
fix incorrect controls display
rnconrad Feb 18, 2022
0368dda
a few report struct fixes
rnconrad Feb 18, 2022
8187b08
add mouse control for pointer, motion emulation
rnconrad Feb 18, 2022
ddbea59
support old ir pointer movement (for now)
rnconrad Feb 18, 2022
501303c
report printing improvements
rnconrad Feb 18, 2022
a66dffd
default value tweaks
rnconrad Feb 19, 2022
d93f0d4
improve latency
rnconrad Feb 19, 2022
a7684f3
Fixed ip socket command line parameter index. Also fixed missing grac…
JRogaishio May 12, 2023
31455a0
Added messaging when successfully binding to ip port
JRogaishio May 13, 2023
876e0bd
Moved documentation to docs folder and added documentation about sock…
JRogaishio May 13, 2023
2d2761d
Update wmemu.c
mariob0y Jan 3, 2024
c2db12a
Update input_socket.c
mariob0y Jan 3, 2024
cef82d9
Merge pull request #1 from mariob0y/patch-1
JRogaishio Oct 12, 2024
ea468f9
Added patch that fixes build error
purplebar0 Nov 12, 2024
00e66f7
Added patch to build script
purplebar0 Nov 12, 2024
e70edc0
Fix build
MilaConLimon Oct 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .gitattributes

This file was deleted.

53 changes: 6 additions & 47 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,47 +1,6 @@
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# =========================
# Operating System Files
# =========================

# OSX
# =========================

.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
bluez-4.101
wmemulator
wmmitm
packedtest
*.o
*.so
22 changes: 18 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
all:
gcc -g -o wmemulator wmemulator.c wiimote.c input.c wm_crypto.c wm_reports.c wm_print.c -lbluetooth -lSDL -lpthread -lm `pkg-config --cflags dbus-1` -ldbus-1 -Wall
gcc -o bdaddr bdaddr.c oui.c -lbluetooth
gcc -o sdptool sdptool.c -lbluetooth
ifeq ($(origin CUSTOM_BUILD),undefined)
LBLUETOOTH=-lbluetooth
CFLAGS=
else
BLUEZ_DIST=$(shell pwd)/bluez-4.101/dist
LBLUETOOTH=-L"$(BLUEZ_DIST)/lib" -I"$(BLUEZ_DIST)/include" -Wl,-rpath="$(BLUEZ_DIST)/lib" -lbluetooth
CFLAGS=-D SDP_SERVER
endif
LDBUS=`pkg-config --cflags dbus-1` -ldbus-1

all: wmemulator packedtest wmmitm
clean:
rm -f wmemulator packedtest wmmitm
wmemulator: wmemulator.c wiimote.c input.c motion.c input_sdl.c input_socket.c wm_crypto.c wm_reports.c wm_print.c sdp.c bdaddr.c adapter.c
gcc $(CFLAGS) -o wmemulator wmemulator.c wiimote.c input.c motion.c input_sdl.c input_socket.c wm_crypto.c wm_reports.c wm_print.c sdp.c bdaddr.c adapter.c $(LBLUETOOTH) -lSDL -lpthread -lm $(LDBUS) -Wall
wmmitm: wmmitm.c wm_print.c sdp.c bdaddr.c adapter.c
gcc $(CFLAGS) -o wmmitm wmmitm.c wm_print.c sdp.c bdaddr.c adapter.c $(LBLUETOOTH) -lpthread -lm $(LDBUS) -Wall
packedtest: packedtest.c
gcc -o packedtest packedtest.c
128 changes: 43 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,123 +4,81 @@ Emulates a Bluetooth Wii controller in software.

![Raspberry Pi 3 running the emulator in Raspbian](rpi_ss.png)

## Why?
### Features

- Useful for building portable console mods with internal controllers
- Could theoretically be used for extra controllers (WIP)
- Can emulate all of the Wiimote's many features and extensions
- Allows use of different input devices (keyboard etc.)
- For the fun/hell of it

## How?
- Emulate the Wiimote's many features and extensions
- Allows use of different input devices (keyboard etc.)

### Build/Install

The following dependencies/packages are required:

- libdbus-1-dev
- libglib2.0-dev
- libsdl1.2-dev

Additionally, bluez-4.101 is required (newer versions currently don't work).

To build the emulator, run the makefile in the source directory. In order to
connect to the Wii, a plugin must be installed that allows pairing using non
UTF-8 pin codes. Copy the contents of the bluez-plugin folder to the
bluez-4.101/plugins folder of the Bluez source and run the makefile in that
directory. Copy the output wmemu.so file to the Bluez installation's plugins
directory (e.g. /usr/lib/bluetooth/plugins) and restart the bluetooth service.
The following dependencies/packages are required (if not already installed):

TODO: Friendlier directions for different distros/targets, prebuilt binaries
- libdbus-1-dev
- libglib2.0-dev
- libsdl1.2-dev

### Step 1: Determine Wiimote Address
Run the build script (in the project directory):

As of now, it is not possible to emulate an arbitrary Wiimote due to the Wii's
fussiness when connecting. So you'll need to determine both the Bluetooth
addresses of a Wii and a Wiimote in order to connect.
> source ./build-custom.sh

There are lots of ways to find the address of a Wiimote. Below are the steps
for one method.
- use hcitool to search for discoverable devices
For more information on the build script, see [this explainer](docs/CustomBuild.md).

> hcitool scan
### Using the Emulator

- press the red sync button under the battery cover of the Wiimote
- the Wiimote should be listed (Nintendo RVL-CNT-01) with its address
Stop any running Bluetooth service, e.g.:

> sudo service bluetooth stop

### Step 2: Determine Wii Address
Start the custom Bluetooth stack (e.g. from the project directory):

Finding a Wii's address is a bit trickier. There are multiple ways to do this
as well, including using a Bluetooth packet sniffer or using a utility via
custom firmware on the Wii. Below is a quicker (although messier) way.
> sudo ./bluez-4.101/dist/sbin/bluetoothd

- change your Bluetooth address to the Wiimote's (you'll need to do this anyway)
Run the emulator (in the project directory):

> sudo ./bdaddr <wiimote address (from part 1)>
> ./wmemulator

- reset your adapter to apply the changes
With no arguments, the emulator will listen for incoming connections (similar to
syncing a real Wiimote). Pressing the sync button on a Wii should cause it to
connect.

> sudo hciconfig hci0 reset
You can also supply the address of a Wii to directly connect to it as long as
you have connected to it before (or you change your device's address to the
address of a trusted Wiimote).

- run the hcidump utility (you may need to download) (any BT activity monitor
can be substituted)
> ./wmemulator XX:XX:XX:XX:XX:XX

> hcidump
You will need to run the custom Bluetooth stack (as described above) whenever
using the emulator (it won't persist after e.g. a device restart). Also, the
custom stack generally won't be useful for anything besides Wiimote emulation.

- press the red sync button on the Wii
- press the red sync button on the Wiimote and after the status LEDs on the
Wiimote blink 1-5 times, disconnect one of the batteries
- if done correctly (with a bit of luck) the Wii will connect to your device,
revealing its address
- this may take few tries -- note that you must press both sync buttons again
each time
To stop the custom stack and restore the original Bluetooth service, e.g.:

### Step 3: Run the Emulator
> sudo killall bluetoothd

Once you have determined the address of a Wii and Wiimote, you can run the
emulator and it will automatically connect to the Wii. As long as the Wiimote
and the Wii are synced, you will no longer need the physical Wiimote. Though
due to using its Bluetooth address, you will not be able to connect it to the
Wii simultaneously with the emulator. Run the following from the WiimoteEmulator
directory and replace the zeros with your Wii's address.
> sudo service bluetooth start

> ./wmemulator 00:00:00:00:00:00
For more information on bluetooth addresses, see [this explainer](docs/BluetoothAddresses.md).

You will need your Bluetooth address to be the Wiimote's address every time you
run the emulator. Note that your adapter may reset to the original address when
you restart your PC, etc.
### Connecting via UDP sockets

In the event that a mishap or bug in the emulator causes your Wii to block
you from connecting, you will need to sync the original controller again to
regain its trust. You will also need to clear the stored link key using
test-device (included with Bluez).
To connect via sockets it is expected that you know the Wii consoles address.

> (somewhere)/bluez-4.101/test/test-device remove <wii address>
#### UNIX

### Other Tools
> ./wmemulator XX:XX:XX:XX:XX:XX unix /tmp/some-path-here

**bdaddr**
#### IP

A redist of the bdaddr utility for Bluez. Might build into some tools, but
ideally in a future version address spoofing won't be needed anymore.
> ./wmemulator XX:XX:XX:XX:XX:XX ip {some-port-number-here}

**packedtest**
#### Data Format

Simple utility for verifying the behavior of packed structs in your
environment. Might be useful for portability checking.
Sockets use the format `type status action`. For example, to press and hold the Wiimote + button you would send `button 1 WIIMOTE_PLUS`. To release the + button you would send `button 0 WIIMOTE_PLUS`.

**sdptool**
**`type`** This can be `analog_motion`, `button`, `hotplug`, or `emulator_control`.

Not useful for anything right now. Part of ongoing work to try to get the Wii
to sync directly with the emulator. Running this tool creates the Wiimote's
SDP records, which are vital to the Wii's initial sync process (but not used
after pairing).
**`status`** This is the enabled / disabled state of the action. '0' = turn off, '1' = turn on. If you send a 1 the button will stay "pressed" until a 0 is sent.

**wiimitm**
**`action`** This is the equivalent to the physical control you want to invoke. For example `WIIMOTE_PLUS` or `IR_UP`

Connects to a Wiimote and a Wii at the same time to eavesdrop on their
communications. All packets sent between the console and controller are
printed in readable format. Useful for debugging, reverse engineering,
or entertaining one's curiosity.
(TODO: Add this to the repo)
For more information on available types and actions, see [this explainer](docs/SocketActions.md).
Loading