New Wiimote Plugin: Added a real wiimote "Pair Up" button on Windows for the Microsof...
[dolphin.git] / Source / Plugins / Plugin_WiimoteNew / Src / WiimoteEmu / EmuSubroutines.cpp
blob23eec2d416b966569f4e394014d8e1f2d8a05601
1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
19 /* HID reports access guide. */
21 /* 0x10 - 0x1a Output EmuMain.cpp: HidOutputReport()
22 0x10 - 0x14: General
23 0x15: Status report request from the Wii
24 0x16 and 0x17: Write and read memory or registers
25 0x19 and 0x1a: General
26 0x20 - 0x22 Input EmuMain.cpp: HidOutputReport() to the destination
27 0x15 leads to a 0x20 Input report
28 0x17 leads to a 0x21 Input report
29 0x10 - 0x1a leads to a 0x22 Input report
30 0x30 - 0x3f Input This file: Update() */
32 #include <vector>
33 #include <string>
34 #include <fstream>
36 #include "Common.h" // Common
37 #include "FileUtil.h"
38 #include "pluginspecs_wiimote.h"
40 #include "WiimoteEmu.h"
41 #include "WiimoteHid.h"
42 #include "../WiimoteReal/WiimoteReal.h"
44 #include "Attachment/Attachment.h"
46 /* Bit shift conversions */
47 u32 swap24(const u8* src)
49 return (src[0] << 16) | (src[1] << 8) | src[2];
52 namespace WiimoteEmu
55 void Wiimote::ReportMode(const wm_report_mode* const dr)
57 //INFO_LOG(WIIMOTE, "Set data report mode");
58 //DEBUG_LOG(WIIMOTE, " Rumble: %x", dr->rumble);
59 //DEBUG_LOG(WIIMOTE, " Continuous: %x", dr->continuous);
60 //DEBUG_LOG(WIIMOTE, " All The Time: %x", dr->all_the_time);
61 //DEBUG_LOG(WIIMOTE, " Mode: 0x%02x", dr->mode);
63 //m_reporting_auto = dr->all_the_time;
64 m_reporting_auto = dr->continuous; // this right?
65 m_reporting_mode = dr->mode;
66 //m_reporting_channel = _channelID; // this is set in every Interrupt/Control Channel now
68 // reset IR camera
69 //memset(m_reg_ir, 0, sizeof(*m_reg_ir)); //ugly hack
71 if (dr->mode > 0x37)
72 PanicAlert("Wiimote: Unsupported Reporting mode.");
73 else if (dr->mode < WM_REPORT_CORE)
74 PanicAlert("Wiimote: Reporting mode < 0x30.");
77 /* Here we process the Output Reports that the Wii sends. Our response will be
78 an Input Report back to the Wii. Input and Output is from the Wii's
79 perspective, Output means data to the Wiimote (from the Wii), Input means
80 data from the Wiimote.
82 The call browser:
84 1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
85 2. Wiimote_ControlChannel > ControlChannel > HidOutputReport
87 The IR enable/disable and speaker enable/disable and mute/unmute values are
88 bit2: 0 = Disable (0x02), 1 = Enable (0x06)
90 void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack)
92 INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, m_reporting_channel, sr->wm);
94 // wiibrew:
95 // In every single Output Report, bit 0 (0x01) of the first byte controls the Rumble feature.
96 m_rumble_on = (sr->data[0] & 0x01) != 0;
98 switch (sr->wm)
100 case WM_RUMBLE : // 0x10
101 // this is handled above
102 return; // no ack
103 break;
105 case WM_LEDS : // 0x11
106 //INFO_LOG(WIIMOTE, "Set LEDs: 0x%02x", sr->data[0]);
107 m_status.leds = sr->data[0] >> 4;
108 return; // no ack
109 break;
111 case WM_REPORT_MODE : // 0x12
112 ReportMode((wm_report_mode*)sr->data);
113 break;
115 case WM_IR_PIXEL_CLOCK : // 0x13
116 //INFO_LOG(WIIMOTE, "WM IR Clock: 0x%02x", sr->data[0]);
117 //m_ir_clock = (sr->data[0] & 0x04) ? 1 : 0;
119 if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set
120 return;
121 break;
123 case WM_SPEAKER_ENABLE : // 0x14
124 //INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]);
125 //PanicAlert( "WM Speaker Enable: %d", sr->data[0] );
126 m_status.speaker = (sr->data[0] & 0x04) ? 1 : 0;
128 if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set
129 return;
130 break;
132 case WM_REQUEST_STATUS : // 0x15
133 RequestStatus((wm_request_status*)sr->data);
134 return; // sends its own ack
135 break;
137 case WM_WRITE_DATA : // 0x16
138 WriteData((wm_write_data*)sr->data);
139 break;
141 case WM_READ_DATA : // 0x17
142 ReadData((wm_read_data*)sr->data);
143 return; // sends its own ack
144 break;
146 case WM_WRITE_SPEAKER_DATA : // 0x18
147 #ifdef USE_WIIMOTE_EMU_SPEAKER
148 SpeakerData((wm_speaker_data*)sr->data);
149 #endif
150 // TODO: Does this need an ack?
151 return; // no ack
152 break;
154 case WM_SPEAKER_MUTE : // 0x19
155 //INFO_LOG(WIIMOTE, "WM Speaker Mute: 0x%02x", sr->data[0]);
156 //PanicAlert( "WM Speaker Mute: %d", sr->data[0] & 0x04 );
157 #ifdef USE_WIIMOTE_EMU_SPEAKER
158 // testing
159 if (sr->data[0] & 0x04)
160 memset(&m_channel_status, 0, sizeof(m_channel_status));
161 #endif
162 m_speaker_mute = (sr->data[0] & 0x04) ? 1 : 0;
164 if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set
165 return;
166 break;
168 case WM_IR_LOGIC: // 0x1a
169 // comment from old plugin:
170 // This enables or disables the IR lights, we update the global variable g_IR
171 // so that WmRequestStatus() knows about it
172 //INFO_LOG(WIIMOTE, "WM IR Enable: 0x%02x", sr->data[0]);
173 m_status.ir = (sr->data[0] & 0x04) ? 1 : 0;
175 if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set
176 return;
177 break;
179 default:
180 PanicAlert("HidOutputReport: Unknown channel 0x%02x", sr->wm);
181 return; // no ack
182 break;
185 // send ack
186 if (send_ack)
187 SendAck(sr->wm);
190 /* This will generate the 0x22 acknowledgement for most Input reports.
191 It has the form of "a1 22 00 00 _reportID 00".
192 The first two bytes are the core buttons data,
193 00 00 means nothing is pressed.
194 The last byte is the success code 00. */
195 void Wiimote::SendAck(u8 _reportID)
197 u8 data[6];
199 data[0] = 0xA1;
200 data[1] = WM_ACK_DATA;
202 wm_acknowledge* const ack = (wm_acknowledge*)(data + 2);
204 ack->buttons = m_status.buttons;
205 ack->reportID = _reportID;
206 ack->errorID = 0;
208 g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, m_reporting_channel, data, sizeof(data));
211 void Wiimote::HandleExtensionSwap()
213 // handle switch extension
214 if (m_extension->active_extension != m_extension->switch_extension)
216 // if an extension is currently connected and we want to switch to a different extension
217 if ((m_extension->active_extension > 0) && m_extension->switch_extension)
218 // detach extension first, wait til next Update() or RequestStatus() call to change to the new extension
219 m_extension->active_extension = 0;
220 else
221 // set the wanted extension
222 m_extension->active_extension = m_extension->switch_extension;
224 // update status struct
225 m_status.extension = m_extension->active_extension ? 1 : 0;
227 // set register, I hate this line
228 m_register[0xa40000] = ((WiimoteEmu::Attachment*)m_extension->attachments[m_extension->active_extension])->reg;
232 // old comment
233 /* Here we produce a 0x20 status report to send to the Wii. We currently ignore
234 the status request rs and all its eventual instructions it may include (for
235 example turn off rumble or something else) and just send the status
236 report. */
237 void Wiimote::RequestStatus(const wm_request_status* const rs)
239 HandleExtensionSwap();
241 // set up report
242 u8 data[8];
243 data[0] = 0xA1;
244 data[1] = WM_STATUS_REPORT;
246 // status values
247 *(wm_status_report*)(data + 2) = m_status;
249 // hybrid wiimote stuff
250 if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && (m_extension->switch_extension <= 0))
252 using namespace WiimoteReal;
254 g_refresh_critsec.Enter();
255 if (g_wiimotes[m_index])
257 wm_request_status rpt;
258 rpt.rumble = 0;
259 g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
261 g_refresh_critsec.Leave();
263 return;
266 // send report
267 g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data));
270 /* Write data to Wiimote and Extensions registers. */
271 void Wiimote::WriteData(const wm_write_data* const wd)
273 u32 address = swap24(wd->address);
275 // ignore the 0x010000 bit
276 address &= 0xFEFFFF;
278 if (wd->size > 16)
280 PanicAlert("WriteData: size is > 16 bytes");
281 return;
284 switch (wd->space)
286 case WM_SPACE_EEPROM :
288 // Write to EEPROM
290 if (address + wd->size > WIIMOTE_EEPROM_SIZE)
292 ERROR_LOG(WIIMOTE, "WriteData: address + size out of bounds!");
293 PanicAlert("WriteData: address + size out of bounds!");
294 return;
296 memcpy(m_eeprom + address, wd->data, wd->size);
298 // write mii data to file
299 // i need to improve this greatly
300 if (address >= 0x0FCA && address < 0x12C0)
302 // writing the whole mii block each write :/
303 std::ofstream file;
304 file.open( (std::string(File::GetUserPath(D_WIIUSER_IDX)) + "mii.bin").c_str(), std::ios::binary | std::ios::out);
305 file.write((char*)m_eeprom + 0x0FCA, 0x02f0);
306 file.close();
309 break;
310 case WM_SPACE_REGS1 :
311 case WM_SPACE_REGS2 :
313 // Write to Control Register
315 // ignore second byte for extension area
316 if (0xA4 == (address >> 16))
317 address &= 0xFF00FF;
319 // write to the register
320 m_register.Write(address, wd->data, wd->size);
322 switch (address >> 16)
324 // speaker
325 case 0xa2 :
326 //PanicAlert("Write to speaker!!");
327 break;
328 // extension register
329 case 0xa4 :
331 // Run the key generation on all writes in the key area, it doesn't matter
332 // that we send it parts of a key, only the last full key will have an effect
333 // I might have f'ed this up
334 if ( address >= 0xa40040 && address <= 0xa4004c )
335 wiimote_gen_key(&m_ext_key, m_reg_ext->encryption_key);
336 //else if ( address >= 0xa40020 && address < 0xa40040 )
337 // PanicAlert("Writing to extension calibration data! Extension may misbehave");
339 break;
340 // ir
341 case 0xB0 :
342 if (5 == m_reg_ir->mode)
343 PanicAlert("IR Full Mode is Unsupported!");
344 break;
348 break;
349 default:
350 PanicAlert("WriteData: unimplemented parameters!");
351 break;
355 /* Read data from Wiimote and Extensions registers. */
356 void Wiimote::ReadData(const wm_read_data* const rd)
358 u32 address = swap24(rd->address);
359 u16 size = Common::swap16(rd->size);
361 // ignore the 0x010000 bit
362 address &= 0xFEFFFF;
364 // hybrid wiimote stuff
365 // relay the read data request to real-wiimote
366 if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && ((0xA4 != (address >> 16)) || (m_extension->switch_extension <= 0)))
368 WiimoteReal::InterruptChannel(m_index, m_reporting_channel, ((u8*)rd) - 2, sizeof(wm_read_data) + 2); // hacky
370 // don't want emu-wiimote to send reply
371 return;
374 ReadRequest rr;
375 u8* block = new u8[size];
377 switch (rd->space)
379 case WM_SPACE_EEPROM :
381 //PanicAlert("ReadData: reading from EEPROM: address: 0x%x size: 0x%x", address, size);
382 // Read from EEPROM
383 if (address + size >= WIIMOTE_EEPROM_FREE_SIZE)
385 if (address + size > WIIMOTE_EEPROM_SIZE)
387 PanicAlert("ReadData: address + size out of bounds");
388 return;
390 // generate a read error
391 size = 0;
394 // read mii data from file
395 // i need to improve this greatly
396 if (address >= 0x0FCA && address < 0x12C0)
398 // reading the whole mii block :/
399 std::ifstream file;
400 file.open( (std::string(File::GetUserPath(D_WIIUSER_IDX)) + "mii.bin").c_str(), std::ios::binary | std::ios::in);
401 file.read((char*)m_eeprom + 0x0FCA, 0x02f0);
402 file.close();
405 // read mem to be sent to wii
406 memcpy( block, m_eeprom + address, size);
408 break;
409 case WM_SPACE_REGS1 :
410 case WM_SPACE_REGS2 :
412 // Read from Control Register
414 // ignore second byte for extension area
415 if (0xA4 == (address >> 16))
416 address &= 0xFF00FF;
418 // read block to send to wii
419 m_register.Read( address, block, size );
421 switch (address >> 16)
423 // speaker
424 case 0xa2 :
425 //PanicAlert("read from speaker!!");
426 break;
427 // extension
428 case 0xa4 :
430 // Encrypt data read from extension register
431 // Check if encrypted reads is on
432 if (0xaa == m_reg_ext->encryption)
433 wiimote_encrypt(&m_ext_key, block, address & 0xffff, (u8)size);
435 //if ( address >= 0xa40008 && address < 0xa40020 )
436 // PanicAlert("Reading extension data from register");
438 break;
439 // motion plus
440 case 0xa6 :
442 // motion plus crap copied from old wiimote plugin
443 //block[0xFC] = 0xA6;
444 //block[0xFD] = 0x20;
445 //block[0xFE] = 0x00;
446 //block[0xFF] = 0x05;
448 break;
451 break;
452 default :
453 PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x)!", size, rd->space);
454 break;
457 // want the requested address, not the above modified one
458 rr.address = swap24(rd->address);
459 rr.size = size;
460 //rr.channel = _channelID;
461 rr.position = 0;
462 rr.data = block;
464 // send up to 16 bytes
465 SendReadDataReply(rr);
467 // if there is more data to be sent, add it to the queue
468 if (rr.size)
469 m_read_requests.push( rr );
470 else
471 delete[] rr.data;
474 // old comment
475 /* Here we produce the actual 0x21 Input report that we send to the Wii. The
476 message is divided into 16 bytes pieces and sent piece by piece. There will
477 be five formatting bytes at the begging of all reports. A common format is
478 00 00 f0 00 20, the 00 00 means that no buttons are pressed, the f means 16
479 bytes in the message, the 0 means no error, the 00 20 means that the message
480 is at the 00 20 offest in the registry that was read.
482 void Wiimote::SendReadDataReply(ReadRequest& _request)
484 u8 data[23];
485 data[0] = 0xA1;
486 data[1] = WM_READ_DATA_REPLY;
488 wm_read_data_reply* const reply = (wm_read_data_reply*)(data + 2);
489 reply->buttons = m_status.buttons;
490 reply->address = Common::swap16(_request.address);
492 // generate a read error
493 // Out of bounds. The real Wiimote generate an error for the first
494 // request to 0x1770 if we dont't replicate that the game will never
495 // read the calibration data at the beginning of Eeprom. I think this
496 // error is supposed to occur when we try to read above the freely
497 // usable space that ends at 0x16ff.
498 if (0 == _request.size)
500 reply->size = 0x0f;
501 reply->error = 0x08;
503 memset(reply->data, 0, sizeof(reply->data));
505 else
507 // Limit the amt to 16 bytes
508 // AyuanX: the MTU is 640B though... what a waste!
509 const int amt = std::min( (unsigned int)16, _request.size );
511 // no error
512 reply->error = 0;
514 // 0x1 means two bytes, 0xf means 16 bytes
515 reply->size = amt - 1;
517 // Clear the mem first
518 memset(reply->data, 0, sizeof(reply->data));
520 // copy piece of mem
521 memcpy(reply->data, _request.data + _request.position, amt);
523 // update request struct
524 _request.size -= amt;
525 _request.position += amt;
526 _request.address += amt;
529 // Send a piece
530 g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data));
533 void Wiimote::DoState(PointerWrap& p)
535 // not working :(
536 //if (p.MODE_READ == p.GetMode())
538 // // LOAD
539 // Reset(); // should cause a status report to be sent, then wii should re-setup wiimote
541 //p.Do(m_reporting_channel);