Stage1.continued: Introducing partial emulated MotionPlus+Nunchuk support, allowing us now for instance to get ingame on RedSteel2. However dont expect too much yet, since this is not completely finished. Wii Sports Resort with mp+nunchuk won't work yet and input from the nunchuk passed through the motionplus does not work properly either. Apart from that Stage1, is almost done.
Just minor stuff that needs to be finished: Dummy motionplus data needs to be kept dynamic(just like wiimote accel data), or it might cause disconnects after some time. Furthermore, there are 1-2 remaining register writes that have to be understood and emulated.(e.g. 0x00F3/F4). In the end just minor stuff. I'll address that in my next commit. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5476 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
99d0bd7762
commit
619dc12349
|
@ -239,12 +239,18 @@ void SendReportCoreAccelIr10Ext(u16 _channelID)
|
|||
FillReportInfo(pReport->c);
|
||||
FillReportAcc(pReport->a);
|
||||
FillReportIRBasic(pReport->ir[0], pReport->ir[1]);
|
||||
if ((WiiMapping[g_ID].bMotionPlusConnected) && (( WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK ) || (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)) )
|
||||
if ((WiiMapping[g_ID].bMotionPlusConnected) )
|
||||
{
|
||||
if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
FillReportMotionPlus(pReport->ext, true);
|
||||
|
||||
if (g_RegExt[g_ID][0xFF] == 0x05) {
|
||||
FillReportMotionPlus(pReport->ext, true);
|
||||
}
|
||||
else {
|
||||
FillReportExtension(pReport->ext);
|
||||
}
|
||||
DEBUG_LOG(WIIMOTE, "Motionplus:Nunchuk data -> ext:%01x mp:%01x [ff:0x%02x]", (pReport->ext.az &0x01), (pReport->ext.bt &0x02),g_RegExt[g_ID][0xFF]);
|
||||
|
||||
}
|
||||
else if (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)
|
||||
{
|
||||
|
|
|
@ -47,12 +47,12 @@ u8 g_Speaker[MAX_WIIMOTES];
|
|||
u8 g_MotionPlus[MAX_WIIMOTES];
|
||||
u8 g_SpeakerMute[MAX_WIIMOTES];
|
||||
|
||||
u8 g_MotionPlusLastWriteReg[MAX_WIIMOTES];
|
||||
int g_MotionPlusReadError[MAX_WIIMOTES];
|
||||
u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
|
||||
|
||||
int g_ID; // Current refreshing Wiimote
|
||||
bool g_ReportingAuto[MAX_WIIMOTES]; // Auto report or passive report
|
||||
bool g_MotionPlusConnected[MAX_WIIMOTES]; //MotionPlusinitiated
|
||||
bool g_InterleavedData[MAX_WIIMOTES]; //sending alternated data packets from the nunchuk/motionplus
|
||||
u8 g_ReportingMode[MAX_WIIMOTES]; // The reporting mode and channel id
|
||||
u16 g_ReportingChannel[MAX_WIIMOTES];
|
||||
|
|
|
@ -87,8 +87,10 @@ extern u8 g_IR[MAX_WIIMOTES];
|
|||
extern u8 g_Leds[MAX_WIIMOTES];
|
||||
extern u8 g_Speaker[MAX_WIIMOTES];
|
||||
extern u8 g_MotionPlus[MAX_WIIMOTES];
|
||||
extern u8 g_MotionPlusLastWriteReg[MAX_WIIMOTES];
|
||||
extern u8 g_SpeakerMute[MAX_WIIMOTES];
|
||||
|
||||
|
||||
extern int g_MotionPlusReadError[MAX_WIIMOTES];
|
||||
extern u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
|
||||
|
||||
|
@ -119,13 +121,13 @@ static const u8 EepromData_16D0[] = {
|
|||
static const u8 motionplus_register[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x79, 0x83, 0x73, 0x54, 0x72, 0xE8, 0x30, 0xC3, 0xCC, 0x4A, 0x34, 0xFC, 0xC8, 0x4F, 0xCC, 0x5B,
|
||||
0x77, 0x49, 0x75, 0xA4, 0x73, 0x9A, 0x35, 0x52, 0xCA, 0x22, 0x37, 0x26, 0x2D, 0xE5, 0xB5, 0xA2,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x78, 0x76, 0xDD, 0xF5, 0x6A, 0x3C, 0xCF, 0xF7, 0x2A, 0x0E, 0x32, 0xEE, 0x82, 0xFE, 0x2E, 0xFD,
|
||||
0x19, 0xE7, 0x0A, 0xCA, 0x67, 0x3B, 0x3A, 0x75, 0xF6, 0x45, 0x55, 0x8E, 0x9D, 0x33, 0xCC, 0xEA,
|
||||
0x6E, 0x52, 0xC6, 0xC6, 0x16, 0x9B, 0xEE, 0x12, 0x2E, 0x3F, 0x77, 0xB1, 0xA1, 0x80, 0x0B, 0x0E,
|
||||
0xC2, 0x25, 0x05, 0xEA, 0xC3, 0x2F, 0x85, 0x1E, 0x31, 0x53, 0x74, 0xC7, 0xF1, 0x93, 0xF1, 0x2D,
|
||||
0x79, 0x83, 0x73, 0x54, 0x72, 0xE8, 0x30, 0xC3, 0xCC, 0x4A, 0x34, 0xFC, 0xC8, 0x4F, 0xCC, 0x5B, //MP calibration data
|
||||
0x77, 0x49, 0x75, 0xA4, 0x73, 0x9A, 0x35, 0x52, 0xCA, 0x22, 0x37, 0x26, 0x2D, 0xE5, 0xB5, 0xA2, //MP calibration data
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //Extensions(NC) calibration data
|
||||
0x1e, 0x54, 0x74, 0xa2, 0x96, 0xec, 0x2b, 0xd6, 0xe1, 0xef, 0xc3, 0xf7, 0x84, 0x9e, 0x06, 0xbb,
|
||||
0x39, 0x33, 0x3d, 0x20, 0x97, 0xed, 0x75, 0x52, 0xfd, 0x98, 0xaf, 0xd8, 0xc9, 0x5a, 0x17, 0x23,
|
||||
0x74, 0x3a, 0x49, 0xd3, 0xb9, 0xf6, 0xff, 0x4f, 0x34, 0xa8, 0x6d, 0xc4, 0x96, 0x5c, 0xcd, 0xb2,
|
||||
0x33, 0x78, 0x98, 0xe9, 0xa9, 0x7f, 0xf7, 0x5e, 0x07, 0x87, 0xbb, 0x29, 0x01, 0x2b, 0x70, 0x3f,
|
||||
0xC1, 0x6D, 0x84, 0x2A, 0xD8, 0x6F, 0x8A, 0xE5, 0x2D, 0x3B, 0x7B, 0xCC, 0xD2, 0x59, 0xD5, 0xD1,
|
||||
0x9F, 0x5B, 0x6F, 0xAE, 0x82, 0xDE, 0xEA, 0xC3, 0x73, 0x42, 0x06, 0xA9, 0x77, 0xFF, 0x61, 0xA8,
|
||||
0x1A, 0x70, 0xE4, 0x16, 0x90, 0x7A, 0x80, 0xF7, 0x79, 0x4B, 0x41, 0x18, 0x82, 0x6C, 0x62, 0x1A,
|
||||
|
@ -174,9 +176,10 @@ static const u8 gh3glp_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x03 };
|
|||
static const u8 ghwtdrums_id[] = { 0x01, 0x00, 0xa4, 0x20, 0x01, 0x03 };
|
||||
static const u8 wbb_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x4, 0x02 };
|
||||
static const u8 motionplus_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x04, 0x05 };
|
||||
static const u8 motionplusnunchuk_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x05, 0x05 };
|
||||
static const u8 motionplusnunchuk_id[] = { 0x00, 0x00, 0xa6, 0x20, 0x05, 0x05 };
|
||||
//initial control packet for datatransfers over 0x37 reports
|
||||
static const u8 motionpluscheck_id[] = { 0xa3, 0x62, 0x45, 0xaa, 0x04, 0x02};
|
||||
static const u8 motionpluscheck_id[] = { 0xa3, 0x62, 0x45, 0xaa, 0x04, 0x02};
|
||||
static const u8 motionpluscheck_id2[] = { 0x39, 0xcd, 0x3f, 0x9a, 0x4b, 0x02};
|
||||
// The id for nothing inserted
|
||||
static const u8 nothing_id[] = { 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e };
|
||||
// The id for a partially inserted extension
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace WiiMoteEmu
|
|||
// Settings
|
||||
accel_cal g_wm;
|
||||
nu_cal g_nu;
|
||||
mp_cal g_mp[2]; //fast[0] and slow[01]-motion
|
||||
cc_cal g_ClassicContCalibration;
|
||||
gh3_cal g_GH3Calibration;
|
||||
|
||||
|
@ -417,6 +418,7 @@ void ResetVariables()
|
|||
{
|
||||
g_ReportingAuto[i] = false;
|
||||
g_MotionPlusReadError[i] = 0;
|
||||
g_MotionPlusLastWriteReg[i] = 0;
|
||||
g_InterleavedData[i] = false;
|
||||
g_ReportingMode[i] = 0;
|
||||
g_ReportingChannel[i] = 0;
|
||||
|
@ -458,6 +460,13 @@ void InitCalibration()
|
|||
g_nu.cal_g.y = nunchuck_calibration[0x05] - nunchuck_calibration[0x01];
|
||||
g_nu.cal_g.z = nunchuck_calibration[0x06] - nunchuck_calibration[0x02];
|
||||
|
||||
g_mp[0].cal_zero.x = ((motion_plus_calibration[0x00]<<6) + (motion_plus_calibration[0x01]>>2));
|
||||
g_mp[0].cal_zero.y = ((motion_plus_calibration[0x02]<<6) + (motion_plus_calibration[0x03]>>2));
|
||||
g_mp[0].cal_zero.z = ((motion_plus_calibration[0x04]<<6) + (motion_plus_calibration[0x05]>>2));
|
||||
g_mp[1].cal_zero.x = ((motion_plus_calibration[0x10]<<6) + (motion_plus_calibration[0x11]>>2));
|
||||
g_mp[1].cal_zero.y = ((motion_plus_calibration[0x12]<<6) + (motion_plus_calibration[0x13]>>2));
|
||||
g_mp[1].cal_zero.z = ((motion_plus_calibration[0x14]<<6) + (motion_plus_calibration[0x15]>>2));
|
||||
|
||||
g_nu.jx.max = nunchuck_calibration[0x08];
|
||||
g_nu.jx.min = nunchuck_calibration[0x09];
|
||||
g_nu.jx.center = nunchuck_calibration[0x0a];
|
||||
|
@ -500,26 +509,28 @@ void UpdateExtRegisterBlocks(int Slot)
|
|||
if (WiiMapping[Slot].iExtensionConnected == EXT_NONE)
|
||||
{
|
||||
memset(g_RegExt[Slot],0,sizeof(g_RegExt[0]));
|
||||
memcpy(g_RegMotionPlus[Slot], motionplus_register, sizeof(motionplus_register));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration)); //reg 32bytes 0x20-3f;
|
||||
g_MotionPlus[Slot] = 0;
|
||||
//memcpy(g_RegMotionPlus[Slot] + 0xfa, motionplus_id, sizeof(motionplus_id));
|
||||
memcpy(g_RegExt[Slot], motionplus_register, sizeof(motionplus_register));
|
||||
memcpy(g_RegExt[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration)); //reg 32bytes 0x20-3f;
|
||||
memcpy(g_RegExt[Slot] + 0xfa, motionplus_id, sizeof(motionplus_id));
|
||||
g_MotionPlus[Slot] = 1;
|
||||
}
|
||||
else if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
memset(g_RegMotionPlus[Slot],0,sizeof(g_RegExt[0]));
|
||||
memcpy(g_RegMotionPlus[Slot], motionplus_register, sizeof(motionplus_register));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration)); //reg 32bytes 0x20-3f;
|
||||
memcpy(g_RegMotionPlus[Slot] + 0x40, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegMotionPlus[Slot] + 0xfa, motionplusnunchuk_id, sizeof(motionplusnunchuk_id));
|
||||
memcpy(g_RegExt[Slot] + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration));
|
||||
memcpy(g_RegExt[Slot] + 0xfa, nunchuck_id, sizeof(nunchuck_id));
|
||||
g_MotionPlus[Slot] = 1;
|
||||
|
||||
g_MotionPlus[Slot] = 0;
|
||||
}
|
||||
g_MotionPlusReadError[Slot] = 0;
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
// Copy extension id and calibration to its register
|
||||
if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUK)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace WiiMoteEmu
|
|||
// Settings
|
||||
extern accel_cal g_wm;
|
||||
extern nu_cal g_nu;
|
||||
extern mp_cal g_mp[2];
|
||||
extern cc_cal g_ClassicContCalibration;
|
||||
extern gh3_cal g_GH3Calibration;
|
||||
|
||||
|
|
|
@ -227,7 +227,6 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
DEBUG_LOG(WIIMOTE, " Case 0xa4: ExtReg");
|
||||
break;
|
||||
|
||||
// MotionPlus is pretty much just a dummy atm :p
|
||||
case 0xA6:
|
||||
block = g_RegMotionPlus[g_ID];
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
|
@ -270,10 +269,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
PanicAlert("WmReadData: address + size out of bounds! [%d %d %d]", address, size, blockSize);
|
||||
return;
|
||||
}
|
||||
//3x read error due activated(or not present device, which is not the case), WII will await a status report after init and attempting to read from write-only area @A600FE/FF
|
||||
if ((g_MotionPlusReadError[g_ID] == 2) && (g_RegExt[g_ID][0xFF]== 0x05)) { //if motionplus is active, its in the current ExtReg, 0xFF will be always 0x05
|
||||
WmRequestStatus(_channelID, (wm_request_status*) rd, 1);
|
||||
}
|
||||
|
||||
// Let this function process the message and send it to the Wii
|
||||
SendReadDataReply(_channelID, block + address, address, addressHI, (u8)size);
|
||||
|
||||
|
@ -341,21 +337,18 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI,
|
|||
pReply->size = 0x0f;
|
||||
pReply->error = 0x08;
|
||||
}
|
||||
|
||||
if (WiiMapping[g_ID].bMotionPlusConnected)
|
||||
{
|
||||
//MP+ will try to read from this Registeraddress, expecting an error if a previous WM+ activation has been succesful
|
||||
//it also returns an error if there was no WM+ present at all
|
||||
if (((_Address == 0x00FE ) || (_Address == 0x00FF )) && (_AddressHI == 0xA6))
|
||||
//It will also return an error if there was no WM+ present at all
|
||||
if (((_Address == 0x00FE ) || (_Address == 0x00FF )) && (_AddressHI == 0xA6) && (g_RegExt[g_ID][0xFF] == 0x05))
|
||||
{
|
||||
//Check if MP+ is activated, resp. if its in the current RegExt.
|
||||
if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[g_ID][0xFF] != 0x05))
|
||||
{
|
||||
pReply->size = 0x0f;
|
||||
pReply->error = 0x07; //error: write-only area when activated/or not present
|
||||
// we use the read error at the same time as an indicator whether we need to send a faked 0x37 report or not
|
||||
g_MotionPlusReadError[g_ID]++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,9 +451,33 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
|
|||
// that we send it parts of a key, only the last full key will have an effect
|
||||
if(address >= 0x40 && address <= 0x4c)
|
||||
wiimote_gen_key(&g_ExtKey[g_ID], &g_RegExt[g_ID][0x40]);
|
||||
|
||||
}
|
||||
if (WiiMapping[g_ID].bMotionPlusConnected) {
|
||||
HandlingMotionPlusWrites(wd->data, addressHI, address);
|
||||
//If the MP+ gets activated, it's important to send a status report if there's another extension connected to MP
|
||||
int sendreport = HandlingMotionPlusWrites(wd->data, addressHI, address);
|
||||
g_MotionPlusLastWriteReg[g_ID] = address;
|
||||
|
||||
switch (sendreport)
|
||||
{
|
||||
//reconnect device; unplug old extension && plug in new extension
|
||||
case 1:
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 0);
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 1);
|
||||
break;
|
||||
//device unplugged(on deactivation)
|
||||
case 2:
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 0);
|
||||
break;
|
||||
//device plugged in(on activation)
|
||||
case 3:
|
||||
WmRequestStatus(_channelID, (wm_request_status*) wd, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -506,8 +523,11 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension)
|
|||
// Check if we have a specific order about the extension status
|
||||
if (Extension == -1)
|
||||
{
|
||||
if (WiiMapping[g_ID].bMotionPlusConnected)
|
||||
pStatus->extension = ((g_MotionPlus[g_ID]) || (WiiMapping[g_ID].iExtensionConnected != EXT_NONE)) ? 1 : 0;
|
||||
else
|
||||
pStatus->extension = (WiiMapping[g_ID].iExtensionConnected == EXT_NONE) ? 0 : 1;
|
||||
// Read config value for the first time
|
||||
pStatus->extension = ((g_MotionPlus[g_ID]) || (WiiMapping[g_ID].iExtensionConnected != EXT_NONE)) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -528,19 +548,25 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension)
|
|||
//ReadDebugging(true, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){
|
||||
//http://snzgoo.blogspot.com for more details on what this is doing
|
||||
int HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){
|
||||
switch (addressHI)
|
||||
{
|
||||
case 0xA4:
|
||||
switch (address)
|
||||
{
|
||||
case 0x00FE:
|
||||
case 0x00FE:
|
||||
if (data[0] == 0x00) {
|
||||
if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[g_ID][0xFF] != 0x05))
|
||||
if (g_RegExt[g_ID][0xFF] == 0x05)
|
||||
{
|
||||
SwapExtRegisters();
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address);
|
||||
if (WiiMapping[g_ID].iExtensionConnected != EXT_NONE){
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address);
|
||||
g_RegMotionPlus[g_ID][0xFE] = 0x00;
|
||||
|
||||
return 1; // we need to issue a 0x20 report, if there's an extension connected to the MP+!
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM+ already inactive", data[0], addressHI, address);
|
||||
|
@ -549,42 +575,105 @@ void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x00FB:
|
||||
//1. Initializing the extension: writing 0x55 ->0xA400F0 and then 0x00 to 0xA400FB.
|
||||
//2. Disables an active wiimote; ext disconnect.
|
||||
if (data[0] == 0x00) {
|
||||
//1. connecting extension
|
||||
if ((g_RegExt[g_ID][0xFF] != 0x05) && (g_RegMotionPlus[g_ID][0xFF] == 0x05))
|
||||
//1. Initializing the pass-through extension: writing 0x55 ->0xA400F0 and then 0x00 to 0xA400FB.
|
||||
//2. Disables an active wiimote; 0x20 report sent when iExtensionConnected != NONE : ext disconnect.
|
||||
//3. single write 0x00 to 0x00FB when MP got activated, part of the MP activation.
|
||||
case 0x00FB:
|
||||
|
||||
if ((data[0] == 0x00) && (g_MotionPlusLastWriteReg[g_ID] == 0xF0)) {
|
||||
|
||||
//1. Default extension init, disable mp if actitaved, else do nothing
|
||||
if (g_RegMotionPlus[g_ID][0xFF] == 0x05) //mp already deactivated, no register swap needed
|
||||
{
|
||||
g_RegMotionPlus[g_ID][0xFE] = 0x04;
|
||||
g_RegMotionPlus[g_ID][0xF7] = 0x08; //control init byte, ingame check
|
||||
SwapExtRegisters();
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Enabling WM+ and swapping rgisters", data[0], addressHI, address);
|
||||
g_MotionPlus[g_ID] = 0;
|
||||
} //2. disconnecting extension
|
||||
else if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[g_ID][0xFF] != 0x05)){
|
||||
g_RegExt[g_ID][0xFE] = 0x04;
|
||||
g_MotionPlus[g_ID] = 1;
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address);
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM+ already disabled [ext:%i] - no swapping", data[0], addressHI, address, WiiMapping[g_ID].iExtensionConnected);
|
||||
g_RegMotionPlus[g_ID][0xFE] = 0x05;
|
||||
g_RegMotionPlus[g_ID][0xF7] = 0x08;
|
||||
|
||||
} //2. disabling wiimote,
|
||||
else if (g_RegExt[g_ID][0xFF] == 0x05){
|
||||
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address)
|
||||
|
||||
if (!WiiMapping[g_ID].iExtensionConnected){
|
||||
g_RegExt[g_ID][0xFE] = 0x05;
|
||||
g_MotionPlus[g_ID] = 0;
|
||||
SwapExtRegisters();
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
g_RegExt[g_ID][0xFE] = 0x05;
|
||||
SwapExtRegisters();
|
||||
g_MotionPlus[g_ID] = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} //3.
|
||||
else if ((data[0] == 0x00) && (g_MotionPlusLastWriteReg[g_ID] != 0xF0)) {
|
||||
|
||||
if (g_RegExt[g_ID][0xFF] == 0x05) {
|
||||
g_RegExt[g_ID][0xF1] = 0x01;
|
||||
g_RegExt[g_ID][0xF7] = 0x08; //init/calibration state flag
|
||||
|
||||
if (WiiMapping[g_ID].iExtensionConnected){
|
||||
//I don't know what these are for: F6h,F8h, F9h; but they seem necessary to be set to 0x00
|
||||
//if there's an extension connected to the MP, else they are 0xFF
|
||||
g_RegExt[g_ID][0xF6] = 0x00;
|
||||
g_RegExt[g_ID][0xF8] = 0x00;
|
||||
g_RegExt[g_ID][0xF9] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//switch for invalid/valid data calibration (00/01)
|
||||
case 0x00F1:
|
||||
if (g_RegExt[g_ID][0xFF] == 0x05) {
|
||||
g_RegExt[g_ID][0xF7] = 0x1A;
|
||||
}
|
||||
break;
|
||||
|
||||
//switch for triggering the calibration/syncing between wiimote and MP (corresponding data will be at 50h)
|
||||
case 0x00F2:
|
||||
if((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegExt[g_ID][0xF7] < 0x0E)) {
|
||||
g_RegExt[g_ID][0xF7] = 0x0E;
|
||||
}
|
||||
break;
|
||||
|
||||
//case 0x00F3/0x00F4: //It'ss probably just the same as either F1/F2, needs more investigation tho,
|
||||
// but most likely just a different calibration sensitivity; wii sports resort does use it, but redsteel doesnt
|
||||
}
|
||||
break;
|
||||
|
||||
//MotionPlus Register
|
||||
case 0xA6:
|
||||
switch (address)
|
||||
{
|
||||
case 0x00FE:
|
||||
//Enabling WM+, swapping extension registers
|
||||
if (data[0] == 0x05) {
|
||||
if ((g_RegExt[g_ID][0xFF] != 0x05) && (g_RegMotionPlus[g_ID][0xFF] == 0x05) ) {
|
||||
//The WII will try to read from the readprotected A6 WM+ register now, we need to reply with an error each time,
|
||||
//plus sent an statusreport 0x20(depending on if nunchuk inserted or not)
|
||||
//Enabling WM+: swapping extension registers
|
||||
if ((data[0] == 0x04) || (data[0] == 0x05)) {
|
||||
if (g_RegMotionPlus[g_ID][0xFF] == 0x05) {
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Enabling WM+ and swapping registers", data[0], addressHI, address);
|
||||
|
||||
//The WII will try to read from the A6 WM+ register directly after activation,
|
||||
//but we need to reply with an error each time as long the mp is still activate.
|
||||
//In addition, we need to sent 1-2 0x20 statusreports depending on if theres an extension connected to the MP or not.
|
||||
g_MotionPlusReadError[g_ID] = 0;
|
||||
|
||||
g_RegMotionPlus[g_ID][0xF7] = 0x08;
|
||||
g_RegMotionPlus[g_ID][0xFE] = data[0];
|
||||
g_MotionPlus[g_ID] = 1;
|
||||
SwapExtRegisters();
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Enabling WM+ and swapping rgisters back", data[0], addressHI, address);
|
||||
|
||||
if (WiiMapping[g_ID].iExtensionConnected != EXT_NONE){
|
||||
|
||||
g_RegExt[g_ID][0xF1] = 0x01;
|
||||
g_RegExt[g_ID][0xF6] = 0x00; // i dont knwo what these are for: F6h,F8h, F9h; but they are necessary to be set to 0x00 if theres a nunchuk/ext connected
|
||||
g_RegExt[g_ID][0xF8] = 0x00;
|
||||
g_RegExt[g_ID][0xF9] = 0x00;
|
||||
return 1; // we need to issue 2 0x20 reports, if there's an extension connected to the MP
|
||||
}
|
||||
return 3; // we need to issue 1 0x20 report, if there's an extension connected to the MP
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM already enabled no register swapping", data[0], addressHI, address);
|
||||
|
@ -592,23 +681,16 @@ void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x00F0: //init() WM+, this will change some control bits in the WM+ register
|
||||
if (data[0] == 0x55) { //enables passthroug, convert to 0405* A6 swap
|
||||
if ((g_RegMotionPlus[g_ID][0xFF] == 0x05))
|
||||
{
|
||||
//control init byte, ingame check
|
||||
g_RegMotionPlus[g_ID][0xF7] = 0x08;
|
||||
|
||||
//motion plus id
|
||||
g_RegMotionPlus[g_ID][0xFE] = 0x05;
|
||||
|
||||
//we will swap the register on write to 0x00FE
|
||||
}
|
||||
else if (g_RegExt[g_ID][0xFF] == 0x05) { //if the wiimote is already active, we will init() the WM+ directly in the ExtReg
|
||||
case 0x00F0: //Part of the WM+ init()
|
||||
if (data[0] == 0x55) {
|
||||
|
||||
//if the wiimote is already active, we will init() the WM+ directly in the ExtReg, shouldnt happen usually
|
||||
if (g_RegExt[g_ID][0xFF] == 0x05) {
|
||||
g_RegExt[g_ID][0xFE] = 0x05;
|
||||
g_RegExt[g_ID][0xF7] = 0x08;
|
||||
g_RegExt[g_ID][0xF7] = 0x08;//calibdata trigger
|
||||
}
|
||||
g_MotionPlus[g_ID] = 0;
|
||||
if (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)
|
||||
g_MotionPlus[g_ID] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -618,6 +700,7 @@ void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){
|
|||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Swapping Ext/WM+-registers
|
||||
|
|
|
@ -53,7 +53,7 @@ int WriteWmReportHdr(u8* dst, u8 wm);
|
|||
void WmSendAck(u16 _channelID, u8 _reportID);
|
||||
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI, int _Size);
|
||||
void SwapExtRegisters();
|
||||
void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address);
|
||||
int HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address);
|
||||
|
||||
void FillReportAcc(wm_accel& _acc);
|
||||
void FillReportInfo(wm_core& _core);
|
||||
|
|
|
@ -1253,10 +1253,10 @@ void FillReportGuitarHero3Extension(wm_GH3_extension& _ext)
|
|||
void FillReportMotionPlus(wm_extension& ext, bool extension){
|
||||
|
||||
//sending initial control packet, this must be sent first, its some kind of verifiation, all control bits are set to 0!
|
||||
if (g_MotionPlusReadError[g_ID]) {
|
||||
|
||||
if ((g_MotionPlusReadError[g_ID]) && (g_RegExt[g_ID][0xFE] == 0x05) && (!extension)) {
|
||||
memcpy(&ext, motionpluscheck_id, sizeof(motionpluscheck_id));
|
||||
g_MotionPlus[g_ID] = (extension) ? 1 : 0;
|
||||
|
||||
//g_MotionPlus[g_ID] = (extension) ? 1 : 0;
|
||||
g_MotionPlusReadError[g_ID] = 0;
|
||||
|
||||
} //nunchuk inserted
|
||||
|
@ -1288,18 +1288,24 @@ void FillReportMotionPlusNoExtension(wm_extension& _ext)
|
|||
{
|
||||
wm_mp_nc_0 ext;
|
||||
memset(&ext, 0, sizeof(wm_mp_nc_0));
|
||||
ext.YawLeftLS = 0x00; //dummy data atm
|
||||
ext.RollLeftLS = 0x00;
|
||||
ext.PitchDownLS = 0x00;
|
||||
ext.pitchfast = 0x00;
|
||||
ext.yawfast = 0x00;
|
||||
ext.YawLeftHI = 0x00;
|
||||
ext.ExtCon = 0x00; // 0 (important, since we don't use a nunchuk here)
|
||||
ext.rollfast = 0x00;
|
||||
ext.RollLeftHI = 0x00;
|
||||
ext.dummy = 0x00; // 0 (important)
|
||||
|
||||
//bookkeeping bits
|
||||
ext.ExtCon = ((WiiMapping[g_ID].iExtensionConnected != EXT_NONE)) ? 1 : 0; //0 = no passed-through ext., 1 = ext. connected;
|
||||
ext.mpdata = 0x01; //1 (important, using MP+ report instead of NC report)
|
||||
ext.PitchDownHI = 0x00;
|
||||
ext.dummy = 0x00; // 0 (important)
|
||||
/*
|
||||
ext.yawslow = 0x01;
|
||||
ext.pitchslow = 0x01;
|
||||
ext.rollslow = 0x01;
|
||||
|
||||
ext.YawLeftLS = g_mp[1].cal_zero.x;
|
||||
ext.RollLeftLS = g_mp[1].cal_zero.y;
|
||||
ext.PitchDownLS = g_mp[1].cal_zero.z;
|
||||
|
||||
ext.YawLeftHI = g_mp[1].cal_zero.x>>8;
|
||||
ext.RollLeftHI = g_mp[1].cal_zero.y>>8;
|
||||
ext.PitchDownHI = g_mp[1].cal_zero.z>>8;
|
||||
*/
|
||||
memcpy(&_ext, &ext, sizeof(ext));
|
||||
|
||||
}
|
||||
|
@ -1316,9 +1322,6 @@ void FillReportMotionPlusNunchukExtension(wm_extension& _ext)
|
|||
ext.ax = g_nu.cal_zero.x;
|
||||
ext.ay = g_nu.cal_zero.y;
|
||||
ext.az = g_nu.cal_zero.z + g_nu.cal_g.z;
|
||||
ext.axLS = 0x00;
|
||||
ext.ayLS = 0x00;
|
||||
ext.azLS = 0x00;
|
||||
|
||||
ext.bz = 0x01;
|
||||
ext.bc = 0x01;
|
||||
|
@ -1326,7 +1329,6 @@ void FillReportMotionPlusNunchukExtension(wm_extension& _ext)
|
|||
ext.mpdata = 0; //0 NC report, interleaved data (important)
|
||||
ext.ExtCon = 1; // must be 1 when in NC-MP+ Mode
|
||||
|
||||
|
||||
if (IsFocus())
|
||||
{
|
||||
int acc_x = g_nu.cal_zero.x;
|
||||
|
|
|
@ -66,6 +66,9 @@ struct wm_accel {
|
|||
u8 x, y, z;
|
||||
};
|
||||
|
||||
struct mp_gyro {
|
||||
u16 x:14, y:14, z:14;
|
||||
};
|
||||
// Four bytes for two objects. Filled with 0xFF if empty
|
||||
struct wm_ir_basic
|
||||
{
|
||||
|
@ -138,23 +141,23 @@ struct wm_classic_extension
|
|||
wm_cc_5 b2; // byte 5
|
||||
};
|
||||
|
||||
struct wm_mp_nc_0 //motionplus+nunchuk_pass-through
|
||||
struct wm_mp_nc_0 //motionplus data
|
||||
{
|
||||
u8 YawLeftLS; //7e
|
||||
u8 RollLeftLS; //82
|
||||
u8 PitchDownLS; //83
|
||||
u8 pitchfast : 1; //1
|
||||
u8 yawfast : 1; //0
|
||||
u8 pitchslow : 1; //1
|
||||
u8 yawslow : 1; //0
|
||||
u8 YawLeftHI : 6; //01 1010 /1a
|
||||
u8 ExtCon : 1; // 1 usually
|
||||
u8 rollfast : 1; //0
|
||||
u8 rollslow : 1; //0
|
||||
u8 RollLeftHI : 6; //00 1010
|
||||
u8 dummy : 1; // 0 usually. 1 in dem fall mhh
|
||||
u8 mpdata : 1; //1 in this case, interleaved motion+ data
|
||||
u8 PitchDownHI : 6;//01 1100
|
||||
}; // default for yaw/roll/pitch around 0x1F7F
|
||||
|
||||
struct wm_mp_nc_1 //motionplus+nunchuk_pass-through
|
||||
struct wm_mp_nc_1 //nunchuk data on motion-plus pass-through
|
||||
{
|
||||
u8 jx;
|
||||
u8 jy;
|
||||
|
@ -378,6 +381,14 @@ struct nu_cal
|
|||
nu_js jx; //
|
||||
nu_js jy; //
|
||||
};
|
||||
|
||||
struct mp_cal
|
||||
{
|
||||
mp_gyro cal_zero;
|
||||
mp_gyro cal_min;
|
||||
mp_gyro cal_max;
|
||||
};
|
||||
|
||||
struct cc_cal
|
||||
{
|
||||
nu_js Lx; //
|
||||
|
|
Loading…
Reference in New Issue