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
if (tmpStatus.WR)
{
g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex);
g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex);
g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex);
g_Channel[3].m_pDevice->SendCommand(g_Channel[3].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_Poll.EN1);
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_Poll.EN3);
g_StatusReg.WR = 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;}
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;
// 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

View File

@ -145,7 +145,7 @@ CSIDevice_GBA::GetData(u32& _Hi, u32& _Low)
// SendCommand
//////////////////////////////////////////////////////////////////////////
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);
}

View File

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

View File

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

View File

@ -55,24 +55,25 @@ private:
enum EDirectCommands
{
CMD_RUMBLE = 0x40
CMD_WRITE = 0x40
};
union UCommand
{
u32 Hex;
struct
{
{
unsigned Parameter1 : 8;
unsigned Parameter2 : 8;
unsigned Command : 8;
unsigned : 8;
};
UCommand() {Hex = 0;}
UCommand() {Hex = 0;}
UCommand(u32 _iValue) {Hex = _iValue;}
};
SOrigin m_origin;
u8 m_Mode;
public:
@ -89,6 +90,6 @@ public:
virtual bool GetData(u32& _Hi, u32& _Low);
// Send a command directly
virtual void SendCommand(u32 _Cmd);
virtual void SendCommand(u32 _Cmd, u8 _Poll);
};
#endif