mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-05-30 06:52:38 +00:00
Stage1: Introducing MotionPlus as emulated extension, allowing us to boot games that require the MotionPlus itself.
I also already implemented most of the needed data structures and datareport handling for the motionplus-nunchuk passthrough mode, which I'll add up next as well. Wii Sports Resort is now bootable by just using an emulated wiimote (only working under the old wiimote plugin atm, I asked billiard to port my commit into his plugin since he knows his plugin better than me and its less work for him than for me, I kept most parts of my code in modules to simplify that task). Upcoming stage2: Faking the motionplus on the fly on real wiimotes, that means you will be able to play, e.g. Redsteel2 with a real wiimote and nunchuk or wii sports resort with just your real wiimote. and nunchuk, but w/o the need of having a real motionpluscontroller connected. The new Zelda 2010 will benefit by that, since it will require a motionplus controller. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5438 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
f6ce87765f
commit
7742e1a6dd
11 changed files with 530 additions and 77 deletions
|
@ -45,7 +45,6 @@ extern SWiimoteInitialize g_WiimoteInitialize;
|
|||
|
||||
namespace WiiMoteEmu
|
||||
{
|
||||
|
||||
extern void PAD_Rumble(u8 _numPAD, unsigned int _uType);
|
||||
|
||||
/* Here we process the Output Reports that the Wii sends. Our response will be
|
||||
|
@ -190,7 +189,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
{
|
||||
u32 address = convert24bit(rd->address);
|
||||
u16 size = convert16bit(rd->size);
|
||||
|
||||
u8 addressHI = (address >> 16) & 0xFE;
|
||||
INFO_LOG(WIIMOTE, "Read data");
|
||||
DEBUG_LOG(WIIMOTE, " Read data Space: %x", rd->space);
|
||||
DEBUG_LOG(WIIMOTE, " Read data Address: 0x%06x", address);
|
||||
|
@ -205,7 +204,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
PanicAlert("WmReadData: address + size out of bounds");
|
||||
return;
|
||||
}
|
||||
SendReadDataReply(_channelID, g_Eeprom[g_ID] + address, address, (int)size);
|
||||
SendReadDataReply(_channelID, g_Eeprom[g_ID] + address, address, addressHI, (int)size);
|
||||
/*DEBUG_LOG(WIIMOTE, "Read RegEeprom: Size: %i, Address: %08x, Offset: %08x",
|
||||
size, address, (address & 0xffff));*/
|
||||
}
|
||||
|
@ -213,7 +212,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
{
|
||||
u8* block;
|
||||
u32 blockSize;
|
||||
switch((address >> 16) & 0xFE)
|
||||
switch(addressHI)
|
||||
{
|
||||
case 0xA2:
|
||||
block = g_RegSpeaker[g_ID];
|
||||
|
@ -230,10 +229,6 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
// MotionPlus is pretty much just a dummy atm :p
|
||||
case 0xA6:
|
||||
block = g_RegMotionPlus[g_ID];
|
||||
block[0xFC] = 0xA6;
|
||||
block[0xFD] = 0x20;
|
||||
block[0xFE] = 0x00;
|
||||
block[0xFF] = 0x05;
|
||||
blockSize = WIIMOTE_REG_EXT_SIZE;
|
||||
DEBUG_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address);
|
||||
break;
|
||||
|
@ -251,7 +246,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
}
|
||||
|
||||
// Encrypt data that is read from the Wiimote Extension Register
|
||||
if(((address >> 16) & 0xfe) == 0xa4)
|
||||
if(addressHI == 0xa4)
|
||||
{
|
||||
// Check if encrypted reads is on
|
||||
if(g_RegExt[g_ID][0xf0] == 0xaa)
|
||||
|
@ -274,9 +269,13 @@ 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, (u8)size);
|
||||
SendReadDataReply(_channelID, block + address, address, addressHI, (u8)size);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -295,7 +294,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
|
|||
_Address: The starting address inside the registry, this is used to check for out of bounds reading
|
||||
_Size: The total size to send
|
||||
*/
|
||||
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size)
|
||||
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI, int _Size)
|
||||
{
|
||||
int dataOffset = 0;
|
||||
const u8* data = (const u8*)_Base;
|
||||
|
@ -340,6 +339,24 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size)
|
|||
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))
|
||||
{
|
||||
//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]++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Logging
|
||||
DEBUG_LOG(WIIMOTE, "SendReadDataReply");
|
||||
|
@ -369,12 +386,11 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size)
|
|||
void WmWriteData(u16 _channelID, wm_write_data* wd)
|
||||
{
|
||||
u32 address = convert24bit(wd->address);
|
||||
|
||||
u8 addressHI = (address >> 16) & 0xFE;
|
||||
INFO_LOG(WIIMOTE, "Write data");
|
||||
DEBUG_LOG(WIIMOTE, " Space: %x", wd->space);
|
||||
DEBUG_LOG(WIIMOTE, " Address: 0x%06x", address);
|
||||
DEBUG_LOG(WIIMOTE, " Size: 0x%02x", wd->size);
|
||||
|
||||
// Write to EEPROM
|
||||
if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM)
|
||||
{
|
||||
|
@ -390,7 +406,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
|
|||
{
|
||||
u8* block;
|
||||
u32 blockSize;
|
||||
switch((address >> 16) & 0xFE)
|
||||
switch(addressHI)
|
||||
{
|
||||
case 0xA2:
|
||||
block = g_RegSpeaker[g_ID];
|
||||
|
@ -422,7 +438,6 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
|
|||
return;
|
||||
}
|
||||
|
||||
// Remove for example 0xa40000 from the address
|
||||
address &= 0xFFFF;
|
||||
|
||||
// Check if the address is within bounds
|
||||
|
@ -430,7 +445,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
|
|||
PanicAlert("WmWriteData: address + size out of bounds!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Finally write the registers to the right structure
|
||||
memcpy(block + address, wd->data, wd->size);
|
||||
|
||||
|
@ -442,7 +457,10 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -487,7 +505,7 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension)
|
|||
if (Extension == -1)
|
||||
{
|
||||
// Read config value for the first time
|
||||
pStatus->extension = (WiiMapping[g_ID].iExtensionConnected == EXT_NONE) ? 0 : 1;
|
||||
pStatus->extension = ((g_MotionPlus[g_ID]) || (WiiMapping[g_ID].iExtensionConnected != EXT_NONE)) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -501,10 +519,121 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension)
|
|||
DEBUG_LOG(WIIMOTE, " IR: %x", pStatus->ir);
|
||||
DEBUG_LOG(WIIMOTE, " LEDs: %x", pStatus->leds);
|
||||
|
||||
|
||||
g_WiimoteInitialize.pWiimoteInput(g_ID, _channelID, DataFrame, Offset);
|
||||
|
||||
// Debugging
|
||||
//ReadDebugging(true, DataFrame, Offset);
|
||||
}
|
||||
|
||||
|
||||
void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){
|
||||
switch (addressHI)
|
||||
{
|
||||
case 0xA4:
|
||||
switch (address)
|
||||
{
|
||||
case 0x00FE:
|
||||
if (data[0] == 0x00) {
|
||||
if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[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);
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM+ already inactive", data[0], addressHI, address);
|
||||
}
|
||||
g_MotionPlus[g_ID] = 1;
|
||||
}
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
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)
|
||||
g_MotionPlusReadError[g_ID] = 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);
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM already enabled no register swapping", data[0], addressHI, 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
|
||||
g_RegExt[g_ID][0xFE] = 0x05;
|
||||
g_RegExt[g_ID][0xF7] = 0x08;
|
||||
}
|
||||
g_MotionPlus[g_ID] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: unknown reason", data[0], addressHI, address);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Swapping Ext/WM+-registers
|
||||
void SwapExtRegisters(){
|
||||
|
||||
memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp));
|
||||
memcpy(g_RegExtTmp, g_RegExt[g_ID], sizeof(g_RegExt[0]));
|
||||
memset(g_RegExt[0], 0, sizeof(g_RegExt[0]));
|
||||
memcpy(g_RegExt[g_ID], g_RegMotionPlus[g_ID], sizeof(g_RegMotionPlus[0]));
|
||||
memset(g_RegMotionPlus[0], 0, sizeof(g_RegMotionPlus[0]));
|
||||
memcpy(g_RegMotionPlus[g_ID], g_RegExtTmp, sizeof(g_RegExtTmp));
|
||||
|
||||
if (g_RegMotionPlus[g_ID][0xFC]) {
|
||||
g_RegMotionPlus[g_ID][0xFC] = 0xa6;
|
||||
}
|
||||
if (g_RegExt[g_ID][0xFC]) {
|
||||
g_RegExt[g_ID][0xFC] = 0xa4;
|
||||
}
|
||||
}
|
||||
|
||||
} // WiiMoteEmu
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue