2 #include "Attachment/Classic.h"
3 #include "Attachment/Nunchuk.h"
5 #include "WiimoteEmu.h"
6 #include "WiimoteHid.h"
13 #define WIIMOTE_PAD_LEFT 0x01
14 #define WIIMOTE_PAD_RIGHT 0x02
15 #define WIIMOTE_PAD_DOWN 0x04
16 #define WIIMOTE_PAD_UP 0x08
17 #define WIIMOTE_PLUS 0x10
19 #define WIIMOTE_TWO 0x0100
20 #define WIIMOTE_ONE 0x0200
21 #define WIIMOTE_B 0x0400
22 #define WIIMOTE_A 0x0800
23 #define WIIMOTE_MINUS 0x1000
24 #define WIIMOTE_HOME 0x8000
29 /* An example of a factory default first bytes of the Eeprom memory. There are differences between
30 different Wiimotes, my Wiimote had different neutral values for the accelerometer. */
31 static const u8 eeprom_data_0
[] = {
32 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
33 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
34 // Accelerometer neutral values
35 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E,
36 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E
38 static const u8 eeprom_data_16D0
[] = {
39 0x00, 0x00, 0x00, 0xFF, 0x11, 0xEE, 0x00, 0x00,
40 0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99,
41 0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13
44 // array of accel data to emulate shaking
45 const u8 shake_data
[8] = { 0x80, 0x40, 0x01, 0x40, 0x80, 0xC0, 0xFF, 0xC0 };
47 const u16 button_bitmasks
[] =
49 WIIMOTE_A
, WIIMOTE_B
, WIIMOTE_ONE
, WIIMOTE_TWO
, WIIMOTE_MINUS
, WIIMOTE_PLUS
, WIIMOTE_HOME
52 const u16 dpad_bitmasks
[] =
54 WIIMOTE_PAD_UP
, WIIMOTE_PAD_DOWN
, WIIMOTE_PAD_LEFT
, WIIMOTE_PAD_RIGHT
56 const u16 dpad_sideways_bitmasks
[] =
58 WIIMOTE_PAD_RIGHT
, WIIMOTE_PAD_LEFT
, WIIMOTE_PAD_UP
, WIIMOTE_PAD_DOWN
61 const char* const named_buttons
[] =
74 m_reporting_mode
= WM_REPORT_CORE
;
75 // i think these two are good
76 m_reporting_channel
= 0;
77 m_reporting_auto
= false;
79 // will make the first Update() call send a status request
80 // the first call to RequestStatus() will then set up the status struct extension bit
81 m_extension
->active_extension
= -1;
84 memset( m_eeprom
, 0, sizeof(m_eeprom
) );
86 memcpy( m_eeprom
, eeprom_data_0
, sizeof(eeprom_data_0
) );
87 // dunno what this is for, copied from old plugin
88 memcpy( m_eeprom
+ 0x16D0, eeprom_data_16D0
, sizeof(eeprom_data_16D0
) );
90 // set up the register
92 m_register
[0xa20000].resize(WIIMOTE_REG_SPEAKER_SIZE
,0);
93 m_register
[0xa40000].resize(WIIMOTE_REG_EXT_SIZE
,0);
94 m_register
[0xa60000].resize(WIIMOTE_REG_EXT_SIZE
,0);
95 m_register
[0xB00000].resize(WIIMOTE_REG_IR_SIZE
,0);
97 //m_reg_speaker = &m_register[0xa20000][0];
98 m_reg_ext
= &m_register
[0xa40000][0];
99 //m_reg_motion_plus = &m_register[0xa60000][0];
100 //m_reg_ir = &m_register[0xB00000][0];
103 memset( &m_status
, 0, sizeof(m_status
) );
104 // Battery levels in voltage
105 // 0x00 - 0x32: level 1
106 // 0x33 - 0x43: level 2
107 // 0x33 - 0x54: level 3
108 // 0x55 - 0xff: level 4
109 m_status
.battery
= 0x5f;
112 Wiimote::Wiimote( const unsigned int index
, SWiimoteInitialize
* const wiimote_initialize
)
113 : m_wiimote_init( wiimote_initialize
)
116 // ---- set up all the controls ----
119 groups
.push_back( m_buttons
= new Buttons( "Buttons" ) );
120 for ( unsigned int i
=0; i
< sizeof(named_buttons
)/sizeof(*named_buttons
); ++i
)
121 m_buttons
->controls
.push_back( new ControlGroup::Input( named_buttons
[i
] ) );
124 //groups.push_back( m_rumble = new ControlGroup( "IR" ) );
125 //m_rumble->controls.push_back( new ControlGroup::Output( "X" ) );
126 //m_rumble->controls.push_back( new ControlGroup::Output( "Y" ) );
127 //m_rumble->controls.push_back( new ControlGroup::Output( "Distance" ) );
128 //m_rumble->controls.push_back( new ControlGroup::Output( "Hide" ) );
131 groups
.push_back( m_tilt
= new Tilt( "Pitch and Roll" ) );
132 //groups.push_back( m_tilt = new Tilt( "Tilt" ) );
133 //groups.push_back( m_swing = new Force( "Swing" ) );
136 groups
.push_back( m_shake
= new Buttons( "Shake" ) );
137 m_shake
->controls
.push_back( new ControlGroup::Input( "X" ) );
138 m_shake
->controls
.push_back( new ControlGroup::Input( "Y" ) );
139 m_shake
->controls
.push_back( new ControlGroup::Input( "Z" ) );
142 groups
.push_back( m_extension
= new Extension( "Extension" ) );
143 m_extension
->attachments
.push_back( new WiimoteEmu::None() );
144 m_extension
->attachments
.push_back( new WiimoteEmu::Nunchuk() );
145 m_extension
->attachments
.push_back( new WiimoteEmu::Classic() );
146 //m_extension->attachments.push_back( new Attachment::GH3() );
149 groups
.push_back( m_dpad
= new Buttons( "D-Pad" ) );
150 for ( unsigned int i
=0; i
< 4; ++i
)
151 m_dpad
->controls
.push_back( new ControlGroup::Input( named_directions
[i
] ) );
154 groups
.push_back( m_rumble
= new ControlGroup( "Rumble" ) );
155 m_rumble
->controls
.push_back( new ControlGroup::Output( "Motor" ) );
158 groups
.push_back( options
= new ControlGroup( "Options" ) );
159 options
->settings
.push_back( new ControlGroup::Setting( "Background Input", false ) );
160 options
->settings
.push_back( new ControlGroup::Setting( "Sideways Wiimote", false ) );
163 // --- reset eeprom/register/values to default ---
167 std::string
Wiimote::GetName() const
169 return std::string("Wiimote") + char('1'+m_index
);
172 void Wiimote::Update()
174 const bool is_sideways
= options
->settings
[1]->value
> 0;
176 // update buttons in status struct
177 m_status
.buttons
= 0;
178 m_buttons
->GetState( &m_status
.buttons
, button_bitmasks
);
179 m_dpad
->GetState( &m_status
.buttons
, is_sideways
? dpad_sideways_bitmasks
: dpad_bitmasks
);
181 // check if a status report needs to be sent
182 // this happens on wiimote sync and when extensions are switched
183 if (m_extension
->active_extension
!= m_extension
->switch_extension
)
185 RequestStatus( m_reporting_channel
, NULL
);
187 // Wiibrew: Following a connection or disconnection event on the Extension Port,
188 // data reporting is disabled and the Data Reporting Mode must be reset before new data can arrive.
190 // after a game receives an unrequested status report,
191 // it expects data reports to stop until it sets the reporting mode again
192 m_reporting_auto
= false;
195 if ( false == m_reporting_auto
)
198 // figure out what data we need
201 size_t rpt_accel
= 0;
205 switch ( m_reporting_mode
)
208 case WM_REPORT_CORE
:
212 //(a1) 31 BB BB AA AA AA
213 case WM_REPORT_CORE_ACCEL
:
214 rpt_size
= 2 + 2 + 3;
218 //(a1) 33 BB BB AA AA AA II II II II II II II II II II II II
219 case WM_REPORT_CORE_ACCEL_IR12
:
220 rpt_size
= 2 + 2 + 3 + 12;
225 //(a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
226 case WM_REPORT_CORE_ACCEL_EXT16
:
227 rpt_size
= 2 + 2 + 3 + 16;
232 //(a1) 37 BB BB AA AA AA II II II II II II II II II II EE EE EE EE EE EE
233 case WM_REPORT_CORE_ACCEL_IR10_EXT6
:
234 rpt_size
= 2 + 2 + 3 + 10 + 6;
238 rpt_ext
= 2 + 2 + 3 + 10;
241 //PanicAlert( "Unsupported Reporting Mode" );
246 // set up output report
247 u8
* const rpt
= new u8
[rpt_size
];
248 memset( rpt
, 0, rpt_size
);
251 rpt
[1] = m_reporting_mode
;
253 // core buttons - always 2
255 *(wm_core
*)(rpt
+ rpt_core
) = m_status
.buttons
;
262 m_tilt
->GetState( &x
, &y
, 0, (PI
/ 2) ); // 90 degrees
264 // this isn't doing anything with those low bits in the calib data, o well
266 const accel_cal
* const cal
= (accel_cal
*)&m_eeprom
[0x16];
267 const u8
* const zero_g
= &cal
->zero_g
.x
;
269 for ( unsigned int i
=0; i
<3; ++i
)
270 one_g
[i
] = (&cal
->one_g
.x
)[i
] - zero_g
[i
];
272 // this math should be good enough :P
273 rpt
[rpt_accel
+ 2] = u8(sin( (PI
/ 2) - std::max( abs(x
), abs(y
) ) ) * one_g
[2] + zero_g
[2]);
277 rpt
[rpt_accel
+ 0] = u8(sin(y
) * -one_g
[1] + zero_g
[1]);
278 rpt
[rpt_accel
+ 1] = u8(sin(x
) * -one_g
[0] + zero_g
[0]);
282 rpt
[rpt_accel
+ 0] = u8(sin(x
) * -one_g
[0] + zero_g
[0]);
283 rpt
[rpt_accel
+ 1] = u8(sin(y
) * one_g
[1] + zero_g
[1]);
287 const unsigned int btns
[] = { 0x01, 0x02, 0x04 };
288 unsigned int shake
= 0;
289 m_shake
->GetState( &shake
, btns
);
290 static unsigned int shake_step
= 0;
293 shake_step
= (shake_step
+ 1) % sizeof(shake_data
);
294 for ( unsigned int i
=0; i
<3; ++i
)
295 if ( shake
& (1 << i
) )
296 rpt
[rpt_accel
+ i
] = shake_data
[shake_step
];
311 m_extension
->GetState(rpt
+ rpt_ext
);
312 wiimote_encrypt(&m_ext_key
, rpt
+ rpt_ext
, 0x00, sizeof(wm_extension
));
314 // i dont think anything accesses the extension data like this, but ill support it
315 memcpy( m_reg_ext
+ 8, rpt
+ rpt_ext
, sizeof(wm_extension
));
319 m_wiimote_init
->pWiimoteInput( m_index
, m_reporting_channel
, rpt
, (u32
)rpt_size
);
324 void Wiimote::ControlChannel(u16 _channelID
, const void* _pData
, u32 _Size
)
327 // Check for custom communication
328 if (99 == _channelID
)
330 // wiimote disconnected
331 //PanicAlert( "Wiimote Disconnected" );
333 // reset eeprom/register/reporting mode
338 hid_packet
* hidp
= (hid_packet
*)_pData
;
340 INFO_LOG(WIIMOTE
, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", m_index
, hidp
->type
, hidp
->param
);
344 case HID_TYPE_HANDSHAKE
:
345 PanicAlert("HID_TYPE_HANDSHAKE - %s", (hidp
->param
== HID_PARAM_INPUT
) ? "INPUT" : "OUPUT");
348 case HID_TYPE_SET_REPORT
:
349 if (HID_PARAM_INPUT
== hidp
->param
)
351 PanicAlert("HID_TYPE_SET_REPORT - INPUT");
355 // AyuanX: My experiment shows Control Channel is never used
356 // shuffle2: but homebrew uses this, so we'll do what we must :)
357 HidOutputReport(_channelID
, (wm_report
*)hidp
->data
);
359 u8 handshake
= HID_HANDSHAKE_SUCCESS
;
360 m_wiimote_init
->pWiimoteInput(m_index
, _channelID
, &handshake
, 1);
362 PanicAlert("HID_TYPE_DATA - OUTPUT: Ambiguous Control Channel Report!");
367 PanicAlert("HID_TYPE_DATA - %s", (hidp
->param
== HID_PARAM_INPUT
) ? "INPUT" : "OUTPUT");
371 PanicAlert("HidControlChannel: Unknown type %x and param %x", hidp
->type
, hidp
->param
);
377 void Wiimote::InterruptChannel(u16 _channelID
, const void* _pData
, u32 _Size
)
379 hid_packet
* hidp
= (hid_packet
*)_pData
;
386 case HID_PARAM_OUTPUT
:
388 wm_report
* sr
= (wm_report
*)hidp
->data
;
389 HidOutputReport(_channelID
, sr
);
394 PanicAlert("HidInput: HID_TYPE_DATA - param 0x%02x", hidp
->type
, hidp
->param
);
400 PanicAlert("HidInput: Unknown type 0x%02x and param 0x%02x", hidp
->type
, hidp
->param
);
405 // TODO: i need to test this
406 void Wiimote::Register::Read( size_t address
, void* dst
, size_t length
)
410 const std::vector
<u8
>* block
= NULL
;
411 size_t addr_start
= 0;
412 size_t addr_end
= address
+length
;
414 // TODO: don't need to start at begin() each time
415 // find block and start of next block
420 if ( address
>= i
->first
)
423 addr_start
= i
->first
;
427 addr_end
= std::min( i
->first
, addr_end
);
431 // read bytes from a mapped block
434 const size_t offset
= std::min( address
- addr_start
, block
->size() );
435 const size_t amt
= std::min( block
->size()-offset
, length
);
437 memcpy( dst
, &block
->operator[](offset
), amt
);
440 dst
= ((u8
*)dst
) + amt
;
444 // read zeros for unmapped regions
445 const size_t amt
= addr_end
- address
;
447 memset( dst
, 0, amt
);
450 dst
= ((u8
*)dst
) + amt
;
455 // TODO: i need to test this
456 void Wiimote::Register::Write( size_t address
, void* src
, size_t length
)
460 std::vector
<u8
>* block
= NULL
;
461 size_t addr_start
= 0;
462 size_t addr_end
= address
+length
;
464 // TODO: don't need to start at begin() each time
465 // find block and start of next block
470 if ( address
>= i
->first
)
473 addr_start
= i
->first
;
477 addr_end
= std::min( i
->first
, addr_end
);
481 // write bytes to a mapped block
484 const size_t offset
= std::min( address
- addr_start
, block
->size() );
485 const size_t amt
= std::min( block
->size()-offset
, length
);
487 memcpy( &block
->operator[](offset
), src
, amt
);
490 src
= ((u8
*)src
) + amt
;
494 // do nothing for unmapped regions
495 const size_t amt
= addr_end
- address
;
498 src
= ((u8
*)src
) + amt
;