correct handling of pad modes

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3325 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-06-04 18:40:04 +00:00
parent 47c69e5f5a
commit 4380898080
7 changed files with 68 additions and 38 deletions

View File

@ -452,10 +452,10 @@ void Write32(const u32 _iValue, const u32 _iAddress)
// send command to devices // send command to devices
if (tmpStatus.WR) if (tmpStatus.WR)
{ {
g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex); g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex, g_Poll.EN0);
g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex); g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex, g_Poll.EN1);
g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex); g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex, g_Poll.EN2);
g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex); g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex, g_Poll.EN3);
g_StatusReg.WR = 0; g_StatusReg.WR = 0;
g_StatusReg.WRST0 = 0; g_StatusReg.WRST0 = 0;

View File

@ -72,7 +72,7 @@ public:
} }
bool GetData(u32& _Hi, u32& _Low) {INFO_LOG(SERIALINTERFACE, "SI DUMMY %i GetData", this->m_iDeviceNumber); return false;} bool GetData(u32& _Hi, u32& _Low) {INFO_LOG(SERIALINTERFACE, "SI DUMMY %i GetData", this->m_iDeviceNumber); return false;}
void SendCommand(u32 _Cmd) {INFO_LOG(SERIALINTERFACE, "SI DUMMY %i SendCommand: %08x", this->m_iDeviceNumber, _Cmd);} void SendCommand(u32 _Cmd, u8 _Poll){INFO_LOG(SERIALINTERFACE, "SI DUMMY %i SendCommand: %08x", this->m_iDeviceNumber, _Cmd);}
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -54,7 +54,7 @@ public:
virtual bool GetData(u32& _Hi, u32& _Low) = 0; virtual bool GetData(u32& _Hi, u32& _Low) = 0;
// Send a command directly (no detour per buffer) // Send a command directly (no detour per buffer)
virtual void SendCommand(u32 _Cmd) = 0; virtual void SendCommand(u32 _Cmd, u8 _Poll) = 0;
}; };
// SI Device IDs // SI Device IDs

View File

@ -145,7 +145,7 @@ CSIDevice_GBA::GetData(u32& _Hi, u32& _Low)
// SendCommand // SendCommand
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void void
CSIDevice_GBA::SendCommand(u32 _Cmd) CSIDevice_GBA::SendCommand(u32 _Cmd, u8 _Poll)
{ {
INFO_LOG(SERIALINTERFACE, "GBA %i SendCommand: (0x%08x)", this->m_iDeviceNumber, _Cmd); INFO_LOG(SERIALINTERFACE, "GBA %i SendCommand: (0x%08x)", this->m_iDeviceNumber, _Cmd);
} }

View File

@ -84,6 +84,6 @@ public:
virtual bool GetData(u32& _Hi, u32& _Low); virtual bool GetData(u32& _Hi, u32& _Low);
// Send a command directly // Send a command directly
virtual void SendCommand(u32 _Cmd); virtual void SendCommand(u32 _Cmd, u8 _Poll);
}; };
#endif #endif

View File

@ -18,6 +18,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "SI.h"
#include "SI_Device.h" #include "SI_Device.h"
#include "SI_DeviceGCController.h" #include "SI_DeviceGCController.h"
@ -44,8 +45,8 @@ CSIDevice_GCController::CSIDevice_GCController(int _iDeviceNumber) :
m_origin.uSubStickStickY = 0x80; m_origin.uSubStickStickY = 0x80;
m_origin.uTrigger_L = 0x1F; // 0-30 is the lower deadzone m_origin.uTrigger_L = 0x1F; // 0-30 is the lower deadzone
m_origin.uTrigger_R = 0x1F; m_origin.uTrigger_R = 0x1F;
// I'm borrowing this variable for the PadAnalogMode // Dunno if we need to do this, game/lib should set it?
m_origin.unk_1 = 3; // Mode 3 as default m_Mode = 0x03; // PadAnalogMode 3 as default
} }
int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength) int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
@ -54,14 +55,14 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
ISIDevice::RunBuffer(_pBuffer, _iLength); ISIDevice::RunBuffer(_pBuffer, _iLength);
int iPosition = 0; int iPosition = 0;
while(iPosition < _iLength) while (iPosition < _iLength)
{ {
// Read the command // Read the command
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]); EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]);
iPosition++; iPosition++;
// Handle it // Handle it
switch(command) switch (command)
{ {
case CMD_RESET: case CMD_RESET:
{ {
@ -144,31 +145,58 @@ CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
return true; return true;
} }
#endif #endif
// Thankfully changing mode does not change the high bits ;)
_Hi = (u32)((u8)PadStatus.stickY); _Hi = (u32)((u8)PadStatus.stickY);
_Hi |= (u32)((u8)PadStatus.stickX << 8); _Hi |= (u32)((u8)PadStatus.stickX << 8);
_Hi |= (u32)((u16)PadStatus.button << 16); _Hi |= (u32)((u16)PadStatus.button << 16);
_Hi |= 0x00800000; // F|RES: means that the pad must be "combined" with the origin to match the "final" OSPad-Struct _Hi |= 0x00800000; // F|RES: means that the pad must be "combined" with the origin to match the "final" OSPad-Struct
//_Hi |= 0x20000000; // ? //_Hi |= 0x20000000; // ?
if (m_origin.unk_1 == 0) // Low bits are packed differently per mode
if (m_Mode == 0 || m_Mode == 5 || m_Mode == 6 || m_Mode == 7)
{ {
// Mode 0, 5, 6, 7 _Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
_Low = (u8)(PadStatus.analogB >> 4); _Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
_Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); _Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 8); // Top 4 bits
_Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 8); _Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 12); // Top 4 bits
_Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 12); _Low |= (u32)((u8)(PadStatus.substickY) << 16); // All 8 bits
_Low |= (u32)((u8)(PadStatus.substickY) << 16); _Low |= (u32)((u8)(PadStatus.substickX) << 24); // All 8 bits
_Low |= (u32)((u8)(PadStatus.substickX) << 24);
} }
else else if (m_Mode == 1)
{ {
// Mode 3 _Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
_Low = (u8)PadStatus.triggerRight; _Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
_Low |= (u32)((u8)PadStatus.triggerLeft << 8); _Low |= (u32)((u8)PadStatus.triggerRight << 8); // All 8 bits
_Low |= (u32)((u8)PadStatus.substickY << 16); _Low |= (u32)((u8)PadStatus.triggerLeft << 16); // All 8 bits
_Low |= (u32)((u8)PadStatus.substickX << 24); _Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
_Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
}
else if (m_Mode == 2)
{
_Low = (u8)(PadStatus.analogB); // All 8 bits
_Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
_Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 16); // Top 4 bits
_Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 20); // Top 4 bits
_Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
_Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
}
else if (m_Mode == 3)
{
// Analog A/B are always 0
_Low = (u8)PadStatus.triggerRight; // All 8 bits
_Low |= (u32)((u8)PadStatus.triggerLeft << 8); // All 8 bits
_Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
}
else if (m_Mode == 4)
{
_Low = (u8)(PadStatus.analogB); // All 8 bits
_Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
// triggerLeft/Right are always 0
_Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
_Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
} }
SetMic(PadStatus.MicButton); // This is dumb and should not be here SetMic(PadStatus.MicButton); // This is dumb and should not be here
@ -179,28 +207,29 @@ CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
// SendCommand // SendCommand
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void void
CSIDevice_GCController::SendCommand(u32 _Cmd) CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
{ {
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber); Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
UCommand command(_Cmd); UCommand command(_Cmd);
switch(command.Command) switch (command.Command)
{ {
// Costis sent it in some demos :) // Costis sent it in some demos :)
case 0x00: case 0x00:
break; break;
case CMD_RUMBLE: case CMD_WRITE:
{ {
unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
unsigned int uStrength = command.Parameter2; unsigned int uStrength = command.Parameter2;
if (pad->PAD_Rumble) if (pad->PAD_Rumble)
pad->PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength); pad->PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength);
// Set PadAnalogMode. Hopefully this will not be confused with rumble messages. Most games if (!_Poll)
// seems to always use uStrength = 3 for all rumble messages. {
if (command.Parameter1 == 0 && command.Parameter2 == 0) m_Mode = command.Parameter2;
m_origin.unk_1 = 0; ERROR_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode);
}
} }
break; break;

View File

@ -55,7 +55,7 @@ private:
enum EDirectCommands enum EDirectCommands
{ {
CMD_RUMBLE = 0x40 CMD_WRITE = 0x40
}; };
union UCommand union UCommand
@ -73,6 +73,7 @@ private:
}; };
SOrigin m_origin; SOrigin m_origin;
u8 m_Mode;
public: public:
@ -89,6 +90,6 @@ public:
virtual bool GetData(u32& _Hi, u32& _Low); virtual bool GetData(u32& _Hi, u32& _Low);
// Send a command directly // Send a command directly
virtual void SendCommand(u32 _Cmd); virtual void SendCommand(u32 _Cmd, u8 _Poll);
}; };
#endif #endif