Moved the GC Adapter processing under "Standard Controller" as it appears the adapter does not work with controllers other than the standard controller (pads, bongos, some dance mats).

This commit is contained in:
skidau 2014-12-11 14:06:35 +11:00
parent 8fdd04e647
commit 30b34f3b2e
6 changed files with 93 additions and 141 deletions

View File

@ -15,9 +15,6 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI.h"
#include "Core/HW/SI_DeviceGBA.h"
#if defined(__LIBUSB__) || defined (_WIN32)
#include "Core/HW/SI_GCAdapter.h"
#endif
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
@ -59,6 +56,56 @@ enum
SI_EXI_CLOCK_COUNT = 0x3C,
};
// SI Channel Output
union USIChannelOut
{
u32 Hex;
struct
{
u32 OUTPUT1 : 8;
u32 OUTPUT0 : 8;
u32 CMD : 8;
u32 : 8;
};
};
// SI Channel Input High u32
union USIChannelIn_Hi
{
u32 Hex;
struct
{
u32 INPUT3 : 8;
u32 INPUT2 : 8;
u32 INPUT1 : 8;
u32 INPUT0 : 6;
u32 ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
u32 ERRSTAT : 1; // 0: no error 1: error on last transfer
};
};
// SI Channel Input Low u32
union USIChannelIn_Lo
{
u32 Hex;
struct
{
u32 INPUT7 : 8;
u32 INPUT6 : 8;
u32 INPUT5 : 8;
u32 INPUT4 : 8;
};
};
// SI Channel
struct SSIChannel
{
USIChannelOut m_Out;
USIChannelIn_Hi m_InHi;
USIChannelIn_Lo m_InLo;
ISIDevice* m_pDevice;
};
// SI Poll: Controls how often a device is polled
union USIPoll
{
@ -337,9 +384,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
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);
#if defined(__LIBUSB__) || defined (_WIN32)
SI_GCAdapter::Output(g_Channel);
#endif
g_StatusReg.WR = 0;
g_StatusReg.WRST0 = 0;
g_StatusReg.WRST1 = 0;
@ -462,29 +507,6 @@ void UpdateDevices()
g_StatusReg.RDST2 = !!g_Channel[2].m_pDevice->GetData(g_Channel[2].m_InHi.Hex, g_Channel[2].m_InLo.Hex);
g_StatusReg.RDST3 = !!g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex);
// Check for connected GC Adapter
#if defined(__LIBUSB__) || defined (_WIN32)
if (SConfig::GetInstance().m_GameCubeAdapter)
{
g_StatusReg.RDST0 |= (SI_GCAdapter::GetDeviceType(0) != SIDEVICE_NONE);
g_StatusReg.RDST1 |= (SI_GCAdapter::GetDeviceType(1) != SIDEVICE_NONE);
g_StatusReg.RDST2 |= (SI_GCAdapter::GetDeviceType(2) != SIDEVICE_NONE);
g_StatusReg.RDST3 |= (SI_GCAdapter::GetDeviceType(3) != SIDEVICE_NONE);
for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
{
SIDevices connected_device = SI_GCAdapter::GetDeviceType(chan);
SIDevices configured_device = SConfig::GetInstance().m_SIDevice[chan];
if (connected_device != SIDEVICE_NONE)
ChangeDevice(connected_device, chan);
else
ChangeDevice(configured_device, chan);
}
SI_GCAdapter::Input(g_Channel);
}
#endif
UpdateInterrupts();
}

View File

@ -20,56 +20,6 @@ enum
namespace SerialInterface
{
// SI Channel Output
union USIChannelOut
{
u32 Hex;
struct
{
u32 OUTPUT1 : 8;
u32 OUTPUT0 : 8;
u32 CMD : 8;
u32 : 8;
};
};
// SI Channel Input High u32
union USIChannelIn_Hi
{
u32 Hex;
struct
{
u32 INPUT3 : 8;
u32 INPUT2 : 8;
u32 INPUT1 : 8;
u32 INPUT0 : 6;
u32 ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
u32 ERRSTAT : 1; // 0: no error 1: error on last transfer
};
};
// SI Channel Input Low u32
union USIChannelIn_Lo
{
u32 Hex;
struct
{
u32 INPUT7 : 8;
u32 INPUT6 : 8;
u32 INPUT5 : 8;
u32 INPUT4 : 8;
};
};
// SI Channel
struct SSIChannel
{
USIChannelOut m_Out;
USIChannelIn_Hi m_InHi;
USIChannelIn_Lo m_InLo;
ISIDevice* m_pDevice;
};
void Init();
void Shutdown();
void DoState(PointerWrap &p);

View File

@ -12,6 +12,9 @@
#include "Core/HW/SI.h"
#include "Core/HW/SI_Device.h"
#include "Core/HW/SI_DeviceGCController.h"
#if defined(__LIBUSB__) || defined (_WIN32)
#include "Core/HW/SI_GCAdapter.h"
#endif
#include "Core/HW/SystemTimers.h"
// --- standard GameCube controller ---
@ -110,6 +113,11 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
memset(&PadStatus, 0, sizeof(PadStatus));
Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
#if defined(__LIBUSB__) || defined (_WIN32)
SI_GCAdapter::Input(ISIDevice::m_iDeviceNumber, &PadStatus);
#endif
Movie::CallGCInputManip(&PadStatus, ISIDevice::m_iDeviceNumber);
Movie::SetPolledDevice();
@ -248,6 +256,9 @@ void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
// get the correct pad number that should rumble locally when using netplay
const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber);
#if defined(__LIBUSB__) || defined (_WIN32)
SI_GCAdapter::Output(numPAD, command.Parameter1 & 0xff);
#endif
if (numPAD < 4)
{
if (uType == 1 && uStrength > 2)

View File

@ -6,7 +6,6 @@
#include "Core/ConfigManager.h"
#include "Core/HW/SI_GCAdapter.h"
#include "InputCommon/GCPadStatus.h"
namespace SI_GCAdapter
{
@ -19,7 +18,7 @@ enum ControllerTypes
static libusb_device_handle* s_handle = nullptr;
static u8 s_controller_type[MAX_SI_CHANNELS] = { CONTROLLER_NONE, CONTROLLER_NONE, CONTROLLER_NONE, CONTROLLER_NONE };
static u8 s_controller_last_rumble[4];
static u8 s_controller_rumble[4];
static std::mutex s_mutex;
static u8 s_controller_payload[37];
@ -60,7 +59,7 @@ void Init()
for (int i = 0; i < MAX_SI_CHANNELS; i++)
{
s_controller_type[i] = CONTROLLER_NONE;
s_controller_last_rumble[i] = 0;
s_controller_rumble[i] = 0;
}
int ret = libusb_init(nullptr);
@ -196,7 +195,7 @@ void Shutdown()
s_handle = nullptr;
}
void Input(SerialInterface::SSIChannel* g_Channel)
void Input(int chan, GCPadStatus* pad)
{
if (s_handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
return;
@ -214,8 +213,6 @@ void Input(SerialInterface::SSIChannel* g_Channel)
Shutdown();
}
else
{
for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
{
u8 type = controller_payload_copy[1 + (9 * chan)] >> 4;
if (type != CONTROLLER_NONE && s_controller_type[chan] == CONTROLLER_NONE)
@ -225,50 +222,35 @@ void Input(SerialInterface::SSIChannel* g_Channel)
if (s_controller_type[chan] != CONTROLLER_NONE)
{
g_Channel[chan].m_InHi.Hex = 0;
g_Channel[chan].m_InLo.Hex = 0;
for (int j = 0; j < 4; j++)
{
g_Channel[chan].m_InHi.Hex |= (controller_payload_copy[2 + chan + j + (8 * chan) + 0] << (8 * (3 - j)));
g_Channel[chan].m_InLo.Hex |= (controller_payload_copy[2 + chan + j + (8 * chan) + 4] << (8 * (3 - j)));
}
pad->button = controller_payload_copy[1 + (9 * chan) + 1] << 8;
u8 buttons_0 = (g_Channel[chan].m_InHi.Hex >> 28) & 0x0f;
u8 buttons_1 = (g_Channel[chan].m_InHi.Hex >> 24) & 0x0f;
u8 buttons_2 = (g_Channel[chan].m_InHi.Hex >> 20) & 0x0f;
u8 buttons_3 = (g_Channel[chan].m_InHi.Hex >> 16) & 0x0f;
g_Channel[chan].m_InHi.Hex = buttons_3 << 28 | buttons_1 << 24 | (buttons_2) << 20 | buttons_0 << 16 | (g_Channel[chan].m_InHi.Hex & 0x0000ffff);
u8 b = controller_payload_copy[1 + (9 * chan) + 2];
if (b & (1 << 0)) pad->button |= PAD_BUTTON_START;
if (b & (1 << 1)) pad->button |= PAD_TRIGGER_Z;
if (b & (1 << 2)) pad->button |= PAD_TRIGGER_R;
if (b & (1 << 3)) pad->button |= PAD_TRIGGER_L;
if (type == CONTROLLER_WIRED || type == CONTROLLER_WIRELESS)
g_Channel[chan].m_InHi.Hex |= (PAD_USE_ORIGIN << 16);
}
pad->stickX = controller_payload_copy[1 + (9 * chan) + 3];
pad->stickY = controller_payload_copy[1 + (9 * chan) + 4];
pad->substickX = controller_payload_copy[1 + (9 * chan) + 5];
pad->substickY = controller_payload_copy[1 + (9 * chan) + 6];
pad->triggerLeft = controller_payload_copy[1 + (9 * chan) + 7];
pad->triggerRight = controller_payload_copy[1 + (9 * chan) + 8];
}
}
}
void Output(SerialInterface::SSIChannel* g_Channel)
void Output(int chan, u8 rumble)
{
if (s_handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
return;
bool rumble_update = false;
u8 current_rumble[4] = { 0, 0, 0, 0 };
for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
// Skip over rumble commands if it has not changed or the controller is wireless
if (rumble != s_controller_rumble[chan] && s_controller_type[chan] != CONTROLLER_WIRELESS)
{
// Skip over rumble commands if the controller is wireless
if (s_controller_type[chan] != CONTROLLER_WIRELESS)
current_rumble[chan] = g_Channel[chan].m_Out.Hex & 0xff;
s_controller_rumble[chan] = rumble;
if (current_rumble[chan] != s_controller_last_rumble[chan])
rumble_update = true;
s_controller_last_rumble[chan] = current_rumble[chan];
}
if (rumble_update)
{
unsigned char rumble[5] = { 0x11, current_rumble[0], current_rumble[1], current_rumble[2], current_rumble[3] };
unsigned char rumble[5] = { 0x11, s_controller_rumble[0], s_controller_rumble[1], s_controller_rumble[2], s_controller_rumble[3] };
int size = 0;
libusb_interrupt_transfer(s_handle, s_endpoint_out, rumble, sizeof(rumble), &size, 0);

View File

@ -6,14 +6,15 @@
#include "Common/Thread.h"
#include "Core/HW/SI.h"
#include "InputCommon/GCPadStatus.h"
namespace SI_GCAdapter
{
void Init();
void Shutdown();
void Input(SerialInterface::SSIChannel* g_Channel);
void Output(SerialInterface::SSIChannel* g_Channel);
void Input(int chan, GCPadStatus* pad);
void Output(int chan, u8 rumble);
SIDevices GetDeviceType(int channel);
void RefreshConnectedDevices();
bool IsDetected();

View File

@ -104,22 +104,8 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
if (NetPlay::IsNetPlayRunning() || Movie::IsMovieActive())
pad_type_choices[i]->Disable();
SIDevices selected_device = SConfig::GetInstance().m_SIDevice[i];
#if defined(__LIBUSB__) || defined (_WIN32)
if (Core::GetState() != Core::CORE_UNINITIALIZED)
{
SI_GCAdapter::RefreshConnectedDevices();
if (SI_GCAdapter::GetDeviceType(i) != SIDEVICE_NONE)
{
pad_type_choices[i]->Disable();
selected_device = SI_GCAdapter::GetDeviceType(i);
}
}
#endif
// Set the saved pad type as the default choice.
switch (selected_device)
switch (SConfig::GetInstance().m_SIDevice[i])
{
case SIDEVICE_GC_CONTROLLER:
pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[1]);