Wii Hacks

        

Monday, January 01, 2007

Wii Remote Speaker Communication Cracked

Carl Kenner is the man when it comes to the Wii Mote. Not only was the he the first person to have a working application for Windows that could read the Wii-Mote, but he did all of the programing with no wii-mote to test with.

Ever since that day he has been the driving force behind many wii-mote hacks featured on this site. His software, GlovePIE is the heart and soul of making the Wii Remote work in Windows, and several sites have started to spring up to host scripts for using the Wii-Mote with various different types of applications. He was one of the first to add Nunchuck support to his app, and his GlovePIE software can also handle multiple Wii-motes.

One of the last pieces of the Wii-Mote to be discovered is it's speaker. Up until now, nobody has been able to successfully communicate with the speaker to produce sounds. Carl made a post today to the WiiLi forums including a script that will bring the Wii Mote's speaker to life. Much of the initial work to find the codes to send to the wii-mote was done by Marcan, so a good chunk of the credit for this discovery should go to him.

Here is the GlovePIE script you will need to test out the Wii-Mote's Speaker from Windows:

// Carl Kenner's Wiimote Speaker Test script! Version 2
// A = start sound, B = stop sound
// Minus = decrease sample frequency
// Plus = increase sample frequency
// It takes a short time to start (due to delays built into Poke)

// Change the next line to set the rate at which sound data is sent
// BUT it must be low enough for the wiimote to respond to the B button
// it may depend on your PC speed. Must be at least 91 for freq 13.
pie.FrameRate = 120 Hz

if not var.initialized then
var.freq = 13 // Set sample rate = 3640 Hz (so computer can keep up)
var.volume = 0x40 // volume = 40 ??? Seems to be about max
debug = var.freq
var.initialized = true
end if

if var.On and (not Wiimote.One) and (not Wiimote.Two) then
// Report 18, send 20 bytes, square wave, 1/4 sample rate freq
WiimoteSend(1, 0x18, 20 shl 3, 0xCC,0x33,0xCC,0x33,0xCC,0x33,0xCC,0x33,0xCC,0x33, 0xCC,0x33,0xCC,0x33,0xCC,0x33,0xCC,0x33,0xCC,0x33)
else if var.On and Wiimote.One then
// Report 18, send 20 bytes, square wave, 1/2 sample rate freq
WiimoteSend(1, 0x18, 20 shl 3, 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3, 0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3)
else if var.On and Wiimote.Two then
// Report 18, send 20 bytes, square wave, 1/8 sample rate freq
WiimoteSend(1, 0x18, 20 shl 3, 0xCC,0xCC,0x33,0x33,0xCC,0xCC,0x33,0x33,0xCC,0xCC, 0x33,0x33,0xCC,0xCC,0x33,0x33,0xCC,0xCC,0x33,0x33)
end if


if pressed(Wiimote.A) then
// Enable Speaker
Wiimote.Report14 = 0x04 | Int(Wiimote.Rumble)
// Mute Speaker
Wiimote.Report19 = 0x04 | Int(Wiimote.Rumble)
// Write 0x01 to register 0xa20009
WiimotePoke(1, 0x04a20009, 0x01)
// Write 0x08 to register 0xa20001
WiimotePoke(1, 0x04a20001, 0x08)
// Write 7-byte configuration to registers 0xa20001-0xa20008
WiimotePoke(1, 0x04a20001, 0x00)
WiimotePoke(1, 0x04a20002, 0x00)
WiimotePoke(1, 0x04a20003, 0x00)
WiimotePoke(1, 0x04a20004, var.freq)
WiimotePoke(1, 0x04a20005, var.volume) // 40
WiimotePoke(1, 0x04a20006, 0x00)
WiimotePoke(1, 0x04a20007, 0x00)
// Write 0x01 to register 0xa20008
WiimotePoke(1, 0x04a20008, 0x01)
// Unmute speaker
Wiimote.Report19 = 0x00 | Int(Wiimote.Rumble)
var.On = true
end if

if pressed(Wiimote.B) then
var.On = false
Wiimote.Report19 = 0x04 | Int(Wiimote.Rumble) // Mute Speaker
Wiimote.Report14 = 0x00 | Int(Wiimote.Rumble) // Disable speaker
end if

if pressed(Wiimote.Plus) then
var.freq--
debug = var.freq
// Mute Speaker
Wiimote.Report19 = 0x04 | Int(Wiimote.Rumble)
// Write 0x01 to register 0xa20009
WiimotePoke(1, 0x04a20009, 0x01)
// Write 0x08 to register 0xa20001
WiimotePoke(1, 0x04a20001, 0x08)
// Write 7-byte configuration to registers 0xa20001-0xa20008
WiimotePoke(1, 0x04a20001, 0x00)
WiimotePoke(1, 0x04a20002, 0x00)
WiimotePoke(1, 0x04a20003, 0x00)
WiimotePoke(1, 0x04a20004, var.freq) // max volume?
WiimotePoke(1, 0x04a20005, var.volume)
WiimotePoke(1, 0x04a20006, 0x00)
WiimotePoke(1, 0x04a20007, 0x00)
// Write 0x01 to register 0xa20008
WiimotePoke(1, 0x04a20008, 0x01)
// Unmute speaker
Wiimote.Report19 = 0x00 | Int(Wiimote.Rumble)
end if

if pressed(Wiimote.Minus) then
var.freq++
debug = var.freq
// Mute Speaker
Wiimote.Report19 = 0x04 | Int(Wiimote.Rumble)
// Write 0x01 to register 0xa20009
WiimotePoke(1, 0x04a20009, 0x01)
// Write 0x08 to register 0xa20001
WiimotePoke(1, 0x04a20001, 0x08)
// Write 7-byte configuration to registers 0xa20001-0xa20008
WiimotePoke(1, 0x04a20001, 0x00)
WiimotePoke(1, 0x04a20002, 0x00)
WiimotePoke(1, 0x04a20003, 0x00)
WiimotePoke(1, 0x04a20004, var.freq) // max volume?
WiimotePoke(1, 0x04a20005, var.volume)
WiimotePoke(1, 0x04a20006, 0x00)
WiimotePoke(1, 0x04a20007, 0x00)
// Write 0x01 to register 0xa20008
WiimotePoke(1, 0x04a20008, 0x01)
// Unmute speaker
Wiimote.Report19 = 0x00 | Int(Wiimote.Rumble)
end if

This is a huge accomplishment and you can bet that soon enough the hackers will be streaming all kinds crappy 4 bit sounds to their wii-motes. Let the fun begin!!!
Once again Carl, great work!

Next up is integrating the Speaker functionality into the other Windows Wii-Mote apps, as well as the Linux and OSX wii-mote programs. Developers will want to check out the WiiLi wiki for information on how to initialize the wii-mote speaker and send sounds to it.

Source: WiiLi.org

UPDATE: My apologies, it was actually marcan who did most of the discovery to get the Wii-Mote speaker working, I've updated the post above to give the proper credit. Thanks Perrpf for pointing out the mistake. Sorry for the mix up.

3 Comments:

Perrpf said...

Sorry, but this is actually wrong.

First of all: Carl did a really good job, no doubt about that - but it was actually marcan who found out almost everything about the speaker, so I think it's marcan who deserves most of the fame.

What Carl recently found out is how to set the sample rate, which for the first time made it possible to play a clean note on the speaker without distortion. That's really nice, but playing a simple clean note isn't what most people will actually want to do with their Wiimote speaker. Most people will want to play sampled sound, and Carl didn't manage to do that yet, so it's simply wrong to say that the speaker communication has really been hacked yet.
But the good news is that this is most probably going to happen very, very soon!

Brian said...

lol

Andrew said...

Idea
Since there is a Bluetooth service that can be used for audio transfer, could it be used to activate the Wiimote speaker

Click Here to Post a Comment

Subscribe to the Nintendo Wii Hacks Blog RSS Feed

Also see:
PSP Hacks
PS3 Hacks
Zune Hacks
iPhone Hacks
Apple TV Hacks