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:
snzgoo 2010-05-26 15:41:47 +00:00
parent 99d0bd7762
commit 619dc12349
9 changed files with 216 additions and 99 deletions

View File

@ -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)
{

View File

@ -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];

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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; //